]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
cmd: fru: Add basic fru format generator
authorMichal Simek <michal.simek@xilinx.com>
Mon, 15 Apr 2019 11:54:09 +0000 (13:54 +0200)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 6 Jun 2019 11:46:52 +0000 (13:46 +0200)
Idea is to have something what can be used for board bringup from
generic board perspective.

There is a violation compare to spec that FRU ID is ASCII8 instead of
binary format but this is really for having something to pass boot and
boot to OS which has better generating options.
Also time should be filled properly.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
cmd/fru.c
common/fru_ops.c
include/fru.h

index 5e3363ec26173eb33b6cea1e3ce5ef54b5c89dda..581f71debf44037533ec06e67b5d4eba85bb96f1 100644 (file)
--- a/cmd/fru.c
+++ b/cmd/fru.c
@@ -32,9 +32,23 @@ static int do_fru_display(cmd_tbl_t *cmdtp, int flag, int argc,
        return CMD_RET_SUCCESS;
 }
 
+static int do_fru_generate(cmd_tbl_t *cmdtp, int flag, int argc,
+                          char *const argv[])
+{
+       unsigned long addr;
+
+       if (argc < cmdtp->maxargs)
+               return CMD_RET_USAGE;
+
+       addr = simple_strtoul(argv[2], NULL, 16);
+
+       return fru_generate(addr, argv[3], argv[4], argv[5], argv[6]);
+}
+
 static cmd_tbl_t cmd_fru_sub[] = {
        U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""),
        U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""),
+       U_BOOT_CMD_MKENT(board_gen, 7, 0, do_fru_generate, "", ""),
 };
 
 static int do_fru(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -60,11 +74,15 @@ static char fru_help_text[] =
        "fru capture <addr> - Parse and capture FRU table present at address.\n"
        "fru display - Displays content of FRU table that was captured using\n"
        "              fru capture command\n"
+       "fru board_gen <addr> <manufacturer> <board name> <serial number>\n"
+       "              <part number> - Generate FRU format with board info\n"
+       "              area filled based on parameters. <addr> is pointing\n"
+       "              to place where FRU is generated.\n"
        ;
 #endif
 
 U_BOOT_CMD(
-       fru, 3, 1, do_fru,
+       fru, 7, 1, do_fru,
        "FRU table info",
        fru_help_text
 )
index 3c9d280453673474a7a3bc2ac4966522a4d4dca3..f96ee5529c6b30032b6c407645469e33a96fcea4 100644 (file)
@@ -59,6 +59,101 @@ static int fru_check_type_len(u8 type_len, u8 language, u8 *type)
        return len;
 }
 
+/* Return len */
+static u8 fru_gen_type_len(u8 *addr, char *name)
+{
+       int len = strlen(name);
+       struct fru_board_info_member *member;
+
+       member = (struct fru_board_info_member *)addr;
+       member->type_len = FRU_TYPELEN_TYPE_ASCII8 << FRU_TYPELEN_TYPE_SHIFT;
+       member->type_len |= len;
+
+       debug("%lx/%lx: Add %s to 0x%lx (len 0x%x)\n", (ulong)addr,
+             (ulong)&member->type_len,  name, (ulong)&member->name, len);
+       memcpy(&member->name, name, len);
+
+       /* Add +1 for type_len parameter */
+       return 1 + len;
+}
+
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+                char *serial_no, char *part_no)
+{
+       struct fru_common_hdr *header = (struct fru_common_hdr *)addr;
+       struct fru_board_info_header *board_info;
+       u8 *member;
+       u8 len, pad, modulo;
+
+       header->version = 1; /* Only version 1.0 is supported now */
+       header->off_internal = 0; /* not present */
+       header->off_chassis = 0; /* not present */
+       header->off_board = (sizeof(*header)) / 8; /* Starting offset 8 */
+       header->off_product = 0; /* not present */
+       header->off_multirec = 0; /* not present */
+       header->pad = 0;
+       /*
+        * This unsigned byte can be used to calculate a zero checksum
+        * for the data area following the header. I.e. the modulo 256 sum of
+        * the record data bytes plus the checksum byte equals zero.
+        */
+       header->crc = 0; /* Clear before calculation */
+       header->crc = 0 - fru_checksum((u8 *)header, sizeof(*header));
+
+       /* board info is just right after header */
+       board_info = (void *)((u8 *)header + sizeof(*header));
+
+       debug("header %lx, board_info %lx\n", (ulong)header, (ulong)board_info);
+
+       board_info->ver = 1; /* 1.0 spec */
+       board_info->lang_code = 0; /* English */
+       board_info->time[0] = 0; /* unspecified */
+       board_info->time[1] = 0; /* unspecified */
+       board_info->time[2] = 0; /* unspecified */
+
+       /* Member fields are just after board_info header */
+       member = (u8 *)board_info + sizeof(*board_info);
+
+       len = fru_gen_type_len(member, manufacturer); /* Board Manufacturer */
+       member += len;
+       len = fru_gen_type_len(member, board_name); /* Board Product name */
+       member += len;
+       len = fru_gen_type_len(member, serial_no); /* Board Serial number */
+       member += len;
+       len = fru_gen_type_len(member, part_no); /* Board part number */
+       member += len;
+       len = fru_gen_type_len(member, "U-Boot generator"); /* File ID */
+       member += len;
+
+       *member++ = 0xc1; /* Indication of no more fields */
+
+       len = member - (u8 *)board_info; /* Find current length */
+       len += 1; /* Add checksum there too for calculation */
+
+       modulo = len % 8;
+
+       if (modulo) {
+               /* Do not fill last item which is checksum */
+               for (pad = 0; pad < 8 - modulo; pad++)
+                       *member++ = 0;
+
+               /* Increase structure size */
+               len += 8 - modulo;
+       }
+
+       board_info->len = len / 8; /* Size in multiples of 8 bytes */
+
+       *member = 0; /* Clear before calculation */
+       *member = 0 - fru_checksum((u8 *)board_info, len);
+
+       debug("checksum %x(len %x)\n", *member, len);
+
+       env_set_hex("fru_addr", addr);
+       env_set_hex("filesize", len);
+
+       return 0;
+}
+
 static int fru_parse_board(unsigned long addr)
 {
        u8 i, type;
index 4c0bb836b2cc937d46c7007f3daa87ec91db42dc..704d6d93f0bbe15557aabb947cf452eab927038a 100644 (file)
@@ -21,6 +21,18 @@ struct fru_common_hdr {
 
 #define FRU_BOARD_MAX_LEN      32
 
+struct __packed fru_board_info_header {
+       u8 ver;
+       u8 len;
+       u8 lang_code;
+       u8 time[3];
+};
+
+struct __packed fru_board_info_member {
+       u8 type_len;
+       u8 *name;
+};
+
 struct fru_board_data {
        u8 ver;
        u8 len;
@@ -59,6 +71,8 @@ struct fru_table {
 
 int fru_display(void);
 int fru_capture(unsigned long addr);
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+                char *serial_no, char *part_no);
 
 extern struct fru_table fru_data;