Initial commit
This commit is contained in:
+262
@@ -0,0 +1,262 @@
|
||||
From 066f647fbec1f3177d673d157b18ff0c0f517627 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
|
||||
|
||||
The current implementation of ipmitool fru edit does not perform proper
|
||||
checks when attempting to resize the FRU. This results in undesireable
|
||||
changes to the FRU in several instances:
|
||||
1. If the FRU is shrinking and a FRU area does not exist (offset 0),
|
||||
ipmitool may attempt to shift it forwards (decrementing the offset).
|
||||
This results in a wraparound to 0xFF, leaving an erroneous field offset.
|
||||
2. If the areas are not in the exact order given as an example in the
|
||||
FRU spec, ipmitool may shift the wrong fields, which would cause data
|
||||
loss. (the FRU spec does not specify a required order for FRU fields)
|
||||
3. If the FRU is being enlarged after a fru field edit, the FRU size is
|
||||
not properly modified before writing the FRU, so the end of the FRU
|
||||
becomes truncated, resulting in data loss.
|
||||
|
||||
This commit addresses these three issues by:
|
||||
1. Confirming that a area's does not have an offset of 0x00 before
|
||||
attempting to shift it.
|
||||
2. Ensuring that the area's offset is after the area that was modified
|
||||
before attempting to shift it.
|
||||
3. Properly edit the size of the FRU before the FRU is written.
|
||||
|
||||
Tested:
|
||||
Shrinking a FRU was tested with and without the change:
|
||||
New Header without change:
|
||||
01 00 00 01 0a ff 00 f5
|
||||
^^
|
||||
Note that the Multi Record area now has an offset of 0xFF.
|
||||
|
||||
New Header with change:
|
||||
01 00 00 01 0a 00 00 f4
|
||||
^^
|
||||
Note that the Multi Record area retains its offset of 0x00.
|
||||
|
||||
This change also includes printouts specifying what offsets are found
|
||||
and when they are being shifted, as well as data being erased if the FRU
|
||||
is being shrunk:
|
||||
Offset: 0
|
||||
Offset: 0
|
||||
Offset: 8
|
||||
Offset: 88 moving by -8 bytes.
|
||||
Offset: 0
|
||||
Erasing leftover data from 200 to 208
|
||||
|
||||
After shrinking the FRU, the FRU was reverted to its original state with
|
||||
the fix in place:
|
||||
01 00 00 01 0b 00 00 f3
|
||||
^^
|
||||
This resulted in only the product area offset being updated as expected.
|
||||
Offset: 0
|
||||
Offset: 0
|
||||
Offset: 8
|
||||
Offset: 80 moving by 8 bytes.
|
||||
Offset: 0
|
||||
|
||||
The implementation of IPMI FRU write used in these tests errors out
|
||||
without writing the FRU if a checksum fails to pass, so without this
|
||||
fix, it was impossible to enlarge the FRU. This is because without the
|
||||
change, the last 8 bytes of the FRU would be truncated which would
|
||||
result in the checksum of the final FRU area being lost which would thus
|
||||
trigger this FRU write failure.
|
||||
|
||||
Signed-off-by: Alex Schendel <alex.schendel@intel.com>
|
||||
---
|
||||
include/ipmitool/ipmi_fru.h | 3 +-
|
||||
lib/ipmi_fru.c | 143 +++++++++++++++++++++++-------------
|
||||
2 files changed, 93 insertions(+), 53 deletions(-)
|
||||
|
||||
diff --git a/include/ipmitool/ipmi_fru.h b/include/ipmitool/ipmi_fru.h
|
||||
index 4d4d6c6..e7e8876 100644
|
||||
--- a/include/ipmitool/ipmi_fru.h
|
||||
+++ b/include/ipmitool/ipmi_fru.h
|
||||
@@ -46,6 +46,7 @@
|
||||
#define GET_FRU_INFO 0x10
|
||||
#define GET_FRU_DATA 0x11
|
||||
#define SET_FRU_DATA 0x12
|
||||
+#define FRU_AREA_COUNT 5
|
||||
|
||||
enum {
|
||||
FRU_CHASSIS_PARTNO,
|
||||
@@ -82,7 +83,7 @@ struct fru_header {
|
||||
uint8_t product;
|
||||
uint8_t multi;
|
||||
} offset;
|
||||
- uint8_t offsets[5];
|
||||
+ uint8_t offsets[FRU_AREA_COUNT];
|
||||
};
|
||||
uint8_t pad;
|
||||
uint8_t checksum;
|
||||
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
|
||||
index 3d1d8a1..2687635 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,
|
||||
#endif
|
||||
|
||||
/* Must move sections */
|
||||
- /* Section that can be modified are as follow
|
||||
- Chassis
|
||||
- Board
|
||||
- product */
|
||||
-
|
||||
- /* Chassis type field */
|
||||
- if (f_type == 'c' )
|
||||
+ /* IPMI FRU Spec does not specify the order of areas in the FRU.
|
||||
+ * Therefore, we must check each section's current offset in order to determine
|
||||
+ * which areas much be adjusted.
|
||||
+ */
|
||||
+
|
||||
+ /* The Internal Use Area does not require the area length be provided, so we must
|
||||
+ * work to calculate the length.
|
||||
+ */
|
||||
+ bool internal_move = false;
|
||||
+ uint8_t nearest_area = fru.size;
|
||||
+ uint8_t last_area = 0x00;
|
||||
+ uint32_t end_of_fru;
|
||||
+ if (header.offset.internal != 0 && header.offset.internal > header_offset)
|
||||
{
|
||||
- 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;
|
||||
+ internal_move = true;
|
||||
}
|
||||
- /* Board type field */
|
||||
- if ((f_type == 'c' ) || (f_type == 'b' ))
|
||||
+ /* Check Chassis, Board, Product, and Multirecord Area offsets to see if they need
|
||||
+ * to be moved.
|
||||
+ */
|
||||
+ for (int i = 0; i < FRU_AREA_COUNT; i++)
|
||||
{
|
||||
- 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;
|
||||
+ #ifdef DBG_RESIZE_FRU
|
||||
+ printf("Offset: %i", header.offsets[i] * 8);
|
||||
+ #endif
|
||||
+ /* Offset of zero means area does not exist.
|
||||
+ * Internal Use Area must be handled separately
|
||||
+ */
|
||||
+ if (header.offsets[i] <= 0 || header.offsets[i] == header.offset.internal)
|
||||
+ {
|
||||
+#ifdef DBG_RESIZE_FRU
|
||||
+ printf("\n");
|
||||
+#endif
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* Internal Use Area length will be calculated by finding the closest area
|
||||
+ * following it.
|
||||
+ */
|
||||
+ if (internal_move && header.offsets[i] > header.offset.internal &&
|
||||
+ header.offsets[i] < nearest_area)
|
||||
+ {
|
||||
+ nearest_area = header.offsets[i];
|
||||
+ }
|
||||
+ if (last_area < header.offsets[i])
|
||||
+ {
|
||||
+ last_area = header.offsets[i];
|
||||
+ end_of_fru = (header.offsets[i] + *(fru_data_old + (header.offsets[i] * 8) + 1)) * 8;
|
||||
+ if (header.offsets[i] == header.offset.multi)
|
||||
+ {
|
||||
+ end_of_fru = (header.offsets[i] + *(fru_data_old + (header.offsets[i] * 8) + 1)) * 8;
|
||||
+ }
|
||||
+ }
|
||||
+ if ((header.offsets[i] * 8) > header_offset)
|
||||
+ {
|
||||
+#ifdef DBG_RESIZE_FRU
|
||||
+ printf(" moving by %i bytes.", change_size_by_8 * 8);
|
||||
+#endif
|
||||
+ uint32_t length = *(fru_data_old + (header.offsets[i] * 8) + 1) * 8;
|
||||
+ /* MultiRecord Area length is third byte rather than second. */
|
||||
+ if(header.offsets[i] == header.offset.multi)
|
||||
+ {
|
||||
+ length = *(fru_data_old + (header.offsets[i] * 8) + 2) * 8;
|
||||
+ }
|
||||
+ memcpy(
|
||||
+ (fru_data_new + ((header.offsets[i] + change_size_by_8) * 8)),
|
||||
+ (fru_data_old + (header.offsets[i]) * 8),
|
||||
+ length
|
||||
+ );
|
||||
+ header.offsets[i] += change_size_by_8;
|
||||
+ }
|
||||
+#ifdef DBG_RESIZE_FRU
|
||||
+ printf("\n");
|
||||
+#endif
|
||||
}
|
||||
-
|
||||
- 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 (internal_move)
|
||||
+ {
|
||||
+ /* If the internal area is the final area in the FRU, then the only bearing
|
||||
+ * we have for the length of the FRU is the size of the FRU.
|
||||
+ */
|
||||
+ uint32_t length = nearest_area - header.offset.internal;
|
||||
+ memcpy(
|
||||
+ (fru_data_new + ((header.offset.internal + change_size_by_8) * 8)),
|
||||
+ (fru_data_old + (header.offset.internal) * 8),
|
||||
+ length
|
||||
+ );
|
||||
+ header.offset.internal += change_size_by_8;
|
||||
}
|
||||
|
||||
/* Adjust length of the section */
|
||||
@@ -5110,27 +5158,18 @@ 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
|
||||
+ /* 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,
|
||||
- fru.size - ((header.offset.product * 8) + product_len_new)
|
||||
- );
|
||||
+ end_of_fru += change_size_by_8 * 8;
|
||||
+ int length_of_erase = change_size_by_8 * -1 * 8;
|
||||
+#ifdef DBG_RESIZE_FRU
|
||||
+ printf("Erasing leftover data from %i to %i\n", end_of_fru, end_of_fru + length_of_erase);
|
||||
+#endif
|
||||
+ memset(fru_data_new + end_of_fru, 0, length_of_erase);
|
||||
}
|
||||
+ /* Step 7 assumes fru.size is the size of the new FRU. */
|
||||
+ fru.size += (change_size_by_8 * 8);
|
||||
}
|
||||
|
||||
/* Update only if it's fits padding length as defined in the spec, otherwise, it's an internal
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
PRIVATE ENTERPRISE NUMBERS
|
||||
|
||||
(last updated 2023-01-25)
|
||||
|
||||
SMI Network Management Private Enterprise Codes:
|
||||
|
||||
Prefix: iso.org.dod.internet.private.enterprise (1.3.6.1.4.1)
|
||||
|
||||
This file is https://www.iana.org/assignments/enterprise-numbers.txt
|
||||
This file has been reduced to entities signing CLAs with OpenBMC
|
||||
https://drive.google.com/drive/folders/1Ooi0RdTcaOWF1DWFJUAJDdN7tRKde7Nl
|
||||
|
||||
Decimal
|
||||
| Organization
|
||||
| | Contact
|
||||
| | | Email
|
||||
| | | |
|
||||
0
|
||||
Reserved
|
||||
Internet Assigned Numbers Authority
|
||||
iana&iana.org
|
||||
2
|
||||
IBM (https://w3.ibm.com/standards )
|
||||
Glenn Daly
|
||||
gdaly&us.ibm.com
|
||||
343
|
||||
Intel Corporation
|
||||
Adam Kaminski
|
||||
adam.kaminski&intel.com
|
||||
674
|
||||
Dell Inc.
|
||||
David L. Douglas
|
||||
david_l_douglas&dell.com
|
||||
1694
|
||||
HCL Technologies Limited
|
||||
Ms. Bindu Dandapani
|
||||
bindud&hcl.in
|
||||
2487
|
||||
Phoenix Technologies Ltd.
|
||||
Ian Anderson
|
||||
ian_anderson&phoenix.com
|
||||
4128
|
||||
ARM Ltd.
|
||||
Jon Brawn
|
||||
jbrawn&arm.com
|
||||
6569
|
||||
INVENTEC CORPORATION
|
||||
JH CHYAN
|
||||
chyan.jh&inventec.com
|
||||
7244
|
||||
Quanta Computer Inc.
|
||||
Strong Chen
|
||||
&strong.chen&quantatw.com
|
||||
8554
|
||||
Departement Elektrotechnik, ETH Zuerich
|
||||
Simon Moser
|
||||
smoser&ee.ethz.ch
|
||||
11129
|
||||
Google, Inc.
|
||||
Ben Laurie
|
||||
benl&google.com
|
||||
11183
|
||||
Mitac International Corp.
|
||||
P.C. Wang
|
||||
p.c.wang&mic.com.tw
|
||||
19046
|
||||
Lenovo Enterprise Business Group
|
||||
Joe Bolan
|
||||
jbolan&lenovo.com
|
||||
20974
|
||||
American Megatrends, Inc
|
||||
Kenny Chiang
|
||||
kennychiang&ami.com.tw
|
||||
33049
|
||||
Mellanox Technologies LTD
|
||||
Sagi Rotem
|
||||
sagir&mellanox.co.il
|
||||
40092
|
||||
Wiwynn Corporation
|
||||
Zong Bing, Wu
|
||||
bing_wu&wiwynn.com
|
||||
40981
|
||||
Facebook, Inc.
|
||||
Neal Poole
|
||||
iana-assign&fb.com
|
||||
42817
|
||||
IBM Platform Firmware Division
|
||||
Jayashankar Padath
|
||||
jayashankar.padath&in.ibm.com
|
||||
45065
|
||||
Insyde
|
||||
Y.C. Lin
|
||||
yc.lin&insyde.com
|
||||
48482
|
||||
Linaro Ltd
|
||||
Dave Pigott
|
||||
dave.pigott&linaro.org
|
||||
48512
|
||||
Inspur Group Co.,Ltd.
|
||||
Chunpeng Mao
|
||||
Maochp&inspur.com
|
||||
49150
|
||||
Vertiv Co
|
||||
John Bogdan
|
||||
john.bogdan&vertivco.com
|
||||
49622
|
||||
ASRock Rack Incorporation
|
||||
Jeff Chan
|
||||
jeff9_chan&asrockrack.com
|
||||
49769
|
||||
YADRO
|
||||
Support
|
||||
snmp&yadro.com
|
||||
51974
|
||||
Raptor Computing Systems, LLC
|
||||
Support Department
|
||||
support&raptorcs.com
|
||||
52538
|
||||
Ampere Computing
|
||||
AJ Shah
|
||||
aj&erecomputing.com
|
||||
52893
|
||||
Inspur Power Systems Co.,Ltd.
|
||||
Bing Liu
|
||||
liubing&inspur.com
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from typing import List
|
||||
|
||||
from sh import curl # type: ignore
|
||||
|
||||
ENTERPRISES = {
|
||||
0: "Reserved",
|
||||
2: "IBM",
|
||||
343: "Intel Corporation",
|
||||
674: "Dell Inc.",
|
||||
1694: "HCL Technologies Limited",
|
||||
2487: "Phoenix Technologies Ltd.",
|
||||
4128: "ARM Ltd.",
|
||||
6569: "INVENTEC CORPORATION",
|
||||
7244: "Quanta Computer Inc.",
|
||||
8554: "Departement Elektrotechnik, ETH Zuerich",
|
||||
11129: "Google, Inc.",
|
||||
11183: "Mitac International Corp.",
|
||||
19046: "Lenovo Enterprise Business Group",
|
||||
20974: "American Megatrends, Inc",
|
||||
33049: "Mellanox Technologies LTD",
|
||||
40092: "Wiwynn Corporation",
|
||||
40981: "Facebook, Inc.",
|
||||
42817: "IBM Platform Firmware Division",
|
||||
45065: "Insyde",
|
||||
48482: "Linaro Ltd",
|
||||
48512: "Inspur Group Co.,Ltd.",
|
||||
49150: "Vertiv Co",
|
||||
49622: "ASRock Rack Incorporation",
|
||||
49769: "YADRO",
|
||||
51974: "Raptor Computing Systems, LLC",
|
||||
52538: "Ampere Computing",
|
||||
52893: "Inspur Power Systems Co.,Ltd.",
|
||||
}
|
||||
|
||||
HEADER = """\
|
||||
This file has been reduced to entities signing CLAs with OpenBMC
|
||||
https://drive.google.com/drive/folders/1Ooi0RdTcaOWF1DWFJUAJDdN7tRKde7Nl\
|
||||
"""
|
||||
|
||||
found_first: bool = False
|
||||
org: List[str] = []
|
||||
|
||||
for ln in curl(
|
||||
"-L", "https://www.iana.org/assignments/enterprise-numbers.txt"
|
||||
).splitlines():
|
||||
line = ln.rstrip()
|
||||
|
||||
# Look for Reserved/EN-0 as the start of the data.
|
||||
if "0" == line:
|
||||
found_first = True
|
||||
|
||||
# Haven't found EN-0, emit as is.
|
||||
if not found_first:
|
||||
print(line)
|
||||
# Look for magic string.
|
||||
if line.startswith("This file is "):
|
||||
print(HEADER)
|
||||
continue
|
||||
|
||||
# Add line into 'org' set.
|
||||
org.append(line)
|
||||
|
||||
# Every 4 lines (EN, Org, Contact, Email) make an org.
|
||||
if len(org) == 4:
|
||||
if int(org[0]) in ENTERPRISES:
|
||||
for g in org:
|
||||
print(g)
|
||||
|
||||
org = []
|
||||
Reference in New Issue
Block a user