From 63d59a50a6809e415cd7d8915533f236f28865f3 Mon Sep 17 00:00:00 2001 From: Alexander Amelkin Date: Wed, 21 Dec 2022 14:57:52 +0300 Subject: fru print: Add area checksum verification Before this change, `ipmitool` would not detect any checksum errors in FRU areas when using 'fru print'. Now it will print whether the area checksum is OK or INVALID for Chassis, Board, and Product areas. Signed-off-by: Alexander Amelkin --- lib/ipmi_fru.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c index 2d8daaf..4d1dbbb 100644 --- a/lib/ipmi_fru.c +++ b/lib/ipmi_fru.c @@ -141,6 +141,50 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, uint32_t offset, uint32_t length, uint8_t *frubuf); void free_fru_bloc(t_ipmi_fru_bloc *bloc); +/** + * Caclculate the simple FRU checksum as per IPMI FRU specification. + * Works both for the whole FRU image and for separate areas. + * + * @param[in] area Pointer to the start of checksummed area, + * the area must end with the checksum byte + * @param[in[ len Length of the checksummed area, including + * the trailing checksum byte + * @returns The calculated checksum byte + */ +static +uint8_t fru_calc_checksum(void *area, size_t len) +{ + uint8_t checksum = 0; + uint8_t * data = area; + size_t i; + + for (i = 0; i < len - 1; i++) + checksum += data[i]; + + return -checksum; +} + +/** + * Check if FRU checksum is valid. Works both on the + * whole FRU image and on separate areas. + * + * @param[in] area Pointer to the start of checksummed area, + * the area must end with the checksum byte + * @param[in[ len Length of the checksummed area, including + * the trailing checksum byte + * @returns The boolean state of checksum validity + * @retval true Checksum is valid + * @retval false Checsum in invalid + */ +static +bool fru_checksum_is_valid(void *area, size_t len) +{ + uint8_t * data = area; + + /* Checksum is valid when the stored checksum equals calculated */ + return data[len - 1] == fru_calc_checksum(area, len); +} + /* get_fru_area_str - Parse FRU area string from raw data * * @data: raw FRU data @@ -1048,6 +1092,12 @@ fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru, } } + /* Check area checksum */ + printf(" Chassis Area Checksum : %s\n", + fru_checksum_is_valid(fru_data, fru_len) + ? "OK" + : "INVALID"); + free_n(&fru_data); } @@ -1159,6 +1209,12 @@ fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru, break; } + /* Check area checksum */ + printf(" Board Area Checksum : %s\n", + fru_checksum_is_valid(fru_data, fru_len) + ? "OK" + : "INVALID"); + free_n(&fru_data); } @@ -1281,6 +1337,12 @@ fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru, break; } + /* Check area checksum */ + printf(" Product Area Checksum : %s\n", + fru_checksum_is_valid(fru_data, fru_len) + ? "OK" + : "INVALID"); + free_n(&fru_data); } -- cgit v1.2.1