bugfix: frudevice: read entire fru contents
The FRU sections do not need to be contiguous, therefore compute the
overall length first to copy it out in its entirety.
Tested: Verified on a FRU that had gaps in the contents that it now
properly parsed the contents after copying it out.
Tested: Verified on a FRU that did not have gaps that it continued to
correctly parse the contents after copying it out.
Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I60eac117c479d72f88a7e8e46884dd858681784b
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index a830c94..7648c4a 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -241,18 +241,23 @@
return device;
}
+ // Copy the IPMI Fru Header
device.insert(device.end(), block_data.begin(), block_data.begin() + 8);
+ int fruLength = 0;
for (size_t jj = 1; jj <= FRU_AREAS.size(); jj++)
{
- auto area_offset = device[jj];
+ // TODO: offset can be 255, device is holding "chars" that's not good.
+ int area_offset = device[jj];
if (area_offset == 0)
{
continue;
}
- area_offset = static_cast<char>(area_offset * 8);
- if (readFromEeprom(file, area_offset, 0x8, block_data.data()) < 0)
+ area_offset *= 8;
+
+ if (readFromEeprom(file, static_cast<uint16_t>(area_offset), 0x2,
+ block_data.data()) < 0)
{
std::cerr << "failed to read bus " << bus << " address " << address
<< "\n";
@@ -261,30 +266,36 @@
return device;
}
+ // Ignore data type.
int length = block_data[1] * 8;
- device.insert(device.end(), block_data.begin(), block_data.begin() + 8);
- length -= 8;
- area_offset = static_cast<char>(area_offset + 8);
+ area_offset += length;
+ fruLength = (area_offset > fruLength) ? area_offset : fruLength;
+ }
- while (length > 0)
+ // You already copied these first 8 bytes (the ipmi fru header size)
+ fruLength -= 8;
+
+ int readOffset = 8;
+
+ while (fruLength > 0)
+ {
+ int to_get = std::min(I2C_SMBUS_BLOCK_MAX, fruLength);
+
+ if (readFromEeprom(file, static_cast<uint16_t>(readOffset),
+ static_cast<uint8_t>(to_get), block_data.data()) < 0)
{
- auto to_get = std::min(I2C_SMBUS_BLOCK_MAX, length);
-
- if (readFromEeprom(file, area_offset, static_cast<uint8_t>(to_get),
- block_data.data()) < 0)
- {
- std::cerr << "failed to read bus " << bus << " address "
- << address << "\n";
- device.clear();
- close(file);
- return device;
- }
-
- device.insert(device.end(), block_data.begin(),
- block_data.begin() + to_get);
- area_offset = static_cast<char>(area_offset + to_get);
- length -= to_get;
+ std::cerr << "failed to read bus " << bus << " address " << address
+ << "\n";
+ device.clear();
+ close(file);
+ return device;
}
+
+ device.insert(device.end(), block_data.begin(),
+ block_data.begin() + to_get);
+
+ readOffset += to_get;
+ fruLength -= to_get;
}
close(file);
@@ -428,45 +439,57 @@
device.insert(device.end(), block_data.begin(),
block_data.begin() + 8);
+ int fruLength = 0;
for (size_t jj = 1; jj <= FRU_AREAS.size(); jj++)
{
- auto area_offset = device[jj];
+ // TODO: offset can be 255, device is holding "chars" that's not
+ // good.
+ int area_offset = device[jj];
if (area_offset == 0)
{
continue;
}
- area_offset = static_cast<char>(area_offset * 8);
- if (read_block_data(flag, file, area_offset, 0x8,
+ area_offset *= 8;
+
+ if (read_block_data(flag, file,
+ static_cast<uint16_t>(area_offset), 0x2,
block_data.data()) < 0)
{
std::cerr << "failed to read bus " << bus << " address "
<< ii << "\n";
return -1;
}
+
+ // Ignore data type.
int length = block_data[1] * 8;
- device.insert(device.end(), block_data.begin(),
- block_data.begin() + 8);
- length -= 8;
- area_offset = static_cast<char>(area_offset + 8);
+ area_offset += length;
+ fruLength = (area_offset > fruLength) ? area_offset : fruLength;
+ }
- while (length > 0)
+ // You already copied these first 8 bytes (the ipmi fru header size)
+ fruLength -= 8;
+
+ int readOffset = 8;
+
+ while (fruLength > 0)
+ {
+ int to_get = std::min(I2C_SMBUS_BLOCK_MAX, fruLength);
+
+ if (read_block_data(
+ flag, file, static_cast<uint16_t>(readOffset),
+ static_cast<uint8_t>(to_get), block_data.data()) < 0)
{
- auto to_get = std::min(I2C_SMBUS_BLOCK_MAX, length);
-
- if (read_block_data(flag, file, area_offset,
- static_cast<uint8_t>(to_get),
- block_data.data()) < 0)
- {
- std::cerr << "failed to read bus " << bus << " address "
- << ii << "\n";
- return -1;
- }
- device.insert(device.end(), block_data.begin(),
- block_data.begin() + to_get);
- area_offset = static_cast<char>(area_offset + to_get);
- length -= to_get;
+ std::cerr << "failed to read bus " << bus << " address "
+ << ii << "\n";
+ return -1;
}
+
+ device.insert(device.end(), block_data.begin(),
+ block_data.begin() + to_get);
+
+ readOffset += to_get;
+ fruLength -= to_get;
}
devices->emplace(ii, device);
}