
From: Graeme Gregory quic_ggregory@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@quicinc.com Signed-off-by: Jae Hyun Yoo quic_jaehyoo@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 */