platform-mc: Support GetPLDMVersion
`GetPLDMCommands` in DSP0240 v1.1.0 requires the PLDM supported type
version. In the current implementation, when detecting new MCTP
endpoint, `pldmd` always send `0xff 0xff 0xff 0xff` version to
`GetPLDMCommand` in discovery steps with the assumption that the
terminus will response for the request with any version of PLDM type.
Some termini don't accept `0xff 0xff 0xff 0xff` as input
version to `GetPLDMCommands` command because value `0xff` only has
meaning `A value of 0xFF in the "update" field indicates that the field
to be ignored.` in the `Section 12.6.1 Version field encoding` in `MCTP
Base spec` DSP0236 v1.3.1 but not in `PLDM base spec` DSP0240 v1.1.0
where `GetPLDMCommand` is detailed.
Support sending `GetPLDMVersion` from the supported PLDM types of one
terminus in the `discovery step` to get the PLDM version. And use that
version as input for `GetPLDMCommands` of that PLDM types to get
the supported PLDM commands.
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Change-Id: Ia33c6722603801431e411eaf0647b74d8a1639d8
diff --git a/platform-mc/terminus.hpp b/platform-mc/terminus.hpp
index 1986da0..e818d32 100644
--- a/platform-mc/terminus.hpp
+++ b/platform-mc/terminus.hpp
@@ -111,6 +111,24 @@
return true;
}
+ /** @brief Set the PLDM supported type version for terminus
+ *
+ * @param[in] type - PLDM supported types
+ * @param[in] version - PLDM supported type version
+ * @return success state - True if success, otherwise False
+ */
+ inline bool setSupportedTypeVersions(const uint8_t type,
+ const ver32_t version)
+ {
+ if (type > PLDM_MAX_TYPES || type >= supportedTypeVersions.size())
+ {
+ return false;
+ }
+ supportedTypeVersions[type] = version;
+
+ return true;
+ }
+
/** @brief Parse the PDRs stored in the member variable, pdrs.
*/
void parseTerminusPDRs();
@@ -267,6 +285,9 @@
*/
std::vector<uint8_t> supportedCmds;
+ /* @brief The PLDM supported type version */
+ std::map<uint8_t, ver32_t> supportedTypeVersions;
+
/* @brief Sensor Auxiliary Name list */
std::vector<std::shared_ptr<SensorAuxiliaryNames>>
sensorAuxiliaryNamesTbl{};
diff --git a/platform-mc/terminus_manager.cpp b/platform-mc/terminus_manager.cpp
index 10adefd..7565ee2 100644
--- a/platform-mc/terminus_manager.cpp
+++ b/platform-mc/terminus_manager.cpp
@@ -352,8 +352,18 @@
type++;
continue;
}
+
+ ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
+ auto rc = co_await getPLDMVersion(tid, type, &version);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to Get PLDM Version for terminus {TID}, PLDM Type {TYPE}, error {ERROR}",
+ "TID", tid, "TYPE", type, "ERROR", rc);
+ }
+ termini[tid]->setSupportedTypeVersions(type, version);
std::vector<bitfield8_t> cmds(PLDM_MAX_CMDS_PER_TYPE / 8);
- auto rc = co_await getPLDMCommands(tid, type, cmds.data());
+ rc = co_await getPLDMCommands(tid, type, version, cmds.data());
if (rc)
{
lg2::error(
@@ -538,12 +548,11 @@
co_return completionCode;
}
-exec::task<int> TerminusManager::getPLDMCommands(pldm_tid_t tid, uint8_t type,
- bitfield8_t* supportedCmds)
+exec::task<int> TerminusManager::getPLDMCommands(
+ pldm_tid_t tid, uint8_t type, ver32_t version, bitfield8_t* supportedCmds)
{
Request request(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES);
auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
- ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
auto rc = encode_get_commands_req(0, type, version, requestMsg);
if (rc)
@@ -627,5 +636,58 @@
co_return rc;
}
+exec::task<int> TerminusManager::getPLDMVersion(pldm_tid_t tid, uint8_t type,
+ ver32_t* version)
+{
+ Request request(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES);
+ auto requestMsg = new (request.data()) pldm_msg;
+
+ auto rc =
+ encode_get_version_req(0, 0, PLDM_GET_FIRSTPART, type, requestMsg);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to encode request getPLDMVersion for terminus ID {TID}, error {RC} ",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ const pldm_msg* responseMsg = nullptr;
+ size_t responseLen = 0;
+
+ rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to send getPLDMVersion message for terminus {TID}, error {RC}",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ /* Process response */
+ uint8_t completionCode = 0;
+ uint8_t transferFlag = 0;
+ uint32_t transferHandle = 0;
+ rc = decode_get_version_resp(responseMsg, responseLen, &completionCode,
+ &transferHandle, &transferFlag, version);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to decode response getPLDMVersion for terminus ID {TID}, error {RC} ",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ if (completionCode != PLDM_SUCCESS)
+ {
+ lg2::error(
+ "Error : getPLDMVersion for terminus ID {TID}, complete code {CC}.",
+ "TID", tid, "CC", completionCode);
+ co_return completionCode;
+ }
+
+ co_return completionCode;
+}
+
} // namespace platform_mc
} // namespace pldm
diff --git a/platform-mc/terminus_manager.hpp b/platform-mc/terminus_manager.hpp
index 2103fc5..8b7cd15 100644
--- a/platform-mc/terminus_manager.hpp
+++ b/platform-mc/terminus_manager.hpp
@@ -201,16 +201,29 @@
*/
exec::task<int> getPLDMTypes(pldm_tid_t tid, uint64_t& supportedTypes);
+ /** @brief Send getPLDMVersion command to destination TID and then return
+ * the version of the PLDM supported type.
+ *
+ * @param[in] tid - Destination TID
+ * @param[in] type - PLDM Type
+ * @param[out] version - PLDM Type version
+ * @return coroutine return_value - PLDM completion code
+ */
+ exec::task<int> getPLDMVersion(pldm_tid_t tid, uint8_t type,
+ ver32_t* version);
+
/** @brief Send getPLDMCommands command to destination TID and then return
* the value of supportedCommands in reference parameter.
*
* @param[in] tid - Destination TID
* @param[in] type - PLDM Type
+ * @param[in] version - PLDM Type version
* @param[in] supportedCmds - Supported commands returned from terminus
* for specific type
* @return coroutine return_value - PLDM completion code
*/
exec::task<int> getPLDMCommands(pldm_tid_t tid, uint8_t type,
+ ver32_t version,
bitfield8_t* supportedCmds);
/** @brief Reference to a Handler object that manages the request/response
diff --git a/platform-mc/test/terminus_manager_test.cpp b/platform-mc/test/terminus_manager_test.cpp
index 6c425f2..7fa8506 100644
--- a/platform-mc/test/terminus_manager_test.cpp
+++ b/platform-mc/test/terminus_manager_test.cpp
@@ -302,6 +302,9 @@
const size_t setTidRespLen = PLDM_SET_TID_RESP_BYTES;
const size_t getPldmTypesRespLen = PLDM_GET_TYPES_RESP_BYTES;
const size_t getPldmCommandRespLen = PLDM_GET_COMMANDS_RESP_BYTES;
+ /* PLDM_GET_VERSION_RESP_BYTES does not include 4 bytes check sum */
+ const size_t getPldmVersionRespLen =
+ PLDM_GET_VERSION_RESP_BYTES + sizeof(uint32_t);
// 0.discover a mctp list
auto rc = mockTerminusManager.clearQueuedResponses();
@@ -329,6 +332,17 @@
sizeof(getPldmTypesResp0));
EXPECT_EQ(rc, PLDM_SUCCESS);
+ /* Response GetPLDMVersion BASE, CC=0 */
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
+ getPldmVersionBaseResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0xf0, 0xf1,
+ 0xf1, 0xba, 0xbe, 0x9d, 0x53};
+
+ rc = mockTerminusManager.enqueueResponse(
+ (pldm_msg*)getPldmVersionBaseResp0.data(),
+ sizeof(getPldmVersionBaseResp0));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
/* Response GetPLDMCommand BASE, CC=0,
* SetTID/GetTID/GetPLDMTypes/GetPLDMCommands */
byte0 = (1 << (PLDM_SET_TID % 8)) + (1 << (PLDM_GET_TID % 8)) +
@@ -345,6 +359,16 @@
sizeof(getPldmCommandBaseResp0));
EXPECT_EQ(rc, PLDM_SUCCESS);
+ /* Response GetPLDMVersion PLATFORM, CC=0 */
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
+ getPldmVersionPlatformResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0xf1, 0xf2,
+ 0xf1, 0x4e, 0x87, 0x72, 0x79};
+
+ rc = mockTerminusManager.enqueueResponse(
+ (pldm_msg*)getPldmVersionPlatformResp0.data(),
+ sizeof(getPldmVersionPlatformResp0));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
/* Response GetPLDMCommand PLATFORM, CC=0,
* SetEventReceiver/PlatformEventMessage/GetSensorReading/SetNumericEffecterValue/GetNumericEffecterValue/GetPDR
*/
@@ -383,6 +407,16 @@
sizeof(getPldmCommandPlatResp0));
EXPECT_EQ(rc, PLDM_SUCCESS);
+ /* Response GetPLDMVersion BIOS, CC=0 */
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
+ getPldmVersionBiosResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0xf0, 0xf0,
+ 0xf1, 0xfb, 0x8f, 0x86, 0x4a};
+
+ rc = mockTerminusManager.enqueueResponse(
+ (pldm_msg*)getPldmVersionBiosResp0.data(),
+ sizeof(getPldmVersionBiosResp0));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
/* Response GetPLDMCommand BIOS, CC=0, GetDateTime/SetDateTime */
/* byte0 command from 1 to 7 */
byte0 = (0 << (PLDM_GET_BIOS_TABLE % 8)) +
@@ -402,6 +436,16 @@
sizeof(getPldmCommandBiosResp0));
EXPECT_EQ(rc, PLDM_SUCCESS);
+ /* Response GetPLDMVersion FRU, CC=0 */
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPldmVersionRespLen>
+ getPldmVersionFruResp0{0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0xf1, 0xf0,
+ 0xf1, 0xcc, 0xe5, 0x44, 0x4b};
+
+ rc = mockTerminusManager.enqueueResponse(
+ (pldm_msg*)getPldmVersionFruResp0.data(),
+ sizeof(getPldmVersionFruResp0));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
/* Response GetPLDMCommand FRU, CC=0,
* GetFRURecordTableMetadata/GetFRURecordTable */
/* byte0 command from 1 to 7 */