ipmitool: fix ipmitool crash when with fru edit

fru edit command can increase fru size. Allocate new fru data with
the bigger size. This fixes ipmitool crash when fru edit increases fru
size.

Tested:
fru edit command that increases fru size complete successfully.

Change-Id: Iac066bdd1e30cb6b205e680ec4c94589b1b24e1e
Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
diff --git a/meta-phosphor/recipes-phosphor/ipmi/ipmitool/0001-Fru-Fix-edit-field-not-checking-area-existence.patch b/meta-phosphor/recipes-phosphor/ipmi/ipmitool/0001-Fru-Fix-edit-field-not-checking-area-existence.patch
index c18d6e1..6b22da6 100644
--- a/meta-phosphor/recipes-phosphor/ipmi/ipmitool/0001-Fru-Fix-edit-field-not-checking-area-existence.patch
+++ b/meta-phosphor/recipes-phosphor/ipmi/ipmitool/0001-Fru-Fix-edit-field-not-checking-area-existence.patch
@@ -1,4 +1,4 @@
-From 066f647fbec1f3177d673d157b18ff0c0f517627 Mon Sep 17 00:00:00 2001
+From 255b93dfe8adcbf286c94706906aa8fdc60d388b Mon Sep 17 00:00:00 2001
 From: Alex Schendel <alex.schendel@intel.com>
 Date: Fri, 9 Jun 2023 16:35:24 -0700
 Subject: [PATCH] Fru: Fix edit field not checking area existence
@@ -64,16 +64,17 @@
 trigger this FRU write failure.
 
 Signed-off-by: Alex Schendel <alex.schendel@intel.com>
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
 ---
  include/ipmitool/ipmi_fru.h |   3 +-
- lib/ipmi_fru.c              | 143 +++++++++++++++++++++++-------------
- 2 files changed, 93 insertions(+), 53 deletions(-)
+ lib/ipmi_fru.c              | 170 +++++++++++++++++++++++-------------
+ 2 files changed, 111 insertions(+), 62 deletions(-)
 
 diff --git a/include/ipmitool/ipmi_fru.h b/include/ipmitool/ipmi_fru.h
-index 4d4d6c6..e7e8876 100644
+index b17870c..549915d 100644
 --- a/include/ipmitool/ipmi_fru.h
 +++ b/include/ipmitool/ipmi_fru.h
-@@ -46,6 +46,7 @@
+@@ -47,6 +47,7 @@
  #define GET_FRU_INFO		0x10
  #define GET_FRU_DATA		0x11
  #define SET_FRU_DATA		0x12
@@ -81,7 +82,7 @@
  
  enum {
  	FRU_CHASSIS_PARTNO,
-@@ -82,7 +83,7 @@ struct fru_header {
+@@ -83,7 +84,7 @@ struct fru_header {
  			uint8_t product;
  			uint8_t multi;
  		} offset;
@@ -91,10 +92,65 @@
  	uint8_t pad;
  	uint8_t checksum;
 diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
-index 3d1d8a1..2687635 100644
+index 4a5018d..f776642 100644
 --- a/lib/ipmi_fru.c
 +++ b/lib/ipmi_fru.c
-@@ -5044,43 +5044,91 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+@@ -130,7 +130,8 @@ static int ipmi_fru_set_field_string(struct ipmi_intf * intf, unsigned
+ static int
+ 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);
++											uint8_t f_type, uint8_t f_index, char *f_string,
++											int new_size);
+ 
+ static void
+ fru_area_print_multirec_bloc(struct ipmi_intf * intf, struct fru_info * fru,
+@@ -4835,12 +4836,19 @@ f_type, uint8_t f_index, char *f_string)
+ 			rc = -1;
+ 			goto ipmi_fru_set_field_string_out;
+ 		}
+-	}
+-	else {
+-		printf("String size are not equal, resizing fru to fit new string\n");
+-		if(
+-				ipmi_fru_set_field_string_rebuild(intf,fruId,fru,header,f_type,f_index,f_string)
+-		)
++    }
++    else {
++		int new_fru_size = fru.size;
++		int change =
++			strlen((const char *)f_string) - strlen((const char *)fru_area);
++		if (change > 0)
++		{
++			/* Fru record is padded to be 8 bytes aligned */
++			new_fru_size = fru.size + change + 8;
++		}
++		if (ipmi_fru_set_field_string_rebuild(intf, fruId, fru, header,
++                                                f_type, f_index, f_string,
++                                                new_fru_size))
+ 		{
+ 			rc = -1;
+ 			goto ipmi_fru_set_field_string_out;
+@@ -4886,7 +4894,8 @@ ipmi_fru_set_field_string_out:
+ static int
+ 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)
++											uint8_t f_type, uint8_t f_index, char *f_string,
++											int new_size)
+ {
+ 	int i = 0;
+ 	uint8_t *fru_data_old = NULL;
+@@ -4903,7 +4912,7 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+ 
+ 	fru_data_old = calloc( fru.size, sizeof(uint8_t) );
+ 
+-	fru_data_new = malloc( fru.size );
++	fru_data_new = malloc( new_size );
+ 
+ 	if (!fru_data_old || !fru_data_new) {
+ 		printf("Out of memory!\n");
+@@ -5043,43 +5052,91 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
  		#endif
  
  		/* Must move sections */
@@ -219,7 +275,7 @@
  		}
  
  		/* Adjust length of the section */
-@@ -5110,27 +5158,18 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
+@@ -5109,27 +5166,18 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
  			memcpy(fru_data_new, pfru_header, sizeof(struct fru_header));
  		}
  
@@ -229,7 +285,9 @@
 -					((header.offset.product) * 8) + product_len_new
 -				);
 -		if(((header.offset.product * 8) + product_len_new - remaining_offset) < 0)
--		{
++		/* If FRU has shrunk in size, zero-out any leftover data */
++		if (change_size_by_8 < 0)
+ 		{
 -			memcpy(
 -						fru_data_new + (header.offset.product * 8) + product_len_new,
 -						fru_data_old + remaining_offset,
@@ -237,9 +295,7 @@
 -					);
 -		}
 -		else
-+		/* If FRU has shrunk in size, zero-out any leftover data */
-+		if (change_size_by_8 < 0)
- 		{
+-		{
 -			memcpy(
 -						fru_data_new + (header.offset.product * 8) + product_len_new,
 -						fru_data_old + remaining_offset,