#!/usr/bin/env python3 # # Name: juniper_qfx5200_eepromconv.py version: 1.0 # # Description: This file contains the code to store the contents of Main Board EEPROM and CPU Board EEPROM in file # # Copyright (c) 2020, Juniper Networks, Inc. # All rights reserved. # # Notice and Disclaimer: This code is licensed to you under the GNU General # Public License as published by the Free Software Foundation, version 3 or # any later version. This code is not an official Juniper product. You can # obtain a copy of the License at # # OSS License: # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Third-Party Code: This code may depend on other components under separate # copyright notice and license terms. Your use of the source code for those # components is subject to the terms and conditions of the respective license # as noted in the Third-Party source code file. import binascii import os import subprocess from sonic_eeprom import eeprom_tlvinfo from sonic_py_common.general import getstatusoutput_noshell def fantype_detect(): refpgaTMC_path = "/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15" AFO = "1" AFI = "0" # default fan type is AFO default_fantype = "0" for filename in os.listdir(refpgaTMC_path): if filename.endswith('_type'): fantype_path = os.path.join(refpgaTMC_path, filename) status, fan_type = getstatusoutput_noshell(['cat', fantype_path]) if ((fan_type == AFO) or (fan_type == AFI)): return fan_type else: pass return default_fantype def main(): AFO_value = "1" eeprom_qfx5200 = Eeprom() fan_type = fantype_detect() # creating the "/var/run/eeprom" file and storing values of CPU board EEPROM and MAIN Board EEPROM in this file. eeprom_file = open("/var/run/eeprom", "a+") eeprom_file.write("\n") if fan_type == AFO_value: eeprom_file.write("Fan Type=AFO\r\n") else: eeprom_file.write("Fan Type=AFI\r\n") eeprom_file.write("\n") # Write the contents of CPU Board EEPROM to file eeprom_file.write("CPU board eeprom (0x51)\r\n") eeprom_file.write("===============================\r\n") eeprom_file.write("Product Name=%s\r\n" % eeprom_qfx5200.modelstr()) eeprom_file.write("Part Number=%s\r\n" % eeprom_qfx5200.part_number_str()) eeprom_file.write("Serial Number=%s\r\n" % eeprom_qfx5200.serial_number_str()) eeprom_file.write("MAC Address=%s\r\n" % eeprom_qfx5200.base_mac_address()) eeprom_file.write("Manufacture Date=%s\r\n" % eeprom_qfx5200.manuDate_str()) eeprom_file.write("Platform Name=%s\r\n" % eeprom_qfx5200.platform_str()) eeprom_file.write("Number of MAC Addresses=%s\r\n" % eeprom_qfx5200.MACsize_str()) eeprom_file.write("Vendor Name=%s\r\n" % eeprom_qfx5200.vendor_name_str()) eeprom_file.write("Manufacture Name=%s\r\n" % eeprom_qfx5200.manufacture_name_str()) eeprom_dict = eeprom_qfx5200.system_eeprom_info() key = '0x29' if key in list(eeprom_dict.keys()): onie_version_str = eeprom_dict.get('0x29', None) else: onie_version_str = "N/A" eeprom_file.write("ONIE Version=%s\r\n" % onie_version_str) vendor_value_formatted, vendor_value_hexvalue = eeprom_qfx5200.vendor_ext_str() eeprom_hex = '/etc/init.d/eeprom_qfx5200_hex' with open(eeprom_hex, 'wb+') as Hexfile: Hexfile.write(vendor_value_hexvalue) # Assembly ID ASMID_str = "0D83" with open(eeprom_hex, 'rb+') as AsmID_Hexfile: AsmID_Hexfile.seek(24, 0) AsmID_Hexfile.write(ASMID_str) AsmID_Hexfile.seek(0, 0) vendorext_read = AsmID_Hexfile.read(58) vendorext = "" vendorext += "0x" + vendorext_read[0:2] for i in range(2, 58, 2): vendorext += " 0x" + vendorext_read[i:i+2] eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext)) with open(eeprom_hex, 'rb') as eeprom_hexfile: eeprom_hexfile.seek(0, 0) IANA_position_read = eeprom_hexfile.read(8) IANA_write = binascii.unhexlify(IANA_position_read) eeprom_file.write("\t") eeprom_file.write("IANA=0x%s\r\n" % IANA_write) eeprom_hexfile.seek(8, 0) AssemblyPartRev_position_read = eeprom_hexfile.read(16) AssemblyPartRev_write = binascii.unhexlify(AssemblyPartRev_position_read) eeprom_file.write("\t") eeprom_file.write("Assembly Part Number Revision=0x%s\r\n" % AssemblyPartRev_write) eeprom_hexfile.seek(24, 0) AssemblyID_write = eeprom_hexfile.read(4) eeprom_file.write("\t") eeprom_file.write("Assembly ID=0x%s\r\n" % AssemblyID_write) eeprom_hexfile.seek(28, 0) HWMajorRev_write = eeprom_hexfile.read(2) eeprom_file.write("\t") eeprom_file.write("HW Major Revision=0x%s\r\n" % HWMajorRev_write) eeprom_hexfile.seek(30, 0) HWMinorRev_write = eeprom_hexfile.read(2) eeprom_file.write("\t") eeprom_file.write("HW Minor Revision=0x%s\r\n" % HWMinorRev_write) eeprom_hexfile.seek(32, 0) Deviation_write = eeprom_hexfile.read(10) eeprom_file.write("\t") eeprom_file.write("Deviation=0x%s\r\n" % Deviation_write) eeprom_hexfile.seek(52, 0) JEDC_write = eeprom_hexfile.read(4) eeprom_file.write("\t") eeprom_file.write("JEDC=0x%s\r\n" % JEDC_write) eeprom_hexfile.seek(56, 0) EEPROM_version_write = eeprom_hexfile.read(2) eeprom_file.write("\t") eeprom_file.write("EEPROM version=0x%s\r\n" % EEPROM_version_write) crc_str = eeprom_dict.get('0xFE', None) eeprom_file.write("CRC=%s\r\n" % crc_str) eeprom_file.write("\n") eeprom_file.write("\n") eeprom_file.write("Main board eeprom (0x57)\r\n") eeprom_file.write("===============================\r\n") MainEepromCreate = '24c02 0x57' out_file = '/sys/bus/i2c/devices/i2c-0/new_device' # Write the contents of Main Board EEPROM to file try: with open(out_file, 'w') as file: file.write(MainEepromCreate) except OSError: print('Error: Execution of "%s" failed', MainEepromCreate) return False MainEepromFileCmd = ['cat', '/sys/bus/i2c/devices/i2c-0/0-0057/eeprom'] out_file = '/etc/init.d/MainEeprom_qfx5200_ascii' try: with open(out_file, 'w') as file: subprocess.call(MainEepromFileCmd, universal_newlines=True, stdout=file) except OSError: print('Error: Execution of "%s" failed', MainEepromFileCmd) return False maineeprom_ascii = '/etc/init.d/MainEeprom_qfx5200_ascii' # Read file contents in Hex format with open(maineeprom_ascii, 'rb') as Hexformat: content = Hexformat.read() Hexformatoutput = binascii.hexlify(content) eeprom_hex = '/etc/init.d/MainEeprom_qfx5200_hex' # Write contents of CPU EEPROM to new file in hexa format with open(eeprom_hex, 'wb+') as Hexfile: Hexfile.write(Hexformatoutput) with open(eeprom_hex, 'rb') as eeprom_hexfile: eeprom_hexfile.seek(8, 0) AssemblyID_read = eeprom_hexfile.read(4) eeprom_file.write("Assembly ID=0x%s\r\n" % AssemblyID_read) eeprom_hexfile.seek(12, 0) MajorHWRev_read = eeprom_hexfile.read(2) eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(MajorHWRev_read)) eeprom_hexfile.seek(14, 0) MinorHWRev_read = eeprom_hexfile.read(2) eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(MinorHWRev_read)) eeprom_hexfile.seek(24, 0) AssemblyPNRev_read = eeprom_hexfile.read(16) AssemblyPNRev_write = binascii.unhexlify(AssemblyPNRev_read) eeprom_file.write("Assembly Part Number Revision=0x%s\r\n" % str(AssemblyPNRev_write)) eeprom_hexfile.seek(40, 0) AssemblyPN_read = eeprom_hexfile.read(24) AssemblyPN_write = binascii.unhexlify(AssemblyPN_read) eeprom_file.write("Assembly Part Number=%s\r\n" % str(AssemblyPN_write)) eeprom_hexfile.seek(64, 0) AssemblySN_read = eeprom_hexfile.read(24) AssemblySN_write = binascii.unhexlify(AssemblySN_read) eeprom_file.write("Assembly Serial Number=%s\r\n" % str(AssemblySN_write)) eeprom_hexfile.seek(90, 0) AssemblyMFGDate_read = eeprom_hexfile.read(8) eeprom_file.write("Manufacture Date=%s\r\n" % str(AssemblyMFGDate_read)) eeprom_hexfile.seek(138, 0) CLEICode_read = eeprom_hexfile.read(20) CLEI_name = binascii.unhexlify(CLEICode_read) eeprom_file.write("CLEI Code=%s\r\n" % str(CLEI_name)) eeprom_hexfile.seek(158, 0) FRUModelNumber_read = eeprom_hexfile.read(46) FRUModelNumber_write = binascii.unhexlify(FRUModelNumber_read) eeprom_file.write("FRU Model Number=%s\r\n" % str(FRUModelNumber_write)) eeprom_hexfile.seek(204, 0) FRUModelMajorNumber_read = eeprom_hexfile.read(2) eeprom_file.write("FRU Model Major Number=0x%s\r\n" % str(FRUModelMajorNumber_read)) eeprom_hexfile.seek(206, 0) FRUModelMinorNumber_read = eeprom_hexfile.read(4) eeprom_file.write("FRU Model Minor Number=0x%s\r\n" % str(FRUModelMinorNumber_read)) eeprom_hexfile.seek(210, 0) Deviation_read = eeprom_hexfile.read(10) eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read)) eeprom_hexfile.seek(232, 0) SerialNumber_read = eeprom_hexfile.read(24) SerialNumber_write = binascii.unhexlify(SerialNumber_read) eeprom_file.write("Chassis Serial Number=%s\r\n" % str(SerialNumber_write)) eeprom_file.close() return True class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): def __init__(self): self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom" super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) self.__eeprom_tlv_dict = dict() try: self.__eeprom_data = self.read_eeprom() except: self.__eeprom_data = "N/A" raise RuntimeError("Eeprom is not Programmed") else: eeprom = self.__eeprom_data if not self.is_valid_tlvinfo_header(eeprom): return total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) tlv_index = self._TLV_INFO_HDR_LEN tlv_end = self._TLV_INFO_HDR_LEN + total_length while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: if not self.is_valid_tlv(eeprom[tlv_index:]): break tlv = eeprom[tlv_index:tlv_index + 2 + ord(eeprom[tlv_index + 1])] code = "0x%02X" % (ord(tlv[0])) if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | (ord(tlv[4]) << 8) | ord(tlv[5])) value += str(tlv[6:6 + ord(tlv[1])]) else: name, value = self.decoder(None, tlv) self.__eeprom_tlv_dict[code] = value if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: break tlv_index += ord(eeprom[tlv_index+1]) + 2 def serial_number_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) if not is_valid: return "N/A" return results[2] def base_mac_address(self): (is_valid, t) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_MAC_BASE) if not is_valid or t[1] != 6: return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data) return ":".join([binascii.b2a_hex(T) for T in t[2]]) def modelstr(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) if not is_valid: return "N/A" return results[2] def part_number_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_PART_NUMBER) if not is_valid: return "N/A" return results[2] def serial_tag_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) if not is_valid: return "N/A" return results[2] def revision_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) if not is_valid: return "N/A" return results[2] def manuDate_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_MANUF_DATE) if not is_valid: return "N/A" return results[2] def platform_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_PLATFORM_NAME) if not is_valid: return "N/A" return results[2] def MACsize_str(self): (is_valid, t) = self.get_tlv_field(self.__eeprom_data, self._TLV_CODE_MAC_SIZE) if not is_valid: return "N/A" return str((ord(t[2][0]) << 8) | ord(t[2][1])) def vendor_name_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_VENDOR_NAME) if not is_valid: return "N/A" return results[2] def manufacture_name_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_MANUF_NAME) if not is_valid: return "N/A" return results[2] def onie_version_str(self): value = "" (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_ONIE_VERSION) if not is_valid: return "N/A" for c in results[2:2 + ord(results[1])]: value += "0x%02X " % (ord(c),) return value def vendor_ext_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_VENDOR_EXT) if not is_valid: return "N/A" vendor_value_formatted = ''.join([" 0x" + "%02X " % ord(x) for x in results[2]]).strip() vendor_value_hexvalue = ''.join(["%02X" % ord(x) for x in results[2]]).strip() return vendor_value_formatted, vendor_value_hexvalue def crc_str(self): (is_valid, results) = self.get_tlv_field( self.__eeprom_data, self._TLV_CODE_CRC_32) if not is_valid: return "N/A" def system_eeprom_info(self): """ Returns a dictionary, where keys are the type code defined in ONIE EEPROM format and values are their corresponding values found in the system EEPROM. """ return self.__eeprom_tlv_dict if __name__ == "__main__": main()