FruDevice: improve warning messages in FRU parse logic
When got any warnings while formatFRU, is hard to understand which
device cause it since formatFRU has no information about device address.
This adds printing device address after parsing FRU data if
error/warning occurs.
Makes some check to be not critical (checksum error and non-zero bytes
after EndOfFields) since we found invalid FRU in FLEXTRONICS
S-1100ADU00-201 PSU where was wrong size in PRODUCT section header:
00000000 01 00 00 00 01 09 00 f5 01 09 19 cb 46 4c 45 58 |............FLEX|
00000010 54 52 4f 4e 49 43 53 cf 53 2d 31 31 30 30 41 44 |TRONICS.S-1100AD|
00000020 55 30 30 2d 32 30 31 ca 47 38 34 30 32 37 2d 30 |U00-201.G84027-0|
00000030 30 37 c2 30 31 cc 45 58 57 44 36 34 39 30 31 31 |07.01.EXWD649011|
00000040 32 31 c0 c0 c1 00 00 dc 00 02 18 3f a7 4c 04 28 |21.........?.L.(|
00000050 0a 37 05 28 23 b0 36 50 46 20 67 2f 3f 0a 1f f8 |.7.(#.6PF g/?...|
00000060 05 00 00 00 21 01 02 0d 6d 83 01 b0 04 74 04 ec |....!...m....t..|
00000070 04 78 00 00 00 ff ff 01 82 0d ae c2 82 b0 04 74 |.x.............t|
00000080 04 ec 04 78 00 00 00 34 08 |...x...4.|
Also fixes some other messages.
Tested: ensure there are expected messages in the log for FRU above:
fru-device[355]: Checksum error in FRU area PRODUCT
fru-device[355]: Computed checksum: 0xb0
fru-device[355]: The read checksum: 0x28
fru-device[355]: Non-zero byte after EndOfFields in FRU area PRODUCT
fru-device[355]: there were warnings while parsing FRU for device at bus 7 address 82
Change-Id: I1e1d08ca0547ec4e6a8ce4e1f71a479622d5f243
Signed-off-by: Andrei Kartashev <a.kartashev@yadro.com>
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index 45d0fd9..3e7cd1a 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -70,6 +70,13 @@
const static constexpr char* I2C_DEV_LOCATION = "/dev";
+enum class resCodes
+{
+ resOK,
+ resWarn,
+ resErr
+};
+
enum class fruAreas
{
fruAreaInternal = 0,
@@ -611,7 +618,7 @@
// Set slave address
if (ioctl(file, I2C_SLAVE, ii) < 0)
{
- std::cerr << "device at bus " << bus << " register " << ii
+ std::cerr << "device at bus " << bus << " address " << ii
<< " busy\n";
continue;
}
@@ -979,13 +986,14 @@
}
}
-bool formatFRU(const std::vector<uint8_t>& fruBytes,
- boost::container::flat_map<std::string, std::string>& result)
+resCodes formatFRU(const std::vector<uint8_t>& fruBytes,
+ boost::container::flat_map<std::string, std::string>& result)
{
+ resCodes ret = resCodes::resOK;
if (fruBytes.size() <= fruBlockSize)
{
std::cerr << "Error: trying to parse empty FRU \n";
- return false;
+ return resCodes::resErr;
}
result["Common_Format_Version"] =
std::to_string(static_cast<int>(*fruBytes.begin()));
@@ -1008,13 +1016,13 @@
if (fruBytesIter + fruBlockSize >= fruBytes.end())
{
std::cerr << "Not enough data to parse \n";
- return false;
+ return resCodes::resErr;
}
// check for format version 1
if (*fruBytesIter != 0x01)
{
std::cerr << "Unexpected version " << *fruBytesIter << "\n";
- return false;
+ return resCodes::resErr;
}
++fruBytesIter;
uint8_t fruAreaSize = *fruBytesIter * fruBlockSize;
@@ -1034,7 +1042,7 @@
ss << "\tThe read checksum: 0x" << std::setw(2)
<< static_cast<int>(*fruBytesIterEndArea) << "\n";
std::cerr << ss.str();
- return false;
+ ret = resCodes::resWarn;
}
switch (area)
@@ -1070,7 +1078,7 @@
if (bytes == 0)
{
std::cerr << "invalid time string encountered\n";
- return false;
+ return resCodes::resErr;
}
result["BOARD_MANUFACTURE_DATE"] = std::string(timeString);
@@ -1092,7 +1100,7 @@
{
std::cerr << "Internal error: unexpected FRU area index: "
<< static_cast<int>(area) << " \n";
- return false;
+ return resCodes::resErr;
}
}
size_t fieldIndex = 0;
@@ -1130,12 +1138,13 @@
else if (state == DecodeState::err)
{
std::cerr << "Error while parsing " << name << "\n";
+ ret = resCodes::resWarn;
// Cancel decoding if failed to parse any of mandatory
// fields
if (fieldIndex < fruAreaFieldNames->size())
{
std::cerr << "Failed to parse mandatory field \n";
- return false;
+ return resCodes::resErr;
}
}
else
@@ -1145,6 +1154,7 @@
std::cerr << "Mandatory fields absent in FRU area "
<< getFruAreaName(area) << " after " << name
<< "\n";
+ ret = resCodes::resWarn;
}
}
} while (state == DecodeState::ok);
@@ -1155,12 +1165,13 @@
{
std::cerr << "Non-zero byte after EndOfFields in FRU area "
<< getFruAreaName(area) << "\n";
+ ret = resCodes::resWarn;
break;
}
}
}
- return true;
+ return ret;
}
std::vector<uint8_t>& getFRUInfo(const uint8_t& bus, const uint8_t& address)
@@ -1188,12 +1199,18 @@
uint32_t bus, uint32_t address)
{
boost::container::flat_map<std::string, std::string> formattedFRU;
- if (!formatFRU(device, formattedFRU))
+ resCodes res = formatFRU(device, formattedFRU);
+ if (res == resCodes::resErr)
{
- std::cerr << "failed to format fru for device at bus " << bus
+ std::cerr << "failed to parse FRU for device at bus " << bus
<< " address " << address << "\n";
return;
}
+ else if (res == resCodes::resWarn)
+ {
+ std::cerr << "there were warnings while parsing FRU for device at bus "
+ << bus << " address " << address << "\n";
+ }
auto productNameFind = formattedFRU.find("BOARD_PRODUCT_NAME");
std::string productName;
@@ -1355,7 +1372,7 @@
return false;
}
// verify legal fru by running it through fru parsing logic
- if (!formatFRU(fru, tmp))
+ if (formatFRU(fru, tmp) != resCodes::resOK)
{
std::cerr << "Invalid fru format during writeFRU\n";
return false;