[PATCH ipmi-fru-parser v2] Update BINARY encoded IPMI FRU area data to FRU Inventory

OpenBMC Patches openbmc-patches at stwcx.xyz
Wed Jun 15 20:20:15 AEST 2016


From: vishwa <vishwanath at in.ibm.com>

IPMI fru record format can contain BINARY and ASCII encodings.
There was an error in the way FRU parser was handling the BINARY
encoded data and that resulted in incorrect updates to FRU Inventory object.

The reason why it was done like that was to workaround a limitation
encountered while creating the dictionary having a name and value pair
where value is an array of bytes.

This proposed fix will convert the array of binary encoded data into ascii
string and updates the FRU inventory as a string. Since string is a single
element, it fits in within the limits of dictionary.

Fixes openbmc/ipmi-fru-parser#3
---
 frup.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/frup.c b/frup.c
index 49718ba..4d3758a 100644
--- a/frup.c
+++ b/frup.c
@@ -770,7 +770,6 @@ ipmi_fru_product_info_area (const void *areabuf,
   return (rv);
 }
 
-
 int _append_to_dict (uint8_t vpd_key_id, uint8_t* vpd_key_val, sd_bus_message* vpdtbl)
 {
     int type_length = vpd_key_val[0];
@@ -778,19 +777,62 @@ int _append_to_dict (uint8_t vpd_key_id, uint8_t* vpd_key_val, sd_bus_message* v
     int vpd_val_len = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
     int sdr=0;
 
+    /* Needed to convert each uint8_t byte to a ascii */
+    char bin_byte[3] = {0};
+
+    /*
+     * Max number of characters needed to represent 1 unsigned byte in string
+     * is number of bytes multipled by 2. Extra 3 for 0x and a ending '\0';
+     */
+    char bin_in_ascii_len = vpd_val_len * 2 + 3;
+
+    /* Binary converted to ascii in array */
+    char *bin_in_ascii = (char *)malloc(bin_in_ascii_len);
+
+    /* For reading byte from the area */
+    size_t val = 0;
+
+    char *bin_copy = &((char *)bin_in_ascii)[2];
+
     switch (type_code)
     {
         case 0:
-            printf ("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] : Len = [%d] : Val = [%s]\n", vpd_key_names [vpd_key_id], vpd_val_len, &vpd_key_val[1]);
-            sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "ay", vpd_val_len, &vpd_key_val[1]);
-            /*sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);*/
+            memset(bin_in_ascii, 0x0, bin_in_ascii_len);
+
+            /* Offset 1 is where actual data starts */
+            for(val = 1; val <= vpd_val_len ; val++)
+            {
+                /* 2 bytes for data and 1 for terminating '\0' */
+                snprintf(bin_byte, 3, "%02x", vpd_key_val[val]);
+
+                /* Its a running string so strip off the '\0' */
+                strncat(bin_copy, bin_byte, 2);
+            }
+
+            /* We need the data represented as 0x...... */
+            if(vpd_val_len > 0)
+            {
+                strncpy(bin_in_ascii, "0x", 2);
+            }
+
+            printf ("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] : Len = [%d] : Val = [%s]\n",
+                    vpd_key_names [vpd_key_id], vpd_val_len, bin_in_ascii);
+            sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", bin_in_ascii);
             break;
+
         case 3:
             printf ("_append_to_dict: VPD Key = [%s] : Type Code = [ASCII+Latin] : Len = [%d] : Val = [%s]\n", vpd_key_names [vpd_key_id], vpd_val_len, &vpd_key_val[1]);
             sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);
             break;
     }
 
+    if(bin_in_ascii)
+    {
+        free(bin_in_ascii);
+        bin_in_ascii = NULL;
+    }
+
+
     if (sdr < 0)
     {
 #if IPMI_FRU_PARSER_DEBUG
@@ -944,7 +986,6 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
   }
  out:
   rv = 0;
- cleanup:
   return (rv);
 }
 
-- 
2.8.4




More information about the openbmc mailing list