Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
@@ -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&amperecomputing.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 = []