#include "common/types.hpp" #include "pldm_cmd_helper.hpp" #include #include #include #include #include #include #include #ifdef OEM_IBM #include "oem/ibm/oem_ibm_state_set.hpp" #endif using namespace pldm::utils; namespace pldmtool { namespace platform { namespace { using namespace pldmtool::helper; static const std::map sensorPresState{ {PLDM_SENSOR_UNKNOWN, "Sensor Unknown"}, {PLDM_SENSOR_NORMAL, "Sensor Normal"}, {PLDM_SENSOR_WARNING, "Sensor Warning"}, {PLDM_SENSOR_CRITICAL, "Sensor Critical"}, {PLDM_SENSOR_FATAL, "Sensor Fatal"}, {PLDM_SENSOR_LOWERWARNING, "Sensor Lower Warning"}, {PLDM_SENSOR_LOWERCRITICAL, "Sensor Lower Critical"}, {PLDM_SENSOR_LOWERFATAL, "Sensor Lower Fatal"}, {PLDM_SENSOR_UPPERWARNING, "Sensor Upper Warning"}, {PLDM_SENSOR_UPPERCRITICAL, "Sensor Upper Critical"}, {PLDM_SENSOR_UPPERFATAL, "Sensor Upper Fatal"}}; static const std::map sensorOpState{ {PLDM_SENSOR_ENABLED, "Sensor Enabled"}, {PLDM_SENSOR_DISABLED, "Sensor Disabled"}, {PLDM_SENSOR_UNAVAILABLE, "Sensor Unavailable"}, {PLDM_SENSOR_STATUSUNKOWN, "Sensor Status Unknown"}, {PLDM_SENSOR_FAILED, "Sensor Failed"}, {PLDM_SENSOR_INITIALIZING, "Sensor Sensor Initializing"}, {PLDM_SENSOR_SHUTTINGDOWN, "Sensor Shutting down"}, {PLDM_SENSOR_INTEST, "Sensor Intest"}}; std::vector> commands; } // namespace using ordered_json = nlohmann::ordered_json; class GetPDR : public CommandInterface { public: ~GetPDR() = default; GetPDR() = delete; GetPDR(const GetPDR&) = delete; GetPDR(GetPDR&&) = default; GetPDR& operator=(const GetPDR&) = delete; GetPDR& operator=(GetPDR&&) = delete; using CommandInterface::CommandInterface; explicit GetPDR(const char* type, const char* name, CLI::App* app) : CommandInterface(type, name, app) { auto pdrOptionGroup = app->add_option_group( "Required Option", "Retrieve individual PDR, all PDRs, PDRs of a requested type or retrieve all PDRs of the requested terminusID"); pdrOptionGroup->add_option( "-d,--data", recordHandle, "retrieve individual PDRs from a PDR Repository\n" "eg: The recordHandle value for the PDR to be retrieved and 0 " "means get first PDR in the repository."); pdrRecType = ""; pdrOptionGroup->add_option("-t, --type", pdrRecType, "retrieve all PDRs of the requested type\n" "supported types:\n" "[terminusLocator, stateSensor, " "numericEffecter, stateEffecter, " "compactNumericSensor, sensorauxname, " "efffecterAuxName, numericsensor, " "EntityAssociation, fruRecord, ... ]"); getPDRGroupOption = pdrOptionGroup->add_option( "-i, --terminusID", pdrTerminus, "retrieve all PDRs of the requested terminusID\n" "supported IDs:\n [1, 2, 208...]"); allPDRs = false; pdrOptionGroup->add_flag("-a, --all", allPDRs, "retrieve all PDRs from a PDR repository"); pdrOptionGroup->require_option(1); } void parseGetPDROptions() { optTIDSet = false; if (getPDRGroupOption->count() > 0) { optTIDSet = true; getPDRs(); } } void getPDRs() { // start the array std::cout << "["; recordHandle = 0; do { CommandInterface::exec(); } while (recordHandle != 0); // close the array std::cout << "]\n"; if (handleFound) { recordHandle = 0; uint32_t prevRecordHandle = 0; do { CommandInterface::exec(); if (recordHandle == prevRecordHandle) { return; } prevRecordHandle = recordHandle; } while (recordHandle != 0); } } void exec() override { if (allPDRs || !pdrRecType.empty()) { if (!pdrRecType.empty()) { std::transform(pdrRecType.begin(), pdrRecType.end(), pdrRecType.begin(), tolower); } // start the array std::cout << "[\n"; // Retrieve all PDR records starting from the first recordHandle = 0; uint32_t prevRecordHandle = 0; std::map recordsSeen; do { CommandInterface::exec(); // recordHandle is updated to nextRecord when // CommandInterface::exec() is successful. // In case of any error, return. if (recordHandle == prevRecordHandle) { return; } // check for circular references. auto result = recordsSeen.emplace(recordHandle, prevRecordHandle); if (!result.second) { std::cerr << "Record handle " << recordHandle << " has multiple references: " << result.first->second << ", " << prevRecordHandle << "\n"; return; } prevRecordHandle = recordHandle; if (recordHandle != 0) { // close the array std::cout << ","; } } while (recordHandle != 0); // close the array std::cout << "]\n"; } else { CommandInterface::exec(); } } std::pair> createRequestMsg() override { std::vector requestMsg(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES); auto request = reinterpret_cast(requestMsg.data()); auto rc = encode_get_pdr_req(instanceId, recordHandle, 0, PLDM_GET_FIRSTPART, UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES); return {rc, requestMsg}; } void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override { uint8_t completionCode = 0; uint8_t recordData[UINT16_MAX] = {0}; uint32_t nextRecordHndl = 0; uint32_t nextDataTransferHndl = 0; uint8_t transferFlag = 0; uint16_t respCnt = 0; uint8_t transferCRC = 0; auto rc = decode_get_pdr_resp( responsePtr, payloadLength, &completionCode, &nextRecordHndl, &nextDataTransferHndl, &transferFlag, &respCnt, recordData, sizeof(recordData), &transferCRC); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { std::cerr << "Response Message Error: " << "rc=" << rc << ",cc=" << (int)completionCode << std::endl; return; } if (optTIDSet && !handleFound) { terminusHandle = getTerminusHandle(recordData, pdrTerminus); if (terminusHandle.has_value()) { recordHandle = 0; return; } else { recordHandle = nextRecordHndl; return; } } else { printPDRMsg(nextRecordHndl, respCnt, recordData, terminusHandle); recordHandle = nextRecordHndl; } } private: const std::map entityType = { {PLDM_ENTITY_UNSPECIFIED, "Unspecified"}, {PLDM_ENTITY_OTHER, "Other"}, {PLDM_ENTITY_NETWORK, "Network"}, {PLDM_ENTITY_GROUP, "Group"}, {PLDM_ENTITY_REMOTE_MGMT_COMM_DEVICE, "Remote Management Communication Device"}, {PLDM_ENTITY_EXTERNAL_ENVIRONMENT, "External Environment"}, {PLDM_ENTITY_COMM_CHANNEL, " Communication Channel"}, {PLDM_ENTITY_TERMINUS, "PLDM Terminus"}, {PLDM_ENTITY_PLATFORM_EVENT_LOG, " Platform Event Log"}, {PLDM_ENTITY_KEYPAD, "keypad"}, {PLDM_ENTITY_SWITCH, "Switch"}, {PLDM_ENTITY_PUSHBUTTON, "Pushbutton"}, {PLDM_ENTITY_DISPLAY, "Display"}, {PLDM_ENTITY_INDICATOR, "Indicator"}, {PLDM_ENTITY_SYS_MGMT_SW, "System Management Software"}, {PLDM_ENTITY_SYS_FIRMWARE, "System Firmware"}, {PLDM_ENTITY_OPERATING_SYS, "Operating System"}, {PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER, "Virtual Machine Manager"}, {PLDM_ENTITY_OS_LOADER, "OS Loader"}, {PLDM_ENTITY_DEVICE_DRIVER, "Device Driver"}, {PLDM_ENTITY_MGMT_CONTROLLER_FW, "Management Controller Firmware"}, {PLDM_ENTITY_SYSTEM_CHASSIS, "System chassis (main enclosure)"}, {PLDM_ENTITY_SUB_CHASSIS, "Sub-chassis"}, {PLDM_ENTITY_DISK_DRIVE_BAY, "Disk Drive Bay"}, {PLDM_ENTITY_PERIPHERAL_BAY, "Peripheral Bay"}, {PLDM_ENTITY_DEVICE_BAY, "Device bay"}, {PLDM_ENTITY_DOOR, "Door"}, {PLDM_ENTITY_ACCESS_PANEL, "Access Panel"}, {PLDM_ENTITY_COVER, "Cover"}, {PLDM_ENTITY_BOARD, "Board"}, {PLDM_ENTITY_CARD, "Card"}, {PLDM_ENTITY_MODULE, "Module"}, {PLDM_ENTITY_SYS_MGMT_MODULE, "System management module"}, {PLDM_ENTITY_SYS_BOARD, "System Board"}, {PLDM_ENTITY_MEMORY_BOARD, "Memory Board"}, {PLDM_ENTITY_MEMORY_MODULE, "Memory Module"}, {PLDM_ENTITY_PROC_MODULE, "Processor Module"}, {PLDM_ENTITY_ADD_IN_CARD, "Add-in Card"}, {PLDM_ENTITY_CHASSIS_FRONT_PANEL_BOARD, "Chassis front panel board(control panel)"}, {PLDM_ENTITY_BACK_PANEL_BOARD, "Back panel board"}, {PLDM_ENTITY_POWER_MGMT, "Power management board"}, {PLDM_ENTITY_POWER_SYS_BOARD, "Power system board"}, {PLDM_ENTITY_DRIVE_BACKPLANE, "Drive backplane"}, {PLDM_ENTITY_SYS_INTERNAL_EXPANSION_BOARD, "System internal expansion board"}, {PLDM_ENTITY_OTHER_SYS_BOARD, "Other system board"}, {PLDM_ENTITY_CHASSIS_BACK_PANEL_BOARD, "Chassis back panel board"}, {PLDM_ENTITY_PROCESSING_BLADE, "Processing blade"}, {PLDM_ENTITY_CONNECTIVITY_SWITCH, "Connectivity switch"}, {PLDM_ENTITY_PROC_MEMORY_MODULE, "Processor/Memory Module"}, {PLDM_ENTITY_IO_MODULE, "I/O Module"}, {PLDM_ENTITY_PROC_IO_MODULE, "Processor I/O Module"}, {PLDM_ENTITY_COOLING_DEVICE, "Cooling device"}, {PLDM_ENTITY_COOLING_SUBSYSTEM, "Cooling subsystem"}, {PLDM_ENTITY_COOLING_UNIT, "Cooling Unit"}, {PLDM_ENTITY_FAN, "Fan"}, {PLDM_ENTITY_PELTIER_COOLING_DEVICE, "Peltier Cooling Device"}, {PLDM_ENTITY_LIQUID_COOLING_DEVICE, "Liquid Cooling Device"}, {PLDM_ENTITY_LIQUID_COOLING_SUBSYSTEM, "Liquid Colling Subsystem"}, {PLDM_ENTITY_OTHER_STORAGE_DEVICE, "Other Storage Device"}, {PLDM_ENTITY_FLOPPY_DRIVE, "Floppy Drive"}, {PLDM_ENTITY_FIXED_DISK_HARD_DRIVE, "Hard Drive"}, {PLDM_ENTITY_CD_DRIVE, "CD Drive"}, {PLDM_ENTITY_CD_DVD_DRIVE, "CD/DVD Drive"}, {PLDM_ENTITY_OTHER_SILICON_STORAGE_DEVICE, "Other Silicon Storage Device"}, {PLDM_ENTITY_SOLID_STATE_SRIVE, "Solid State Drive"}, {PLDM_ENTITY_POWER_SUPPLY, "Power supply"}, {PLDM_ENTITY_BATTERY, "Battery"}, {PLDM_ENTITY_SUPER_CAPACITOR, "Super Capacitor"}, {PLDM_ENTITY_POWER_CONVERTER, "Power Converter"}, {PLDM_ENTITY_DC_DC_CONVERTER, "DC-DC Converter"}, {PLDM_ENTITY_AC_MAINS_POWER_SUPPLY, "AC mains power supply"}, {PLDM_ENTITY_DC_MAINS_POWER_SUPPLY, "DC mains power supply"}, {PLDM_ENTITY_PROC, "Processor"}, {PLDM_ENTITY_CHIPSET_COMPONENT, "Chipset Component"}, {PLDM_ENTITY_MGMT_CONTROLLER, "Management Controller"}, {PLDM_ENTITY_PERIPHERAL_CONTROLLER, "Peripheral Controller"}, {PLDM_ENTITY_SEEPROM, "SEEPROM"}, {PLDM_ENTITY_NVRAM_CHIP, "NVRAM Chip"}, {PLDM_ENTITY_FLASH_MEMORY_CHIP, "FLASH Memory chip"}, {PLDM_ENTITY_MEMORY_CHIP, "Memory Chip"}, {PLDM_ENTITY_MEMORY_CONTROLLER, "Memory Controller"}, {PLDM_ENTITY_NETWORK_CONTROLLER, "Network Controller"}, {PLDM_ENTITY_IO_CONTROLLER, "I/O Controller"}, {PLDM_ENTITY_SOUTH_BRIDGE, "South Bridge"}, {PLDM_ENTITY_REAL_TIME_CLOCK, "Real Time Clock (RTC)"}, {PLDM_ENTITY_FPGA_CPLD_DEVICE, "FPGA/CPLD Configurable Logic Device"}, {PLDM_ENTITY_OTHER_BUS, "Other Bus"}, {PLDM_ENTITY_SYS_BUS, "System Bus"}, {PLDM_ENTITY_I2C_BUS, "I2C Bus"}, {PLDM_ENTITY_SMBUS_BUS, "SMBus Bus"}, {PLDM_ENTITY_SPI_BUS, "SPI Bus"}, {PLDM_ENTITY_PCI_BUS, "PCI Bus"}, {PLDM_ENTITY_PCI_EXPRESS_BUS, "PCI Express Bus"}, {PLDM_ENTITY_PECI_BUS, "PECI Bus"}, {PLDM_ENTITY_LPC_BUS, "LPC Bus"}, {PLDM_ENTITY_USB_BUS, "USB Bus"}, {PLDM_ENTITY_FIREWIRE_BUS, "FireWire Bus"}, {PLDM_ENTITY_SCSI_BUS, "SCSI Bus"}, {PLDM_ENTITY_SATA_SAS_BUS, "SATA/SAS Bus"}, {PLDM_ENTITY_PROC_FRONT_SIDE_BUS, "Processor/Front-side Bus"}, {PLDM_ENTITY_INTER_PROC_BUS, "Inter-processor Bus"}, {PLDM_ENTITY_CONNECTOR, "Connector"}, {PLDM_ENTITY_SLOT, "Slot"}, {PLDM_ENTITY_CABLE, "Cable(electrical or optical)"}, {PLDM_ENTITY_INTERCONNECT, "Interconnect"}, {PLDM_ENTITY_PLUG, "Plug"}, {PLDM_ENTITY_SOCKET, "Socket"}, }; const std::map stateSet = { {PLDM_STATE_SET_HEALTH_STATE, "Health State"}, {PLDM_STATE_SET_AVAILABILITY, "Availability"}, {PLDM_STATE_SET_PREDICTIVE_CONDITION, "Predictive Condition"}, {PLDM_STATE_SET_REDUNDANCY_STATUS, "Redundancy Status"}, {PLDM_STATE_SET_HEALTH_REDUNDANCY_TREND, "Health/Redundancy Trend"}, {PLDM_STATE_SET_GROUP_RESOURCE_LEVEL, "Group Resource Level"}, {PLDM_STATE_SET_REDUNDANCY_ENTITY_ROLE, "Redundancy Entity Role"}, {PLDM_STATE_SET_OPERATIONAL_STATUS, "Operational Status"}, {PLDM_STATE_SET_OPERATIONAL_STRESS_STATUS, "Operational Stress Status"}, {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, "Operational Fault Status"}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, "Operational Running Status"}, {PLDM_STATE_SET_OPERATIONAL_CONNECTION_STATUS, "Operational Connection Status"}, {PLDM_STATE_SET_PRESENCE, "Presence"}, {PLDM_STATE_SET_PERFORMANCE, "Performance"}, {PLDM_STATE_SET_CONFIGURATION_STATE, "Configuration State"}, {PLDM_STATE_SET_CHANGED_CONFIGURATION, "Changed Configuration"}, {PLDM_STATE_SET_IDENTIFY_STATE, "Identify State"}, {PLDM_STATE_SET_VERSION, "Version"}, {PLDM_STATE_SET_ALARM_STATE, "Alarm State"}, {PLDM_STATE_SET_DEVICE_INITIALIZATION, "Device Initialization"}, {PLDM_STATE_SET_THERMAL_TRIP, "Thermal Trip"}, {PLDM_STATE_SET_HEARTBEAT, "Heartbeat"}, {PLDM_STATE_SET_LINK_STATE, "Link State"}, {PLDM_STATE_SET_SMOKE_STATE, "Smoke State"}, {PLDM_STATE_SET_HUMIDITY_STATE, "Humidity State"}, {PLDM_STATE_SET_DOOR_STATE, "Door State"}, {PLDM_STATE_SET_SWITCH_STATE, "Switch State"}, {PLDM_STATE_SET_LOCK_STATE, "Lock State"}, {PLDM_STATE_SET_PHYSICAL_SECURITY, "Physical Security"}, {PLDM_STATE_SET_DOCK_AUTHORIZATION, "Dock Authorization"}, {PLDM_STATE_SET_HW_SECURITY, "Hardware Security"}, {PLDM_STATE_SET_PHYSICAL_COMM_CONNECTION, "Physical Communication Connection"}, {PLDM_STATE_SET_COMM_LEASH_STATUS, "Communication Leash Status"}, {PLDM_STATE_SET_FOREIGN_NW_DETECTION_STATUS, "Foreign Network Detection Status"}, {PLDM_STATE_SET_PASSWORD_PROTECTED_ACCESS_SECURITY, "Password-Protected Access Security"}, {PLDM_STATE_SET_SECURITY_ACCESS_PRIVILEGE_LEVEL, "Security Access –PrivilegeLevel"}, {PLDM_STATE_SET_SESSION_AUDIT, "PLDM Session Audit"}, {PLDM_STATE_SET_SW_TERMINATION_STATUS, "Software Termination Status"}, {PLDM_STATE_SET_STORAGE_MEDIA_ACTIVITY, "Storage Media Activity"}, {PLDM_STATE_SET_BOOT_RESTART_CAUSE, "Boot/Restart Cause"}, {PLDM_STATE_SET_BOOT_RESTART_REQUEST, "Boot/Restart Request"}, {PLDM_STATE_SET_ENTITY_BOOT_STATUS, "Entity Boot Status"}, {PLDM_STATE_SET_BOOT_ERROR_STATUS, "Boot ErrorStatus"}, {PLDM_STATE_SET_BOOT_PROGRESS, "Boot Progress"}, {PLDM_STATE_SET_SYS_FIRMWARE_HANG, "System Firmware Hang"}, {PLDM_STATE_SET_POST_ERRORS, "POST Errors"}, {PLDM_STATE_SET_LOG_FILL_STATUS, "Log Fill Status"}, {PLDM_STATE_SET_LOG_FILTER_STATUS, "Log Filter Status"}, {PLDM_STATE_SET_LOG_TIMESTAMP_CHANGE, "Log Timestamp Change"}, {PLDM_STATE_SET_INTERRUPT_REQUESTED, "Interrupt Requested"}, {PLDM_STATE_SET_INTERRUPT_RECEIVED, "Interrupt Received"}, {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_REQUESTED, "Diagnostic Interrupt Requested"}, {PLDM_STATE_SET_DIAGNOSTIC_INTERRUPT_RECEIVED, "Diagnostic Interrupt Received"}, {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_REQUESTED, "I/O Channel Check NMI Requested"}, {PLDM_STATE_SET_IO_CHANNEL_CHECK_NMI_RECEIVED, "I/O Channel Check NMI Received"}, {PLDM_STATE_SET_FATAL_NMI_REQUESTED, "Fatal NMI Requested"}, {PLDM_STATE_SET_FATAL_NMI_RECEIVED, "Fatal NMI Received"}, {PLDM_STATE_SET_SOFTWARE_NMI_REQUESTED, "Software NMI Requested"}, {PLDM_STATE_SET_SOFTWARE_NMI_RECEIVED, "Software NMI Received"}, {PLDM_STATE_SET_SMI_REQUESTED, "SMI Requested"}, {PLDM_STATE_SET_SMI_RECEIVED, "SMI Received"}, {PLDM_STATE_SET_PCI_PERR_REQUESTED, "PCI PERR Requested"}, {PLDM_STATE_SET_PCI_PERR_RECEIVED, "PCI PERR Received"}, {PLDM_STATE_SET_PCI_SERR_REQUESTED, "PCI SERR Requested "}, {PLDM_STATE_SET_PCI_SERR_RECEIVED, "PCI SERR Received"}, {PLDM_STATE_SET_BUS_ERROR_STATUS, "Bus Error Status"}, {PLDM_STATE_SET_WATCHDOG_STATUS, "Watchdog Status"}, {PLDM_STATE_SET_POWER_SUPPLY_STATE, "Power Supply State"}, {PLDM_STATE_SET_DEVICE_POWER_STATE, "Device Power State"}, {PLDM_STATE_SET_ACPI_POWER_STATE, "ACPI Power State"}, {PLDM_STATE_SET_BACKUP_POWER_SOURCE, "Backup Power Source"}, {PLDM_STATE_SET_SYSTEM_POWER_STATE, "System Power State "}, {PLDM_STATE_SET_BATTERY_ACTIVITY, "Battery Activity"}, {PLDM_STATE_SET_BATTERY_STATE, "Battery State"}, {PLDM_STATE_SET_PROC_POWER_STATE, "Processor Power State"}, {PLDM_STATE_SET_POWER_PERFORMANCE_STATE, "Power-Performance State"}, {PLDM_STATE_SET_PROC_ERROR_STATUS, "Processor Error Status"}, {PLDM_STATE_SET_BIST_FAILURE_STATUS, "BIST FailureStatus"}, {PLDM_STATE_SET_IBIST_FAILURE_STATUS, "IBIST FailureStatus"}, {PLDM_STATE_SET_PROC_HANG_IN_POST, "Processor Hang in POST"}, {PLDM_STATE_SET_PROC_STARTUP_FAILURE, "Processor Startup Failure"}, {PLDM_STATE_SET_UNCORRECTABLE_CPU_ERROR, "Uncorrectable CPU Error"}, {PLDM_STATE_SET_MACHINE_CHECK_ERROR, "Machine Check Error"}, {PLDM_STATE_SET_CORRECTED_MACHINE_CHECK, "Corrected Machine Check"}, {PLDM_STATE_SET_CACHE_STATUS, "Cache Status"}, {PLDM_STATE_SET_MEMORY_ERROR_STATUS, "Memory Error Status"}, {PLDM_STATE_SET_REDUNDANT_MEMORY_ACTIVITY_STATUS, "Redundant Memory Activity Status"}, {PLDM_STATE_SET_ERROR_DETECTION_STATUS, "Error Detection Status"}, {PLDM_STATE_SET_STUCK_BIT_STATUS, "Stuck Bit Status"}, {PLDM_STATE_SET_SCRUB_STATUS, "Scrub Status"}, {PLDM_STATE_SET_SLOT_OCCUPANCY, "Slot Occupancy"}, {PLDM_STATE_SET_SLOT_STATE, "Slot State"}, }; const std::array sensorInit = { "noInit", "useInitPDR", "enableSensor", "disableSensor"}; const std::array effecterInit = { "noInit", "useInitPDR", "enableEffecter", "disableEffecter"}; const std::map pdrType = { {PLDM_TERMINUS_LOCATOR_PDR, "Terminus Locator PDR"}, {PLDM_NUMERIC_SENSOR_PDR, "Numeric Sensor PDR"}, {PLDM_NUMERIC_SENSOR_INITIALIZATION_PDR, "Numeric Sensor Initialization PDR"}, {PLDM_STATE_SENSOR_PDR, "State Sensor PDR"}, {PLDM_STATE_SENSOR_INITIALIZATION_PDR, "State Sensor Initialization PDR"}, {PLDM_SENSOR_AUXILIARY_NAMES_PDR, "Sensor Auxiliary Names PDR"}, {PLDM_OEM_UNIT_PDR, "OEM Unit PDR"}, {PLDM_OEM_STATE_SET_PDR, "OEM State Set PDR"}, {PLDM_NUMERIC_EFFECTER_PDR, "Numeric Effecter PDR"}, {PLDM_NUMERIC_EFFECTER_INITIALIZATION_PDR, "Numeric Effecter Initialization PDR"}, {PLDM_COMPACT_NUMERIC_SENSOR_PDR, "Compact Numeric Sensor PDR"}, {PLDM_STATE_EFFECTER_PDR, "State Effecter PDR"}, {PLDM_STATE_EFFECTER_INITIALIZATION_PDR, "State Effecter Initialization PDR"}, {PLDM_EFFECTER_AUXILIARY_NAMES_PDR, "Effecter Auxiliary Names PDR"}, {PLDM_EFFECTER_OEM_SEMANTIC_PDR, "Effecter OEM Semantic PDR"}, {PLDM_PDR_ENTITY_ASSOCIATION, "Entity Association PDR"}, {PLDM_ENTITY_AUXILIARY_NAMES_PDR, "Entity Auxiliary Names PDR"}, {PLDM_OEM_ENTITY_ID_PDR, "OEM Entity ID PDR"}, {PLDM_INTERRUPT_ASSOCIATION_PDR, "Interrupt Association PDR"}, {PLDM_EVENT_LOG_PDR, "PLDM Event Log PDR"}, {PLDM_PDR_FRU_RECORD_SET, "FRU Record Set PDR"}, {PLDM_OEM_DEVICE_PDR, "OEM Device PDR"}, {PLDM_OEM_PDR, "OEM PDR"}, }; static inline const std::map setThermalTrip{ {PLDM_STATE_SET_THERMAL_TRIP_STATUS_NORMAL, "Normal"}, {PLDM_STATE_SET_THERMAL_TRIP_STATUS_THERMAL_TRIP, "Thermal Trip"}}; static inline const std::map setIdentifyState{ {PLDM_STATE_SET_IDENTIFY_STATE_UNASSERTED, "Identify State Unasserted"}, {PLDM_STATE_SET_IDENTIFY_STATE_ASSERTED, "Identify State Asserted"}}; static inline const std::map setBootProgressState{ {PLDM_STATE_SET_BOOT_PROG_STATE_NOT_ACTIVE, "Boot Not Active"}, {PLDM_STATE_SET_BOOT_PROG_STATE_COMPLETED, "Boot Completed"}, {PLDM_STATE_SET_BOOT_PROG_STATE_MEM_INITIALIZATION, "Memory Initialization"}, {PLDM_STATE_SET_BOOT_PROG_STATE_SEC_PROC_INITIALIZATION, "Secondary Processor(s) Initialization"}, {PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG, "PCI Resource Configuration"}, {PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS, "Starting Operating System"}, {PLDM_STATE_SET_BOOT_PROG_STATE_BASE_BOARD_INITIALIZATION, "Baseboard Initialization"}, {PLDM_STATE_SET_BOOT_PROG_STATE_PRIMARY_PROC_INITIALIZATION, "Primary Processor Initialization"}, {PLDM_STATE_SET_BOOT_PROG_STATE_OSSTART, "OSStart"}}; static inline const std::map setOpFaultStatus{ {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NORMAL, "Normal"}, {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_ERROR, "Error"}, {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS_NON_RECOVERABLE_ERROR, "Non Recoverable Error"}}; static inline const std::map setSysPowerState{ {PLDM_STATE_SET_SYS_POWER_STATE_OFF_SOFT_GRACEFUL, "Off-Soft Graceful"}}; static inline const std::map setSWTerminationStatus{ {PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED, "Graceful Restart Requested"}}; static inline const std::map setAvailability{ {PLDM_STATE_SET_AVAILABILITY_REBOOTING, "Rebooting"}}; static inline const std::map setHealthState{ {PLDM_STATE_SET_HEALTH_STATE_NORMAL, "Normal"}, {PLDM_STATE_SET_HEALTH_STATE_NON_CRITICAL, "Non-Critical"}, {PLDM_STATE_SET_HEALTH_STATE_CRITICAL, "Critical"}, {PLDM_STATE_SET_HEALTH_STATE_FATAL, "Fatal"}, {PLDM_STATE_SET_HEALTH_STATE_UPPER_NON_CRITICAL, "Upper Non-Critical"}, {PLDM_STATE_SET_HEALTH_STATE_LOWER_NON_CRITICAL, "Lower Non-Critical"}, {PLDM_STATE_SET_HEALTH_STATE_UPPER_CRITICAL, "Upper Critical"}, {PLDM_STATE_SET_HEALTH_STATE_LOWER_CRITICAL, "Lower Critical"}, {PLDM_STATE_SET_HEALTH_STATE_UPPER_FATAL, "Upper Fatal"}, {PLDM_STATE_SET_HEALTH_STATE_LOWER_FATAL, "Lower Fatal"}}; static inline const std::map setOperationalRunningState{ {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STARTING, "Starting"}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPING, "Stopping"}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED, "Stopped"}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE, "In Service"}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_ABORTED, "Aborted"}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT, "Dormant"}}; static inline const std::map setPowerDeviceState{ {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_UNKNOWN, "Unknown"}, {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_FULLY_ON, "Fully-On"}, {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_INTERMEDIATE_1, "Intermediate State-1"}, {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_INTERMEDIATE_2, "Intermediate State-2"}, {PLDM_STATE_SET_ACPI_DEVICE_POWER_STATE_OFF, "Off"}}; static inline const std::map> populatePStateMaps{ {PLDM_STATE_SET_THERMAL_TRIP, setThermalTrip}, {PLDM_STATE_SET_IDENTIFY_STATE, setIdentifyState}, {PLDM_STATE_SET_BOOT_PROGRESS, setBootProgressState}, {PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS, setOpFaultStatus}, {PLDM_STATE_SET_SYSTEM_POWER_STATE, setSysPowerState}, {PLDM_STATE_SET_SW_TERMINATION_STATUS, setSWTerminationStatus}, {PLDM_STATE_SET_AVAILABILITY, setAvailability}, {PLDM_STATE_SET_HEALTH_STATE, setHealthState}, {PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, setOperationalRunningState}, {PLDM_STATE_SET_DEVICE_POWER_STATE, setPowerDeviceState}, }; const std::map strToPdrType = { {"terminuslocator", PLDM_TERMINUS_LOCATOR_PDR}, {"statesensor", PLDM_STATE_SENSOR_PDR}, {"sensorauxname", PLDM_SENSOR_AUXILIARY_NAMES_PDR}, {"numericeffecter", PLDM_NUMERIC_EFFECTER_PDR}, {"efffecterauxname", PLDM_EFFECTER_AUXILIARY_NAMES_PDR}, {"numericsensor", PLDM_NUMERIC_SENSOR_PDR}, {"compactnumericsensor", PLDM_COMPACT_NUMERIC_SENSOR_PDR}, {"stateeffecter", PLDM_STATE_EFFECTER_PDR}, {"entityassociation", PLDM_PDR_ENTITY_ASSOCIATION}, {"frurecord", PLDM_PDR_FRU_RECORD_SET}, // Add other types }; bool isLogicalBitSet(const uint16_t entity_type) { return entity_type & 0x8000; } uint16_t getEntityTypeForLogicalEntity(const uint16_t logical_entity_type) { return logical_entity_type & 0x7FFF; } std::string getEntityName(pldm::pdr::EntityType type) { uint16_t entityNumber = type; std::string entityName = "[Physical] "; if (isLogicalBitSet(type)) { entityName = "[Logical] "; entityNumber = getEntityTypeForLogicalEntity(type); } try { return entityName + entityType.at(entityNumber); } catch (const std::out_of_range& e) { auto OemString = std::to_string(static_cast(entityNumber)); if (type >= PLDM_OEM_ENTITY_TYPE_START && type <= PLDM_OEM_ENTITY_TYPE_END) { #ifdef OEM_IBM if (OemIBMEntityType.contains(entityNumber)) { return entityName + OemIBMEntityType.at(entityNumber) + "(OEM)"; } #endif return entityName + OemString + "(OEM)"; } return OemString; } } std::string getStateSetName(uint16_t id) { auto typeString = std::to_string(id); try { return stateSet.at(id) + "(" + typeString + ")"; } catch (const std::out_of_range& e) { return typeString; } } std::vector getStateSetPossibleStateNames(uint16_t stateId, const std::vector& value) { std::vector data{}; for (const auto& s : value) { std::map stateNameMaps; auto pstr = std::to_string(s); #ifdef OEM_IBM if (stateId >= PLDM_OEM_STATE_SET_ID_START && stateId < PLDM_OEM_STATE_SET_ID_END) { if (populateOemIBMStateMaps.contains(stateId)) { const std::map stateNames = populateOemIBMStateMaps.at(stateId); stateNameMaps.insert(stateNames.begin(), stateNames.end()); } } #endif if (populatePStateMaps.contains(stateId)) { const std::map stateNames = populatePStateMaps.at(stateId); stateNameMaps.insert(stateNames.begin(), stateNames.end()); } if (stateNameMaps.contains(s)) { data.push_back(stateNameMaps.at(s) + "(" + pstr + ")"); } else { data.push_back(pstr); } } return data; } std::string getPDRType(uint8_t type) { auto typeString = std::to_string(type); try { return pdrType.at(type); } catch (const std::out_of_range& e) { return typeString; } } void printCommonPDRHeader(const pldm_pdr_hdr* hdr, ordered_json& output) { output["recordHandle"] = hdr->record_handle; output["PDRHeaderVersion"] = unsigned(hdr->version); output["PDRType"] = getPDRType(hdr->type); output["recordChangeNumber"] = hdr->record_change_num; output["dataLength"] = hdr->length; } std::vector printPossibleStates(uint8_t possibleStatesSize, const bitfield8_t* states) { uint8_t possibleStatesPos{}; std::vector data{}; auto printStates = [&possibleStatesPos, &data](const bitfield8_t& val) { std::stringstream pstates; for (int i = 0; i < CHAR_BIT; i++) { if (val.byte & (1 << i)) { pstates << (possibleStatesPos * CHAR_BIT + i); data.push_back( static_cast(std::stoi(pstates.str()))); pstates.str(""); } } possibleStatesPos++; }; std::for_each(states, states + possibleStatesSize, printStates); return data; } void printStateSensorPDR(const uint8_t* data, ordered_json& output) { auto pdr = reinterpret_cast(data); output["PLDMTerminusHandle"] = pdr->terminus_handle; output["sensorID"] = pdr->sensor_id; output["entityType"] = getEntityName(pdr->entity_type); output["entityInstanceNumber"] = pdr->entity_instance; output["containerID"] = pdr->container_id; output["sensorInit"] = sensorInit[pdr->sensor_init]; output["sensorAuxiliaryNamesPDR"] = (pdr->sensor_auxiliary_names_pdr ? true : false); output["compositeSensorCount"] = unsigned(pdr->composite_sensor_count); auto statesPtr = pdr->possible_states; auto compCount = pdr->composite_sensor_count; while (compCount--) { auto state = reinterpret_cast( statesPtr); output.emplace(("stateSetID[" + std::to_string(compCount) + "]"), getStateSetName(state->state_set_id)); output.emplace( ("possibleStatesSize[" + std::to_string(compCount) + "]"), state->possible_states_size); output.emplace( ("possibleStates[" + std::to_string(compCount) + "]"), getStateSetPossibleStateNames( state->state_set_id, printPossibleStates(state->possible_states_size, state->states))); if (compCount) { statesPtr += sizeof(state_sensor_possible_states) + state->possible_states_size - 1; } } } void printPDRFruRecordSet(uint8_t* data, ordered_json& output) { if (data == NULL) { return; } data += sizeof(pldm_pdr_hdr); pldm_pdr_fru_record_set* pdr = reinterpret_cast(data); if (!pdr) { std::cerr << "Failed to get the FRU record set PDR" << std::endl; return; } output["PLDMTerminusHandle"] = unsigned(pdr->terminus_handle); output["FRURecordSetIdentifier"] = unsigned(pdr->fru_rsi); output["entityType"] = getEntityName(pdr->entity_type); output["entityInstanceNumber"] = unsigned(pdr->entity_instance); output["containerID"] = unsigned(pdr->container_id); } void printPDREntityAssociation(uint8_t* data, ordered_json& output) { const std::map assocationType = { {PLDM_ENTITY_ASSOCIAION_PHYSICAL, "Physical"}, {PLDM_ENTITY_ASSOCIAION_LOGICAL, "Logical"}, }; if (data == NULL) { return; } data += sizeof(pldm_pdr_hdr); pldm_pdr_entity_association* pdr = reinterpret_cast(data); if (!pdr) { std::cerr << "Failed to get the PDR eneity association" << std::endl; return; } output["containerID"] = int(pdr->container_id); if (assocationType.contains(pdr->association_type)) { output["associationType"] = assocationType.at(pdr->association_type); } else { std::cout << "Get associationType failed.\n"; } output["containerEntityType"] = getEntityName(pdr->container.entity_type); output["containerEntityInstanceNumber"] = int(pdr->container.entity_instance_num); output["containerEntityContainerID"] = int(pdr->container.entity_container_id); output["containedEntityCount"] = static_cast(pdr->num_children); auto child = reinterpret_cast(&pdr->children[0]); for (int i = 0; i < pdr->num_children; ++i) { output.emplace("containedEntityType[" + std::to_string(i + 1) + "]", getEntityName(child->entity_type)); output.emplace("containedEntityInstanceNumber[" + std::to_string(i + 1) + "]", unsigned(child->entity_instance_num)); output.emplace("containedEntityContainerID[" + std::to_string(i + 1) + "]", unsigned(child->entity_container_id)); ++child; } } /** @brief Format the Sensor/Effecter Aux Name PDR types to json output * * @param[in] data - reference to the Sensor/Effecter Aux Name PDR * @param[out] output - PDRs data fields in Json format */ void printAuxNamePDR(uint8_t* data, ordered_json& output) { constexpr uint8_t nullTerminator = 0; struct pldm_effecter_aux_name_pdr* auxNamePdr = (struct pldm_effecter_aux_name_pdr*)data; if (!auxNamePdr) { std::cerr << "Failed to get Aux Name PDR" << std::endl; return; } std::string sPrefix = "effecter"; if (auxNamePdr->hdr.type == PLDM_SENSOR_AUXILIARY_NAMES_PDR) { sPrefix = "sensor"; } output["terminusHandle"] = int(auxNamePdr->terminus_handle); output[sPrefix + "Id"] = int(auxNamePdr->effecter_id); output[sPrefix + "Count"] = int(auxNamePdr->effecter_count); const uint8_t* ptr = auxNamePdr->effecter_names; for (auto i : std::views::iota(0, (int)auxNamePdr->effecter_count)) { const uint8_t nameStringCount = static_cast(*ptr); ptr += sizeof(uint8_t); for (auto j : std::views::iota(0, (int)nameStringCount)) { std::string nameLanguageTagKey = sPrefix + std::to_string(j) + "_nameLanguageTag" + std::to_string(i); std::string entityAuxNameKey = sPrefix + std::to_string(j) + "_entityAuxName" + std::to_string(i); std::string nameLanguageTag(reinterpret_cast(ptr), 0, PLDM_STR_UTF_8_MAX_LEN); ptr += nameLanguageTag.size() + sizeof(nullTerminator); std::u16string u16NameString( reinterpret_cast(ptr), 0, PLDM_STR_UTF_16_MAX_LEN); ptr += (u16NameString.size() + sizeof(nullTerminator)) * sizeof(uint16_t); std::transform(u16NameString.cbegin(), u16NameString.cend(), u16NameString.begin(), [](uint16_t utf16) { return be16toh(utf16); }); std::string nameString = std::wstring_convert, char16_t>{} .to_bytes(u16NameString); output[nameLanguageTagKey] = nameLanguageTag; output[entityAuxNameKey] = nameString; } } } void printNumericEffecterPDR(uint8_t* data, ordered_json& output) { struct pldm_numeric_effecter_value_pdr* pdr = (struct pldm_numeric_effecter_value_pdr*)data; if (!pdr) { std::cerr << "Failed to get numeric effecter PDR" << std::endl; return; } output["PLDMTerminusHandle"] = int(pdr->terminus_handle); output["effecterID"] = int(pdr->effecter_id); output["entityType"] = int(pdr->entity_type); output["entityInstanceNumber"] = int(pdr->entity_instance); output["containerID"] = int(pdr->container_id); output["effecterSemanticID"] = int(pdr->effecter_semantic_id); output["effecterInit"] = unsigned(pdr->effecter_init); output["effecterAuxiliaryNames"] = (unsigned(pdr->effecter_auxiliary_names) ? true : false); output["baseUnit"] = unsigned(pdr->base_unit); output["unitModifier"] = unsigned(pdr->unit_modifier); output["rateUnit"] = unsigned(pdr->rate_unit); output["baseOEMUnitHandle"] = unsigned(pdr->base_oem_unit_handle); output["auxUnit"] = unsigned(pdr->aux_unit); output["auxUnitModifier"] = unsigned(pdr->aux_unit_modifier); output["auxrateUnit"] = unsigned(pdr->aux_rate_unit); output["auxOEMUnitHandle"] = unsigned(pdr->aux_oem_unit_handle); output["isLinear"] = (unsigned(pdr->is_linear) ? true : false); output["effecterDataSize"] = unsigned(pdr->effecter_data_size); output["resolution"] = unsigned(pdr->resolution); output["offset"] = unsigned(pdr->offset); output["accuracy"] = unsigned(pdr->accuracy); output["plusTolerance"] = unsigned(pdr->plus_tolerance); output["minusTolerance"] = unsigned(pdr->minus_tolerance); output["stateTransitionInterval"] = unsigned(pdr->state_transition_interval); output["TransitionInterval"] = unsigned(pdr->transition_interval); switch (pdr->effecter_data_size) { case PLDM_EFFECTER_DATA_SIZE_UINT8: output["maxSettable"] = unsigned(pdr->max_settable.value_u8); output["minSettable"] = unsigned(pdr->min_settable.value_u8); break; case PLDM_EFFECTER_DATA_SIZE_SINT8: output["maxSettable"] = unsigned(pdr->max_settable.value_s8); output["minSettable"] = unsigned(pdr->min_settable.value_s8); break; case PLDM_EFFECTER_DATA_SIZE_UINT16: output["maxSettable"] = unsigned(pdr->max_settable.value_u16); output["minSettable"] = unsigned(pdr->min_settable.value_u16); break; case PLDM_EFFECTER_DATA_SIZE_SINT16: output["maxSettable"] = unsigned(pdr->max_settable.value_s16); output["minSettable"] = unsigned(pdr->min_settable.value_s16); break; case PLDM_EFFECTER_DATA_SIZE_UINT32: output["maxSettable"] = unsigned(pdr->max_settable.value_u32); output["minSettable"] = unsigned(pdr->min_settable.value_u32); break; case PLDM_EFFECTER_DATA_SIZE_SINT32: output["maxSettable"] = unsigned(pdr->max_settable.value_s32); output["minSettable"] = unsigned(pdr->min_settable.value_s32); break; default: break; } output["rangeFieldFormat"] = unsigned(pdr->range_field_format); output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); switch (pdr->range_field_format) { case PLDM_RANGE_FIELD_FORMAT_UINT8: output["nominalValue"] = unsigned(pdr->nominal_value.value_u8); output["normalMax"] = unsigned(pdr->normal_max.value_u8); output["normalMin"] = unsigned(pdr->normal_min.value_u8); output["ratedMax"] = unsigned(pdr->rated_max.value_u8); output["ratedMin"] = unsigned(pdr->rated_min.value_u8); break; case PLDM_RANGE_FIELD_FORMAT_SINT8: output["nominalValue"] = unsigned(pdr->nominal_value.value_s8); output["normalMax"] = unsigned(pdr->normal_max.value_s8); output["normalMin"] = unsigned(pdr->normal_min.value_s8); output["ratedMax"] = unsigned(pdr->rated_max.value_s8); output["ratedMin"] = unsigned(pdr->rated_min.value_s8); break; case PLDM_RANGE_FIELD_FORMAT_UINT16: output["nominalValue"] = unsigned(pdr->nominal_value.value_u16); output["normalMax"] = unsigned(pdr->normal_max.value_u16); output["normalMin"] = unsigned(pdr->normal_min.value_u16); output["ratedMax"] = unsigned(pdr->rated_max.value_u16); output["ratedMin"] = unsigned(pdr->rated_min.value_u16); break; case PLDM_RANGE_FIELD_FORMAT_SINT16: output["nominalValue"] = unsigned(pdr->nominal_value.value_s16); output["normalMax"] = unsigned(pdr->normal_max.value_s16); output["normalMin"] = unsigned(pdr->normal_min.value_s16); output["ratedMax"] = unsigned(pdr->rated_max.value_s16); output["ratedMin"] = unsigned(pdr->rated_min.value_s16); break; case PLDM_RANGE_FIELD_FORMAT_UINT32: output["nominalValue"] = unsigned(pdr->nominal_value.value_u32); output["normalMax"] = unsigned(pdr->normal_max.value_u32); output["normalMin"] = unsigned(pdr->normal_min.value_u32); output["ratedMax"] = unsigned(pdr->rated_max.value_u32); output["ratedMin"] = unsigned(pdr->rated_min.value_u32); break; case PLDM_RANGE_FIELD_FORMAT_SINT32: output["nominalValue"] = unsigned(pdr->nominal_value.value_s32); output["normalMax"] = unsigned(pdr->normal_max.value_s32); output["normalMin"] = unsigned(pdr->normal_min.value_s32); output["ratedMax"] = unsigned(pdr->rated_max.value_s32); output["ratedMin"] = unsigned(pdr->rated_min.value_s32); break; case PLDM_RANGE_FIELD_FORMAT_REAL32: output["nominalValue"] = unsigned(pdr->nominal_value.value_f32); output["normalMax"] = unsigned(pdr->normal_max.value_f32); output["normalMin"] = unsigned(pdr->normal_min.value_f32); output["ratedMax"] = unsigned(pdr->rated_max.value_f32); output["ratedMin"] = unsigned(pdr->rated_min.value_f32); break; default: break; } } void printStateEffecterPDR(const uint8_t* data, ordered_json& output) { auto pdr = reinterpret_cast(data); output["PLDMTerminusHandle"] = pdr->terminus_handle; output["effecterID"] = pdr->effecter_id; output["entityType"] = getEntityName(pdr->entity_type); output["entityInstanceNumber"] = pdr->entity_instance; output["containerID"] = pdr->container_id; output["effecterSemanticID"] = pdr->effecter_semantic_id; output["effecterInit"] = effecterInit[pdr->effecter_init]; output["effecterDescriptionPDR"] = (pdr->has_description_pdr ? true : false); output["compositeEffecterCount"] = unsigned(pdr->composite_effecter_count); auto statesPtr = pdr->possible_states; auto compEffCount = pdr->composite_effecter_count; while (compEffCount--) { auto state = reinterpret_cast( statesPtr); output.emplace(("stateSetID[" + std::to_string(compEffCount) + "]"), getStateSetName(state->state_set_id)); output.emplace( ("possibleStatesSize[" + std::to_string(compEffCount) + "]"), state->possible_states_size); output.emplace( ("possibleStates[" + std::to_string(compEffCount) + "]"), getStateSetPossibleStateNames( state->state_set_id, printPossibleStates(state->possible_states_size, state->states))); if (compEffCount) { statesPtr += sizeof(state_effecter_possible_states) + state->possible_states_size - 1; } } } bool checkTerminusHandle(const uint8_t* data, std::optional terminusHandle) { struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; if (pdr->type == PLDM_TERMINUS_LOCATOR_PDR) { auto tlpdr = reinterpret_cast(data); if (tlpdr->terminus_handle != terminusHandle) { return true; } } else if (pdr->type == PLDM_STATE_SENSOR_PDR) { auto sensor = reinterpret_cast(data); if (sensor->terminus_handle != terminusHandle) { return true; } } else if (pdr->type == PLDM_NUMERIC_EFFECTER_PDR) { auto numericEffecter = reinterpret_cast(data); if (numericEffecter->terminus_handle != terminusHandle) { return true; } } else if (pdr->type == PLDM_STATE_EFFECTER_PDR) { auto stateEffecter = reinterpret_cast(data); if (stateEffecter->terminus_handle != terminusHandle) { return true; } } else if (pdr->type == PLDM_PDR_FRU_RECORD_SET) { data += sizeof(pldm_pdr_hdr); auto fru = reinterpret_cast(data); if (fru->terminus_handle != terminusHandle) { return true; } } else { // Entity association PDRs does not have terminus handle return true; } return false; } void printTerminusLocatorPDR(const uint8_t* data, ordered_json& output) { const std::array terminusLocatorType = { "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"}; auto pdr = reinterpret_cast(data); output["PLDMTerminusHandle"] = pdr->terminus_handle; output["validity"] = (pdr->validity ? "valid" : "notValid"); output["TID"] = unsigned(pdr->tid); output["containerID"] = pdr->container_id; output["terminusLocatorType"] = terminusLocatorType[pdr->terminus_locator_type]; output["terminusLocatorValueSize"] = unsigned(pdr->terminus_locator_value_size); if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID) { auto locatorValue = reinterpret_cast( pdr->terminus_locator_value); output["EID"] = unsigned(locatorValue->eid); } } std::optional getTerminusHandle(uint8_t* data, std::optional tid) { struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; if (pdr->type == PLDM_TERMINUS_LOCATOR_PDR) { auto pdr = reinterpret_cast(data); if (pdr->tid == tid) { handleFound = true; return pdr->terminus_handle; } } return std::nullopt; } /** @brief Format the Numeric Sensor PDR types to json output * * @param[in] data - reference to the Numeric Sensor PDR * @param[in] data_length - number of PDR data bytes * @param[out] output - PDRs data fields in Json format */ void printNumericSensorPDR(const uint8_t* data, const uint16_t data_length, ordered_json& output) { struct pldm_numeric_sensor_value_pdr pdr; int rc = decode_numeric_sensor_pdr_data(data, (size_t)data_length, &pdr); if (rc != PLDM_SUCCESS) { std::cerr << "Failed to get numeric sensor PDR" << std::endl; return; } output["PLDMTerminusHandle"] = pdr.terminus_handle; output["sensorID"] = pdr.sensor_id; output["entityType"] = getEntityName(pdr.entity_type); output["entityInstanceNumber"] = pdr.entity_instance_num; output["containerID"] = pdr.container_id; output["sensorInit"] = pdr.sensor_init; output["sensorAuxiliaryNamesPDR"] = (pdr.sensor_auxiliary_names_pdr) ? true : false; output["baseUnit"] = pdr.base_unit; output["unitModifier"] = pdr.unit_modifier; output["rateUnit"] = pdr.rate_unit; output["baseOEMUnitHandle"] = pdr.base_oem_unit_handle; output["auxUnit"] = pdr.aux_unit; output["auxUnitModifier"] = pdr.aux_unit_modifier; output["auxrateUnit"] = pdr.aux_rate_unit; output["rel"] = pdr.rel; output["auxOEMUnitHandle"] = pdr.aux_oem_unit_handle; output["isLinear"] = (pdr.is_linear) ? true : false; output["sensorDataSize"] = pdr.sensor_data_size; output["resolution"] = pdr.resolution; output["offset"] = pdr.offset; output["accuracy"] = pdr.accuracy; output["plusTolerance"] = pdr.plus_tolerance; output["minusTolerance"] = pdr.minus_tolerance; switch (pdr.sensor_data_size) { case PLDM_SENSOR_DATA_SIZE_UINT8: output["hysteresis"] = pdr.hysteresis.value_u8; output["maxReadable"] = pdr.max_readable.value_u8; output["minReadable"] = pdr.min_readable.value_u8; break; case PLDM_SENSOR_DATA_SIZE_SINT8: output["hysteresis"] = pdr.hysteresis.value_s8; output["maxReadable"] = pdr.max_readable.value_s8; output["minReadable"] = pdr.min_readable.value_s8; break; case PLDM_SENSOR_DATA_SIZE_UINT16: output["hysteresis"] = pdr.hysteresis.value_u16; output["maxReadable"] = pdr.max_readable.value_u16; output["minReadable"] = pdr.min_readable.value_u16; break; case PLDM_SENSOR_DATA_SIZE_SINT16: output["hysteresis"] = pdr.hysteresis.value_s16; output["maxReadable"] = pdr.max_readable.value_s16; output["minReadable"] = pdr.min_readable.value_s16; break; case PLDM_SENSOR_DATA_SIZE_UINT32: output["hysteresis"] = pdr.hysteresis.value_u32; output["maxReadable"] = pdr.max_readable.value_u32; output["minReadable"] = pdr.min_readable.value_u32; break; case PLDM_SENSOR_DATA_SIZE_SINT32: output["hysteresis"] = pdr.hysteresis.value_s32; output["maxReadable"] = pdr.max_readable.value_s32; output["minReadable"] = pdr.min_readable.value_s32; break; default: break; } output["supportedThresholds"] = pdr.supported_thresholds.byte; output["thresholAndHysteresisVolatility"] = pdr.threshold_and_hysteresis_volatility.byte; output["stateTransitionInterval"] = pdr.state_transition_interval; output["updateInterval"] = pdr.update_interval; output["rangeFieldFormat"] = pdr.range_field_format; output["rangeFieldSupport"] = pdr.range_field_support.byte; switch (pdr.range_field_format) { case PLDM_RANGE_FIELD_FORMAT_UINT8: output["nominalValue"] = pdr.nominal_value.value_u8; output["normalMax"] = pdr.normal_max.value_u8; output["normalMin"] = pdr.normal_min.value_u8; output["warningHigh"] = pdr.warning_high.value_u8; output["warningLow"] = pdr.warning_low.value_u8; output["criticalHigh"] = pdr.critical_high.value_u8; output["criticalLow"] = pdr.critical_low.value_u8; output["fatalHigh"] = pdr.fatal_high.value_u8; output["fatalLeow"] = pdr.fatal_low.value_u8; break; case PLDM_RANGE_FIELD_FORMAT_SINT8: output["nominalValue"] = pdr.nominal_value.value_s8; output["normalMax"] = pdr.normal_max.value_s8; output["normalMin"] = pdr.normal_min.value_s8; output["warningHigh"] = pdr.warning_high.value_s8; output["warningLow"] = pdr.warning_low.value_s8; output["criticalHigh"] = pdr.critical_high.value_s8; output["criticalLow"] = pdr.critical_low.value_s8; output["fatalHigh"] = pdr.fatal_high.value_s8; output["fatalLeow"] = pdr.fatal_low.value_s8; break; case PLDM_RANGE_FIELD_FORMAT_UINT16: output["nominalValue"] = pdr.nominal_value.value_u16; output["normalMax"] = pdr.normal_max.value_u16; output["normalMin"] = pdr.normal_min.value_u16; output["warningHigh"] = pdr.warning_high.value_u16; output["warningLow"] = pdr.warning_low.value_u16; output["criticalHigh"] = pdr.critical_high.value_u16; output["criticalLow"] = pdr.critical_low.value_u16; output["fatalHigh"] = pdr.fatal_high.value_u16; output["fatalLeow"] = pdr.fatal_low.value_u16; break; case PLDM_RANGE_FIELD_FORMAT_SINT16: output["nominalValue"] = pdr.nominal_value.value_s16; output["normalMax"] = pdr.normal_max.value_s16; output["normalMin"] = pdr.normal_min.value_s16; output["warningHigh"] = pdr.warning_high.value_s16; output["warningLow"] = pdr.warning_low.value_s16; output["criticalHigh"] = pdr.critical_high.value_s16; output["criticalLow"] = pdr.critical_low.value_s16; output["fatalHigh"] = pdr.fatal_high.value_s16; output["fatalLeow"] = pdr.fatal_low.value_s16; break; case PLDM_RANGE_FIELD_FORMAT_UINT32: output["nominalValue"] = pdr.nominal_value.value_u32; output["normalMax"] = pdr.normal_max.value_u32; output["normalMin"] = pdr.normal_min.value_u32; output["warningHigh"] = pdr.warning_high.value_u32; output["warningLow"] = pdr.warning_low.value_u32; output["criticalHigh"] = pdr.critical_high.value_u32; output["criticalLow"] = pdr.critical_low.value_u32; output["fatalHigh"] = pdr.fatal_high.value_u32; output["fatalLeow"] = pdr.fatal_low.value_u32; break; case PLDM_RANGE_FIELD_FORMAT_SINT32: output["nominalValue"] = pdr.nominal_value.value_s32; output["normalMax"] = pdr.normal_max.value_s32; output["normalMin"] = pdr.normal_min.value_s32; output["warningHigh"] = pdr.warning_high.value_s32; output["warningLow"] = pdr.warning_low.value_s32; output["criticalHigh"] = pdr.critical_high.value_s32; output["criticalLow"] = pdr.critical_low.value_s32; output["fatalHigh"] = pdr.fatal_high.value_s32; output["fatalLeow"] = pdr.fatal_low.value_s32; break; case PLDM_RANGE_FIELD_FORMAT_REAL32: output["nominalValue"] = pdr.nominal_value.value_f32; output["normalMax"] = pdr.normal_max.value_f32; output["normalMin"] = pdr.normal_min.value_f32; output["warningHigh"] = pdr.warning_high.value_f32; output["warningLow"] = pdr.warning_low.value_f32; output["criticalHigh"] = pdr.critical_high.value_f32; output["criticalLow"] = pdr.critical_low.value_f32; output["fatalHigh"] = pdr.fatal_high.value_f32; output["fatalLeow"] = pdr.fatal_low.value_f32; break; default: break; } } /** @brief Format the Compact Numeric Sensor PDR types to json output * * @param[in] data - reference to the Compact Numeric Sensor PDR * @param[out] output - PDRs data fields in Json format */ void printCompactNumericSensorPDR(const uint8_t* data, ordered_json& output) { struct pldm_compact_numeric_sensor_pdr* pdr = (struct pldm_compact_numeric_sensor_pdr*)data; if (!pdr) { std::cerr << "Failed to get compact numeric sensor PDR" << std::endl; return; } output["PLDMTerminusHandle"] = int(pdr->terminus_handle); output["sensorID"] = int(pdr->sensor_id); output["entityType"] = getEntityName(pdr->entity_type); output["entityInstanceNumber"] = int(pdr->entity_instance); output["containerID"] = int(pdr->container_id); output["sensorNameStringByteLength"] = int(pdr->sensor_name_length); if (pdr->sensor_name_length == 0) { output["Name"] = std::format("PLDM_Device_TID{}_SensorId{}", unsigned(pdr->terminus_handle), unsigned(pdr->sensor_id)); } else { std::string sTemp(reinterpret_cast(pdr->sensor_name), pdr->sensor_name_length); output["Name"] = sTemp; } output["baseUnit"] = unsigned(pdr->base_unit); output["unitModifier"] = signed(pdr->unit_modifier); output["occurrenceRate"] = unsigned(pdr->occurrence_rate); output["rangeFieldSupport"] = unsigned(pdr->range_field_support.byte); if (pdr->range_field_support.bits.bit0) { output["warningHigh"] = int(pdr->warning_high); } if (pdr->range_field_support.bits.bit1) { output["warningLow"] = int(pdr->warning_low); } if (pdr->range_field_support.bits.bit2) { output["criticalHigh"] = int(pdr->critical_high); } if (pdr->range_field_support.bits.bit3) { output["criticalLow"] = int(pdr->critical_low); } if (pdr->range_field_support.bits.bit4) { output["fatalHigh"] = int(pdr->fatal_high); } if (pdr->range_field_support.bits.bit5) { output["fatalLow"] = int(pdr->fatal_low); } } void printPDRMsg(uint32_t& nextRecordHndl, const uint16_t respCnt, uint8_t* data, std::optional terminusHandle) { if (data == NULL) { std::cerr << "Failed to get PDR message" << std::endl; return; } ordered_json output; output["nextRecordHandle"] = nextRecordHndl; output["responseCount"] = respCnt; struct pldm_pdr_hdr* pdr = (struct pldm_pdr_hdr*)data; if (!pdr) { return; } if (!pdrRecType.empty()) { // Need to return if the requested PDR type // is not supported if (!strToPdrType.contains(pdrRecType)) { std::cerr << "PDR type '" << pdrRecType << "' is not supported or invalid\n"; // PDR type not supported, setting next record handle to // 0 to avoid looping through all PDR records nextRecordHndl = 0; return; } // Do not print PDR record if the current record // PDR type does not match with requested type if (pdr->type != strToPdrType.at(pdrRecType)) { return; } } if (pdrTerminus.has_value()) { if (checkTerminusHandle(data, terminusHandle)) { std::cerr << "The Terminus handle doesn't match return" << std::endl; return; } } printCommonPDRHeader(pdr, output); switch (pdr->type) { case PLDM_TERMINUS_LOCATOR_PDR: printTerminusLocatorPDR(data, output); break; case PLDM_STATE_SENSOR_PDR: printStateSensorPDR(data, output); break; case PLDM_NUMERIC_EFFECTER_PDR: printNumericEffecterPDR(data, output); break; case PLDM_NUMERIC_SENSOR_PDR: printNumericSensorPDR(data, respCnt, output); break; case PLDM_SENSOR_AUXILIARY_NAMES_PDR: printAuxNamePDR(data, output); break; case PLDM_EFFECTER_AUXILIARY_NAMES_PDR: printAuxNamePDR(data, output); break; case PLDM_STATE_EFFECTER_PDR: printStateEffecterPDR(data, output); break; case PLDM_PDR_ENTITY_ASSOCIATION: printPDREntityAssociation(data, output); break; case PLDM_PDR_FRU_RECORD_SET: printPDRFruRecordSet(data, output); break; case PLDM_COMPACT_NUMERIC_SENSOR_PDR: printCompactNumericSensorPDR(data, output); break; default: break; } pldmtool::helper::DisplayInJson(output); } private: bool optTIDSet = false; uint32_t recordHandle; bool allPDRs; std::string pdrRecType; std::optional pdrTerminus; std::optional terminusHandle; bool handleFound = false; CLI::Option* getPDRGroupOption = nullptr; }; class SetStateEffecter : public CommandInterface { public: ~SetStateEffecter() = default; SetStateEffecter() = delete; SetStateEffecter(const SetStateEffecter&) = delete; SetStateEffecter(SetStateEffecter&&) = default; SetStateEffecter& operator=(const SetStateEffecter&) = delete; SetStateEffecter& operator=(SetStateEffecter&&) = delete; // compositeEffecterCount(value: 0x01 to 0x08) * stateField(2) static constexpr auto maxEffecterDataSize = 16; // compositeEffecterCount(value: 0x01 to 0x08) static constexpr auto minEffecterCount = 1; static constexpr auto maxEffecterCount = 8; explicit SetStateEffecter(const char* type, const char* name, CLI::App* app) : CommandInterface(type, name, app) { app->add_option( "-i, --id", effecterId, "A handle that is used to identify and access the effecter") ->required(); app->add_option("-c, --count", effecterCount, "The number of individual sets of effecter information") ->required(); app->add_option( "-d,--data", effecterData, "Set effecter state data\n" "eg: requestSet0 effecterState0 noChange1 dummyState1 ...") ->required(); } std::pair> createRequestMsg() override { std::vector requestMsg( sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES); auto request = reinterpret_cast(requestMsg.data()); if (effecterCount > maxEffecterCount || effecterCount < minEffecterCount) { std::cerr << "Request Message Error: effecterCount size " << effecterCount << "is invalid\n"; auto rc = PLDM_ERROR_INVALID_DATA; return {rc, requestMsg}; } if (effecterData.size() > maxEffecterDataSize) { std::cerr << "Request Message Error: effecterData size " << effecterData.size() << "is invalid\n"; auto rc = PLDM_ERROR_INVALID_DATA; return {rc, requestMsg}; } auto stateField = parseEffecterData(effecterData, effecterCount); if (!stateField) { std::cerr << "Failed to parse effecter data, effecterCount size " << effecterCount << "\n"; auto rc = PLDM_ERROR_INVALID_DATA; return {rc, requestMsg}; } auto rc = encode_set_state_effecter_states_req( instanceId, effecterId, effecterCount, stateField->data(), request); return {rc, requestMsg}; } void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override { uint8_t completionCode = 0; auto rc = decode_set_state_effecter_states_resp( responsePtr, payloadLength, &completionCode); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { std::cerr << "Response Message Error: " << "rc=" << rc << ",cc=" << (int)completionCode << "\n"; return; } ordered_json data; data["Response"] = "SUCCESS"; pldmtool::helper::DisplayInJson(data); } private: uint16_t effecterId; uint8_t effecterCount; std::vector effecterData; }; class SetNumericEffecterValue : public CommandInterface { public: ~SetNumericEffecterValue() = default; SetNumericEffecterValue() = delete; SetNumericEffecterValue(const SetNumericEffecterValue&) = delete; SetNumericEffecterValue(SetNumericEffecterValue&&) = default; SetNumericEffecterValue& operator=(const SetNumericEffecterValue&) = delete; SetNumericEffecterValue& operator=(SetNumericEffecterValue&&) = delete; explicit SetNumericEffecterValue(const char* type, const char* name, CLI::App* app) : CommandInterface(type, name, app) { app->add_option( "-i, --id", effecterId, "A handle that is used to identify and access the effecter") ->required(); app->add_option("-s, --size", effecterDataSize, "The bit width and format of the setting value for the " "effecter. enum value: {uint8, sint8, uint16, sint16, " "uint32, sint32}\n") ->required(); app->add_option("-d,--data", maxEffecterValue, "The setting value of numeric effecter being " "requested\n") ->required(); } std::pair> createRequestMsg() override { std::vector requestMsg( sizeof(pldm_msg_hdr) + PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3); uint8_t* effecterValue = (uint8_t*)&maxEffecterValue; auto request = reinterpret_cast(requestMsg.data()); size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES; if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16 || effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) { payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 1; } if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32 || effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) { payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3; } auto rc = encode_set_numeric_effecter_value_req( 0, effecterId, effecterDataSize, effecterValue, request, payload_length); return {rc, requestMsg}; } void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override { uint8_t completionCode = 0; auto rc = decode_set_numeric_effecter_value_resp( responsePtr, payloadLength, &completionCode); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { std::cerr << "Response Message Error: " << "rc=" << rc << ",cc=" << (int)completionCode << std::endl; return; } ordered_json data; data["Response"] = "SUCCESS"; pldmtool::helper::DisplayInJson(data); } private: uint16_t effecterId; uint8_t effecterDataSize; uint64_t maxEffecterValue; }; class GetStateSensorReadings : public CommandInterface { public: ~GetStateSensorReadings() = default; GetStateSensorReadings() = delete; GetStateSensorReadings(const GetStateSensorReadings&) = delete; GetStateSensorReadings(GetStateSensorReadings&&) = default; GetStateSensorReadings& operator=(const GetStateSensorReadings&) = delete; GetStateSensorReadings& operator=(GetStateSensorReadings&&) = delete; explicit GetStateSensorReadings(const char* type, const char* name, CLI::App* app) : CommandInterface(type, name, app) { app->add_option( "-i, --sensor_id", sensorId, "Sensor ID that is used to identify and access the sensor") ->required(); app->add_option("-r, --rearm", sensorRearm, "Each bit location in this field corresponds to a " "particular sensor") ->required(); } std::pair> createRequestMsg() override { std::vector requestMsg( sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES); auto request = reinterpret_cast(requestMsg.data()); uint8_t reserved = 0; bitfield8_t bf; bf.byte = sensorRearm; auto rc = encode_get_state_sensor_readings_req(instanceId, sensorId, bf, reserved, request); return {rc, requestMsg}; } void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override { uint8_t completionCode = 0; uint8_t compSensorCount = 0; std::array stateField{}; auto rc = decode_get_state_sensor_readings_resp( responsePtr, payloadLength, &completionCode, &compSensorCount, stateField.data()); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { std::cerr << "Response Message Error: " << "rc=" << rc << ",cc=" << (int)completionCode << std::endl; return; } ordered_json output; output["compositeSensorCount"] = (int)compSensorCount; for (size_t i = 0; i < compSensorCount; i++) { if (sensorOpState.contains(stateField[i].sensor_op_state)) { output.emplace(("sensorOpState[" + std::to_string(i) + "]"), sensorOpState.at(stateField[i].sensor_op_state)); } if (sensorPresState.contains(stateField[i].present_state)) { output.emplace(("presentState[" + std::to_string(i) + "]"), sensorPresState.at(stateField[i].present_state)); } if (sensorPresState.contains(stateField[i].previous_state)) { output.emplace( ("previousState[" + std::to_string(i) + "]"), sensorPresState.at(stateField[i].previous_state)); } if (sensorPresState.contains(stateField[i].event_state)) { output.emplace(("eventState[" + std::to_string(i) + "]"), sensorPresState.at(stateField[i].event_state)); } } pldmtool::helper::DisplayInJson(output); } private: uint16_t sensorId; uint8_t sensorRearm; }; class GetSensorReading : public CommandInterface { public: ~GetSensorReading() = default; GetSensorReading() = delete; GetSensorReading(const GetSensorReading&) = delete; GetSensorReading(GetSensorReading&&) = default; GetSensorReading& operator=(const GetSensorReading&) = delete; GetSensorReading& operator=(GetSensorReading&&) = delete; explicit GetSensorReading(const char* type, const char* name, CLI::App* app) : CommandInterface(type, name, app) { app->add_option( "-i, --sensor_id", sensorId, "Sensor ID that is used to identify and access the sensor") ->required(); app->add_option("-r, --rearm", rearm, "Manually re-arm EventState after " "responding to this request") ->required(); } std::pair> createRequestMsg() override { std::vector requestMsg(sizeof(pldm_msg_hdr) + PLDM_GET_SENSOR_READING_REQ_BYTES); auto request = reinterpret_cast(requestMsg.data()); auto rc = encode_get_sensor_reading_req(instanceId, sensorId, rearm, request); return {rc, requestMsg}; } void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override { uint8_t completionCode = 0; uint8_t sensorDataSize = 0; uint8_t sensorOperationalState = 0; uint8_t sensorEventMessageEnable = 0; uint8_t presentState = 0; uint8_t previousState = 0; uint8_t eventState = 0; std::array presentReading{}; // maximum size for the present Value is uint32 // according to spec DSP0248 auto rc = decode_get_sensor_reading_resp( responsePtr, payloadLength, &completionCode, &sensorDataSize, &sensorOperationalState, &sensorEventMessageEnable, &presentState, &previousState, &eventState, presentReading.data()); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { std::cerr << "Response Message Error: " << "rc=" << rc << ",cc=" << (int)completionCode << std::endl; return; } ordered_json output; output["sensorDataSize"] = getSensorState(sensorDataSize, &sensorDataSz); output["sensorOperationalState"] = getSensorState(sensorOperationalState, &sensorOpState); output["sensorEventMessageEnable"] = getSensorState(sensorEventMessageEnable, &sensorEventMsgEnable); output["presentState"] = getSensorState(presentState, &sensorPresState); output["previousState"] = getSensorState(previousState, &sensorPresState); output["eventState"] = getSensorState(eventState, &sensorPresState); switch (sensorDataSize) { case PLDM_SENSOR_DATA_SIZE_UINT8: { output["presentReading"] = *(reinterpret_cast(presentReading.data())); break; } case PLDM_SENSOR_DATA_SIZE_SINT8: { output["presentReading"] = *(reinterpret_cast(presentReading.data())); break; } case PLDM_SENSOR_DATA_SIZE_UINT16: { output["presentReading"] = *(reinterpret_cast(presentReading.data())); break; } case PLDM_SENSOR_DATA_SIZE_SINT16: { output["presentReading"] = *(reinterpret_cast(presentReading.data())); break; } case PLDM_SENSOR_DATA_SIZE_UINT32: { output["presentReading"] = *(reinterpret_cast(presentReading.data())); break; } case PLDM_SENSOR_DATA_SIZE_SINT32: { output["presentReading"] = *(reinterpret_cast(presentReading.data())); break; } default: { std::cerr << "Unknown Sensor Data Size : " << static_cast(sensorDataSize) << std::endl; break; } } pldmtool::helper::DisplayInJson(output); } private: uint16_t sensorId; uint8_t rearm; const std::map sensorDataSz = { {PLDM_SENSOR_DATA_SIZE_UINT8, "uint8"}, {PLDM_SENSOR_DATA_SIZE_SINT8, "uint8"}, {PLDM_SENSOR_DATA_SIZE_UINT16, "uint16"}, {PLDM_SENSOR_DATA_SIZE_SINT16, "uint16"}, {PLDM_SENSOR_DATA_SIZE_UINT32, "uint32"}, {PLDM_SENSOR_DATA_SIZE_SINT32, "uint32"}}; static inline const std::map sensorEventMsgEnable{ {PLDM_NO_EVENT_GENERATION, "Sensor No Event Generation"}, {PLDM_EVENTS_DISABLED, "Sensor Events Disabled"}, {PLDM_EVENTS_ENABLED, "Sensor Events Enabled"}, {PLDM_OP_EVENTS_ONLY_ENABLED, "Sensor Op Events Only Enabled"}, {PLDM_STATE_EVENTS_ONLY_ENABLED, "Sensor State Events Only Enabled"}}; std::string getSensorState(uint8_t state, const std::map* cont) { auto typeString = std::to_string(state); try { return cont->at(state); } catch (const std::out_of_range& e) { return typeString; } } }; class GetNumericEffecterValue : public CommandInterface { public: ~GetNumericEffecterValue() = default; GetNumericEffecterValue() = delete; GetNumericEffecterValue(const GetNumericEffecterValue&) = delete; GetNumericEffecterValue(GetNumericEffecterValue&&) = default; GetNumericEffecterValue& operator=(const GetNumericEffecterValue&) = delete; GetNumericEffecterValue& operator=(GetNumericEffecterValue&&) = delete; explicit GetNumericEffecterValue(const char* type, const char* name, CLI::App* app) : CommandInterface(type, name, app) { app->add_option( "-i, --effecter_id", effecterId, "A handle that is used to identify and access the effecter") ->required(); } std::pair> createRequestMsg() override { std::vector requestMsg( sizeof(pldm_msg_hdr) + PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES); auto request = reinterpret_cast(requestMsg.data()); auto rc = encode_get_numeric_effecter_value_req(instanceId, effecterId, request); return {rc, requestMsg}; } void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override { uint8_t completionCode = 0; uint8_t effecterDataSize = 0; uint8_t effecterOperationalState = 0; std::array pendingValue{}; // maximum size for the pending Value is uint32 // according to spec DSP0248 std::array presentValue{}; // maximum size for the present Value is uint32 // according to spec DSP0248 auto rc = decode_get_numeric_effecter_value_resp( responsePtr, payloadLength, &completionCode, &effecterDataSize, &effecterOperationalState, pendingValue.data(), presentValue.data()); if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) { std::cerr << "Response Message Error: " << "rc=" << rc << ",cc=" << static_cast(completionCode) << std::endl; return; } ordered_json output; output["effecterDataSize"] = static_cast(effecterDataSize); output["effecterOperationalState"] = getOpState(effecterOperationalState); switch (effecterDataSize) { case PLDM_EFFECTER_DATA_SIZE_UINT8: { output["pendingValue"] = *(reinterpret_cast(pendingValue.data())); output["presentValue"] = *(reinterpret_cast(presentValue.data())); break; } case PLDM_EFFECTER_DATA_SIZE_SINT8: { output["pendingValue"] = *(reinterpret_cast(pendingValue.data())); output["presentValue"] = *(reinterpret_cast(presentValue.data())); break; } case PLDM_EFFECTER_DATA_SIZE_UINT16: { output["pendingValue"] = *(reinterpret_cast(pendingValue.data())); output["presentValue"] = *(reinterpret_cast(presentValue.data())); break; } case PLDM_EFFECTER_DATA_SIZE_SINT16: { output["pendingValue"] = *(reinterpret_cast(pendingValue.data())); output["presentValue"] = *(reinterpret_cast(presentValue.data())); break; } case PLDM_EFFECTER_DATA_SIZE_UINT32: { output["pendingValue"] = *(reinterpret_cast(pendingValue.data())); output["presentValue"] = *(reinterpret_cast(presentValue.data())); break; } case PLDM_EFFECTER_DATA_SIZE_SINT32: { output["pendingValue"] = *(reinterpret_cast(pendingValue.data())); output["presentValue"] = *(reinterpret_cast(presentValue.data())); break; } default: { std::cerr << "Unknown Effecter Data Size : " << static_cast(effecterDataSize) << std::endl; break; } } pldmtool::helper::DisplayInJson(output); } private: uint16_t effecterId; static inline const std::map numericEffecterOpState{ {EFFECTER_OPER_STATE_ENABLED_UPDATEPENDING, "Effecter Enabled Update Pending"}, {EFFECTER_OPER_STATE_ENABLED_NOUPDATEPENDING, "Effecter Enabled No Update Pending"}, {EFFECTER_OPER_STATE_DISABLED, "Effecter Disabled"}, {EFFECTER_OPER_STATE_UNAVAILABLE, "Effecter Unavailable"}, {EFFECTER_OPER_STATE_STATUSUNKNOWN, "Effecter Status Unknown"}, {EFFECTER_OPER_STATE_FAILED, "Effecter Failed"}, {EFFECTER_OPER_STATE_INITIALIZING, "Effecter Initializing"}, {EFFECTER_OPER_STATE_SHUTTINGDOWN, "Effecter Shutting Down"}, {EFFECTER_OPER_STATE_INTEST, "Effecter In Test"}}; std::string getOpState(uint8_t state) { auto typeString = std::to_string(state); try { return numericEffecterOpState.at(state); } catch (const std::out_of_range& e) { return typeString; } } }; void registerCommand(CLI::App& app) { auto platform = app.add_subcommand("platform", "platform type command"); platform->require_subcommand(1); auto getPDR = platform->add_subcommand("GetPDR", "get platform descriptor records"); commands.push_back(std::make_unique("platform", "getPDR", getPDR)); auto setStateEffecterStates = platform->add_subcommand( "SetStateEffecterStates", "set effecter states"); commands.push_back(std::make_unique( "platform", "setStateEffecterStates", setStateEffecterStates)); auto setNumericEffecterValue = platform->add_subcommand( "SetNumericEffecterValue", "set the value for a PLDM Numeric Effecter"); commands.push_back(std::make_unique( "platform", "setNumericEffecterValue", setNumericEffecterValue)); auto getStateSensorReadings = platform->add_subcommand( "GetStateSensorReadings", "get the state sensor readings"); commands.push_back(std::make_unique( "platform", "getStateSensorReadings", getStateSensorReadings)); auto getNumericEffecterValue = platform->add_subcommand( "GetNumericEffecterValue", "get the numeric effecter value"); commands.push_back(std::make_unique( "platform", "getNumericEffecterValue", getNumericEffecterValue)); auto getSensorReading = platform->add_subcommand( "GetSensorReading", "get the numeric sensor reading"); commands.push_back(std::make_unique( "platform", "getSensorReading", getSensorReading)); } void parseGetPDROption() { for (const auto& command : commands) { if (command.get()->getPLDMType() == "platform" && command.get()->getCommandName() == "getPDR") { auto getPDR = dynamic_cast(command.get()); getPDR->parseGetPDROptions(); } } } } // namespace platform } // namespace pldmtool