diff options
-rw-r--r-- | src/include/runtime/generic_hbrt_fsp_message.H | 105 | ||||
-rw-r--r-- | src/include/runtime/interface.h | 18 | ||||
-rw-r--r-- | src/include/usr/runtime/runtime_reasoncodes.H | 6 | ||||
-rw-r--r-- | src/usr/isteps/pm/runtime/test/firmwareRequestTest.H | 136 | ||||
-rw-r--r-- | src/usr/testcore/rtloader/loader.H | 129 | ||||
-rw-r--r-- | src/usr/util/runtime/makefile | 1 | ||||
-rw-r--r-- | src/usr/util/runtime/rt_fwnotify.C | 354 | ||||
-rw-r--r-- | src/usr/vpd/runtime/rt_vpd.C | 44 |
8 files changed, 688 insertions, 105 deletions
diff --git a/src/include/runtime/generic_hbrt_fsp_message.H b/src/include/runtime/generic_hbrt_fsp_message.H index 742270e66..1eebb7b09 100644 --- a/src/include/runtime/generic_hbrt_fsp_message.H +++ b/src/include/runtime/generic_hbrt_fsp_message.H @@ -34,40 +34,105 @@ * FSP/HWSV team to send and receive data. */ + +/** + * Values for the GenericFspMboxMessage_t::magic + * and GenericFspMboxMessage_t::structVer data members + */ +const uint32_t GFMM_MAGIC_NUMBER = 0x4746464D; // `GFFM` +const uint16_t GFMM_VERSION = 1; + +/** + * Values for the GenericFspMboxMessage_t::__req flag + */ +enum GENERIC_FSP_MBOX_MESSAGE_FLOW +{ + GFMM_RESPONSE = 0, + GFMM_REQUEST = 1, +}; + /** - * This struct sends an MBox message to the FSP + * Values for the GenericFspMboxMessage_t::__onlyError flag + */ +enum GENERIC_FSP_MBOX_MESSAGE_ERROR_FLAG +{ + GFMM_NOT_ERROR_ONLY = 0, + GFMM_ERROR_ONLY = 1, +}; + +/** + * The different message types for the GenericFspMboxMessage_t + */ +enum GENERIC_FSP_MBOX_MESSAGE_MSG_TYPE +{ + GFMM_MSG_TOD_BACKUP_RESET = 0x0001, + GFMM_MSG_TOD_BACKUP_RESET_INFORM_PHYP = 0x0002, + GFMM_MSG_TOD_TOPOLOGY_DATA = 0x0003, + GFMM_MSG_SBE_ERROR = 0x000000E1, + GFMM_MSG_SBE_RECOVERY_SUCCESS = 0x000000E2, + GFMM_MSG_SBE_RECOVERY_FAILED = 0x000000E3, +}; + +/** + * This generates a sequence ID that the GenericFspMboxMessage_t + * consumes. + */ +struct SeqId_t +{ +public: + static uint16_t getNextSeqId(); + static uint16_t getCurrentSeqId(); + +private: + static uint16_t GFMM_SEQ_ID; +}; + +/** + * This struct sends/receives an MBox message to the FSP */ struct GenericFspMboxMessage_t { - uint32_t msgq; // Example: MBOX::FSP_VPD_MSGQ - uint32_t msgType; // Example: VPD_MSG_TYPE:VPD_WRITE_PROC + uint32_t magic; // ='GFMM' + uint32_t dataSize; // total number of bytes in the entire message, + // includes structure plus data buffer, + // minimum is sizeof(GenericFspMboxMessage_t) + uint8_t structVer; // =1, allow for future modifications + uint8_t reserved; // unused, just for alignment and expansion + uint16_t seqnum; // incremented for each new request, bit0=1 indicates + // the request came from the FSP, i.e. 0x0000->0x7FFF + // are from HBRT, 0x8000->0xFFFF are from HWSV. + uint32_t msgq; // Example: MBOX::FSP_VPD_MSGQ + uint32_t msgType; // Example: VPD_MSG_TYPE:VPD_WRITE_PROC struct // flags { - uint32_t __reserved__async:1; - uint32_t __reserved__pseudosync:1; - uint32_t __reserved__unused:30; + uint32_t __req:1; // 1=this is a request, 0=this is a response + uint32_t __async:1; // =0 for now, future async req/resp support + uint32_t __onlyError:1; // 1=this is a response that only contains a + // single 32-bit plid in the first 4 bytes of + // the data payload + uint32_t __unused:29; // reserved for future }; uint64_t data; // generic member that can be used // to do casting to other types: // MyDataType_t* mydatatype = // (MyDataType_t*)&(l_generic_msg.data); -} PACKED ; -/** - * This struct receives the response message from the FSP - */ -struct GenericFspRspMessage_t -{ - uint32_t msgq; // Example: MBOX::FSP_VPD_MSGQ - uint32_t msgType; // Example: VPD_MSG_TYPE:VPD_WRITE_PROC - struct // flags + // A method to set the local vars to a default state + void initialize() { - uint32_t __reserved__async:1; - uint32_t __reserved__pseudosync:1; - uint32_t __reserved__unused:30; + magic = GFMM_MAGIC_NUMBER; + dataSize = sizeof(GenericFspMboxMessage_t); + structVer = GFMM_VERSION; + reserved = 0; + seqnum = SeqId_t::getNextSeqId(); + msgq = 0; + msgType = 0; + __req = GFMM_RESPONSE; + __async = 0; + __onlyError = GFMM_NOT_ERROR_ONLY; + __unused = 0; + data = 0; }; - uint32_t errPlid; // error log id } PACKED ; - #endif // __RUNTIME__GENERIC_HBRT_FSP_MESSAGE_H diff --git a/src/include/runtime/interface.h b/src/include/runtime/interface.h index 7258826ca..8aad5d5fb 100644 --- a/src/include/runtime/interface.h +++ b/src/include/runtime/interface.h @@ -503,7 +503,7 @@ typedef struct hostInterfaces HBRT_FW_MSG_TYPE_RESP_NOP = 1, HBRT_FW_MSG_TYPE_RESP_GENERIC = 2, HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE = 3, - HBRT_FW_MSG_HBRT_FSP = 4, + HBRT_FW_MSG_HBRT_FSP_REQ = 4, HBRT_FW_MSG_TYPE_ERROR_LOG = 5, HBRT_FW_MSG_HBRT_FSP_RESP = 6, }; @@ -550,21 +550,17 @@ typedef struct hostInterfaces } __attribute__ ((packed)) error_log; // This struct is sent from HBRT with - // io_type set to HBRT_FW_MSG_HBRT_FSP - // This struct sends an MBox message to the FSP - struct GenericFspMboxMessage_t generic_message; - - // This struct is sent from FSP with - // io_type set to HBRT_FW_MSG_HBRT_FSP_RESP - // This struct receives a message from the FSP - struct GenericFspRspMessage_t generic_message_resp; - + // io_type set to HBRT_FW_MSG_HBRT_FSP_REQ or + // HBRT_FW_MSG_HBRT_FSP_RESP + // This struct sends/receives an MBox message to the FSP + struct GenericFspMboxMessage_t generic_msg; }; // end union }; // end struct hbrt_fw_msg // Created a static constexpr to return the base size of hbrt_fw_msg // Can't do #define - sizeof not allowed to be used in #defines - static constexpr size_t HBRT_FW_MSG_BASE_SIZE = sizeof(uint64_t); + static constexpr size_t HBRT_FW_MSG_BASE_SIZE = + sizeof(hbrt_fw_msg::io_type); /** * @brief Send a request to firmware, and receive a response diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index 4ce07c0c2..5b38a8b08 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -60,6 +60,7 @@ namespace RUNTIME MOD_FILL_RSVMEM_HBDATA = 0x20, /**< populate_hbruntime.C */ MOD_ATTR_RUNTIME_CHECK_PREP_FAIL = 0x21, /**< populate_hbruntime.C */ MOD_PM_RT_FIRMWARE_REQUEST = 0x22, /**< rt_pm.C */ + MOD_RT_FIRMWARE_NOTIFY = 0x23, /**< rt_fwnotify.C */ }; enum RuntimeReasonCode @@ -114,6 +115,11 @@ namespace RUNTIME RC_TPM_HDAT_BAD_NUM_I2C = RUNTIME_COMP_ID | 0x2F, RC_INVALID_LID = RUNTIME_COMP_ID | 0x30, RC_PREVER_INVALID_SIZE = RUNTIME_COMP_ID | 0x31, + RC_FW_NOTIFY_RT_INVALID_MSG = RUNTIME_COMP_ID | 0x32, + RC_FW_NOTIFY_RT_INVALID_MSG_TYPE = RUNTIME_COMP_ID | 0x33, + RC_FW_REQUEST_RT_NULL_PTR = RUNTIME_COMP_ID | 0x34, + RC_SBE_RT_INVALID_HUID = RUNTIME_COMP_ID | 0x35, + RC_SBE_RT_RECOVERY_ERR = RUNTIME_COMP_ID | 0x36, }; enum UserDetailsTypes diff --git a/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H b/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H index 231197ec3..22d5bfc31 100644 --- a/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H +++ b/src/usr/isteps/pm/runtime/test/firmwareRequestTest.H @@ -25,6 +25,8 @@ #include <cxxtest/TestSuite.H> #include <runtime/interface.h> +#include <errl/hberrltypes.H> +#include <string.h> extern trace_desc_t* g_trac_pnor; @@ -61,7 +63,7 @@ class FirmwareRequestTest : public CxxTest::TestSuite hostInterfaces::hbrt_fw_msg l_resp_fw_msg; - uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); + size_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); size_t rc = g_hostInterfaces->firmware_request( sizeof(l_req_fw_msg), &l_req_fw_msg, &l_resp_fw_msg_size, &l_resp_fw_msg); @@ -125,7 +127,7 @@ class FirmwareRequestTest : public CxxTest::TestSuite l_req_fw_msg.error_log.i_data = 0xAA; hostInterfaces::hbrt_fw_msg l_resp_fw_msg; - uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); + size_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); size_t rc = g_hostInterfaces->firmware_request( sizeof(l_req_fw_msg), &l_req_fw_msg, &l_resp_fw_msg_size, &l_resp_fw_msg); @@ -183,36 +185,94 @@ class FirmwareRequestTest : public CxxTest::TestSuite // Test HBRT to FSP // populate the firmware_request structure with arbitrary data hostInterfaces::hbrt_fw_msg l_req_fw_msg; - l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP; - l_req_fw_msg.generic_message.msgq = 0x300; - l_req_fw_msg.generic_message.msgType = 0x400; - l_req_fw_msg.generic_message.data = 0xDEADBEEF; + l_req_fw_msg.generic_msg.initialize(); + + if (l_req_fw_msg.generic_msg.magic != GFMM_MAGIC_NUMBER) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "magic was not properly initialized"); + } + + if (l_req_fw_msg.generic_msg.dataSize != + sizeof(l_req_fw_msg.generic_msg)) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "dataSize was not properly initialized"); + } + + if (l_req_fw_msg.generic_msg.structVer != GFMM_VERSION) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "structVer was not properly initialized"); + } + + if (l_req_fw_msg.generic_msg.seqnum != SeqId_t::getCurrentSeqId()) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "seqnum was not properly initialized"); + } + + l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg.generic_msg.magic = 0x100; + l_req_fw_msg.generic_msg.dataSize = + sizeof(l_req_fw_msg.generic_msg); + l_req_fw_msg.generic_msg.structVer = 0x20; + l_req_fw_msg.generic_msg.seqnum = 0x300; + l_req_fw_msg.generic_msg.msgq = 0x400; + l_req_fw_msg.generic_msg.msgType = 0x500; + l_req_fw_msg.generic_msg.__req = GFMM_REQUEST; + l_req_fw_msg.generic_msg.__onlyError = GFMM_ERROR_ONLY; + uint32_t l_plid = 0x600; + uint32_t l_huid = 0x700; + l_req_fw_msg.generic_msg.data = + TWO_UINT32_TO_UINT64(l_plid, l_huid); TRACFCOMP(g_trac_pnor, "FirmwareRequestTest::testFirmwareRequestHbrtToFsp req: " - "type:%d, msgq:0x%.8X, msgType:0x%.8X, data:0x%.8X", + "type:%d, magic:0x%.8X, dataSize:%d, structVer:0x%.8X, " + "seqnum:%.8X, msgq:0x%.8X, msgType:0x%.8X, __req:%d, " + "__onlyError:%d, data:0x%.8X, plid:0x%.8X, huid:0x%.8X", l_req_fw_msg.io_type, - l_req_fw_msg.generic_message.msgq, - l_req_fw_msg.generic_message.msgType, - l_req_fw_msg.generic_message.data); + l_req_fw_msg.generic_msg.magic, + l_req_fw_msg.generic_msg.dataSize, + l_req_fw_msg.generic_msg.structVer, + l_req_fw_msg.generic_msg.seqnum, + l_req_fw_msg.generic_msg.msgq, + l_req_fw_msg.generic_msg.msgType, + l_req_fw_msg.generic_msg.__req, + l_req_fw_msg.generic_msg.__onlyError, + l_req_fw_msg.generic_msg.data, + l_req_fw_msg.generic_msg.data >> 32, + 0x0000FFFF & l_req_fw_msg.generic_msg.data); hostInterfaces::hbrt_fw_msg l_resp_fw_msg; - uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); + size_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); + memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size); size_t rc = g_hostInterfaces->firmware_request( sizeof(l_req_fw_msg), &l_req_fw_msg, &l_resp_fw_msg_size, &l_resp_fw_msg); TRACFCOMP(g_trac_pnor, "FirmwareRequestTest::testFirmwareRequestHbrtToFsp resp: " - "type:0x%.8X, msgq:0x%.8X, msgType:0x%.8X," - " errPlid:0x%X, rc=%d", + "type:%d, magic:0x%.8X, dataSize:%d, structVer:0x%.8X, " + "seqnum:%.8X, msgq:0x%.8X, msgType:0x%.8X, __req:%d, " + "__onlyError:%d, data:0x%.8X, plid:0x%.8X, huid:0x%.8X, " + "rc=%d", l_resp_fw_msg.io_type, - l_resp_fw_msg.generic_message_resp.msgq, - l_resp_fw_msg.generic_message_resp.msgType, - l_resp_fw_msg.generic_message_resp.errPlid, + l_resp_fw_msg.generic_msg.magic, + l_resp_fw_msg.generic_msg.dataSize, + l_resp_fw_msg.generic_msg.structVer, + l_resp_fw_msg.generic_msg.seqnum, + l_resp_fw_msg.generic_msg.msgq, + l_resp_fw_msg.generic_msg.msgType, + l_resp_fw_msg.generic_msg.__req, + l_resp_fw_msg.generic_msg.__onlyError, + l_resp_fw_msg.generic_msg.data, + l_resp_fw_msg.generic_msg.data >> 32, + 0x0000FFFF & l_resp_fw_msg.generic_msg.data, rc); - if (rc != 0) + if (rc != 5) { TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " "firmware_request - HBRT to FSP failed - " @@ -227,26 +287,62 @@ class FirmwareRequestTest : public CxxTest::TestSuite "received incorrect msg_type"); } - if (l_resp_fw_msg.generic_message_resp.msgq != 0x800) + if (l_resp_fw_msg.generic_msg.magic != 0x10) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "firmware_request - HBRT to FSP failed - " + "received incorrect magic"); + } + + if (l_resp_fw_msg.generic_msg.dataSize != 32) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "firmware_request - HBRT to FSP failed - " + "received incorrect datSize"); + } + + + if (l_resp_fw_msg.generic_msg.structVer != 0x02) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "firmware_request - HBRT to FSP failed - " + "received incorrect structVer"); + } + + if (l_resp_fw_msg.generic_msg.seqnum != 0x30) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "firmware_request - HBRT to FSP failed - " + "received incorrect seqnum"); + } + + if (l_resp_fw_msg.generic_msg.msgq != 0x40) { TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " "firware_request - HBRT to FSP failed - " "received incorrect msgq"); } - if (l_resp_fw_msg.generic_message_resp.msgType != 0x900) + if (l_resp_fw_msg.generic_msg.msgType != 0x50) { TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " "firware_request - HBRT to FSP failed - " "received incorrect msgType"); } - if (l_resp_fw_msg.generic_message_resp.errPlid != 0xA00) + if (l_resp_fw_msg.generic_msg.data >> 32 != 0x60) { TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " "firware_request - HBRT to FSP failed - " "received incorrect errPlid"); } + + if ((0x0000FFFF & l_resp_fw_msg.generic_msg.data) != 0x70) + { + TS_FAIL("FirmwareRequestTest::testFirmwareRequestHbrtToFsp: " + "firware_request - HBRT to FSP failed - " + "received incorrect huid"); + } } TRACFCOMP(g_trac_pnor, EXIT_MRK "FirmwareRequestTest::testFirmwareRequestHbrtToFsp"); diff --git a/src/usr/testcore/rtloader/loader.H b/src/usr/testcore/rtloader/loader.H index 62e251370..973afd158 100644 --- a/src/usr/testcore/rtloader/loader.H +++ b/src/usr/testcore/rtloader/loader.H @@ -194,7 +194,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite if (cv_hb_data_addr != 0) { // unmap virtual memory - TRACFCOMP( g_trac_hbrt, "tearDown(): unmap hb_data virt addr %p", + TRACFCOMP(g_trac_hbrt, + "tearDown(): unmap hb_data virt addr %p", reinterpret_cast<void*>(cv_hb_data_addr)); int l_rc = mm_block_unmap( @@ -212,7 +213,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite } else { - TRACFCOMP( g_trac_hbrt, "tearDown(): skipping unmap hb_data virt addr"); + TRACFCOMP( g_trac_hbrt, + "tearDown(): skipping unmap hb_data virt addr"); } } @@ -399,7 +401,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite static uint64_t rt_get_hb_data(uint32_t i_instance) { - TRACFCOMP( g_trac_hbrt, ENTER_MRK"rt_get_hb_data> i_instance=%d", i_instance ); + TRACFCOMP( g_trac_hbrt, + ENTER_MRK"rt_get_hb_data> i_instance=%d", i_instance ); uint64_t l_totalSize = 0; uint64_t l_vAddr = 0; @@ -510,7 +513,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite l_err = PNOR::getSectionInfo(l_id, l_info); if (l_err) { - TRACFCOMP(g_trac_hbrt, "rt_pnor_read: getSectionInfo errored"); + TRACFCOMP(g_trac_hbrt, + "rt_pnor_read: getSectionInfo errored"); break; } @@ -532,7 +536,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite " deviceRead: offset:0x%X, flashAddr:0x%X, size:0x%X", i_offset, l_flashAddr, l_bytes_to_read); - l_err = DeviceFW::deviceRead (pnor_target, o_data, l_bytes_to_read, + l_err = DeviceFW::deviceRead (pnor_target, o_data, + l_bytes_to_read, DEVICE_PNOR_ADDRESS(i_proc, l_flashAddr)); if (l_err) { @@ -582,7 +587,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite l_err = PNOR::getSectionInfo(l_id, l_info); if (l_err) { - TRACFCOMP(g_trac_hbrt, "rt_pnor_write: getSectionInfo errored"); + TRACFCOMP(g_trac_hbrt, + "rt_pnor_write: getSectionInfo errored"); break; } @@ -601,7 +607,8 @@ class RuntimeLoaderTest : public CxxTest::TestSuite DEVICE_PNOR_ADDRESS(i_proc, l_flashAddr)); if (l_err) { - TRACFCOMP(g_trac_hbrt, "rt_pnor_write: deviceWrite errored"); + TRACFCOMP(g_trac_hbrt, + "rt_pnor_write: deviceWrite errored"); break; } } while (0); @@ -716,7 +723,7 @@ class RuntimeLoaderTest : public CxxTest::TestSuite static int rt_firmware_request(uint64_t i_reqLen, void *i_req, uint64_t* o_respLen, void *o_resp ) { - int retVal = 0; + size_t retVal = 0; do { if (i_req == nullptr || @@ -732,13 +739,6 @@ class RuntimeLoaderTest : public CxxTest::TestSuite hostInterfaces::hbrt_fw_msg* l_resp_fw_msg = (hostInterfaces::hbrt_fw_msg*) o_resp; - if (*o_respLen < (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(l_resp_fw_msg->resp_generic))) - { - retVal = -EINVAL; - break; - } - if (hostInterfaces::HBRT_FW_MSG_TYPE_REQ_HCODE_UPDATE == l_req_fw_msg->io_type) { @@ -749,6 +749,13 @@ class RuntimeLoaderTest : public CxxTest::TestSuite break; } + if (*o_respLen < (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + sizeof(l_resp_fw_msg->resp_generic))) + { + retVal = -EINVAL; + break; + } + TRACFCOMP(g_trac_hbrt, "rt_firmware_request for HCODE SCOM update: " "type:%d, chipId:0x%X, section:%d, " @@ -786,6 +793,12 @@ class RuntimeLoaderTest : public CxxTest::TestSuite break; } + if (*o_respLen < (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + sizeof(l_resp_fw_msg->resp_generic))) + { + retVal = -EINVAL; + break; + } TRACFCOMP(g_trac_hbrt, "rt_firmware_request for error log: " @@ -803,41 +816,86 @@ class RuntimeLoaderTest : public CxxTest::TestSuite retVal = 0; // just return 0 for testing } - else if (hostInterfaces::HBRT_FW_MSG_HBRT_FSP + else if (hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ == l_req_fw_msg->io_type) { if (i_reqLen < (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(l_req_fw_msg->generic_message))) + sizeof(l_req_fw_msg->generic_msg))) { retVal = -EINVAL; break; } + if (*o_respLen < (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + + sizeof(l_resp_fw_msg->generic_msg))) + { + retVal = -EINVAL; + break; + } + + uint32_t* l_data = + (uint32_t*) &(l_req_fw_msg->generic_msg.data); TRACFCOMP(g_trac_hbrt, - "rt_firmware_request for VPD Write Msg: " - "type:0x%.8X, msgq:0x%.8X, VPD type:0x%.8X, data:0x%X", + "rt_firmware_request for VPD Write Msg request: " + "type:%d, magic:0x%.8X, dataSize:%d, structVer:0x%.8X, " + "seqnum:%d, msgq:0x%.8X, msgType:0x%.8X, __req:%d, " + "__onlyError:%d, data:0x%.8X, plid:0x%.8X, huid:0x%.8X", l_req_fw_msg->io_type, - l_req_fw_msg->generic_message.msgq, - l_req_fw_msg->generic_message.msgType, - l_req_fw_msg->generic_message.data); - - l_resp_fw_msg->io_type = - hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP; + l_req_fw_msg->generic_msg.magic, + l_req_fw_msg->generic_msg.dataSize, + l_req_fw_msg->generic_msg.structVer, + l_req_fw_msg->generic_msg.seqnum, + l_req_fw_msg->generic_msg.msgq, + l_req_fw_msg->generic_msg.msgType, + l_req_fw_msg->generic_msg.__req, + l_req_fw_msg->generic_msg.__onlyError, + l_req_fw_msg->generic_msg.data, + l_data[0], + l_data[1]); // random testing data - l_resp_fw_msg->generic_message_resp.msgq = 0x800; - l_resp_fw_msg->generic_message_resp.msgType = 0x900; - l_resp_fw_msg->generic_message_resp.errPlid = 0xA00; - retVal = 0; + struct + { + uint32_t plid; + uint32_t huid; + } l_resp_data; + l_resp_fw_msg->io_type = + hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP; + l_resp_fw_msg->generic_msg.magic = 0x10; + l_resp_fw_msg->generic_msg.dataSize = + sizeof(l_resp_fw_msg->generic_msg); + l_resp_fw_msg->generic_msg.structVer = 0x2; + l_resp_fw_msg->generic_msg.seqnum = 0x30; + l_resp_fw_msg->generic_msg.msgq = 0x40; + l_resp_fw_msg->generic_msg.msgType = 0x50; + l_resp_fw_msg->generic_msg.__req = GFMM_RESPONSE; + l_resp_fw_msg->generic_msg.__onlyError = + GFMM_NOT_ERROR_ONLY; + l_resp_data.plid = 0x60; + l_resp_data.huid = 0x70; + memcpy(&(l_resp_fw_msg->generic_msg.data), + &(l_resp_data), + sizeof(l_resp_fw_msg->generic_msg.data)); + retVal = 5; TRACFCOMP(g_trac_hbrt, "rt_firmware_request for VPD Write Msg response: " - "type:0x%.8X, msgq:0x%.8X, msgType:0x%.8X," - " errPlid:0x%X, retVal=%d", + "type:%d, magic:0x%.8X, dataSize:%d, structVer:0x%.8X, " + "seqnum:%d, msgq:0x%.8X, msgType:0x%.8X, __req:%d, " + "__onlyError:%d, data:0x%.8X, plid:0x%.8X, huid:0x%.8X, " + "retVal=%d", l_resp_fw_msg->io_type, - l_resp_fw_msg->generic_message_resp.msgq, - l_resp_fw_msg->generic_message_resp.msgType, - l_resp_fw_msg->generic_message_resp.errPlid, + l_resp_fw_msg->generic_msg.magic, + l_resp_fw_msg->generic_msg.dataSize, + l_resp_fw_msg->generic_msg.structVer, + l_resp_fw_msg->generic_msg.seqnum, + l_resp_fw_msg->generic_msg.msgq, + l_resp_fw_msg->generic_msg.msgType, + l_resp_fw_msg->generic_msg.__req, + l_resp_fw_msg->generic_msg.__onlyError, + l_resp_fw_msg->generic_msg.data, + l_resp_fw_msg->generic_msg.data >> 32, + 0x0000FFFF & l_resp_fw_msg->generic_msg.data, retVal); } else @@ -864,7 +922,4 @@ uint64_t RuntimeLoaderTest::cv_hb_data_addr = 0; uint64_t RuntimeLoaderTest::cv_comm_addr = 0; uint64_t RuntimeLoaderTest::cv_comm_phys_addr = 0; - - - #endif diff --git a/src/usr/util/runtime/makefile b/src/usr/util/runtime/makefile index 1ad51cf82..089ca750e 100644 --- a/src/usr/util/runtime/makefile +++ b/src/usr/util/runtime/makefile @@ -44,6 +44,7 @@ OBJS += util_rt.o OBJS += utilrsvdmem.o OBJS += utilxipimage.o OBJS += utilcommonattr.o +OBJS += rt_fwnotify.o SUBDIRS += test.d diff --git a/src/usr/util/runtime/rt_fwnotify.C b/src/usr/util/runtime/rt_fwnotify.C new file mode 100644 index 000000000..939270c3c --- /dev/null +++ b/src/usr/util/runtime/rt_fwnotify.C @@ -0,0 +1,354 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/util/runtime/rt_fwnotify.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +//#include <sbeio/sbe_retry_handler.H> // SbeRetryHandler +#include <runtime/interface.h> // firmware_notify +#include <runtime/runtime_reasoncodes.H> // MOD_RT_FIRMWARE_NOTIFY, etc +#include <errl/errlentry.H> // ErrlEntry +#include <errl/errlmanager.H> // errlCommit +#include <targeting/common/target.H> // TargetHandle_t, getTargetFromHuid + +using namespace TARGETING; +using namespace RUNTIME; +using namespace ERRORLOG; +using namespace MBOX; +//using namespace SBEIO; + +trace_desc_t* g_trac_hwsv = nullptr; +TRAC_INIT(&g_trac_hwsv, "HWSV_TRACE", 4*KILOBYTE); + +/** + * @brief The lower and upper bounds for the sequence ID. + **/ +const uint16_t GFMM_SEQ_ID_MIN = 0x0000; +const uint16_t GFMM_SEQ_ID_MAX = 0x7FFF; + +/** + * @brief Set the sequence ID to the minimum value + **/ +uint16_t SeqId_t::GFMM_SEQ_ID = GFMM_SEQ_ID_MIN; + +/** + * @brief Gets the next sequence ID. + * @return The next sequence ID value within it's lower and upper bound + **/ +uint16_t SeqId_t::getNextSeqId() +{ + if (SeqId_t::GFMM_SEQ_ID < GFMM_SEQ_ID_MAX) + { + ++SeqId_t::GFMM_SEQ_ID; + } + else + { + SeqId_t::GFMM_SEQ_ID = GFMM_SEQ_ID_MIN; + } + + return SeqId_t::GFMM_SEQ_ID; +} + +/** + * @brief Gets the current value of the sequence ID. + * @return The current value of the sequence ID. + **/ +uint16_t SeqId_t::getCurrentSeqId() +{ + return SeqId_t::GFMM_SEQ_ID; +} + +/** + * @brief Attempt an SBE recovery after an SBE error + * @param[in] uint64_t i_data Contains and plid (in the first 4 bytes) + * and a HUID (in the last 4 bytes) + * @platform FSP, OpenPOWER + **/ +void sbeAttemptRecovery(uint64_t i_data) +{ + errlHndl_t l_err = nullptr; + + do + { + // Create a useful structure to get to the data + // The data is expected to be a plid (in the first 4 bytes) + // followed by a HUID (in the last 4 bytes). + struct sbeErrorData_t + { + uint32_t plid; + uint32_t huid; + } PACKED ; + + sbeErrorData_t *l_sbeErrorDataReq = (sbeErrorData_t*)(&i_data); + TargetHandle_t l_target = + Target::getTargetFromHuid(l_sbeErrorDataReq->huid); + if (nullptr == l_target) + { + TRACFCOMP( g_trac_hwsv, "firmware_notify: No target assoicated " + "with HUID:0x%.8X", l_sbeErrorDataReq->huid); + /*@ + * @errortype ERRL_SEV_PREDICTIVE + * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RUNTIME::RC_SBE_RT_INVALID_HUID + * @userdata1 HUID of target + * @userdata2 HWSV error log id (plid) + * @devdesc SBE error recovery attempt failed + */ + l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_NOTIFY, + RC_SBE_RT_INVALID_HUID, + l_sbeErrorDataReq->huid, + l_sbeErrorDataReq->plid, + true); + break; + } + + // Make the call to SbeExtractDD to attempt SBE recovery + // Get the SBE Retry Handler + //SbeRetryHandler l_SBEobj = SbeRetryHandler(); + + // Need to set the Plid from SbeRetryHandler (still being debated) + // to l_sbeErrorDataReq->plid; + + // Retry the recovery of the SBE + //l_SBEobj.main_sbe_handler(l_target, false); + + // Get the recovery results + // NOTE: This method is not in place yet + //bool l_recoverySuccessful = l_SBEobj.isSbeRestarted(); + + // Set to TRUE for now + bool l_recoverySuccessful = true; + + if (nullptr == g_hostInterfaces || + nullptr == g_hostInterfaces->firmware_request) + { + TRACFCOMP( g_trac_hwsv, "firmware_notify: Hypervisor " + "firmware_request interface not linked"); + + /*@ + * @errortype ERRL_SEV_PREDICTIVE + * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RUNTIME::RC_FW_REQUEST_RT_NULL_PTR + * @userdata1 HUID of target + * @userdata2 HWSV error log id (plid) + * @devdesc SBE error recovery attempt failed + */ + l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_NOTIFY, + RC_FW_REQUEST_RT_NULL_PTR, + l_sbeErrorDataReq->huid, + l_sbeErrorDataReq->plid, + true); + + + break; + } + + // Create the firmware_request request structure to send data + hostInterfaces::hbrt_fw_msg l_req_fw_msg; + memset(&l_req_fw_msg, 0, sizeof(l_req_fw_msg)); + + // Set the data for the request + l_req_fw_msg.io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg.generic_msg.initialize(); + l_req_fw_msg.generic_msg.msgq = GFMM_MSG_SBE_ERROR; + l_req_fw_msg.generic_msg.__req = GFMM_REQUEST; + l_req_fw_msg.generic_msg.__onlyError = GFMM_NOT_ERROR_ONLY; + l_req_fw_msg.generic_msg.data = i_data; + + if (l_recoverySuccessful) + { + l_req_fw_msg.generic_msg.msgType= GFMM_MSG_SBE_RECOVERY_SUCCESS; + } + else + { + l_req_fw_msg.generic_msg.msgType = GFMM_MSG_SBE_RECOVERY_FAILED; + } + + // Create the firmware_request response structure to receive data + hostInterfaces::hbrt_fw_msg l_resp_fw_msg; + size_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg); + memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size); + + size_t rc = g_hostInterfaces->firmware_request(sizeof(l_req_fw_msg), + &l_req_fw_msg, + &l_resp_fw_msg_size, + &l_resp_fw_msg); + + // Error log id + uint32_t l_errPlid(0); + + sbeErrorData_t *l_sbeErrorDataResp = + (sbeErrorData_t*)&(l_resp_fw_msg.generic_msg.data); + + // Capture the error log ID if any + // The return code (rc) may return OK, but there still may be an issue + // with the HWSV code on the FSP. + if ((hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP + == l_resp_fw_msg.io_type) && + (0 != l_sbeErrorDataResp->plid) ) + { + l_errPlid = l_sbeErrorDataResp->plid; + } + + // Gather up the error data and create an error log out of it + if (rc || l_errPlid) + { + /*@ + * @errortype ERRL_SEV_PREDICTIVE + * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RUNTIME::RC_SBE_RT_RECOVERY_ERR + * @userdata1[0:31] Firmware Request return code + * @userdata1[32:63] HWSV error log id (plid) + * @userdata2[0:31] MBOX message type + * @userdata2[32:63] Message Tyepe + * @devdesc SBE error recovery attempt failed + */ + l_err = new ERRORLOG::ErrlEntry( + ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_NOTIFY, + RC_SBE_RT_RECOVERY_ERR, + TWO_UINT32_TO_UINT64(rc, l_errPlid), + TWO_UINT32_TO_UINT64( + l_resp_fw_msg.generic_msg.msgq, + l_resp_fw_msg.generic_msg.msgType), + true); + + l_err->addFFDC( RUNTIME_COMP_ID, + &l_resp_fw_msg, + l_resp_fw_msg_size, + 0, 0, false ); + + if (sizeof(l_req_fw_msg) > 0) + { + l_err->addFFDC( RUNTIME_COMP_ID, + &l_req_fw_msg, + sizeof(l_req_fw_msg), + 0, 0, false ); + } + + l_err->collectTrace( "SBE", 256); + + if (l_errPlid) + { + l_err->plid(l_errPlid); + } + + break; + } + } while(0); + + if (l_err) + { + //Commit the error if it exists + errlCommit(l_err, RUNTIME_COMP_ID); + } +} + +/** + * @brief Receive an async notification from firmware + * @param[in] i_len length of notification data + * @param[in] i_data notification data + * @platform FSP, OpenPOWER + */ +void firmware_notify( uint64_t i_len, void *i_data ) +{ + errlHndl_t l_err = nullptr; + + do + { + // make sure the length of the data is not less than the + // structure we are expecting to receive + if (i_len < sizeof(GenericFspMboxMessage_t)) + { + TRACFCOMP( g_trac_hwsv, + "firmware_notify: Received a non GenericFspMboxMessage " + "data stream" ); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RUNTIME::RC_FW_NOTIFY_RT_INVALID_MSG + * @userdata1 Unused + * @userdata2 Unused + * @devdesc Error with Firmware Notify request + */ + l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_NOTIFY, + RC_FW_NOTIFY_RT_INVALID_MSG, + 0, 0, true); + break; + } + + // Cast the data to the structure we wish to parse + GenericFspMboxMessage_t* genericMsg = + static_cast<GenericFspMboxMessage_t*>(i_data); + + // Do function based on message type (msgType) + switch(genericMsg->msgType) + { + case GFMM_MSG_SBE_ERROR: sbeAttemptRecovery(genericMsg->data); + break; + + default: + { + TRACFCOMP( g_trac_hwsv, "firmware_notify: Unknown " + "message type:0x%.8X, message queue id:0x%.8X ", + genericMsg->msgq, genericMsg->msgType); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_RT_FIRMWARE_NOTIFY + * @reasoncode RUNTIME::RC_FW_NOTIFY_RT_INVALID_MSG_TYPE + * @userdata1 Message Queue ID + * @userdata2 Message Type + * @devdesc Error with Firmware Notify request + */ + l_err = new ErrlEntry( ERRL_SEV_PREDICTIVE, + MOD_RT_FIRMWARE_NOTIFY, + RC_FW_NOTIFY_RT_INVALID_MSG_TYPE, + genericMsg->msgq, + genericMsg->msgType, + true); + } + break; + }; + + } while(0); + + if (l_err) + { + //Commit the error if it exists + errlCommit(l_err, RUNTIME_COMP_ID); + } +}; + +struct registerFwNotify +{ + registerFwNotify() + { + getRuntimeInterfaces()->firmware_notify = &firmware_notify; + } +}; + +registerFwNotify g_registerFwNotify; diff --git a/src/usr/vpd/runtime/rt_vpd.C b/src/usr/vpd/runtime/rt_vpd.C index d23fc969d..d85440e56 100644 --- a/src/usr/vpd/runtime/rt_vpd.C +++ b/src/usr/vpd/runtime/rt_vpd.C @@ -419,9 +419,12 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, } // Get an accurate size of memory actually needed to transport the data + size_t l_generic_msg_size = + sizeof(hostInterfaces::hbrt_fw_msg::generic_msg) + + i_numBytes - + sizeof(hostInterfaces::hbrt_fw_msg::generic_msg.data); size_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(hostInterfaces::hbrt_fw_msg::generic_message) + - i_numBytes; + l_generic_msg_size; //create the firmware_request structure to carry the vpd write msg data l_req_fw_msg = @@ -429,10 +432,14 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, memset(l_req_fw_msg, 0, l_req_fw_msg_size); // populate the firmware_request structure with given data - l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP; - l_req_fw_msg->generic_message.msgq = MBOX::FSP_VPD_MSGQ; - l_req_fw_msg->generic_message.msgType = i_type; - memcpy(&l_req_fw_msg->generic_message.data, i_data, i_numBytes); + l_req_fw_msg->io_type = hostInterfaces::HBRT_FW_MSG_HBRT_FSP_REQ; + l_req_fw_msg->generic_msg.initialize(); + l_req_fw_msg->generic_msg.dataSize = l_generic_msg_size; + l_req_fw_msg->generic_msg.msgq = MBOX::FSP_VPD_MSGQ; + l_req_fw_msg->generic_msg.msgType = i_type; + l_req_fw_msg->generic_msg.__req = GFMM_REQUEST; + l_req_fw_msg->generic_msg.__onlyError = GFMM_NOT_ERROR_ONLY; + memcpy(&l_req_fw_msg->generic_msg.data, i_data, i_numBytes); // set up the response struct, note that for messages to the FSP // the response size must match the request size @@ -447,7 +454,7 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, TRACFBIN( g_trac_vpd, INFO_MRK"Sending firmware_request", l_req_fw_msg, hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(hostInterfaces::hbrt_fw_msg::generic_message) ); + sizeof(hostInterfaces::hbrt_fw_msg::generic_msg) ); size_t rc = g_hostInterfaces->firmware_request(l_req_fw_msg_size, l_req_fw_msg, &l_resp_fw_msg_size, @@ -457,13 +464,15 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, // Capture the err log id if any // The return code (rc) may return OK, but there still may be an issue // with the HWSV code on the FSP. - if ((l_resp_fw_msg_size >= (hostInterfaces::HBRT_FW_MSG_BASE_SIZE + - sizeof(l_resp_fw_msg->generic_message_resp))) && - (hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP - == l_resp_fw_msg->io_type) && - (0 != l_resp_fw_msg->generic_message_resp.errPlid) ) + // Only checking for a PLID regardless of what the flag __onlyError is + // set to. I am not expecting any extra data and not sure what to do + // with it if I get it. + if ( (hostInterfaces::HBRT_FW_MSG_HBRT_FSP_RESP == + l_resp_fw_msg->io_type) && + (0 != l_resp_fw_msg->generic_msg.data >> 32) ) { - l_userData2 = l_resp_fw_msg->generic_message_resp.errPlid; + // extract the plid from the first 32 bits + l_userData2 = l_resp_fw_msg->generic_msg.data >> 32; } // gather up the error data and create an err log out of it @@ -471,10 +480,11 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, { TRACFCOMP(g_trac_vpd, ERR_MRK"firmware request: " - "firmware request for FSP VPD write message rc 0x%X, " - "target 0x%llX, VPD type %.8X, record %d, offset 0x%X", - rc, get_huid(i_target), i_type, i_record.rec_num, - i_record.offset ); + "firmware request for FSP VPD write message rc: 0x%X, " + "HUID:0x%llX, plid:%.8X, VPD type:%.8X, " + "record:%d, offset:0x%X, ", + rc, get_huid(i_target), l_userData2, + i_type, i_record.rec_num, i_record.offset ); /*@ * @errortype |