summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Amelkin <alexander@amelkin.msk.ru>2022-12-21 14:57:52 +0300
committerAlexander Amelkin <mocbuhtig@amelkin.msk.ru>2022-12-21 15:15:55 +0300
commit63d59a50a6809e415cd7d8915533f236f28865f3 (patch)
tree1a11a6e86e22017b4c3ab6dc3588b9fd9a8f8b0a
parentf033b5549e90d7ae05cb5e331d887354f50bf7d6 (diff)
downloadipmitool-63d59a50a6809e415cd7d8915533f236f28865f3.tar.gz
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 <alexander@amelkin.msk.ru>
-rw-r--r--lib/ipmi_fru.c62
1 files changed, 62 insertions, 0 deletions
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);
}