libpldm: add APIs for FRU record set PDR ops
Add APIs for:
- adding FRU record set PDRs to a PDR repository
- finding FRU record set PDRs in a PDR repository based on the FRU
record set identifier.
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: I2b233af1325849cfc5d7de6a9a69af6771b222b2
diff --git a/libpldm/pdr.c b/libpldm/pdr.c
index 692a035..5e792a5 100644
--- a/libpldm/pdr.c
+++ b/libpldm/pdr.c
@@ -236,3 +236,68 @@
return record->record_handle;
}
+
+uint32_t pldm_pdr_add_fru_record_set(pldm_pdr *repo, uint16_t terminus_handle,
+ uint16_t fru_rsi, uint16_t entity_type,
+ uint16_t entity_instance_num,
+ uint16_t container_id)
+{
+ uint32_t size = sizeof(struct pldm_pdr_hdr) +
+ sizeof(struct pldm_pdr_fru_record_set);
+ uint8_t data[size];
+
+ struct pldm_pdr_hdr *hdr = (struct pldm_pdr_hdr *)&data;
+ hdr->version = 1;
+ hdr->record_handle = 0;
+ hdr->type = PLDM_PDR_FRU_RECORD_SET;
+ hdr->record_change_num = 0;
+ hdr->length = sizeof(struct pldm_pdr_fru_record_set);
+ struct pldm_pdr_fru_record_set *fru =
+ (struct pldm_pdr_fru_record_set *)((uint8_t *)hdr +
+ sizeof(struct pldm_pdr_hdr));
+ fru->terminus_handle = terminus_handle;
+ fru->fru_rsi = fru_rsi;
+ fru->entity_type = entity_type;
+ fru->entity_instance_num = entity_instance_num;
+ fru->container_id = container_id;
+
+ return pldm_pdr_add(repo, data, size, 0);
+}
+
+const pldm_pdr_record *pldm_pdr_fru_record_set_find_by_rsi(
+ const pldm_pdr *repo, uint16_t fru_rsi, uint16_t *terminus_handle,
+ uint16_t *entity_type, uint16_t *entity_instance_num,
+ uint16_t *container_id)
+{
+ assert(terminus_handle != NULL);
+ assert(entity_type != NULL);
+ assert(entity_instance_num != NULL);
+ assert(container_id != NULL);
+
+ uint8_t *data = NULL;
+ uint32_t size = 0;
+ const pldm_pdr_record *curr_record = pldm_pdr_find_record_by_type(
+ repo, PLDM_PDR_FRU_RECORD_SET, NULL, &data, &size);
+ while (curr_record != NULL) {
+ struct pldm_pdr_fru_record_set *fru =
+ (struct pldm_pdr_fru_record_set
+ *)(data + sizeof(struct pldm_pdr_hdr));
+ if (fru->fru_rsi == fru_rsi) {
+ *terminus_handle = fru->terminus_handle;
+ *entity_type = fru->entity_type;
+ *entity_instance_num = fru->entity_instance_num;
+ *container_id = fru->container_id;
+ return curr_record;
+ }
+ data = NULL;
+ curr_record = pldm_pdr_find_record_by_type(
+ repo, PLDM_PDR_FRU_RECORD_SET, curr_record, &data, &size);
+ }
+
+ *terminus_handle = 0;
+ *entity_type = 0;
+ *entity_instance_num = 0;
+ *container_id = 0;
+
+ return NULL;
+}
diff --git a/libpldm/pdr.h b/libpldm/pdr.h
index eb4a3bb..7fe0f23 100644
--- a/libpldm/pdr.h
+++ b/libpldm/pdr.h
@@ -133,6 +133,47 @@
const pldm_pdr_record *curr_record, uint8_t **data,
uint32_t *size);
+/* ======================= */
+/* FRU Record Set PDR APIs */
+/* ======================= */
+
+/** @brief Add a FRU record set PDR record to a PDR repository
+ *
+ * @param[in/out] repo - opaque pointer acting as a PDR repo handle
+ * @param[in] terminus_handle - PLDM terminus handle of terminus owning the PDR
+ * record
+ * @param[in] fru_rsi - FRU record set identifier
+ * @param[in] entity_type - entity type of FRU
+ * @param[in] entity_instance_num - entity instance number of FRU
+ * @param[in] container_id - container id of FRU
+ *
+ * @return uint32_t - record handle assigned to PDR record
+ */
+uint32_t pldm_pdr_add_fru_record_set(pldm_pdr *repo, uint16_t terminus_handle,
+ uint16_t fru_rsi, uint16_t entity_type,
+ uint16_t entity_instance_num,
+ uint16_t container_id);
+
+/** @brief Find a FRU record set PDR by FRU record set identifier
+ *
+ * @param[in] repo - opaque pointer acting as a PDR repo handle
+ * @param[in] fru_rsi - FRU record set identifier
+ * @param[in] terminus_handle - *terminus_handle will be FRU terminus handle of
+ * found PDR, or 0 if not found
+ * @param[in] entity_type - *entity_type will be FRU entity type of found PDR,
+ * or 0 if not found
+ * @param[in] entity_instance_num - *entity_instance_num will be FRU entity
+ * instance number of found PDR, or 0 if not found
+ * @param[in] container_id - *cintainer_id will be FRU container id of found
+ * PDR, or 0 if not found
+ *
+ * @return uint32_t - record handle assigned to PDR record
+ */
+const pldm_pdr_record *pldm_pdr_fru_record_set_find_by_rsi(
+ const pldm_pdr *repo, uint16_t fru_rsi, uint16_t *terminus_handle,
+ uint16_t *entity_type, uint16_t *entity_instance_num,
+ uint16_t *container_id);
+
#ifdef __cplusplus
}
#endif
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 5341f6f..0cce1b4 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -45,6 +45,7 @@
*/
enum pldm_pdr_types {
PLDM_STATE_EFFECTER_PDR = 11,
+ PLDM_PDR_FRU_RECORD_SET = 20,
};
/** @brief PLDM effecter initialization schemes
@@ -77,6 +78,18 @@
uint16_t length;
} __attribute__((packed));
+/** @struct pldm_pdr_fru_record_set
+ *
+ * Structure representing PLDM FRU record set PDR
+ */
+struct pldm_pdr_fru_record_set {
+ uint16_t terminus_handle;
+ uint16_t fru_rsi;
+ uint16_t entity_type;
+ uint16_t entity_instance_num;
+ uint16_t container_id;
+} __attribute__((packed));
+
/** @struct pldm_state_effecter_pdr
*
* Structure representing PLDM state effecter PDR
diff --git a/test/libpldm_pdr_test.cpp b/test/libpldm_pdr_test.cpp
index fbae94a..c1caf20 100644
--- a/test/libpldm_pdr_test.cpp
+++ b/test/libpldm_pdr_test.cpp
@@ -209,3 +209,111 @@
pldm_pdr_destroy(repo);
}
+
+TEST(PDRUpdate, testAddFruRecordSet)
+{
+ auto repo = pldm_pdr_init();
+
+ auto handle = pldm_pdr_add_fru_record_set(repo, 1, 10, 1, 0, 100);
+ EXPECT_EQ(handle, 1);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo),
+ sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ uint32_t size{};
+ uint32_t nextRecHdl{};
+ uint8_t* outData = nullptr;
+ auto hdl = pldm_pdr_find_record(repo, 0, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(nextRecHdl, 0);
+ pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(outData);
+ EXPECT_EQ(hdr->version, 1);
+ EXPECT_EQ(hdr->type, PLDM_PDR_FRU_RECORD_SET);
+ EXPECT_EQ(hdr->length, sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(hdr->record_handle, 1);
+ pldm_pdr_fru_record_set* fru = reinterpret_cast<pldm_pdr_fru_record_set*>(
+ outData + sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(fru->terminus_handle, 1);
+ EXPECT_EQ(fru->fru_rsi, 10);
+ EXPECT_EQ(fru->entity_type, 1);
+ EXPECT_EQ(fru->entity_instance_num, 0);
+ EXPECT_EQ(fru->container_id, 100);
+ outData = nullptr;
+
+ handle = pldm_pdr_add_fru_record_set(repo, 2, 11, 2, 1, 101);
+ EXPECT_EQ(handle, 2);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo),
+ 2 * (sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set)));
+ hdl = pldm_pdr_find_record(repo, 2, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(nextRecHdl, 0);
+ hdr = reinterpret_cast<pldm_pdr_hdr*>(outData);
+ EXPECT_EQ(hdr->version, 1);
+ EXPECT_EQ(hdr->type, PLDM_PDR_FRU_RECORD_SET);
+ EXPECT_EQ(hdr->length, sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(hdr->record_handle, 2);
+ fru = reinterpret_cast<pldm_pdr_fru_record_set*>(outData +
+ sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(fru->terminus_handle, 2);
+ EXPECT_EQ(fru->fru_rsi, 11);
+ EXPECT_EQ(fru->entity_type, 2);
+ EXPECT_EQ(fru->entity_instance_num, 1);
+ EXPECT_EQ(fru->container_id, 101);
+ outData = nullptr;
+
+ hdl = pldm_pdr_find_record(repo, 1, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(nextRecHdl, 2);
+ hdr = reinterpret_cast<pldm_pdr_hdr*>(outData);
+ EXPECT_EQ(hdr->version, 1);
+ EXPECT_EQ(hdr->type, PLDM_PDR_FRU_RECORD_SET);
+ EXPECT_EQ(hdr->length, sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(hdr->record_handle, 1);
+ fru = reinterpret_cast<pldm_pdr_fru_record_set*>(outData +
+ sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(fru->terminus_handle, 1);
+ EXPECT_EQ(fru->fru_rsi, 10);
+ EXPECT_EQ(fru->entity_type, 1);
+ EXPECT_EQ(fru->entity_instance_num, 0);
+ EXPECT_EQ(fru->container_id, 100);
+ outData = nullptr;
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRUpdate, tesFindtFruRecordSet)
+{
+ auto repo = pldm_pdr_init();
+
+ uint16_t terminusHdl{};
+ uint16_t entityType{};
+ uint16_t entityInstanceNum{};
+ uint16_t containerId{};
+ auto first = pldm_pdr_add_fru_record_set(repo, 1, 1, 1, 0, 100);
+ auto second = pldm_pdr_add_fru_record_set(repo, 1, 2, 1, 1, 100);
+ auto third = pldm_pdr_add_fru_record_set(repo, 1, 3, 1, 2, 100);
+ EXPECT_EQ(first, pldm_pdr_get_record_handle(
+ repo, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 1, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId)));
+ EXPECT_EQ(second, pldm_pdr_get_record_handle(
+ repo, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 2, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId)));
+ EXPECT_EQ(third, pldm_pdr_get_record_handle(
+ repo, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 3, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId)));
+ EXPECT_EQ(terminusHdl, 1);
+ EXPECT_EQ(entityType, 1);
+ EXPECT_EQ(entityInstanceNum, 2);
+ EXPECT_EQ(containerId, 100);
+ EXPECT_EQ(nullptr, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 4, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId));
+
+ pldm_pdr_destroy(repo);
+}