readeeprom: Allow FRU ID 0 to be selected
We incorrectly checked that FRU ID != 0, which is the default FRU ID.
Actually, the IPMI spec specifies FRU ID 0xff as reserved, so the check
was changed to prevent that ID from being used instead.
Split out fruid parsing code to its own function to cover various edge
and failure cases.
Tested:
Ran 'phosphor-read-eeprom --eeprom fru.bin --fruid=0' and checked that
values are reported to inventory as expected.
Ran with '--fruid=ff' ('invalid' FRU ID): rejected
Ran with '--fruid=xx' (non-HEX FRU ID): rejected
Ran with '--fruid=100' (out-of-range FRU ID): rejected
Ran with '--fruid="0 0"' (invalid number): rejected
Ran with '--fruid=10.0' (non-integer): rejected
Ran with '--fruid=0x12' (valid HEX FRU ID): accepted
Ran with '--fruid=fe' (valid HEX FRU ID): accepted
Change-Id: Ic1fb79cefc6931f21d0b5cb4363ad5fd44f47c92
Signed-off-by: Oskar Senft <osk@google.com>
diff --git a/readeeprom.cpp b/readeeprom.cpp
index d518a83..f5fa148 100644
--- a/readeeprom.cpp
+++ b/readeeprom.cpp
@@ -17,13 +17,51 @@
exit(-1);
}
+static uint8_t parse_fruid_or_exit(const char* fruid_str, char** argv)
+{
+ const uint8_t MAX_FRU_ID = 0xfe;
+ unsigned long fruid;
+ char* endptr = NULL;
+
+ // The FRUID string must not be empty.
+ if (fruid_str == nullptr || *fruid_str == '\0')
+ {
+ exit_with_error("Empty fruid.", argv);
+ }
+
+ errno = 0;
+ fruid = std::strtoul(fruid_str, &endptr, 16);
+
+ // Handle error cases
+ if (errno == ERANGE)
+ {
+ exit_with_error("fruid is out of range.", argv);
+ }
+ if (errno != 0)
+ {
+ exit_with_error("Could not parse fruid.", argv);
+ }
+ if (*endptr != '\0')
+ {
+ // The string was not fully parsed, e.g. contains invalid characters
+ exit_with_error("Invalid fruid.", argv);
+ }
+ if (fruid > MAX_FRU_ID)
+ {
+ // The string was parsed, but the set FRUID is too large.
+ exit_with_error("fruid is out of range.", argv);
+ }
+
+ return fruid;
+}
+
//--------------------------------------------------------------------------
// This gets called by udev monitor soon after seeing hog plugs for EEPROMS.
//--------------------------------------------------------------------------
int main(int argc, char** argv)
{
int rc = 0;
- uint8_t fruid = 0;
+ uint8_t fruid;
// Read the arguments.
auto cli_options = std::make_unique<ArgumentParser>(argc, argv);
@@ -44,12 +82,7 @@
}
// Extract the fruid
- fruid = std::strtol(fruid_str.c_str(), NULL, 16);
- if (fruid == 0)
- {
- // User has not passed in the appropriate argument value
- exit_with_error("Invalid fruid.", argv);
- }
+ fruid = parse_fruid_or_exit(fruid_str.c_str(), argv);
// Finished getting options out, so release the parser.
cli_options.release();