]> Git Repo - u-boot.git/blobdiff - board/xilinx/common/fru_ops.c
Restore patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"
[u-boot.git] / board / xilinx / common / fru_ops.c
index 44f0913f2eb776a5861aa01b6934fc640b6ee48a..610293bccf78d96c2f2e5826dae54f115ba41868 100644 (file)
@@ -1,20 +1,22 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * (C) Copyright 2019 - 2020 Xilinx, Inc.
+ * (C) Copyright 2019 - 2022, Xilinx, Inc.
+ * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc.
  */
 
-#include <common.h>
 #include <cpu_func.h>
 #include <env.h>
 #include <fdtdec.h>
 #include <log.h>
 #include <malloc.h>
+#include <net.h>
+#include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
 
 #include "fru.h"
 
-struct fru_table fru_data __section(.data);
+struct fru_table fru_data __section(".data");
 
 static u16 fru_cal_area_len(u8 len)
 {
@@ -39,12 +41,20 @@ static int fru_check_language(u8 code)
 u8 fru_checksum(u8 *addr, u8 len)
 {
        u8 checksum = 0;
+       u8 cnt = len;
 
        while (len--) {
+               if (*addr == 0)
+                       cnt--;
+
                checksum += *addr;
                addr++;
        }
 
+       /* If all data bytes are 0's return error */
+       if (!cnt)
+               return EINVAL;
+
        return checksum;
 }
 
@@ -52,9 +62,6 @@ static int fru_check_type_len(u8 type_len, u8 language, u8 *type)
 {
        int len;
 
-       if (type_len == FRU_TYPELEN_EOF)
-               return -EINVAL;
-
        *type = (type_len & FRU_TYPELEN_CODE_MASK) >> FRU_TYPELEN_TYPE_SHIFT;
 
        len = type_len & FRU_TYPELEN_LEN_MASK;
@@ -163,9 +170,16 @@ static int fru_parse_board(unsigned long addr)
 {
        u8 i, type;
        int len;
-       u8 *data, *term, *limit;
+       u8 *data, *term, *limit, *next_addr, *eof;
 
        memcpy(&fru_data.brd.ver, (void *)addr, 6);
+
+       /*
+        * eof marks the last data byte (without checksum). That's why checksum
+        * is address length - 1 and last data byte is length - 2.
+        */
+       eof = (u8 *)(fru_data.brd.len * 8 + addr - 2);
+
        addr += 6;
        data = (u8 *)&fru_data.brd.manufacturer_type_len;
 
@@ -175,10 +189,21 @@ static int fru_parse_board(unsigned long addr)
        for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) {
                len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code,
                                         &type);
+               next_addr = (u8 *)addr + 1;
+
+               if ((u8 *)addr >= eof) {
+                       debug("Reach EOF record: addr %lx, eof %lx\n", addr,
+                             (unsigned long)eof);
+                       break;
+               }
+
                /*
-                * Stop cature if it end of fields
+                * Stop capture if the type is ASCII and valid field length
+                * is 1 (0xc1) and next FRU data is less than 0x20 (space " ")
+                * or it is 0x7f (delete 'DEL').
                 */
-               if (len == -EINVAL)
+               if (type == FRU_TYPELEN_TYPE_ASCII8 && len == 1 &&
+                   (*next_addr < 0x20 || *next_addr == 0x7F))
                        break;
 
                /* Stop when amount of chars is more then fields to record */
@@ -210,10 +235,47 @@ static int fru_parse_board(unsigned long addr)
        return 0;
 }
 
+static 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;
+
+       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 == FRU_MULTIREC_TYPE_OEM) {
+                       struct fru_multirec_mac *mac = (void *)addr + hdr_len;
+                       u32 type = FRU_DUT_MACID;
+
+                       if (CONFIG_IS_ENABLED(FRU_SC))
+                               type = FRU_SC_MACID;
+
+                       if (mac->ver == type) {
+                               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));
+
+       return 0;
+}
+
 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) {
@@ -222,7 +284,7 @@ int fru_capture(unsigned long addr)
        }
 
        hdr = (struct fru_common_hdr *)addr;
-
+       memset((void *)&fru_data, 0, sizeof(fru_data));
        memcpy((void *)&fru_data, (void *)hdr,
               sizeof(struct fru_common_hdr));
 
@@ -235,6 +297,11 @@ int fru_capture(unsigned long addr)
 
        env_set_hex("fru_addr", addr);
 
+       if (hdr->off_multirec) {
+               multirec_addr += fru_cal_area_len(hdr->off_multirec);
+               fru_parse_multirec(multirec_addr);
+       }
+
        return 0;
 }
 
@@ -281,9 +348,11 @@ static int fru_display_board(struct fru_board_data *brd, int verbose)
        for (u8 i = 0; i < (sizeof(boardinfo) / sizeof(*boardinfo)); i++) {
                len = fru_check_type_len(*data++, brd->lang_code,
                                         &type);
-               if (len == -EINVAL) {
-                       printf("**** EOF for Board Area ****\n");
-                       break;
+
+               /* Empty record has no len/type filled */
+               if (!len) {
+                       debug("%s not found\n", boardinfo[i]);
+                       continue;
                }
 
                if (type <= FRU_TYPELEN_TYPE_ASCII8 &&
@@ -293,11 +362,6 @@ static int fru_display_board(struct fru_board_data *brd, int verbose)
                else
                        debug("Type code: %s\n", typecode[type + 1]);
 
-               if (!len) {
-                       debug("%s not found\n", boardinfo[i]);
-                       continue;
-               }
-
                switch (type) {
                case FRU_TYPELEN_TYPE_BINARY:
                        debug("Length: %d\n", len);
This page took 0.032693 seconds and 4 git commands to generate.