pdr: Implement terminus locator PDR for BMC
This commit creates the TL PDR for the BMC. The TID and MCTP EID for
BMC is static, 1 and 8 respectively. BMC PDRs are assigned the value
of 1 for PLDMTerminusHandle. Added the parser for terminus locator
PDR in pldmtool.
Tested:
/tmp/pldmtool platform GetPdr -d 0
nextRecordHandle: 2
responseCount: 19
recordHandle: 1
PDRHeaderVersion: 1
PDRType: 1
recordChangeNumber: 0
dataLength: 9
PLDMTerminusHandle: 1
validity: valid
TID: 1
containerID: 0
terminusLocatorType: MCTP_EID
terminusLocatorValueSize: 1
EID: 8
Change-Id: I596301d6c676b450ae1f2cef872966b4c40d8bae
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/libpldm/platform.h b/libpldm/platform.h
index ed175a9..91128b7 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -241,6 +241,22 @@
PLDM_EVENT_LOGGING_REJECTED = 0x05
};
+/** @brief PLDM Terminus Locator PDR validity
+ */
+enum pldm_terminus_locator_pdr_validity {
+ PLDM_TL_PDR_NOT_VALID,
+ PLDM_TL_PDR_VALID
+};
+
+/** @brief PLDM Terminus Locator type
+ */
+enum pldm_terminus_locator_type {
+ PLDM_TERMINUS_LOCATOR_TYPE_UID,
+ PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID,
+ PLDM_TERMINUS_LOCATOR_TYPE_SMBUS_RELATIVE,
+ PLDM_TERMINUS_LOCATOR_TYPE_SYS_SW
+};
+
/** @struct pldm_pdr_hdr
*
* Structure representing PLDM common PDR header
@@ -253,6 +269,30 @@
uint16_t length;
} __attribute__((packed));
+/** @struct pldm_terminus_locator_pdr
+ *
+ * Structure representing PLDM terminus locator PDR
+ */
+struct pldm_terminus_locator_pdr {
+ struct pldm_pdr_hdr hdr;
+ uint16_t terminus_handle;
+ uint8_t validity;
+ uint8_t tid;
+ uint16_t container_id;
+ uint8_t terminus_locator_type;
+ uint8_t terminus_locator_value_size;
+ uint8_t terminus_locator_value[1];
+} __attribute__((packed));
+
+/** @struct pldm_terminus_locator_type_mctp_eid
+ *
+ * Structure representing terminus locator value for
+ * terminus locator type MCTP_EID
+ */
+struct pldm_terminus_locator_type_mctp_eid {
+ uint8_t eid;
+} __attribute__((packed));
+
/** @struct pldm_pdr_entity_association
*
* Structure representing PLDM Entity Association PDR
diff --git a/libpldmresponder/pdr.hpp b/libpldmresponder/pdr.hpp
index c6f05a2..0745384 100644
--- a/libpldmresponder/pdr.hpp
+++ b/libpldmresponder/pdr.hpp
@@ -16,6 +16,10 @@
namespace pdr
{
+constexpr uint8_t BmcMctpEid = 8;
+constexpr uint8_t BmcPldmTerminusHandle = 1;
+constexpr uint8_t BmcTerminusId = 1;
+
/** @brief Build (if not built already) and retrieve PDR by the PDR types
*
* @param[in] dir - directory housing platform specific PDR JSON files
diff --git a/libpldmresponder/pdr_state_effecter.hpp b/libpldmresponder/pdr_state_effecter.hpp
index 1391def..173d328 100644
--- a/libpldmresponder/pdr_state_effecter.hpp
+++ b/libpldmresponder/pdr_state_effecter.hpp
@@ -2,7 +2,8 @@
#include "libpldm/platform.h"
-#include "libpldmresponder/pdr_utils.hpp"
+#include "pdr.hpp"
+#include "pdr_utils.hpp"
namespace pldm
{
@@ -62,7 +63,7 @@
pdr->hdr.record_change_num = 0;
pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
- pdr->terminus_handle = 0;
+ pdr->terminus_handle = pdr::BmcPldmTerminusHandle;
pdr->effecter_id = handler.getNextEffecterId();
pdr->entity_type = e.value("type", 0);
pdr->entity_instance = e.value("instance", 0);
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 211ff65..3a9266e 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -3,6 +3,7 @@
#include "common/utils.hpp"
#include "event_parser.hpp"
+#include "pdr.hpp"
#include "pdr_numeric_effecter.hpp"
#include "pdr_state_effecter.hpp"
#include "platform_numeric_effecter.hpp"
@@ -137,6 +138,7 @@
{
if (!pdrCreated)
{
+ generateTerminusLocatorPDR(pdrRepo);
generate(*dBusIntf, pdrJsonsDir, pdrRepo);
pdrCreated = true;
}
@@ -556,6 +558,33 @@
return ccOnlyResponse(request, rc);
}
+void Handler::generateTerminusLocatorPDR(Repo& repo)
+{
+ std::vector<uint8_t> pdrBuffer(sizeof(pldm_terminus_locator_pdr));
+
+ auto pdr = reinterpret_cast<pldm_terminus_locator_pdr*>(pdrBuffer.data());
+
+ pdr->hdr.record_handle = 0;
+ pdr->hdr.version = 1;
+ pdr->hdr.type = PLDM_TERMINUS_LOCATOR_PDR;
+ pdr->hdr.record_change_num = 0;
+ pdr->hdr.length = sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr);
+ pdr->terminus_handle = BmcPldmTerminusHandle;
+ pdr->validity = PLDM_TL_PDR_VALID;
+ pdr->tid = BmcTerminusId;
+ pdr->container_id = 0x0;
+ pdr->terminus_locator_type = PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID;
+ pdr->terminus_locator_value_size =
+ sizeof(pldm_terminus_locator_type_mctp_eid);
+ auto locatorValue = reinterpret_cast<pldm_terminus_locator_type_mctp_eid*>(
+ pdr->terminus_locator_value);
+ locatorValue->eid = BmcMctpEid;
+
+ PdrEntry pdrEntry{};
+ pdrEntry.data = pdrBuffer.data();
+ pdrEntry.size = pdrBuffer.size();
+ repo.addRecord(pdrEntry);
+}
} // namespace platform
} // namespace responder
} // namespace pldm
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index 1ff6bc4..5cf2534 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -68,6 +68,7 @@
{
if (!buildPDRLazily)
{
+ generateTerminusLocatorPDR(pdrRepo);
generate(*dBusIntf, pdrJsonsDir, pdrRepo);
pdrCreated = true;
}
@@ -402,6 +403,12 @@
return rc;
}
+ /** @brief Build BMC Terminus Locator PDR
+ *
+ * @param[in] repo - instance of concrete implementation of Repo
+ */
+ void generateTerminusLocatorPDR(Repo& repo);
+
private:
pdr_utils::Repo pdrRepo;
uint16_t nextEffecterId{};
diff --git a/pldmtool/pldm_platform_cmd.cpp b/pldmtool/pldm_platform_cmd.cpp
index 0e3cc58..d54ec20 100644
--- a/pldmtool/pldm_platform_cmd.cpp
+++ b/pldmtool/pldm_platform_cmd.cpp
@@ -553,6 +553,34 @@
}
}
+ void printTerminusLocatorPDR(const uint8_t* data)
+ {
+ const std::array<std::string_view, 4> terminusLocatorType = {
+ "UID", "MCTP_EID", "SMBusRelative", "systemSoftware"};
+
+ auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(data);
+
+ std::cout << "PLDMTerminusHandle: " << pdr->terminus_handle
+ << std::endl;
+ std::cout << "validity: " << (pdr->validity ? "valid" : "notValid")
+ << std::endl;
+ std::cout << "TID: " << unsigned(pdr->tid) << std::endl;
+ std::cout << "containerID: " << pdr->container_id << std::endl;
+ std::cout << "terminusLocatorType: "
+ << terminusLocatorType[pdr->terminus_locator_type]
+ << std::endl;
+ std::cout << "terminusLocatorValueSize: "
+ << unsigned(pdr->terminus_locator_value_size) << std::endl;
+
+ if (pdr->terminus_locator_type == PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID)
+ {
+ auto locatorValue =
+ reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
+ pdr->terminus_locator_value);
+ std::cout << "EID: " << unsigned(locatorValue->eid) << std::endl;
+ }
+ }
+
void printPDRMsg(const uint32_t nextRecordHndl, const uint16_t respCnt,
uint8_t* data)
{
@@ -568,6 +596,9 @@
printCommonPDRHeader(pdr);
switch (pdr->type)
{
+ case PLDM_TERMINUS_LOCATOR_PDR:
+ printTerminusLocatorPDR(data);
+ break;
case PLDM_STATE_SENSOR_PDR:
printStateSensorPDR(data);
break;
diff --git a/test/libpldmresponder_pdr_effecter_test.cpp b/test/libpldmresponder_pdr_effecter_test.cpp
index a2a7288..390db58 100644
--- a/test/libpldmresponder_pdr_effecter_test.cpp
+++ b/test/libpldmresponder_pdr_effecter_test.cpp
@@ -37,18 +37,18 @@
// Check first PDR
pdr_utils::PdrEntry e;
- auto record1 = pdr::getRecordByHandle(outRepo, 1, e);
- ASSERT_NE(record1, nullptr);
+ auto record2 = pdr::getRecordByHandle(outRepo, 2, e);
+ ASSERT_NE(record2, nullptr);
pldm_state_effecter_pdr* pdr =
reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
- ASSERT_EQ(pdr->hdr.record_handle, 1);
+ ASSERT_EQ(pdr->hdr.record_handle, 2);
ASSERT_EQ(pdr->hdr.version, 1);
ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
ASSERT_EQ(pdr->hdr.record_change_num, 0);
ASSERT_EQ(pdr->hdr.length, 23);
- ASSERT_EQ(pdr->terminus_handle, 0);
+ ASSERT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
ASSERT_EQ(pdr->effecter_id, 1);
ASSERT_EQ(pdr->entity_type, 33);
ASSERT_EQ(pdr->entity_instance, 0);
@@ -70,17 +70,17 @@
ASSERT_EQ(dbusMappings1[0].objectPath, "/foo/bar");
// Check second PDR
- auto record2 = pdr::getRecordByHandle(outRepo, 2, e);
- ASSERT_NE(record2, nullptr);
+ auto record3 = pdr::getRecordByHandle(outRepo, 3, e);
+ ASSERT_NE(record3, nullptr);
pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
- ASSERT_EQ(pdr->hdr.record_handle, 2);
+ ASSERT_EQ(pdr->hdr.record_handle, 3);
ASSERT_EQ(pdr->hdr.version, 1);
ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
ASSERT_EQ(pdr->hdr.record_change_num, 0);
ASSERT_EQ(pdr->hdr.length, 24);
- ASSERT_EQ(pdr->terminus_handle, 0);
+ ASSERT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
ASSERT_EQ(pdr->effecter_id, 2);
ASSERT_EQ(pdr->entity_type, 100);
ASSERT_EQ(pdr->entity_instance, 0);
@@ -136,12 +136,12 @@
// Check first PDR
pdr_utils::PdrEntry e;
- auto record = pdr::getRecordByHandle(outRepo, 3, e);
+ auto record = pdr::getRecordByHandle(outRepo, 4, e);
ASSERT_NE(record, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
- EXPECT_EQ(pdr->hdr.record_handle, 3);
+ EXPECT_EQ(pdr->hdr.record_handle, 4);
EXPECT_EQ(pdr->hdr.version, 1);
EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
EXPECT_EQ(pdr->hdr.record_change_num, 0);
@@ -207,4 +207,4 @@
containerId, stateSetId, true);
ASSERT_EQ(effecterId, PLDM_INVALID_EFFECTER_ID);
pldm_pdr_destroy(inPDRRepo);
-}
+}
\ No newline at end of file
diff --git a/test/libpldmresponder_platform_test.cpp b/test/libpldmresponder_platform_test.cpp
index 4183a0a..424aa08 100644
--- a/test/libpldmresponder_platform_test.cpp
+++ b/test/libpldmresponder_platform_test.cpp
@@ -228,7 +228,7 @@
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
pdr_utils::PdrEntry e;
- auto record1 = pdr::getRecordByHandle(outRepo, 1, e);
+ auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
ASSERT_NE(record1, nullptr);
pldm_state_effecter_pdr* pdr =
reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
@@ -268,7 +268,7 @@
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
pdr_utils::PdrEntry e;
- auto record1 = pdr::getRecordByHandle(outRepo, 1, e);
+ auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
ASSERT_NE(record1, nullptr);
pldm_state_effecter_pdr* pdr =
reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
@@ -313,8 +313,8 @@
getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
pdr_utils::PdrEntry e;
- auto record3 = pdr::getRecordByHandle(numericEffecterPDRs, 3, e);
- ASSERT_NE(record3, nullptr);
+ auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
+ ASSERT_NE(record4, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
@@ -355,8 +355,8 @@
getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
pdr_utils::PdrEntry e;
- auto record3 = pdr::getRecordByHandle(numericEffecterPDRs, 3, e);
- ASSERT_NE(record3, nullptr);
+ auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
+ ASSERT_NE(record4, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
@@ -520,3 +520,43 @@
ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
}
}
+
+TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
+{
+ auto inPDRRepo = pldm_pdr_init();
+ auto outPDRRepo = pldm_pdr_init();
+ Repo outRepo(outPDRRepo);
+ MockdBusHandler mockedUtils;
+ Handler handler(&mockedUtils, "", "", inPDRRepo, nullptr, nullptr);
+ Repo inRepo(inPDRRepo);
+ getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
+
+ // 1 BMC terminus locator PDR in the PDR repository
+ ASSERT_EQ(outRepo.getRecordCount(), 1);
+
+ pdr_utils::PdrEntry entry;
+ auto record = pdr::getRecordByHandle(outRepo, 1, entry);
+ ASSERT_NE(record, nullptr);
+
+ auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
+ EXPECT_EQ(pdr->hdr.record_handle, 1);
+ EXPECT_EQ(pdr->hdr.version, 1);
+ EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
+ EXPECT_EQ(pdr->hdr.record_change_num, 0);
+ EXPECT_EQ(pdr->hdr.length,
+ sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
+ EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
+ EXPECT_EQ(pdr->tid, BmcTerminusId);
+ EXPECT_EQ(pdr->container_id, 0);
+ EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
+ EXPECT_EQ(pdr->terminus_locator_value_size,
+ sizeof(pldm_terminus_locator_type_mctp_eid));
+ auto locatorValue =
+ reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
+ pdr->terminus_locator_value);
+ EXPECT_EQ(locatorValue->eid, BmcMctpEid);
+
+ pldm_pdr_destroy(inPDRRepo);
+ pldm_pdr_destroy(outPDRRepo);
+}