Support the MultiRecord section in FRUs
Add support for FRUs containing a MultiRecord section to
ipmiStorageWriteFruData().
Before this patch, the presence of a MultiRecord section was ignored.
lastRecordStart would point to the last section populated before the
MultiRecord section (e.g. the Product section).
Now, if there is a MultiRecord section, walk the MultiRecord headers to
find the last one and set lastRecordStart appropriately.
Tested:
I have a system with an eeprom containing a MultiRecord section with two
records. Writes to that FRU work after this change.
Signed-off-by: Peter Lundgren <peterlundgren@google.com>
Change-Id: Iea269ad386b1cbc7b4876ddeb9cfac3b9e83f541
diff --git a/src/storagecommands.cpp b/src/storagecommands.cpp
index 631d063..cc0203d 100644
--- a/src/storagecommands.cpp
+++ b/src/storagecommands.cpp
@@ -372,26 +372,48 @@
{
FRUHeader* header = reinterpret_cast<FRUHeader*>(fruCache.data());
+ int areaLength = 0;
int lastRecordStart = std::max(
- header->internalOffset,
- std::max(header->chassisOffset,
- std::max(header->boardOffset, header->productOffset)));
- // TODO: Handle Multi-Record FRUs?
-
+ {header->internalOffset, header->chassisOffset, header->boardOffset,
+ header->productOffset, header->multiRecordOffset});
lastRecordStart *= 8; // header starts in are multiples of 8 bytes
- // get the length of the area in multiples of 8 bytes
- if (lastWriteAddr > (lastRecordStart + 1))
+ if (header->multiRecordOffset)
{
- // second byte in record area is the length
- int areaLength(fruCache[lastRecordStart + 1]);
- areaLength *= 8; // it is in multiples of 8 bytes
-
- if (lastWriteAddr >= (areaLength + lastRecordStart))
+ // This FRU has a MultiRecord Area
+ uint8_t endOfList = 0;
+ // Walk the MultiRecord headers until the last record
+ while (!endOfList)
{
- atEnd = true;
+ // The MSB in the second byte of the MultiRecord header signals
+ // "End of list"
+ endOfList = fruCache[lastRecordStart + 1] & 0x80;
+ // Third byte in the MultiRecord header is the length
+ areaLength = fruCache[lastRecordStart + 2];
+ // This length is in bytes (not 8 bytes like other headers)
+ areaLength += 5; // The length omits the 5 byte header
+ if (!endOfList)
+ {
+ // Next MultiRecord header
+ lastRecordStart += areaLength;
+ }
}
}
+ else
+ {
+ // This FRU does not have a MultiRecord Area
+ // Get the length of the area in multiples of 8 bytes
+ if (lastWriteAddr > (lastRecordStart + 1))
+ {
+ // second byte in record area is the length
+ areaLength = fruCache[lastRecordStart + 1];
+ areaLength *= 8; // it is in multiples of 8 bytes
+ }
+ }
+ if (lastWriteAddr >= (areaLength + lastRecordStart))
+ {
+ atEnd = true;
+ }
}
uint8_t countWritten = 0;