122 lines
3.6 KiB
Diff
122 lines
3.6 KiB
Diff
|
From 497f7767cd8e80ad67d08680ae165271441017fc Mon Sep 17 00:00:00 2001
|
||
|
From: Alexander Amelkin <alexander@amelkin.msk.ru>
|
||
|
Date: Thu, 2 Feb 2017 15:25:44 +0300
|
||
|
Subject: [PATCH 15/17] ID:477 - fru: Fix decoding of non-text data in
|
||
|
get_fru_area_str()
|
||
|
|
||
|
The get_fru_area_str() function is used to decode FRU area
|
||
|
fields into text. Areas may be encoded as text, binary,
|
||
|
BCDplus or 6-bit ASCII. Decoding of 6-bit ASCII and BCDplus
|
||
|
was broken. There was an error in the formulas used to
|
||
|
calculate the resulting string length, plus the decoding
|
||
|
formulas for BCDplus was wrong.
|
||
|
|
||
|
For BCDplus the resulting length was considered equal
|
||
|
the encoded data length, while in fact it's twice as big.
|
||
|
Only one character instead of two was being extracted from
|
||
|
a single input byte while two nibbles must have been taken
|
||
|
into account.
|
||
|
|
||
|
For 6-bit ASCII rounding of 3 to 4 bytes conversion was done
|
||
|
improperly adding 2 to the original length instead of the
|
||
|
result of multiplication.
|
||
|
---
|
||
|
lib/ipmi_fru.c | 32 ++++++++++++++++----------------
|
||
|
1 file changed, 16 insertions(+), 16 deletions(-)
|
||
|
|
||
|
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
|
||
|
index cf00eff..42c1f19 100644
|
||
|
--- a/lib/ipmi_fru.c
|
||
|
+++ b/lib/ipmi_fru.c
|
||
|
@@ -107,7 +107,7 @@ char * get_fru_area_str(uint8_t * data, uint32_t * offset)
|
||
|
{
|
||
|
static const char bcd_plus[] = "0123456789 -.:,_";
|
||
|
char * str;
|
||
|
- int len, off, size, i, j, k, typecode;
|
||
|
+ int len, off, size, i, j, k, typecode, char_idx;
|
||
|
union {
|
||
|
uint32_t bits;
|
||
|
char chars[4];
|
||
|
@@ -126,15 +126,15 @@ char * get_fru_area_str(uint8_t * data, uint32_t * offset)
|
||
|
|
||
|
switch (typecode) {
|
||
|
case 0: /* 00b: binary/unspecified */
|
||
|
- /* hex dump -> 2x length */
|
||
|
- size = (len*2);
|
||
|
+ case 1: /* 01b: BCD plus */
|
||
|
+ /* hex dump or BCD -> 2x length */
|
||
|
+ size = (len * 2);
|
||
|
break;
|
||
|
case 2: /* 10b: 6-bit ASCII */
|
||
|
/* 4 chars per group of 1-3 bytes */
|
||
|
- size = ((((len+2)*4)/3) & ~3);
|
||
|
+ size = (((len * 4 + 2) / 3) & ~3);
|
||
|
break;
|
||
|
case 3: /* 11b: 8-bit ASCII */
|
||
|
- case 1: /* 01b: BCD plus */
|
||
|
/* no length adjustment */
|
||
|
size = len;
|
||
|
break;
|
||
|
@@ -149,7 +149,7 @@ char * get_fru_area_str(uint8_t * data, uint32_t * offset)
|
||
|
return NULL;
|
||
|
memset(str, 0, size+1);
|
||
|
|
||
|
- if (len == 0) {
|
||
|
+ if (size == 0) {
|
||
|
str[0] = '\0';
|
||
|
*offset = off;
|
||
|
return str;
|
||
|
@@ -157,30 +157,30 @@ char * get_fru_area_str(uint8_t * data, uint32_t * offset)
|
||
|
|
||
|
switch (typecode) {
|
||
|
case 0: /* Binary */
|
||
|
- strncpy(str, buf2str(&data[off], len), len*2);
|
||
|
+ strncpy(str, buf2str(&data[off], len), size);
|
||
|
break;
|
||
|
|
||
|
case 1: /* BCD plus */
|
||
|
- for (k=0; k<len; k++)
|
||
|
- str[k] = bcd_plus[(data[off+k] & 0x0f)];
|
||
|
+ for (k = 0; k < size; k++)
|
||
|
+ str[k] = bcd_plus[((data[off + k / 2] >> ((k % 2) ? 0 : 4)) & 0x0f)];
|
||
|
str[k] = '\0';
|
||
|
break;
|
||
|
|
||
|
case 2: /* 6-bit ASCII */
|
||
|
- for (i=j=0; i<len; i+=3) {
|
||
|
+ for (i = j = 0; i < len; i += 3) {
|
||
|
u.bits = 0;
|
||
|
- k = ((len-i) < 3 ? (len-i) : 3);
|
||
|
+ k = ((len - i) < 3 ? (len - i) : 3);
|
||
|
#if WORDS_BIGENDIAN
|
||
|
u.chars[3] = data[off+i];
|
||
|
u.chars[2] = (k > 1 ? data[off+i+1] : 0);
|
||
|
u.chars[1] = (k > 2 ? data[off+i+2] : 0);
|
||
|
-#define CHAR_IDX 3
|
||
|
+ char_idx = 3;
|
||
|
#else
|
||
|
memcpy((void *)&u.bits, &data[off+i], k);
|
||
|
-#define CHAR_IDX 0
|
||
|
+ char_idx = 0;
|
||
|
#endif
|
||
|
for (k=0; k<4; k++) {
|
||
|
- str[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20);
|
||
|
+ str[j++] = ((u.chars[char_idx] & 0x3f) + 0x20);
|
||
|
u.bits >>= 6;
|
||
|
}
|
||
|
}
|
||
|
@@ -188,8 +188,8 @@ char * get_fru_area_str(uint8_t * data, uint32_t * offset)
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
- memcpy(str, &data[off], len);
|
||
|
- str[len] = '\0';
|
||
|
+ memcpy(str, &data[off], size);
|
||
|
+ str[size] = '\0';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
1.8.5.6
|
||
|
|