diff --git a/bindings/sysman/python/README.md b/bindings/sysman/python/README.md index 1a5d15a6..4be5d919 100644 --- a/bindings/sysman/python/README.md +++ b/bindings/sysman/python/README.md @@ -180,6 +180,7 @@ SUPPORTED APIs | `zesDeviceGetHealthStatusExt` | Device | 0.1.4 | None | | `zesDeviceSetHealthStatusExt` | Device | 0.1.4 | Linux: Requires superuser; persisted to non-volatile memory | | `zesDeviceEnumFirmwares` | Device | 0.1.4 | None | +| `zesFirmwareGetProperties` | Firmware | 0.1.4 | None | | **Memory Management** |-|-|-| | `zesDeviceEnumMemoryModules` | Memory | 0.1.0 | None | | `zesMemoryGetProperties` | Memory | 0.1.0 | None | diff --git a/bindings/sysman/python/source/pyzes/__init__.py b/bindings/sysman/python/source/pyzes/__init__.py index fb287d2d..823f73f3 100644 --- a/bindings/sysman/python/source/pyzes/__init__.py +++ b/bindings/sysman/python/source/pyzes/__init__.py @@ -508,6 +508,7 @@ class zes_firmware_handle_t(c_void_p): ZES_STRUCTURE_TYPE_INFO_LOG_METADATA_EXT = 0x00020022 ZES_STRUCTURE_TYPE_INFO_LOG_READ_STATUS_EXT = 0x00020023 ZES_STRUCTURE_TYPE_DRIVER_PROPERTIES = 0x2F +ZES_STRUCTURE_TYPE_FIRMWARE_PROPERTIES = 0x8 ## Core ze_device UUID struct ## @@ -1069,6 +1070,18 @@ class zes_info_log_read_status_ext_t(_PrintableStructure): _fmt_ = {"consumedDataSize": "%d bytes"} +class zes_firmware_properties_t(_PrintableStructure): + _fields_ = [ + ("stype", c_int32), + ("pNext", c_void_p), + ("onSubdevice", ze_bool_t), + ("subdeviceId", c_uint32), + ("canControl", ze_bool_t), + ("name", c_char * ZES_STRING_PROPERTY_SIZE), + ("version", c_char * ZES_STRING_PROPERTY_SIZE), + ] + + ## Function access ## _getFunctionPointerList: Dict[str, Any] = dict() @@ -1482,6 +1495,26 @@ def zesDeviceEnumFirmwares(hDevice, pCount, phFirmware): return retVal +def zesFirmwareGetProperties(hFirmware, pProperties): + """Wraps API: + ze_result_t zesFirmwareGetProperties( + zes_firmware_handle_t hFirmware, + zes_firmware_properties_t* pProperties) + + Parameters: + hFirmware: firmware handle + pProperties: POINTER(zes_firmware_properties_t) - properties structure to fill + Returns: + ze_result_t - return code only, properties are filled into pProperties + """ + funcPtr = getFunctionPointerList("zesFirmwareGetProperties") + funcPtr.argtypes = [zes_firmware_handle_t, POINTER(zes_firmware_properties_t)] + funcPtr.restype = ze_result_t + + retVal = funcPtr(hFirmware, pProperties) + return retVal + + ## Memory management functions ## def zesDeviceEnumMemoryModules(hDevice, pCount, phMemory): """Wraps API: diff --git a/bindings/sysman/python/source/pyzes/examples/pyzes_black_box_test.py b/bindings/sysman/python/source/pyzes/examples/pyzes_black_box_test.py index 4da9431f..1748a9a8 100755 --- a/bindings/sysman/python/source/pyzes/examples/pyzes_black_box_test.py +++ b/bindings/sysman/python/source/pyzes/examples/pyzes_black_box_test.py @@ -2177,6 +2177,51 @@ def test_device_health_module(device_handle, device_index, set_health=None): return True +def test_firmware_module(device_handle, device_index): + """Test firmware enumeration and properties""" + print(f"\n---- Device {device_index} Firmware Test ----") + + firmware_count = c_uint32(0) + rc = pz.zesDeviceEnumFirmwares(device_handle, byref(firmware_count), None) + if not check_rc(f"zesDeviceEnumFirmwares(device {device_index}, count)", rc): + return False + + if firmware_count.value == 0: + print_verbose("No firmware components found on this device") + return True + + print_verbose(f"Found {firmware_count.value} firmware component(s)") + + FirmwareArray = pz.zes_firmware_handle_t * firmware_count.value + firmware_handles = FirmwareArray() + + rc = pz.zesDeviceEnumFirmwares( + device_handle, byref(firmware_count), firmware_handles + ) + if not check_rc(f"zesDeviceEnumFirmwares(device {device_index}, handles)", rc): + return False + + for i in range(firmware_count.value): + print_verbose(f"\n Firmware {i}:") + + props = pz.zes_firmware_properties_t() + props.stype = pz.ZES_STRUCTURE_TYPE_FIRMWARE_PROPERTIES + props.pNext = None + + rc = pz.zesFirmwareGetProperties(firmware_handles[i], byref(props)) + if not check_rc(f"zesFirmwareGetProperties(firmware {i})", rc): + continue + + print_verbose(f" Name: {props.name.decode('utf-8', errors='ignore')}") + print_verbose(f" Version: {props.version.decode('utf-8', errors='ignore')}") + print_verbose(f" On Subdevice: {bool(props.onSubdevice)}") + if props.onSubdevice: + print_verbose(f" Subdevice ID: {props.subdeviceId}") + print_verbose(f" Can Control: {bool(props.canControl)}") + + return True + + def test_memory_modules(device_handle, device_index): """Test memory module enumeration and operations""" print(f"\n---- Device {device_index} Memory Modules Test ----") @@ -2889,6 +2934,8 @@ def run_all_tests(): test_vf_management_module(devices[device_idx], device_idx) + test_firmware_module(devices[device_idx], device_idx) + if not test_info_log_module(drivers[driver_idx], driver_idx): success = False @@ -2923,6 +2970,7 @@ def main(): %(prog)s -re --clear-ras-state # RAS tests, clear all error counters (root) %(prog)s -s # Standby tests only %(prog)s -v # VF management tests only + %(prog)s -i # Firmware tests only %(prog)s -L # Info log properties tests only %(prog)s -L --instanceapi # Info log tests, verify peek and read on a named collection instance %(prog)s -L --instanceread --instance mylog --buffersize 1024 # Info log tests, read the records of a named 1 MB collection instance @@ -3031,6 +3079,9 @@ def main(): parser.add_argument( "-v", "--vftelemetry", action="store_true", help="Run only VF management tests" ) + parser.add_argument( + "-i", "--firmware", action="store_true", help="Run only firmware tests" + ) parser.add_argument( "-L", "--infolog", @@ -3139,6 +3190,7 @@ def main(): or args.rasexp or args.standby or args.vftelemetry + or args.firmware or args.infolog or args.driverproperties or args.event @@ -3250,6 +3302,9 @@ def main(): if args.vftelemetry: test_vf_management_module(devices[device_idx], device_idx) + if args.firmware: + test_firmware_module(devices[device_idx], device_idx) + if args.reset is not None and args.reset_device in (None, device_idx): test_device_reset( devices[device_idx], diff --git a/bindings/sysman/python/test/unit_tests/test_device.py b/bindings/sysman/python/test/unit_tests/test_device.py index 42b3b541..edef739c 100644 --- a/bindings/sysman/python/test/unit_tests/test_device.py +++ b/bindings/sysman/python/test/unit_tests/test_device.py @@ -188,6 +188,36 @@ def mock_enum_firmwares(device_handle, count_ptr, handles_ptr): mock_get_func.assert_called_with("zesDeviceEnumFirmwares") mock_func.assert_called_once() + def test_GivenValidFirmwareHandleWhenCallingZesFirmwareGetPropertiesThenCallSucceedsWithValidProperties( + self, mock_get_func + ): + def mock_get_properties(firmware_handle, properties_ptr): + properties = properties_ptr._obj + properties.onSubdevice = 1 + properties.subdeviceId = 1 + properties.canControl = 1 + properties.name = b"GFX" + properties.version = b"DG02_2.2421" + return self.pyzes.ZE_RESULT_SUCCESS + + mock_func = MagicMock(side_effect=mock_get_properties) + mock_get_func.return_value = mock_func + + firmware_handle = self.pyzes.zes_firmware_handle_t() + properties = self.pyzes.zes_firmware_properties_t() + properties.stype = self.pyzes.ZES_STRUCTURE_TYPE_FIRMWARE_PROPERTIES + + result = self.pyzes.zesFirmwareGetProperties(firmware_handle, byref(properties)) + + self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS) + self.assertEqual(properties.onSubdevice, 1) + self.assertEqual(properties.subdeviceId, 1) + self.assertEqual(properties.canControl, 1) + self.assertEqual(properties.name, b"GFX") + self.assertEqual(properties.version, b"DG02_2.2421") + mock_get_func.assert_called_with("zesFirmwareGetProperties") + mock_func.assert_called_once() + if __name__ == "__main__": unittest.main()