[RFC PATCH 1/2] cmd/fru: cmd/fru: move FRU handling support to common region
Jae Hyun Yoo
quic_jaehyoo at quicinc.com
Wed Jul 27 01:50:04 CEST 2022
From: Graeme Gregory <quic_ggregory at quicinc.com>
The FRU handling was added as a Xilinx board dependent support but it
would be useful for other boards too, so this commit moves the FRU
handling support to the common region to be enabled by CONFIG_CMD_FRU.
Since the Multirecord parsing logic should be implemented on each OEM
board specifically, it defines 'fru_parse_multirec' as a weak function
so that it can be replaced with the board specific implementation.
Signed-off-by: Graeme Gregory <quic_ggregory at quicinc.com>
Signed-off-by: Jae Hyun Yoo <quic_jaehyoo at quicinc.com>
---
board/xilinx/Kconfig | 8 ---
board/xilinx/common/Makefile | 3 --
board/xilinx/common/board.c | 63 +++++++++++++++++++----
cmd/Kconfig | 8 +++
cmd/Makefile | 1 +
{board/xilinx/common => cmd}/fru.c | 3 +-
common/Makefile | 2 +
{board/xilinx/common => common}/fru_ops.c | 37 ++++++-------
{board/xilinx/common => include}/fru.h | 15 +-----
9 files changed, 82 insertions(+), 58 deletions(-)
rename {board/xilinx/common => cmd}/fru.c (99%)
rename {board/xilinx/common => common}/fru_ops.c (93%)
rename {board/xilinx/common => include}/fru.h (85%)
diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig
index 17880661736d..110706b20fa3 100644
--- a/board/xilinx/Kconfig
+++ b/board/xilinx/Kconfig
@@ -74,11 +74,3 @@ config ZYNQ_GEM_I2C_MAC_OFFSET
Set the MAC offset for i2C.
endif
-
-config CMD_FRU
- bool "FRU information for product"
- help
- This option enables FRU commands to capture and display FRU
- information present in the device. The FRU Information is used
- to primarily to provide "inventory" information about the boards
- that the FRU Information Device is located on.
diff --git a/board/xilinx/common/Makefile b/board/xilinx/common/Makefile
index cdc3c9677432..e33baaae1159 100644
--- a/board/xilinx/common/Makefile
+++ b/board/xilinx/common/Makefile
@@ -8,6 +8,3 @@ obj-y += board.o
ifndef CONFIG_ARCH_ZYNQ
obj-$(CONFIG_DISPLAY_CPUINFO) += cpu-info.o
endif
-ifndef CONFIG_SPL_BUILD
-obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o
-endif
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 9b4aded466ab..061082dbe6d6 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -8,6 +8,7 @@
#include <efi.h>
#include <efi_loader.h>
#include <env.h>
+#include <fru.h>
#include <log.h>
#include <asm/global_data.h>
#include <asm/sections.h>
@@ -25,8 +26,6 @@
#include <linux/kernel.h>
#include <uuid.h>
-#include "fru.h"
-
#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
struct efi_fw_image fw_images[] = {
#if defined(XILINX_BOOT_IMAGE_GUID)
@@ -88,6 +87,9 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
#define EEPROM_HDR_NO_OF_MAC_ADDR 4
#define EEPROM_HDR_ETH_ALEN ETH_ALEN
#define EEPROM_HDR_UUID_LEN 16
+#define EEPROM_MULTIREC_TYPE_XILINX_OEM 0xD2
+#define EEPROM_MULTIREC_MAC_OFFSET 4
+#define EEPROM_MULTIREC_DUT_MACID 0x31
struct xilinx_board_description {
u32 header;
@@ -116,6 +118,14 @@ struct xilinx_legacy_format {
char unused3[29]; /* 0xe3 */
};
+struct fru_multirec_mac {
+ u8 xlnx_iana_id[3];
+ u8 ver;
+ u8 macid[EEPROM_HDR_NO_OF_MAC_ADDR][ETH_ALEN];
+};
+
+static u8 parsed_macid[EEPROM_HDR_NO_OF_MAC_ADDR][ETH_ALEN];
+
static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size)
{
int i;
@@ -197,9 +207,42 @@ static bool xilinx_detect_legacy(u8 *buffer)
return true;
}
+int fru_parse_multirec(unsigned long addr)
+{
+ u8 hdr_len = sizeof(struct fru_multirec_hdr);
+ struct fru_multirec_hdr mrc;
+ u8 checksum;
+ int mac_len;
+
+ debug("%s: multirec addr %lx\n", __func__, addr);
+
+ do {
+ memcpy(&mrc.rec_type, (void *)addr, hdr_len);
+
+ checksum = fru_checksum((u8 *)addr, hdr_len);
+ if (checksum) {
+ debug("%s header CRC error\n", __func__);
+ return -EINVAL;
+ }
+
+ if (mrc.rec_type == EEPROM_MULTIREC_TYPE_XILINX_OEM) {
+ struct fru_multirec_mac *mac = (void *)addr + hdr_len;
+
+ if (mac->ver == EEPROM_MULTIREC_DUT_MACID) {
+ mac_len = mrc.len - EEPROM_MULTIREC_MAC_OFFSET;
+ memcpy(parsed_macid, mac->macid, mac_len);
+ }
+ }
+ addr += mrc.len + hdr_len;
+ } while (!(mrc.type & FRU_LAST_REC));
+
+ return 0;
+}
+
static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
struct xilinx_board_description *desc)
{
+ const struct fru_table *fru_data;
int i, ret, eeprom_size;
u8 *fru_content;
u8 id = 0;
@@ -237,30 +280,32 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
goto end;
}
+ fru_data = fru_get_fru_data();
+
/* It is clear that FRU was captured and structures were filled */
- strlcpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
+ strlcpy(desc->manufacturer, (char *)fru_data->brd.manufacturer_name,
sizeof(desc->manufacturer));
- strlcpy(desc->uuid, (char *)fru_data.brd.uuid,
+ strlcpy(desc->uuid, (char *)fru_data->brd.uuid,
sizeof(desc->uuid));
- strlcpy(desc->name, (char *)fru_data.brd.product_name,
+ strlcpy(desc->name, (char *)fru_data->brd.product_name,
sizeof(desc->name));
for (i = 0; i < sizeof(desc->name); i++) {
if (desc->name[i] == ' ')
desc->name[i] = '\0';
}
- strlcpy(desc->revision, (char *)fru_data.brd.rev,
+ strlcpy(desc->revision, (char *)fru_data->brd.rev,
sizeof(desc->revision));
for (i = 0; i < sizeof(desc->revision); i++) {
if (desc->revision[i] == ' ')
desc->revision[i] = '\0';
}
- strlcpy(desc->serial, (char *)fru_data.brd.serial_number,
+ strlcpy(desc->serial, (char *)fru_data->brd.serial_number,
sizeof(desc->serial));
while (id < EEPROM_HDR_NO_OF_MAC_ADDR) {
- if (is_valid_ethaddr((const u8 *)fru_data.mac.macid[id]))
+ if (is_valid_ethaddr((const u8 *)parsed_macid[id]))
memcpy(&desc->mac_addr[id],
- (char *)fru_data.mac.macid[id], ETH_ALEN);
+ (char *)parsed_macid[id], ETH_ALEN);
id++;
}
diff --git a/cmd/Kconfig b/cmd/Kconfig
index a8260aa170d0..644c907bf83a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1053,6 +1053,14 @@ config CMD_FPGAD
fpga_get_reg() function. This functions similarly to the 'md'
command.
+config CMD_FRU
+ bool "FRU information for product"
+ help
+ This option enables FRU commands to capture and display FRU
+ information present in the device. The FRU Information is used
+ to primarily to provide "inventory" information about the boards
+ that the FRU Information Device is located on.
+
config CMD_FUSE
bool "fuse - support for the fuse subssystem"
help
diff --git a/cmd/Makefile b/cmd/Makefile
index 5e43a1e022e8..10a18d02eb08 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_CMD_SQUASHFS) += sqfs.o
obj-$(CONFIG_CMD_FLASH) += flash.o
obj-$(CONFIG_CMD_FPGA) += fpga.o
obj-$(CONFIG_CMD_FPGAD) += fpgad.o
+obj-$(CONFIG_CMD_FRU) += fru.o
obj-$(CONFIG_CMD_FS_GENERIC) += fs.o
obj-$(CONFIG_CMD_FUSE) += fuse.o
obj-$(CONFIG_CMD_GETTIME) += gettime.o
diff --git a/board/xilinx/common/fru.c b/cmd/fru.c
similarity index 99%
rename from board/xilinx/common/fru.c
rename to cmd/fru.c
index f6ca46c3cecc..dd0b56f05698 100644
--- a/board/xilinx/common/fru.c
+++ b/cmd/fru.c
@@ -6,10 +6,9 @@
#include <common.h>
#include <command.h>
#include <fdtdec.h>
+#include <fru.h>
#include <malloc.h>
-#include "fru.h"
-
static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
diff --git a/common/Makefile b/common/Makefile
index 2ed8672c3ac1..d5c9de33ac07 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -112,3 +112,5 @@ obj-$(CONFIG_$(SPL_TPL_)STACKPROTECTOR) += stackprot.o
obj-$(CONFIG_SCP03) += scp03.o
obj-$(CONFIG_QFW) += qfw.o
+
+obj-$(CONFIG_CMD_FRU) += fru_ops.o
diff --git a/board/xilinx/common/fru_ops.c b/common/fru_ops.c
similarity index 93%
rename from board/xilinx/common/fru_ops.c
rename to common/fru_ops.c
index 49846ae3d660..0c5e264226ed 100644
--- a/board/xilinx/common/fru_ops.c
+++ b/common/fru_ops.c
@@ -9,7 +9,6 @@
#include <fdtdec.h>
#include <log.h>
#include <malloc.h>
-#include <net.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
@@ -219,12 +218,11 @@ static int fru_parse_board(unsigned long addr)
return 0;
}
-static int fru_parse_multirec(unsigned long addr)
+__weak int fru_parse_multirec(unsigned long addr)
{
- struct fru_multirec_hdr mrc;
- u8 checksum = 0;
u8 hdr_len = sizeof(struct fru_multirec_hdr);
- int mac_len = 0;
+ struct fru_multirec_hdr mrc;
+ u8 checksum;
debug("%s: multirec addr %lx\n", __func__, addr);
@@ -237,14 +235,9 @@ static int fru_parse_multirec(unsigned long addr)
return -EINVAL;
}
- if (mrc.rec_type == FRU_MULTIREC_TYPE_OEM) {
- struct fru_multirec_mac *mac = (void *)addr + hdr_len;
+ debug("%s: multirec rec_type: 0x%x, type: 0x%x, len: %d\n",
+ __func__, mrc.rec_type, mrc.type, mrc.len);
- if (mac->ver == FRU_DUT_MACID) {
- mac_len = mrc.len - FRU_MULTIREC_MAC_OFFSET;
- memcpy(&fru_data.mac.macid, mac->macid, mac_len);
- }
- }
addr += mrc.len + hdr_len;
} while (!(mrc.type & FRU_LAST_REC));
@@ -255,7 +248,6 @@ int fru_capture(unsigned long addr)
{
struct fru_common_hdr *hdr;
u8 checksum = 0;
- unsigned long multirec_addr = addr;
checksum = fru_checksum((u8 *)addr, sizeof(struct fru_common_hdr));
if (checksum) {
@@ -270,17 +262,13 @@ int fru_capture(unsigned long addr)
fru_data.captured = true;
- if (hdr->off_board) {
- addr += fru_cal_area_len(hdr->off_board);
- fru_parse_board(addr);
- }
+ if (hdr->off_board)
+ fru_parse_board(addr + fru_cal_area_len(hdr->off_board));
- env_set_hex("fru_addr", addr);
+ if (hdr->off_multirec)
+ fru_parse_multirec(addr + fru_cal_area_len(hdr->off_multirec));
- if (hdr->off_multirec) {
- multirec_addr += fru_cal_area_len(hdr->off_multirec);
- fru_parse_multirec(multirec_addr);
- }
+ env_set_hex("fru_addr", addr);
return 0;
}
@@ -413,3 +401,8 @@ int fru_display(int verbose)
return fru_display_board(&fru_data.brd, verbose);
}
+
+const struct fru_table *fru_get_fru_data(void)
+{
+ return &fru_data;
+}
diff --git a/board/xilinx/common/fru.h b/include/fru.h
similarity index 85%
rename from board/xilinx/common/fru.h
rename to include/fru.h
index 59f6b722cf12..b497a8835695 100644
--- a/board/xilinx/common/fru.h
+++ b/include/fru.h
@@ -6,7 +6,6 @@
#ifndef __FRU_H
#define __FRU_H
-#include <net.h>
struct fru_common_hdr {
u8 version;
@@ -20,7 +19,6 @@ struct fru_common_hdr {
};
#define FRU_BOARD_MAX_LEN 32
-#define FRU_MAX_NO_OF_MAC_ADDR 4
struct __packed fru_board_info_header {
u8 ver;
@@ -66,16 +64,9 @@ struct fru_multirec_hdr {
u8 hdr_csum;
};
-struct fru_multirec_mac {
- u8 xlnx_iana_id[3];
- u8 ver;
- u8 macid[FRU_MAX_NO_OF_MAC_ADDR][ETH_ALEN];
-};
-
struct fru_table {
struct fru_common_hdr hdr;
struct fru_board_data brd;
- struct fru_multirec_mac mac;
bool captured;
};
@@ -86,10 +77,7 @@ struct fru_table {
#define FRU_LANG_CODE_ENGLISH 0
#define FRU_LANG_CODE_ENGLISH_1 25
#define FRU_TYPELEN_EOF 0xC1
-#define FRU_MULTIREC_TYPE_OEM 0xD2
-#define FRU_MULTIREC_MAC_OFFSET 4
#define FRU_LAST_REC BIT(7)
-#define FRU_DUT_MACID 0x31
/* This should be minimum of fields */
#define FRU_BOARD_AREA_TOTAL_FIELDS 5
@@ -102,7 +90,6 @@ int fru_capture(unsigned long addr);
int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
char *serial_no, char *part_no, char *revision);
u8 fru_checksum(u8 *addr, u8 len);
-
-extern struct fru_table fru_data;
+const struct fru_table *fru_get_fru_data(void);
#endif /* FRU_H */
--
2.25.1
More information about the U-Boot
mailing list