############################################################################# # Celestica # # Component contains an implementation of SONiC Platform Base API and # provides the components firmware management function # ############################################################################# import os.path import shutil try: from sonic_platform_base.component_base import ComponentBase from .helper import APIHelper except ImportError as e: raise ImportError(str(e) + "- required module not found") CPLD_ADDR_MAPPING = { "CPLD1": "0x100", "CPLD2": "0x200", "CPLD3": "0x280", "CPLD4": "0x300", "CPLD5": "0x380" } GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg" BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "CPLD5", "BIOS"] COMPONENT_DES_LIST = ["Used for managing the CPU", "Used for managing QSFP+ ports (1-10)", "Used for managing QSFP+ ports (11-21)", "Used for misc status and control", "Used for managing QSFP+ ports (22-32)", "Basic Input/Output System"] class Component(ComponentBase): """Platform-specific Component class""" DEVICE_TYPE = "component" def __init__(self, component_index): ComponentBase.__init__(self) self.index = component_index self._api_helper = APIHelper() self.name = self.get_name() def __get_bios_version(self): # Retrieves the BIOS firmware version try: with open(BIOS_VERSION_PATH, 'r') as fd: bios_version = fd.read() return bios_version.strip() except Exception as e: return None def get_register_value(self, register): # Retrieves the cpld register value with open(GETREG_PATH, 'w') as file: file.write(register + '\n') with open(GETREG_PATH, 'r') as file: raw_data = file.readline() return raw_data.strip() def __get_cpld_version(self): # Retrieves the CPLD firmware version cpld_version = dict() for cpld_name in CPLD_ADDR_MAPPING: try: cpld_addr = CPLD_ADDR_MAPPING[cpld_name] cpld_version_raw = self.get_register_value(cpld_addr) cpld_version_str = "{}.{}".format(int(cpld_version_raw[2], 16), int( cpld_version_raw[3], 16)) if cpld_version_raw is not None else 'None' cpld_version[cpld_name] = cpld_version_str except Exception as e: cpld_version[cpld_name] = 'None' return cpld_version def get_name(self): """ Retrieves the name of the component Returns: A string containing the name of the component """ return COMPONENT_NAME_LIST[self.index] def get_description(self): """ Retrieves the description of the component Returns: A string containing the description of the component """ return COMPONENT_DES_LIST[self.index] def get_firmware_version(self): """ Retrieves the firmware version of module Returns: string: The firmware versions of the module """ fw_version = None if self.name == "BIOS": fw_version = self.__get_bios_version() elif "CPLD" in self.name: cpld_version = self.__get_cpld_version() fw_version = cpld_version.get(self.name) return fw_version def get_available_firmware_version(self, image_path): """ Retrieves the available firmware version of the component Note: the firmware version will be read from image Args: image_path: A string, path to firmware image Returns: A string containing the available firmware version of the component """ return "N/A" def get_firmware_update_notification(self, image_path): """ Retrieves a notification on what should be done in order to complete the component firmware update Args: image_path: A string, path to firmware image Returns: A string containing the component firmware update notification if required. By default 'None' value will be used, which indicates that no actions are required """ return "None" def install_firmware(self, image_path): """ Install firmware to module Args: image_path: A string, path to firmware image Returns: A boolean, True if install successfully, False if not """ if not os.path.isfile(image_path): return False if "CPLD" in self.name: img_name = os.path.basename(image_path) root, ext = os.path.splitext(img_name) ext = ".vme" if ext == "" else ext new_image_path = os.path.join("/tmp", (root.lower() + ext)) shutil.copy(image_path, new_image_path) install_command = ["ispvm", str(new_image_path)] # elif self.name == "BIOS": # install_command = "afulnx_64 %s /p /b /n /x /r" % image_path return self._api_helper.run_command(install_command) def update_firmware(self, image_path): """ Updates firmware of the component This API performs firmware update: it assumes firmware installation and loading in a single call. In case platform component requires some extra steps (apart from calling Low Level Utility) to load the installed firmware (e.g, reboot, power cycle, etc.) - this will be done automatically by API Args: image_path: A string, path to firmware image Raises: RuntimeError: update failed """ return False ############################################################## ###################### Device methods ######################## ############################################################## def get_presence(self): """ Retrieves the presence of the FAN Returns: bool: True if FAN is present, False if not """ return True def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return 'N/A' def get_serial(self): """ Retrieves the serial number of the device Returns: string: Serial number of device """ return 'N/A' def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True def get_position_in_parent(self): """ Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position for some reason, or if the associated value of entPhysicalContainedIn is'0', then the value '-1' is returned Returns: integer: The 1-based relative physical position in parent device or -1 if cannot determine the position """ return -1 def is_replaceable(self): """ Indicate whether this device is replaceable. Returns: bool: True if it is replaceable. """ return False