@@ -171,6 +171,7 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
{
int i, ret, eeprom_size;
u8 *fru_content;
+ u8 id = 0;
/* FIXME this is shortcut - if eeprom type is wrong it will fail */
eeprom_size = i2c_eeprom_size(dev);
@@ -218,6 +219,14 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
sizeof(desc->revision));
strncpy(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]))
+ memcpy(&desc->mac_addr[id],
+ (char *)fru_data.mac.macid[id], ETH_ALEN);
+ id++;
+ }
+
desc->header = EEPROM_HEADER_MAGIC;
end:
@@ -6,6 +6,7 @@
#ifndef __FRU_H
#define __FRU_H
+#include <net.h>
struct fru_common_hdr {
u8 version;
@@ -19,6 +20,7 @@ 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;
@@ -56,9 +58,24 @@ struct fru_board_data {
u8 uuid[FRU_BOARD_MAX_LEN];
};
+struct fru_multirec_hdr {
+ u8 rec_type;
+ u8 type;
+ u8 len;
+ u8 csum;
+ 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;
};
@@ -69,6 +86,10 @@ 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
@@ -9,6 +9,7 @@
#include <fdtdec.h>
#include <log.h>
#include <malloc.h>
+#include <net.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
@@ -218,10 +219,43 @@ 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;
+
+ 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));
+
+ 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) {
@@ -243,6 +277,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;
}