From patchwork Tue Oct 20 14:50:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1384982 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.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.a=rsa-sha256 header.s=20150623 header.b=mLO8Ar0C; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CFxQ91TLmz9sPB for ; Wed, 21 Oct 2020 01:50:57 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0B7C0823D4; Tue, 20 Oct 2020 16:50:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; 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="mLO8Ar0C"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9DC6081B79; Tue, 20 Oct 2020 16:50:40 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 78A2A81B79 for ; Tue, 20 Oct 2020 16:50:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=monstr@monstr.eu Received: by mail-wr1-x442.google.com with SMTP id t9so2494357wrq.11 for ; Tue, 20 Oct 2020 07:50:37 -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 :mime-version:content-transfer-encoding; bh=753oGtanOPjruG7VSAPKSMzKKoxgJUf3rvw+BlQKDWQ=; b=mLO8Ar0CFUcIPxRSKArErEzsteIJV78ANFuf/a7O4CWXtDIzdpGSxsZJT5Xrvrnr7y 3PymQnLvIIadWRF5VChKu89udUicM1Gm4hTvzLjTDFnyuM/EKmXbk+WFfVdmtn/wQpa3 UDAPF9WFqObhUIsZLtTYaS09357fyWFciCROHI9Aqu7hiT2ogeVE6KSzRzOtm1NSG3lK 7MzPNo4vfxxORf/Fe/IznBeC92wazBVJqBaqImUktSEmS2iubFS7LIDT/AzraZUcLfT7 UdH+NLyhiIIg9Mc+AUtrHK8R+KKCVSJZuvrowtzERj8Ozm4AF0w9rH8CTYjHwHXNOo1m Tiuw== 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:mime-version:content-transfer-encoding; bh=753oGtanOPjruG7VSAPKSMzKKoxgJUf3rvw+BlQKDWQ=; b=G9jPSwzvp/Fi8vMAt0zhxMBO/+u9ZrhhB7MlNnXfpeOlivEn8GSH5xMf2VaekaH8ol A4yB2gT5XnW/Dt6c+vYIFgU1JMIZMJA+1v2eXr5M7mTHe1aRH1sJfLiFEWfER9jpoPgl aQvZaL8KNSnFW8pLOWI6Bcnrl5REMFV3qBIGhcnrnihUTfLtS3HpRzL5gja427L8Mqjf JOlrhASBF7Pt7tjsXuFaiDHVk1LZVj93JuDBv117yWxANe0SjSf1EF5Qj20TlvAJ8dsc YvCsg4vXaJ9U4xmn2yIvem8XEtG/dk/nuV9VdV++eiJEAIt2dzyxvFiXlvmhTNTWJXD2 ldBw== X-Gm-Message-State: AOAM533UW99E5OBCm+fAdaLqnyLf8TMAwSSBlwkwVW1MHoQPBObZh5+S BtyQA1GGa7CUAkrja8ryfB5vQ6LAwmDkBVdR X-Google-Smtp-Source: ABdhPJwSgVp7gCXtBvokMdwf5AWNe2Q9V74R39xCl6uPiBXIrxEcPAbpnWyY43AlVQq7PaLK+8VinQ== X-Received: by 2002:adf:ef83:: with SMTP id d3mr3957156wro.393.1603205436602; Tue, 20 Oct 2020 07:50:36 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id d2sm3471314wrq.34.2020.10.20.07.50.36 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 20 Oct 2020 07:50:36 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Subject: [PATCH 1/4] xilinx: common: Add Makefile to common folder Date: Tue, 20 Oct 2020 16:50:27 +0200 Message-Id: <9d6e0d0213b2a4e927ef8e2b0ca330f270368eb3.1603205426.git.michal.simek@xilinx.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean There is no need to reference files in common folder back. Simply adding Makefile to this folder does the job because this "common" location is already wired in main Makefile. Signed-off-by: Michal Simek --- board/xilinx/common/Makefile | 7 +++++++ board/xilinx/versal/Makefile | 1 - board/xilinx/zynq/Makefile | 1 - board/xilinx/zynqmp/Makefile | 1 - 4 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 board/xilinx/common/Makefile diff --git a/board/xilinx/common/Makefile b/board/xilinx/common/Makefile new file mode 100644 index 000000000000..3600da464b87 --- /dev/null +++ b/board/xilinx/common/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# (C) Copyright 2020 Xilinx, Inc. +# Michal Simek +# + +obj-y += board.o diff --git a/board/xilinx/versal/Makefile b/board/xilinx/versal/Makefile index 90e034315406..4a46ca02d705 100644 --- a/board/xilinx/versal/Makefile +++ b/board/xilinx/versal/Makefile @@ -6,4 +6,3 @@ obj-y := board.o obj-$(CONFIG_CMD_VERSAL) += cmds.o -obj-y += ../common/board.o diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile index 096a7aceb939..856617158917 100644 --- a/board/xilinx/zynq/Makefile +++ b/board/xilinx/zynq/Makefile @@ -4,7 +4,6 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y := board.o -obj-y += ../common/board.o ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"") PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE)) diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 398c6aaa452a..7d8277ca4004 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -4,7 +4,6 @@ # Michal Simek obj-y := zynqmp.o -obj-y += ../common/board.o ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"") PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE)) From patchwork Tue Oct 20 14:50:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1384983 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.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.a=rsa-sha256 header.s=20150623 header.b=qswOVCrk; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CFxQT2ZK7z9sPB for ; Wed, 21 Oct 2020 01:51:13 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 00F0E82432; Tue, 20 Oct 2020 16:50:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; 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="qswOVCrk"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9A240823DD; Tue, 20 Oct 2020 16:50:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3684B81260 for ; Tue, 20 Oct 2020 16:50:39 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=monstr@monstr.eu Received: by mail-wm1-x330.google.com with SMTP id c77so2088067wmd.4 for ; Tue, 20 Oct 2020 07:50:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monstr-eu.20150623.gappssmtp.com; s=20150623; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3CnlUUFoNd6QVxFIHCXk3us8RdDOn7q09iM4mZCLCjs=; b=qswOVCrklikqeUXYwmyc5NXLWOez08vspZ7/X8cMZPvlF1nReIo1vF8VZOTC8GqMmx C8YrGMQ7ne0V3anz/ru3V22htFaaq5hLvRq1YhRtjVO7CIPNJo8VY+SSE68njPmIdiw3 gs0elOBtqKTz/GVbTZrStzprDOR1vaBwWlXoFezOXajysaBbYH8bT1ykfViP2jIB/mvX sB8RzXfBq5M/2cTPmvx5GUOcSy0n9BrE8eM6fp3fDIoRiuWCh7eGiKhccqZRTaMk+5CC 3ZE6Fzn/U2ShoLVT563wxkVFtTFYMcgOpVHKWILuh9tIXx16ZKqC01VZUPvO8gtWKzCr NVUA== 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:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=3CnlUUFoNd6QVxFIHCXk3us8RdDOn7q09iM4mZCLCjs=; b=X6d9UJR+OKGF/Dnw+Zi19YsVtFxP+TShtsXcIKwW+KMWkQK58OQRc91vNj/Bq+2Bcn 2jV13aQYpgzyx9xwl6H6h/o5GO/rGRhDN7f7GgP3YLsM7bXaiMMME54DTNbMeqmpWiRF p538T+8xMHftY9mZX/65E0OHYdwB1zUJnAT12H2Of/rEaP9h6gZdtrvnzYTfVxQAVX+e clyYP+ar82jrHZv3XPbP2yepoJ9F0prpiBWYoP1Z2ADhDdLwNyeVzkDoy1OozAFagFku 0BxbsoW4+BWD9jPYCrANNNhozRv9u04zeWV00bDwMOFsMXRJhuiLGTqcPQZBUKBTty++ Ljtw== X-Gm-Message-State: AOAM531xlhbQZpzI5bH3uRuo9tQeqYi6jp5Epd8bWX0iHMlAMMry72cr 7NHWXdfiCABr25WpSiwpW7pjVmkJy2vahyl5 X-Google-Smtp-Source: ABdhPJzPwQGr9rKa6hw662SuXUsu5fSoeQjDV5koSsI+wOUuT3BC4bFcF780I2x8393/jvgDfxrnlA== X-Received: by 2002:a7b:c7c9:: with SMTP id z9mr3307723wmk.136.1603205438206; Tue, 20 Oct 2020 07:50:38 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id o186sm3091279wmb.12.2020.10.20.07.50.37 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 20 Oct 2020 07:50:37 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Cc: Siva Durga Prasad Paladugu , Michal Simek , T Karthik Reddy Subject: [PATCH 2/4] xilinx: cmd: Add support for FRU commands Date: Tue, 20 Oct 2020 16:50:28 +0200 Message-Id: X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean From: Siva Durga Prasad Paladugu This patch adds support for fru commands "fru capture" and "fru display". The fru capture parses the FRU table present at an address and stores in a structure for later use. The fru display prints the content of captured structured in a readable format. As of now, it supports only common header and board area of FRU. Also, it supports only English language code and ASCII8/BINARY formats. fru_data variable is placed to data section because fru parser can be called very early before bss is initialized. And also information needs to be shared that's why it is exported via header. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- board/xilinx/Kconfig | 8 + board/xilinx/common/Makefile | 3 + board/xilinx/common/fru.c | 73 +++++++++ board/xilinx/common/fru.h | 66 ++++++++ board/xilinx/common/fru_ops.c | 263 ++++++++++++++++++++++++++++++++ board/xilinx/zynqmp/MAINTAINERS | 1 + 6 files changed, 414 insertions(+) create mode 100644 board/xilinx/common/fru.c create mode 100644 board/xilinx/common/fru.h create mode 100644 board/xilinx/common/fru_ops.c diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig index 01d7f8eac1c9..51f6d2bac8ad 100644 --- a/board/xilinx/Kconfig +++ b/board/xilinx/Kconfig @@ -73,3 +73,11 @@ 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 3600da464b87..212028478c0e 100644 --- a/board/xilinx/common/Makefile +++ b/board/xilinx/common/Makefile @@ -5,3 +5,6 @@ # obj-y += board.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o +endif diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c new file mode 100644 index 000000000000..0ab9f2a78bd9 --- /dev/null +++ b/board/xilinx/common/fru.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 - 2020 Xilinx, Inc. + */ + +#include +#include +#include +#include + +#include "fru.h" + +static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + unsigned long addr; + char *endp; + + if (argc < cmdtp->maxargs) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[2], &endp, 16); + if (*argv[1] == 0 || *endp != 0) + return -1; + + return fru_capture(addr); +} + +static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + fru_display(1); + return CMD_RET_SUCCESS; +} + +static struct cmd_tbl cmd_fru_sub[] = { + U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""), + U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""), +}; + +static int do_fru(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct cmd_tbl *c; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + c = find_cmd_tbl(argv[1], &cmd_fru_sub[0], + ARRAY_SIZE(cmd_fru_sub)); + if (!c) + return CMD_RET_USAGE; + + ret = c->cmd(c, flag, argc, argv); + + return cmd_process_error(c, ret); +} + +/***************************************************/ +#ifdef CONFIG_SYS_LONGHELP +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" + ; +#endif + +U_BOOT_CMD( + fru, 3, 1, do_fru, + "FRU table info", + fru_help_text +) diff --git a/board/xilinx/common/fru.h b/board/xilinx/common/fru.h new file mode 100644 index 000000000000..a0413cf7f698 --- /dev/null +++ b/board/xilinx/common/fru.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Xilinx, Inc. + * Siva Durga Prasad Paladugu + */ + +#ifndef __FRU_H +#define __FRU_H + +struct fru_common_hdr { + u8 version; + u8 off_internal; + u8 off_chassis; + u8 off_board; + u8 off_product; + u8 off_multirec; + u8 pad; + u8 crc; +}; + +#define FRU_BOARD_MAX_LEN 32 + +struct fru_board_data { + u8 ver; + u8 len; + u8 lang_code; + u8 time[3]; + u8 manufacturer_type_len; + u8 manufacturer_name[FRU_BOARD_MAX_LEN]; + u8 product_name_type_len; + u8 product_name[FRU_BOARD_MAX_LEN]; + u8 serial_number_type_len; + u8 serial_number[FRU_BOARD_MAX_LEN]; + u8 part_number_type_len; + u8 part_number[FRU_BOARD_MAX_LEN]; + u8 file_id_type_len; + u8 file_id[FRU_BOARD_MAX_LEN]; +}; + +struct fru_table { + bool captured; + struct fru_common_hdr hdr; + struct fru_board_data brd; +}; + +#define FRU_TYPELEN_CODE_MASK 0xC0 +#define FRU_TYPELEN_LEN_MASK 0x3F +#define FRU_COMMON_HDR_VER_MASK 0xF +#define FRU_COMMON_HDR_LEN_MULTIPLIER 8 +#define FRU_LANG_CODE_ENGLISH 0 +#define FRU_LANG_CODE_ENGLISH_1 25 +#define FRU_TYPELEN_EOF 0xC1 + +/* This should be minimum of fields */ +#define FRU_BOARD_AREA_TOTAL_FIELDS 5 +#define FRU_TYPELEN_TYPE_SHIFT 6 +#define FRU_TYPELEN_TYPE_BINARY 0 +#define FRU_TYPELEN_TYPE_ASCII8 3 + +int fru_display(int verbose); +int fru_capture(unsigned long addr); +u8 fru_checksum(u8 *addr, u8 len); + +extern struct fru_table fru_data; + +#endif /* FRU_H */ diff --git a/board/xilinx/common/fru_ops.c b/board/xilinx/common/fru_ops.c new file mode 100644 index 000000000000..491e92a7afba --- /dev/null +++ b/board/xilinx/common/fru_ops.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 - 2020 Xilinx, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fru.h" + +struct fru_table fru_data __section(.data); + +static u16 fru_cal_area_len(u8 len) +{ + return len * FRU_COMMON_HDR_LEN_MULTIPLIER; +} + +static u8 fru_version(u8 ver) +{ + return ver & FRU_COMMON_HDR_VER_MASK; +} + +static int fru_check_language(u8 code) +{ + if (code != FRU_LANG_CODE_ENGLISH && code != FRU_LANG_CODE_ENGLISH_1) { + printf("FRU_ERROR: Only English Language is supported\n"); + return -EINVAL; + } + + return 0; +} + +u8 fru_checksum(u8 *addr, u8 len) +{ + u8 checksum = 0; + + while (len--) { + checksum += *addr; + addr++; + } + + return checksum; +} + +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; + + return len; +} + +static int fru_parse_board(unsigned long addr) +{ + u8 i, type; + int len; + u8 *data, *term; + + memcpy(&fru_data.brd.ver, (void *)addr, 6); + addr += 6; + data = (u8 *)&fru_data.brd.manufacturer_type_len; + + for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) { + len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code, + &type); + /* + * Stop cature if it end of fields + */ + if (len == -EINVAL) + break; + + /* This record type/len field */ + *data++ = *(u8 *)addr; + + /* Add offset to match data */ + addr += 1; + + /* If len is 0 it means empty field that's why skip writing */ + if (!len) + continue; + + /* Record data field */ + memcpy(data, (u8 *)addr, len); + term = data + (u8)len; + *term = 0; + addr += len; + } + + if (i < FRU_BOARD_AREA_TOTAL_FIELDS) { + printf("Board area require minimum %d fields\n", + FRU_BOARD_AREA_TOTAL_FIELDS); + return -EINVAL; + } + + return 0; +} + +int fru_capture(unsigned long addr) +{ + struct fru_common_hdr *hdr; + u8 checksum = 0; + + checksum = fru_checksum((u8 *)addr, sizeof(struct fru_common_hdr)); + if (checksum) { + printf("%s Common header CRC error\n", __func__); + return -EINVAL; + } + + hdr = (struct fru_common_hdr *)addr; + + memcpy((void *)&fru_data.hdr, (void *)hdr, + sizeof(struct fru_common_hdr)); + + fru_data.captured = true; + + if (hdr->off_board) { + addr += fru_cal_area_len(hdr->off_board); + fru_parse_board(addr); + } + + env_set_hex("fru_addr", addr); + + return 0; +} + +static int fru_display_board(struct fru_board_data *brd, int verbose) +{ + u32 time = 0; + u8 type; + int len; + u8 *data; + static const char * const typecode[] = { + "Binary/Unspecified", + "BCD plus", + "6-bit ASCII", + "8-bit ASCII", + "2-byte UNICODE" + }; + static const char * const boardinfo[] = { + "Manufacturer Name", + "Product Name", + "Serial No", + "Part Number", + "File ID" + }; + + if (verbose) { + printf("*****BOARD INFO*****\n"); + printf("Version:%d\n", fru_version(brd->ver)); + printf("Board Area Length:%d\n", fru_cal_area_len(brd->len)); + } + + if (fru_check_language(brd->lang_code)) + return -EINVAL; + + time = brd->time[2] << 16 | brd->time[1] << 8 | + brd->time[0]; + + if (verbose) + printf("Time in Minutes from 0:00hrs 1/1/96: %d\n", time); + + data = (u8 *)&brd->manufacturer_type_len; + + 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; + } + + if (type <= FRU_TYPELEN_TYPE_ASCII8 && + (brd->lang_code == FRU_LANG_CODE_ENGLISH || + brd->lang_code == FRU_LANG_CODE_ENGLISH_1)) + debug("Type code: %s\n", typecode[type]); + 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); + printf(" %s: 0x%x\n", boardinfo[i], *data); + break; + case FRU_TYPELEN_TYPE_ASCII8: + debug("Length: %d\n", len); + printf(" %s: %s\n", boardinfo[i], data); + break; + default: + debug("Unsupported type %x\n", type); + } + + data += FRU_BOARD_MAX_LEN; + } + + return 0; +} + +static void fru_display_common_hdr(struct fru_common_hdr *hdr, int verbose) +{ + if (!verbose) + return; + + printf("*****COMMON HEADER*****\n"); + printf("Version:%d\n", fru_version(hdr->version)); + if (hdr->off_internal) + printf("Internal Use Area Offset:%d\n", + fru_cal_area_len(hdr->off_internal)); + else + printf("*** No Internal Area ***\n"); + + if (hdr->off_chassis) + printf("Chassis Info Area Offset:%d\n", + fru_cal_area_len(hdr->off_chassis)); + else + printf("*** No Chassis Info Area ***\n"); + + if (hdr->off_board) + printf("Board Area Offset:%d\n", + fru_cal_area_len(hdr->off_board)); + else + printf("*** No Board Area ***\n"); + + if (hdr->off_product) + printf("Product Info Area Offset:%d\n", + fru_cal_area_len(hdr->off_product)); + else + printf("*** No Product Info Area ***\n"); + + if (hdr->off_multirec) + printf("MultiRecord Area Offset:%d\n", + fru_cal_area_len(hdr->off_multirec)); + else + printf("*** No MultiRecord Area ***\n"); +} + +int fru_display(int verbose) +{ + if (!fru_data.captured) { + printf("FRU data not available please run fru parse\n"); + return -EINVAL; + } + + fru_display_common_hdr(&fru_data.hdr, verbose); + + return fru_display_board(&fru_data.brd, verbose); +} diff --git a/board/xilinx/zynqmp/MAINTAINERS b/board/xilinx/zynqmp/MAINTAINERS index 04fc7f32fe86..9cd4f3f53efd 100644 --- a/board/xilinx/zynqmp/MAINTAINERS +++ b/board/xilinx/zynqmp/MAINTAINERS @@ -3,6 +3,7 @@ M: Michal Simek S: Maintained F: arch/arm/dts/zynqmp-* F: arch/arm/dts/avnet-ultra96* +F: board/xilinx/common/ F: board/xilinx/zynqmp/ F: include/configs/xilinx_zynqmp* F: configs/xilinx_zynqmp* From patchwork Tue Oct 20 14:50:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1384984 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.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.a=rsa-sha256 header.s=20150623 header.b=hP7ZivFS; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CFxQj6C9Hz9sPB for ; Wed, 21 Oct 2020 01:51:25 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 57D9282435; Tue, 20 Oct 2020 16:50:48 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; 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="hP7ZivFS"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AEB3182424; Tue, 20 Oct 2020 16:50:43 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9E96282361 for ; Tue, 20 Oct 2020 16:50:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=monstr@monstr.eu Received: by mail-wr1-x441.google.com with SMTP id h5so2498974wrv.7 for ; Tue, 20 Oct 2020 07:50:40 -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 :mime-version:content-transfer-encoding; bh=a5mwCsoJbZcP0FdXWmnwFQP3NKvbJCNy744gDgIkJo4=; b=hP7ZivFSWwRLt+0fW+R3M0xiWytZqn0zKBnOyLfdA4pI01doUpkmuUcSskc7vNxFRP zebgI6uf+Yahj8o0hEpHXH+ZM9lFDaQVu9d2Vv7PkboPwUjGvgJACUbuAfTRA/eKjSUa 4jlHXYov5QPwFPdSYae/zu+3U3RZDWKmWX9Xi4Hr/sK4SLWG2Vx9a+Lxm09/p6Aa5CvR BsHr3xE4Ctj6dQ8pwXWC+rcyW+0hW08gyJfeBZBJojFpz1aKp95TiSoXnucpcrcCPCib kRgvi8OiNEKMdax41ZpHQI72UOYGJl4Orbn0HWxyxFHwNn92nRLo0Jq6gIAT2QWQNfwZ VTbg== 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:mime-version:content-transfer-encoding; bh=a5mwCsoJbZcP0FdXWmnwFQP3NKvbJCNy744gDgIkJo4=; b=sVP/LsdM5BPjEWQMKmYHog+SHjFvlQk6lzvuX911l3SrcbQFd+0emgpZt3CWXDuuB3 gUGHcAP/tfC0nGPk6r81rxmIRh2Q2juNw5nrkPhixPB8gVkb/PWwZfW95ELEMg/qktR7 xXNRmUiRTL6tHDN5THeptW07yVZ4jJmsRCU8wDJObMLog81ZqOc3ci+aDmmf/ZLZmCai qGBjxtnCeekSC9UroDi9j7H8dDugCn7inTbjULfgRO5GJPhLEahRwT36JGPfo27KX8l1 IPo9J4JB8UkBd/c9BueKT0fYaU04hwMTKW5dBqL+jAZIMwNI2i0JYrK13i2RRob+vqCH kTKg== X-Gm-Message-State: AOAM531X/h59vIpOmv7QOPh8MXPqT3fwRKM6cf5+nEWq2b8kfE+Jau06 coBv+YKJmGVxst4j80ngCzFF1Qv7EEifZIkB X-Google-Smtp-Source: ABdhPJy4FdjyKKnrsVMFfWyh+alvIVpwITUYtpGF3Aa6wNGurOcS5kRoPT6rFRA/PIZvPibh66nq5g== X-Received: by 2002:a5d:4987:: with SMTP id r7mr3709970wrq.327.1603205439677; Tue, 20 Oct 2020 07:50:39 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id p67sm3028210wmp.11.2020.10.20.07.50.39 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 20 Oct 2020 07:50:39 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Subject: [PATCH 3/4] xilinx: cmd: Add basic fru format generator Date: Tue, 20 Oct 2020 16:50:29 +0200 Message-Id: <63b0e9b6925d1e5c6d6a4e4a616e5a70e5de5073.1603205426.git.michal.simek@xilinx.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean 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 There is also support for revision field which is Xilinx specific field. Signed-off-by: Michal Simek --- board/xilinx/common/fru.c | 20 ++++++- board/xilinx/common/fru.h | 17 ++++++ board/xilinx/common/fru_ops.c | 101 +++++++++++++++++++++++++++++++++- 3 files changed, 136 insertions(+), 2 deletions(-) diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c index 0ab9f2a78bd9..ccf48723ff89 100644 --- a/board/xilinx/common/fru.c +++ b/board/xilinx/common/fru.c @@ -33,9 +33,23 @@ static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } +static int do_fru_generate(struct cmd_tbl *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], argv[7]); +} + static struct cmd_tbl 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, 8, 0, do_fru_generate, "", ""), }; static int do_fru(struct cmd_tbl *cmdtp, int flag, int argc, @@ -63,11 +77,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\n" + " board info area filled based on parameters. is\n" + " pointing to place where FRU is generated.\n" ; #endif U_BOOT_CMD( - fru, 3, 1, do_fru, + fru, 8, 1, do_fru, "FRU table info", fru_help_text ) diff --git a/board/xilinx/common/fru.h b/board/xilinx/common/fru.h index a0413cf7f698..a3e652025714 100644 --- a/board/xilinx/common/fru.h +++ b/board/xilinx/common/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; @@ -35,6 +47,9 @@ struct fru_board_data { u8 part_number[FRU_BOARD_MAX_LEN]; u8 file_id_type_len; u8 file_id[FRU_BOARD_MAX_LEN]; + /* Xilinx custom fields */ + u8 rev_type_len; + u8 rev[FRU_BOARD_MAX_LEN]; }; struct fru_table { @@ -59,6 +74,8 @@ struct fru_table { int fru_display(int verbose); 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; diff --git a/board/xilinx/common/fru_ops.c b/board/xilinx/common/fru_ops.c index 491e92a7afba..fc3add7d93da 100644 --- a/board/xilinx/common/fru_ops.c +++ b/board/xilinx/common/fru_ops.c @@ -62,6 +62,103 @@ 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, char *revision) +{ + 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; + len = fru_gen_type_len(member, revision); /* Revision */ + 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(addr %x)\n", *member, len); + + env_set_hex("fru_addr", addr); + env_set_hex("filesize", (unsigned long)member - addr + 1); + + return 0; +} + static int fru_parse_board(unsigned long addr) { u8 i, type; @@ -153,7 +250,9 @@ static int fru_display_board(struct fru_board_data *brd, int verbose) "Product Name", "Serial No", "Part Number", - "File ID" + "File ID", + /* Xilinx spec */ + "Revision Number", }; if (verbose) { From patchwork Tue Oct 20 14:50:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1384985 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.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.a=rsa-sha256 header.s=20150623 header.b=zKwGJMvX; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CFxQy1blMz9sPB for ; Wed, 21 Oct 2020 01:51:38 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D85F182431; Tue, 20 Oct 2020 16:50:49 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; 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="zKwGJMvX"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 628518242B; Tue, 20 Oct 2020 16:50:45 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 01E7E823B7 for ; Tue, 20 Oct 2020 16:50:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=monstr@monstr.eu Received: by mail-wm1-x342.google.com with SMTP id b127so2238697wmb.3 for ; Tue, 20 Oct 2020 07:50:41 -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 :mime-version:content-transfer-encoding; bh=sgpuRnUbfxd0+OfhgFIYX1bmF2pVtbIAfsMMTx0r3vk=; b=zKwGJMvXuy5Ols6FjXvT8uqhH0AxQ+46iCC8mDKahVI5Q4DP7uP2+zkDBadcMKGb0S dXVQfP8INm8vMPNThvAXJ3bcFszi2Jh2WY8nqKCNgq0x74ztJjPXWeSbyt46TvOCNDg2 mNGEJuxJZl7oTcxco1lxstPFu4T+e1cZygUGcjn4XzVVyj9ei+D9CmPCFO1GbiX6uMYt iYVV7re6ny/lt3Csw48XFquVk8xamaja7/h4/9nxR2GlJQlroOo/BHdefmFIS7kdGGYK /sYjAWgYQ37IAqs6g9WH1og8+WK+Re28CLK0py8z91qgDK3Xx3CZnf/4eImEbDtgJeEN Epgw== 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:mime-version:content-transfer-encoding; bh=sgpuRnUbfxd0+OfhgFIYX1bmF2pVtbIAfsMMTx0r3vk=; b=bKXlJuPQ+ZIKLrg0YFPo+CBzz6QP0jb0TgXBD9e0DD2os28jEYXjk3hPDQ5RloEnOe ws6Vc7aAJ6rO0ldPnRrsWkblsJStSiVEaQq1DiRpiZyzHfyoe9N6rO/zijMC9lsVz+bw zNkS6nAU4mnSokMKQRzFUNZ5FO3Y8UU1QtkuzOtDKVjEQnAF2wlGSPkchlchq/GPGEC1 PVFUfHzs0saNYkObJeo8R0YtMX59Jz0Z2EhVaXiZLVTWtMtpQoc2B/BR0VcDhzsxxG16 Iobw22770AyN9p/ImdEpdovvAsgNi31R4xmHXHv250tUhQw7KkJCp99Qkzcxfv6zPBpt f5aA== X-Gm-Message-State: AOAM532xpPAI40eK0zguTWDCgcXSNwj01kxgqTfPoVGl3sgFxreeaaaX V4cXWj5/E3sM/+eEVIzaMaPtk+vG0yUx5DJb X-Google-Smtp-Source: ABdhPJz+qkTA/aV/mGS2psm8y4ZGto5YrbaD8a+4SZCXoC45skhQ/8OeG26SbGhvTHRXMgf3Hovrpw== X-Received: by 2002:a7b:ce85:: with SMTP id q5mr3277598wmj.35.1603205441267; Tue, 20 Oct 2020 07:50:41 -0700 (PDT) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id x81sm2939885wmb.11.2020.10.20.07.50.40 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 20 Oct 2020 07:50:40 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Subject: [PATCH 4/4] xilinx: board: Add FRU decoder support Date: Tue, 20 Oct 2020 16:50:30 +0200 Message-Id: <3555a6e1068378d9bdd0ea0129129c7bdbd9a6e9.1603205426.git.michal.simek@xilinx.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean FMC cards are using FRU format for card identification. That's why add support for this format. Signed-off-by: Michal Simek --- board/xilinx/common/board.c | 83 ++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index 0d0c21ca3d40..74e81c18bd5a 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -17,6 +17,8 @@ #include #include +#include "fru.h" + #if defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) { @@ -65,7 +67,7 @@ struct xilinx_board_description { static int highest_id = -1; static struct xilinx_board_description **board_info; -#define XILINX_I2C_DETECTION_BITS 8 +#define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr) /* Variable which stores pointer to array which stores eeprom content */ struct xilinx_legacy_format { @@ -160,6 +162,82 @@ static bool xilinx_detect_legacy(u8 *buffer) return true; } +static int xilinx_read_eeprom_fru(struct udevice *dev, char *name, + struct xilinx_board_description *desc) +{ + int ret, eeprom_size; + u8 *fru_content; + + /* FIXME this is shortcut - if eeprom type is wrong it will fail */ + eeprom_size = i2c_eeprom_size(dev); + + fru_content = calloc(1, eeprom_size); + if (!fru_content) + return -ENOMEM; + + debug("%s: I2C EEPROM read pass data at %p\n", __func__, + fru_content); + + ret = dm_i2c_read(dev, 0, (uchar *)fru_content, + eeprom_size); + if (ret) { + debug("%s: I2C EEPROM read failed\n", __func__); + free(fru_content); + return ret; + } + + printf("Xilinx I2C FRU format at %s:\n", name); + fru_capture((unsigned long)fru_content); + ret = fru_display(0); + if (ret) { + printf("FRU format decoding failed.\n"); + return ret; + } + + if (desc->header == EEPROM_HEADER_MAGIC) { + debug("Information already filled\n"); + return -EINVAL; + } + + /* It is clear that FRU was captured and structures were filled */ + strncpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name, + sizeof(desc->manufacturer)); + strncpy(desc->name, (char *)fru_data.brd.product_name, + sizeof(desc->name)); + strncpy(desc->revision, (char *)fru_data.brd.rev, + sizeof(desc->revision)); + strncpy(desc->serial, (char *)fru_data.brd.serial_number, + sizeof(desc->serial)); + desc->header = EEPROM_HEADER_MAGIC; + + return 0; +} + +static bool xilinx_detect_fru(u8 *buffer) +{ + u8 checksum = 0; + int i; + + checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr)); + if (checksum) { + debug("%s Common header CRC FAIL\n", __func__); + return false; + } + + bool all_zeros = true; + /* Checksum over all zeros is also zero that's why detect this case */ + for (i = 0; i < sizeof(struct fru_common_hdr); i++) { + if (buffer[i] != 0) + all_zeros = false; + } + + if (all_zeros) + return false; + + debug("%s Common header CRC PASS\n", __func__); + return true; +} + static int xilinx_read_eeprom_single(char *name, struct xilinx_board_description *desc) { @@ -184,6 +262,9 @@ static int xilinx_read_eeprom_single(char *name, debug("%s: i2c memory detected: %s\n", __func__, name); + if (CONFIG_IS_ENABLED(CMD_FRU) && xilinx_detect_fru(buffer)) + return xilinx_read_eeprom_fru(dev, name, desc); + if (xilinx_detect_legacy(buffer)) return xilinx_read_eeprom_legacy(dev, name, desc);