diff options
author | Roland Veloz <rveloz@us.ibm.com> | 2017-11-21 15:02:53 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-12-20 17:47:12 -0500 |
commit | 8e6bd68539af8394a3f96dab15464edc151794bb (patch) | |
tree | 03e3f07d0599bc0e60b54e4e3aa4d4c38b333f37 /src | |
parent | 5cd50322982059a6b71d5957e22f6f85da17404e (diff) | |
download | blackbird-hostboot-8e6bd68539af8394a3f96dab15464edc151794bb.tar.gz blackbird-hostboot-8e6bd68539af8394a3f96dab15464edc151794bb.zip |
Updated the GenericFspMboxMessage_t struct
The GenericFspMboxMessage_t struct has been expanded to provide
a lot more data than before. The highlights are that it now
carries the data size, an error only flag, a sequence number
and a magic number to identify the message. An initialize
method has been provided to set some of these to default
values. In addition the message types are consolidated into
one enum. All enums have a prefix of GFMM to avoid name
collisions. The sequence number is an auto incrementing
number so we can keep track if the messages are received out
of order.
Change-Id: Ic0f1c2546ff1ce14f163d1da55646ed089216d19
RTC: 182267
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/49960
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src')
-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 |