summaryrefslogtreecommitdiff
path: root/sysutils/ipmitool/files/patch-fru-PR368
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/ipmitool/files/patch-fru-PR368')
-rw-r--r--sysutils/ipmitool/files/patch-fru-PR368296
1 files changed, 296 insertions, 0 deletions
diff --git a/sysutils/ipmitool/files/patch-fru-PR368 b/sysutils/ipmitool/files/patch-fru-PR368
new file mode 100644
index 000000000000..bdef578767ec
--- /dev/null
+++ b/sysutils/ipmitool/files/patch-fru-PR368
@@ -0,0 +1,296 @@
+From 81011685ea5e8897f8c0971eca5feb93c6880f09 Mon Sep 17 00:00:00 2001
+From: Andrew Liao <andrew8325@outlook.com>
+Date: Fri, 23 Sep 2022 10:11:04 +0800
+Subject: [PATCH 1/2] fru: Update the fru section offset only when they exist
+ (offset is not 0)
+
+---
+ lib/ipmi_fru.c | 52 ++++++++++++++++++++++++++++----------------------
+ 1 file changed, 29 insertions(+), 23 deletions(-)
+
+diff --git lib/ipmi_fru.c lib/ipmi_fru.c
+index 3d1d8a1a..a994f3cf 100644
+--- lib/ipmi_fru.c
++++ lib/ipmi_fru.c
+@@ -5052,35 +5052,41 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ /* Chassis type field */
+ if (f_type == 'c' )
+ {
+- printf("Moving Section Chassis, from %i to %i\n",
+- ((header.offset.board) * 8),
+- ((header.offset.board + change_size_by_8) * 8)
+- );
+- memcpy(
+- (fru_data_new + ((header.offset.board + change_size_by_8) * 8)),
+- (fru_data_old + (header.offset.board) * 8),
+- board_len
+- );
+- header.offset.board += change_size_by_8;
++ if (header.offset.board != 0) {
++ printf("Moving Section Chassis, from %i to %i\n",
++ ((header.offset.board) * 8),
++ ((header.offset.board + change_size_by_8) * 8)
++ );
++ memcpy(
++ (fru_data_new + ((header.offset.board + change_size_by_8) * 8)),
++ (fru_data_old + (header.offset.board) * 8),
++ board_len
++ );
++ header.offset.board += change_size_by_8;
++ }
+ }
+ /* Board type field */
+ if ((f_type == 'c' ) || (f_type == 'b' ))
+ {
+- printf("Moving Section Product, from %i to %i\n",
+- ((header.offset.product) * 8),
+- ((header.offset.product + change_size_by_8) * 8)
+- );
+- memcpy(
+- (fru_data_new + ((header.offset.product + change_size_by_8) * 8)),
+- (fru_data_old + (header.offset.product) * 8),
+- product_len
+- );
+- header.offset.product += change_size_by_8;
++ if (header.offset.product != 0) {
++ printf("Moving Section Product, from %i to %i\n",
++ ((header.offset.product) * 8),
++ ((header.offset.product + change_size_by_8) * 8)
++ );
++ memcpy(
++ (fru_data_new + ((header.offset.product + change_size_by_8) * 8)),
++ (fru_data_old + (header.offset.product) * 8),
++ product_len
++ );
++ header.offset.product += change_size_by_8;
++ }
+ }
+
+- if ((f_type == 'c' ) || (f_type == 'b' ) || (f_type == 'p' )) {
+- printf("Change multi offset from %d to %d\n", header.offset.multi, header.offset.multi + change_size_by_8);
+- header.offset.multi += change_size_by_8;
++ if (header.offset.multi != 0) {
++ if ((f_type == 'c' ) || (f_type == 'b' ) || (f_type == 'p' )) {
++ printf("Change multi offset from %d to %d\n", header.offset.multi, header.offset.multi + change_size_by_8);
++ header.offset.multi += change_size_by_8;
++ }
+ }
+
+ /* Adjust length of the section */
+
+From fe70e7d81334ba37614ca5cd0580b2a91a969fc1 Mon Sep 17 00:00:00 2001
+From: "Andrew.Liao" <andrew.liao@quantatw.com>
+Date: Mon, 26 Sep 2022 17:16:52 +0800
+Subject: [PATCH 2/2] fru: Adjust the fru section by their offset order
+
+Originally, ipmitool will assume the FRU section offset will follow a specific order, but this is not true (or not be defined in IPMI FRU SPEC). So change the FRU edit method, now it will:
+ - Calculate the section offset one by one according to their offset
+ - Ignore the FRU section offset if its offset is 00 (area does not exist)
+ - If the new FRU become smaller, reset the redundant data to 0
+Fixes #364
+---
+ lib/ipmi_fru.c | 151 +++++++++++++++++++++++++++++--------------------
+ 1 file changed, 90 insertions(+), 61 deletions(-)
+
+diff --git lib/ipmi_fru.c lib/ipmi_fru.c
+index a994f3cf..3bf8416d 100644
+--- lib/ipmi_fru.c
++++ lib/ipmi_fru.c
+@@ -4889,7 +4889,7 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ struct fru_info fru, struct fru_header header,
+ uint8_t f_type, uint8_t f_index, char *f_string)
+ {
+- int i = 0;
++ int i = 0, j;
+ uint8_t *fru_data_old = NULL;
+ uint8_t *fru_data_new = NULL;
+ uint8_t *fru_area = NULL;
+@@ -4901,6 +4901,7 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ uint32_t counter;
+ unsigned char cksum;
+ int rc = 1;
++ char section_list[] = {'i', 'c', 'b', 'p', 'm'};
+
+ fru_data_old = calloc( fru.size, sizeof(uint8_t) );
+
+@@ -5018,8 +5019,10 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ 5) Check if section must be resize. This occur when padding length is not between 0 and 7 */
+ if( (padding_len < 0) || (padding_len >= 8))
+ {
+- uint32_t remaining_offset = ((header.offset.product * 8) + product_len);
+- int change_size_by_8;
++ int change_size_by_8, section_len;
++ char *name;
++ uint8_t *section_offset_by_8;
++ uint8_t last_offset_by_8 = 0;
+
+ if(padding_len >= 8)
+ {
+@@ -5044,48 +5047,85 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ #endif
+
+ /* Must move sections */
+- /* Section that can be modified are as follow
+- Chassis
+- Board
+- product */
++ /* The IPMI FRU SPEC doesn't define the sequence of each FRU area.
++ * Therefore we need to find out the affected section in this change based on
++ * their current offset and adjust each of them.
++ */
+
+- /* Chassis type field */
+- if (f_type == 'c' )
+- {
+- if (header.offset.board != 0) {
+- printf("Moving Section Chassis, from %i to %i\n",
+- ((header.offset.board) * 8),
+- ((header.offset.board + change_size_by_8) * 8)
+- );
+- memcpy(
+- (fru_data_new + ((header.offset.board + change_size_by_8) * 8)),
+- (fru_data_old + (header.offset.board) * 8),
+- board_len
+- );
+- header.offset.board += change_size_by_8;
++ /* Find out the section behind the edited section and adjust them */
++ for (j = 0; j < sizeof(section_list); j++) {
++ section_offset_by_8 = NULL;
++ name = NULL;
++
++ switch (section_list[j]) {
++ case 'i':
++ section_offset_by_8 = &header.offset.internal;
++ name = "Internal";
++ break;
++ case 'c':
++ section_offset_by_8 = &header.offset.chassis;
++ name = "Chassis";
++ break;
++ case 'b':
++ section_offset_by_8 = &header.offset.board;
++ name = "Board";
++ break;
++ case 'p':
++ section_offset_by_8 = &header.offset.product;
++ name = "Product";
++ break;
++ case 'm':
++ section_offset_by_8 = &header.offset.multi;
++ name = "MitiRecord";
++ break;
++ default:
++ /* Should not go into here */
++ break;
+ }
+- }
+- /* Board type field */
+- if ((f_type == 'c' ) || (f_type == 'b' ))
+- {
+- if (header.offset.product != 0) {
+- printf("Moving Section Product, from %i to %i\n",
+- ((header.offset.product) * 8),
+- ((header.offset.product + change_size_by_8) * 8)
++
++ /* Should never happened */
++ if (section_offset_by_8 == NULL || name == NULL) {
++ continue;
++ }
++
++ /* Ignore the section that doesn't exist */
++ if (*section_offset_by_8 == 0) {
++ continue;
++ }
++
++ /* Store the last offset in case we need to reset the last part */
++ if (last_offset_by_8 < *section_offset_by_8) {
++ last_offset_by_8 = *section_offset_by_8;
++ }
++
++ /* Adjust the section offset that locates behind the current edit section */
++ if (*section_offset_by_8 > (header_offset / 8)) {
++
++ /* Make sure the adjusted offset range is still inside the FRU field */
++ section_len = *(fru_data_old + (*section_offset_by_8 * 8) + 1) * 8;
++ if (((*section_offset_by_8 * 8) + section_len + (change_size_by_8 * 8)) > fru.size)
++ {
++ /* Return error if oversize */
++ printf("Internal error, section %s out of FRU field. %i > %i\n",
++ name,
++ ((*section_offset_by_8 * 8) + section_len + (change_size_by_8 * 8)),
++ fru.size);
++ rc = -1;
++ goto ipmi_fru_set_field_string_rebuild_out;
++ }
++
++ /* Copy the section to adjusted offset */
++ printf("Moving Section %s, from %i to %i\n",
++ name,
++ ((*section_offset_by_8) * 8),
++ ((*section_offset_by_8 + change_size_by_8) * 8)
+ );
+ memcpy(
+- (fru_data_new + ((header.offset.product + change_size_by_8) * 8)),
+- (fru_data_old + (header.offset.product) * 8),
+- product_len
++ (fru_data_new + ((*section_offset_by_8 + change_size_by_8) * 8)),
++ (fru_data_old + (*section_offset_by_8) * 8),
++ section_len
+ );
+- header.offset.product += change_size_by_8;
+- }
+- }
+-
+- if (header.offset.multi != 0) {
+- if ((f_type == 'c' ) || (f_type == 'b' ) || (f_type == 'p' )) {
+- printf("Change multi offset from %d to %d\n", header.offset.multi, header.offset.multi + change_size_by_8);
+- header.offset.multi += change_size_by_8;
++ *section_offset_by_8 += change_size_by_8;
+ }
+ }
+
+@@ -5101,7 +5141,6 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ else if( f_type == 'p')
+ {
+ *(fru_data_new + product_offset + 1) += change_size_by_8;
+- product_len_new = *(fru_data_new + product_offset + 1) * 8;
+ }
+
+ /* Rebuild Header checksum */
+@@ -5116,26 +5155,16 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ memcpy(fru_data_new, pfru_header, sizeof(struct fru_header));
+ }
+
+- /* Move remaining sections in 1 copy */
+- printf("Moving Remaining Bytes (Multi-Rec , etc..), from %i to %i\n",
+- remaining_offset,
+- ((header.offset.product) * 8) + product_len_new
+- );
+- if(((header.offset.product * 8) + product_len_new - remaining_offset) < 0)
+- {
+- memcpy(
+- fru_data_new + (header.offset.product * 8) + product_len_new,
+- fru_data_old + remaining_offset,
+- fru.size - remaining_offset
+- );
+- }
+- else
+- {
+- memcpy(
+- fru_data_new + (header.offset.product * 8) + product_len_new,
+- fru_data_old + remaining_offset,
+- fru.size - ((header.offset.product * 8) + product_len_new)
+- );
++ /* Reset the last part to 0 if the new FRU is smaller them old one */
++ if (change_size_by_8 < 0) {
++ section_len = *(fru_data_old + (last_offset_by_8 * 8) + 1) * 8;
++
++ /* Get the reset start offset and reset size */
++ int reset_start = ((last_offset_by_8 * 8) + section_len + (change_size_by_8 * 8));
++ int reset_size = (change_size_by_8 * (-1)) * 8;
++
++ printf("Reset to 0 from %i to %i\n", reset_start, reset_start + reset_size);
++ memset(fru_data_new + reset_start, 0, reset_size);
+ }
+ }
+