From: Graeme Gregory <quic_ggreg...@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_ggreg...@quicinc.com>
Signed-off-by: Jae Hyun Yoo <quic_jaeh...@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

Reply via email to