From patchwork Mon Oct 14 13:29:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1176367 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=monstr-eu.20150623.gappssmtp.com header.i=@monstr-eu.20150623.gappssmtp.com header.b="AII9w1mW"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46sKFC6TrFz9s4Y for ; Tue, 15 Oct 2019 00:30:39 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 76093C21E47; Mon, 14 Oct 2019 13:29:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 5475EC21E13; Mon, 14 Oct 2019 13:29:41 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 74EA0C21D8A; Mon, 14 Oct 2019 13:29:24 +0000 (UTC) Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) by lists.denx.de (Postfix) with ESMTPS id 058A7C21CB1 for ; Mon, 14 Oct 2019 13:29:22 +0000 (UTC) Received: by mail-wr1-f65.google.com with SMTP id o18so19704528wrv.13 for ; Mon, 14 Oct 2019 06:29:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monstr-eu.20150623.gappssmtp.com; s=20150623; h=sender:from:to:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=HedqXzzeKHFfGbH+LDF3/63bOVIRnnIGUJclyeoaTS4=; b=AII9w1mWUcILT1vbbAoFWXLaDaK5JheGsnlbNA/tlLc6c6hMmn8kBsdgtFePUlrJba AhdVHB8rMcA2vyX3oTVwGQWlUqHCllLlAXD1ArQYeG8XtZLza6Kek2xNnHvuV+F0Oomw qUCpzfuuX33f3v3OO6Hs0o7s8ffbLPc2WYJwMhZN2A9xfo1QXU9VWO+EzHX5jvVukhk6 V52pIGR1z6I8kkc4Umh48EDXx8qtQh+HuB5oBzNUiuvcghdkjw53GM1Sq6TSTx6X9B1b wOwI1GU6mo3mHD6KqShVrEBoDqZVnnswePsSXbKtnT8Pr0VUavUrl9FFSo2nnCHDPch0 KdNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references:in-reply-to:references; bh=HedqXzzeKHFfGbH+LDF3/63bOVIRnnIGUJclyeoaTS4=; b=rdSXJwwWfBbU4M3XSaR1X5qQDLkbcC3t6Mc14HoJ8PHLKO5pC6svZaQbxGnnjpRjJ0 u4NYDmilt941bV/1IJ9gWQoUozH5/3zJjjcOwJyUBAiaArJzg9/ABLpNuM9eOk6F1EY2 rxxFkICgqrUpcel3Y0bJBM6xY0nEWz1Agw4e3172Gz5j9Dg8rDb778WAPowUCvhnEjt4 zCrdfpRrFsNUQ/pNZqgI4DgsEIp1F1vv4dyKceiSom9lFZ/K8gImXnuA9DW68oHVSebS XeIrPA90Zy1r6au6xyK1QvjjQSs3mJcHY+tScHFID6NDZr/6NAuJITTixq99iq9VQMfD rQZQ== X-Gm-Message-State: APjAAAXE2jwAc1377Qm9aGe+U1j60HV35iKbwN5Gb9iyUFWgVGC3rfJ9 VhDT1nvLDMS5GwiY/nBZ+9gcZ+893i1JIA== X-Google-Smtp-Source: APXvYqw+qYay7RR4T89pB8IhqXpFkfXm2t1i2Nn//9wquzJXW49kfnFq2MXvcZpghIUICF/p5WrFJg== X-Received: by 2002:adf:ed88:: with SMTP id c8mr7273866wro.214.1571059761223; Mon, 14 Oct 2019 06:29:21 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id u26sm18323338wrd.87.2019.10.14.06.29.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 14 Oct 2019 06:29:20 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Date: Mon, 14 Oct 2019 15:29:13 +0200 Message-Id: <7107f1af7f5f813ec1282fd1ac2c0c5aa50a9c52.1571059751.git.michal.simek@xilinx.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: Subject: [U-Boot] [PATCH 2/3] cmd: fru: Add basic fru format generator X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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. For example: fru board_gen 1000 XILINX versal-x-prc-01-revA serialX partX Signed-off-by: Michal Simek --- cmd/fru.c | 20 +++++++++- common/fru_ops.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ include/fru.h | 14 +++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/cmd/fru.c b/cmd/fru.c index d5e96cfe8984..3bbc4d272adb 100644 --- a/cmd/fru.c +++ b/cmd/fru.c @@ -31,9 +31,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, @@ -58,11 +72,15 @@ static char fru_help_text[] = "capture - 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 \n" + " - Generate FRU format with board info\n" + " area filled based on parameters. 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 ) diff --git a/common/fru_ops.c b/common/fru_ops.c index dd54bd9c0214..d9c00b12da03 100644 --- a/common/fru_ops.c +++ b/common/fru_ops.c @@ -58,6 +58,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; diff --git a/include/fru.h b/include/fru.h index 38fdfad409c4..09de266477d4 100644 --- a/include/fru.h +++ b/include/fru.h @@ -20,6 +20,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; @@ -58,6 +70,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;