fru: Add an API to delete the FRU record from the FRUTable
This method can be used to remove the FRU record entry from
the FRU record set Table when a FRU is removed during the
Concurrent Maintenance Operation of the FRU. The Concurrent
Maintenance Operation is the ability to replace, remove, or
update a FRU while the system remains operational, without
requiring a full system shutdown or reboot.
Tested:
Removed a Fan FRU from the system - the FRU record is deleted
and verified that the table is updated.
pldmd[940]: Removing Individual FRU [ /xyz/openbmc_project/inventory
/system/chassis/motherboard/fan0 ] with entityid [ 93, 1, 3 ]
pldmd[940]: record is deleted: numRecs before deletion is 207
pldmd[940]: record is deleted: numRecs after deletion is 206
pldmd[940]: Table updated
Change-Id: I3ae9f87fe1afe81c3a3925c24583a622791c781a
Signed-off-by: Pavithra Barithaya <pavithrabarithaya07@gmail.com>
diff --git a/libpldmresponder/fru.cpp b/libpldmresponder/fru.cpp
index e3b89d0..ff6643a 100644
--- a/libpldmresponder/fru.cpp
+++ b/libpldmresponder/fru.cpp
@@ -343,6 +343,70 @@
}
}
+void FruImpl::deleteFRURecord(uint16_t rsi)
+{
+ std::vector<uint8_t> updatedFruTbl;
+ size_t pos = 0;
+
+ while (pos < table.size())
+ {
+ // Ensure enough space for the record header
+ if ((table.size() - pos) < sizeof(struct pldm_fru_record_data_format))
+ {
+ // Log or handle corrupt/truncated record
+ error("Error: Incomplete FRU record header");
+ return;
+ }
+
+ auto recordSetSrc =
+ reinterpret_cast<const struct pldm_fru_record_data_format*>(
+ &table[pos]);
+
+ size_t recordLen = sizeof(struct pldm_fru_record_data_format) -
+ sizeof(struct pldm_fru_record_tlv);
+
+ const struct pldm_fru_record_tlv* tlv = recordSetSrc->tlvs;
+
+ for (uint8_t i = 0; i < recordSetSrc->num_fru_fields; ++i)
+ {
+ if ((table.size() - pos) < (recordLen + sizeof(*tlv)))
+ {
+ error("Error: Incomplete TLV header");
+ return;
+ }
+
+ size_t len = sizeof(*tlv) - 1 + tlv->length;
+
+ if ((table.size() - pos) < (recordLen + len))
+ {
+ error("Error: Incomplete TLV data");
+ return;
+ }
+
+ recordLen += len;
+
+ // Advance to next tlv
+ tlv = reinterpret_cast<const struct pldm_fru_record_tlv*>(
+ reinterpret_cast<const uint8_t*>(tlv) + len);
+ }
+
+ if ((le16toh(recordSetSrc->record_set_id) != rsi && rsi != 0))
+ {
+ std::copy(table.begin() + pos, table.begin() + pos + recordLen,
+ std::back_inserter(updatedFruTbl));
+ }
+ else
+ {
+ // Deleted record
+ numRecs--;
+ }
+
+ pos += recordLen;
+ }
+ // Replace the old table with the updated one
+ table = std::move(updatedFruTbl);
+}
+
std::vector<uint8_t> FruImpl::tableResize()
{
std::vector<uint8_t> tempTable;
diff --git a/libpldmresponder/fru.hpp b/libpldmresponder/fru.hpp
index d4e0ff4..6586fad 100644
--- a/libpldmresponder/fru.hpp
+++ b/libpldmresponder/fru.hpp
@@ -249,6 +249,13 @@
const fru_parser::FruRecordInfos& recordInfos,
const pldm_entity& entity);
+ /** @brief Deletes a FRU record from record set table.
+ * @param[in] rsi - the FRU Record Set Identifier
+ *
+ * @return
+ */
+ void deleteFRURecord(uint16_t rsi);
+
/** @brief Associate sensor/effecter to FRU entity
*/
dbus::AssociatedEntityMap associatedEntityMap;