From patchwork Thu Aug 25 16:42:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jae Hyun Yoo X-Patchwork-Id: 1670339 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=a+RPM1lj; 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 ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MD87J2qqXz1yg7 for ; Fri, 26 Aug 2022 02:49:00 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 49E9984897; Thu, 25 Aug 2022 18:48:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.b="a+RPM1lj"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A22F984899; Thu, 25 Aug 2022 18:48:47 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A23D184881 for ; Thu, 25 Aug 2022 18:48:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=quic_jaehyoo@quicinc.com Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27PBba9r024476; Thu, 25 Aug 2022 16:48:20 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=vr1TziKQXnJd+aXoKuV4J/i/uw5hRsudleRuWRDst/g=; b=a+RPM1ljNtnvJyXOxK5xC8CuXGXnxHfKNeBGrtMC50YxgA/1TMwIJl10QxAnR3UFSFgp cCK2WBu9vuyupi0K/9/w517yYSXDG7qBSr/mCGv55Jm+XKJz9ITQlO38BtnxTBU0U4ke wrm1TJ5GyIEy5j4pQSV57svZ8tQ00ILTYjxR8fgQdldckCgC6H/RNwCxDGZe8koPVjjI YqmDxF2l1FcGMSOZKbVjd3060AeHYTaC+8rhIyf2yNjiuijnsENwTw1z7uych/7Q3WL4 CH37yCgIOycz/99k83tOJndaBoIiMMeIc7iQqY0YHbLzxvO/5C0AUehd34pxwUYX981a 7Q== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j63v3jbx7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:48:19 +0000 Received: from pps.filterd (NALASPPMTA03.qualcomm.com [127.0.0.1]) by NALASPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGhIga018305; Thu, 25 Aug 2022 16:43:18 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 3j47bn72pr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:18 +0000 Received: from NALASPPMTA03.qualcomm.com (NALASPPMTA03.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27PGcZBV011965; Thu, 25 Aug 2022 16:43:18 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 27PGhIUS018295 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:18 +0000 Received: from maru.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Thu, 25 Aug 2022 09:43:16 -0700 From: Jae Hyun Yoo To: Michal Simek , Ovidiu Panait , Simon Glass , Mario Six , Masahisa Kojima , =?utf-8?q?Pali_Roh=C3=A1r?= , Heinrich Schuchardt , Ashok Reddy Soma , "Thomas Huth" , Huang Jianan , Chris Morgan , Roland Gaudig , Patrick Delaunay , Alexandru Gagniuc CC: Jamie Iles , Graeme Gregory , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Jae Hyun Yoo , Subject: [PATCH v4 1/6] xilinx: common: refactor FRU handling support Date: Thu, 25 Aug 2022 09:42:40 -0700 Message-ID: <20220825164245.1606958-2-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> References: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: sGfWPuH8DJFBfjc8cFFFjxQSjHzMPWpi X-Proofpoint-GUID: sGfWPuH8DJFBfjc8cFFFjxQSjHzMPWpi X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-25_08,2022-08-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 spamscore=0 adultscore=0 malwarescore=0 clxscore=1015 suspectscore=0 mlxlogscore=999 mlxscore=0 phishscore=0 priorityscore=1501 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208250063 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean Refactor FRU handling support to remove Xilinx customization dependency. With this change, single or multiple custom board fields and multi-records can be added dynamically using linked list so that each board support can utilize them in their own custom way. It's a preparation change for moving the FRU command support to common region. Signed-off-by: Jae Hyun Yoo --- Changes from v3: * None. Changes from v2: * None. Changes from v1: * Newly added in v2. board/xilinx/common/board.c | 63 ++++++++-- board/xilinx/common/fru.c | 12 +- board/xilinx/common/fru.h | 76 +++++++----- board/xilinx/common/fru_ops.c | 227 ++++++++++++++++++++++++---------- 4 files changed, 263 insertions(+), 115 deletions(-) diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index 9b4aded466ab..e979f0176273 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -88,6 +88,9 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) #define EEPROM_HDR_NO_OF_MAC_ADDR 4 #define EEPROM_HDR_ETH_ALEN ETH_ALEN #define EEPROM_HDR_UUID_LEN 16 +#define EEPROM_MULTIREC_TYPE_XILINX_OEM 0xD2 +#define EEPROM_MULTIREC_MAC_OFFSET 4 +#define EEPROM_MULTIREC_DUT_MACID 0x31 struct xilinx_board_description { u32 header; @@ -116,6 +119,19 @@ struct xilinx_legacy_format { char unused3[29]; /* 0xe3 */ }; +struct xilinx_multirec_mac { + u8 xlnx_iana_id[3]; + u8 ver; + u8 macid[EEPROM_HDR_NO_OF_MAC_ADDR][ETH_ALEN]; +}; + +enum xilinx_board_custom_field { + brd_custom_field_rev = 0, + brd_custom_field_pcie, + brd_custom_field_uuid, + brd_custom_field_max +}; + static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size) { int i; @@ -200,9 +216,14 @@ static bool xilinx_detect_legacy(u8 *buffer) static int xilinx_read_eeprom_fru(struct udevice *dev, char *name, struct xilinx_board_description *desc) { + u8 parsed_macid[EEPROM_HDR_NO_OF_MAC_ADDR][ETH_ALEN] = { 0 }; + struct fru_custom_info custom_info[brd_custom_field_max] = { 0 }; + struct fru_custom_field_node *ci_node; + struct fru_multirec_node *mr_node; + const struct fru_table *fru_data; int i, ret, eeprom_size; u8 *fru_content; - u8 id = 0; + u8 id = 0, field = 0; /* FIXME this is shortcut - if eeprom type is wrong it will fail */ eeprom_size = i2c_eeprom_size(dev); @@ -237,30 +258,56 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name, goto end; } + fru_data = fru_get_fru_data(); + + list_for_each_entry(ci_node, &fru_data->brd.custom_fields, list) { + custom_info[field].type_len = ci_node->info.type_len; + memcpy(custom_info[field].data, ci_node->info.data, + ci_node->info.type_len & FRU_TYPELEN_LEN_MASK); + if (++field < brd_custom_field_max) + break; + } + + list_for_each_entry(mr_node, &fru_data->multi_recs, list) { + struct fru_multirec_hdr *hdr = &mr_node->info.hdr; + + if (hdr->rec_type == EEPROM_MULTIREC_TYPE_XILINX_OEM) { + struct xilinx_multirec_mac *mac; + + mac = (struct xilinx_multirec_mac *)mr_node->info.data; + if (mac->ver == EEPROM_MULTIREC_DUT_MACID) { + int mac_len = hdr->len - + EEPROM_MULTIREC_MAC_OFFSET; + + memcpy(parsed_macid, mac->macid, mac_len); + } + } + } + /* It is clear that FRU was captured and structures were filled */ - strlcpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name, + strlcpy(desc->manufacturer, (char *)fru_data->brd.manufacturer_name, sizeof(desc->manufacturer)); - strlcpy(desc->uuid, (char *)fru_data.brd.uuid, + strlcpy(desc->uuid, (char *)custom_info[brd_custom_field_uuid].data, sizeof(desc->uuid)); - strlcpy(desc->name, (char *)fru_data.brd.product_name, + strlcpy(desc->name, (char *)fru_data->brd.product_name, sizeof(desc->name)); for (i = 0; i < sizeof(desc->name); i++) { if (desc->name[i] == ' ') desc->name[i] = '\0'; } - strlcpy(desc->revision, (char *)fru_data.brd.rev, + strlcpy(desc->revision, (char *)custom_info[brd_custom_field_rev].data, sizeof(desc->revision)); for (i = 0; i < sizeof(desc->revision); i++) { if (desc->revision[i] == ' ') desc->revision[i] = '\0'; } - strlcpy(desc->serial, (char *)fru_data.brd.serial_number, + strlcpy(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])) + if (is_valid_ethaddr((const u8 *)parsed_macid[id])) memcpy(&desc->mac_addr[id], - (char *)fru_data.mac.macid[id], ETH_ALEN); + (char *)parsed_macid[id], ETH_ALEN); id++; } diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c index f6ca46c3cecc..0d72911df04d 100644 --- a/board/xilinx/common/fru.c +++ b/board/xilinx/common/fru.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * (C) Copyright 2019 - 2020 Xilinx, Inc. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -43,7 +44,7 @@ static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc, addr = hextoul(argv[2], NULL); - return fru_generate(addr, argv[3], argv[4], argv[5], argv[6], argv[7]); + return fru_generate(addr, argc - 3, argv + 3); } static struct cmd_tbl cmd_fru_sub[] = { @@ -78,14 +79,15 @@ static char fru_help_text[] = "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" + " [custom ...] - Generate FRU\n" + " format with board info area filled based on\n" + " parameters. is pointing to place where FRU is\n" + " generated.\n" ; #endif U_BOOT_CMD( - fru, 8, 1, do_fru, + fru, CONFIG_SYS_MAXARGS, 1, do_fru, "FRU table info", fru_help_text ) diff --git a/board/xilinx/common/fru.h b/board/xilinx/common/fru.h index 59f6b722cf12..41655864dbf5 100644 --- a/board/xilinx/common/fru.h +++ b/board/xilinx/common/fru.h @@ -2,11 +2,13 @@ /* * (C) Copyright 2019 Xilinx, Inc. * Siva Durga Prasad Paladugu + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __FRU_H #define __FRU_H -#include + +#include struct fru_common_hdr { u8 version; @@ -17,21 +19,31 @@ struct fru_common_hdr { u8 off_multirec; u8 pad; u8 crc; -}; +} __packed; -#define FRU_BOARD_MAX_LEN 32 -#define FRU_MAX_NO_OF_MAC_ADDR 4 +#define FRU_INFO_FIELD_LEN_MAX 32 +#define FRU_MULTIREC_DATA_LEN_MAX 255 -struct __packed fru_board_info_header { +struct fru_board_info_header { u8 ver; u8 len; u8 lang_code; u8 time[3]; -}; +} __packed; -struct __packed fru_board_info_member { +struct fru_board_info_member { u8 type_len; u8 *name; +} __packed; + +struct fru_custom_info { + u8 type_len; + u8 data[FRU_INFO_FIELD_LEN_MAX]; +} __packed; + +struct fru_custom_field_node { + struct list_head list; + struct fru_custom_info info; }; struct fru_board_data { @@ -40,22 +52,16 @@ struct fru_board_data { u8 lang_code; u8 time[3]; u8 manufacturer_type_len; - u8 manufacturer_name[FRU_BOARD_MAX_LEN]; + u8 manufacturer_name[FRU_INFO_FIELD_LEN_MAX]; u8 product_name_type_len; - u8 product_name[FRU_BOARD_MAX_LEN]; + u8 product_name[FRU_INFO_FIELD_LEN_MAX]; u8 serial_number_type_len; - u8 serial_number[FRU_BOARD_MAX_LEN]; + u8 serial_number[FRU_INFO_FIELD_LEN_MAX]; u8 part_number_type_len; - u8 part_number[FRU_BOARD_MAX_LEN]; + u8 part_number[FRU_INFO_FIELD_LEN_MAX]; 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]; - u8 pcie_type_len; - u8 pcie[FRU_BOARD_MAX_LEN]; - u8 uuid_type_len; - u8 uuid[FRU_BOARD_MAX_LEN]; + u8 file_id[FRU_INFO_FIELD_LEN_MAX]; + struct list_head custom_fields; }; struct fru_multirec_hdr { @@ -64,32 +70,35 @@ struct fru_multirec_hdr { u8 len; u8 csum; u8 hdr_csum; -}; +} __packed; -struct fru_multirec_mac { - u8 xlnx_iana_id[3]; - u8 ver; - u8 macid[FRU_MAX_NO_OF_MAC_ADDR][ETH_ALEN]; +struct fru_multirec_info { + struct fru_multirec_hdr hdr; + u8 data[FRU_MULTIREC_DATA_LEN_MAX]; +} __packed; + +struct fru_multirec_node { + struct list_head list; + struct fru_multirec_info info; }; struct fru_table { struct fru_common_hdr hdr; struct fru_board_data brd; - struct fru_multirec_mac mac; + struct list_head multi_recs; bool captured; }; -#define FRU_TYPELEN_CODE_MASK 0xC0 -#define FRU_TYPELEN_LEN_MASK 0x3F +#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 -#define FRU_MULTIREC_TYPE_OEM 0xD2 -#define FRU_MULTIREC_MAC_OFFSET 4 #define FRU_LAST_REC BIT(7) -#define FRU_DUT_MACID 0x31 +#define FRU_MULTIREC_TYPE_OEM_START 0xC0 +#define FRU_MULTIREC_TYPE_OEM_END 0xFF /* This should be minimum of fields */ #define FRU_BOARD_AREA_TOTAL_FIELDS 5 @@ -99,10 +108,9 @@ 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); +int fru_generate(unsigned long addr, int argc, char *const argv[]); u8 fru_checksum(u8 *addr, u8 len); - -extern struct fru_table fru_data; +int fru_check_type_len(u8 type_len, u8 language, u8 *type); +const struct fru_table *fru_get_fru_data(void); #endif /* FRU_H */ diff --git a/board/xilinx/common/fru_ops.c b/board/xilinx/common/fru_ops.c index 49846ae3d660..8291e347716b 100644 --- a/board/xilinx/common/fru_ops.c +++ b/board/xilinx/common/fru_ops.c @@ -1,21 +1,24 @@ // SPDX-License-Identifier: GPL-2.0 /* * (C) Copyright 2019 - 2020 Xilinx, Inc. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include -#include #include #include +#include #include #include -#include #include -#include +#include #include "fru.h" -struct fru_table fru_data __section(".data"); +struct fru_table fru_data __section(".data") = { + .brd.custom_fields = LIST_HEAD_INIT(fru_data.brd.custom_fields), + .multi_recs = LIST_HEAD_INIT(fru_data.multi_recs), +}; static u16 fru_cal_area_len(u8 len) { @@ -57,7 +60,7 @@ u8 fru_checksum(u8 *addr, u8 len) return checksum; } -static int fru_check_type_len(u8 type_len, u8 language, u8 *type) +int fru_check_type_len(u8 type_len, u8 language, u8 *type) { int len; @@ -89,8 +92,7 @@ static u8 fru_gen_type_len(u8 *addr, char *name) return 1 + len; } -int fru_generate(unsigned long addr, char *manufacturer, char *board_name, - char *serial_no, char *part_no, char *revision) +int fru_generate(unsigned long addr, int argc, char *const argv[]) { struct fru_common_hdr *header = (struct fru_common_hdr *)addr; struct fru_board_info_header *board_info; @@ -126,18 +128,10 @@ int fru_generate(unsigned long addr, char *manufacturer, char *board_name, /* 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; + while (--argc > 0 && ++argv) { + len = fru_gen_type_len(member, *argv); + member += len; + } *member++ = 0xc1; /* Indication of no more fields */ @@ -168,6 +162,35 @@ int fru_generate(unsigned long addr, char *manufacturer, char *board_name, return 0; } +static void fru_delete_custom_fields(struct list_head *custom_fields) +{ + struct fru_custom_field_node *node, *next; + + list_for_each_entry_safe(node, next, custom_fields, list) { + list_del(&node->list); + kfree(node); + } +} + +static int fru_append_custom_info(unsigned long addr, + struct list_head *custom_fields) +{ + struct fru_custom_info *info = (struct fru_custom_info *)addr; + struct fru_custom_field_node *ci_new; + + ci_new = kzalloc(sizeof(*ci_new), GFP_KERNEL); + if (!ci_new) + return -ENOMEM; + + ci_new->info.type_len = info->type_len; + memcpy(&ci_new->info.data, (void *)info->data, + ci_new->info.type_len & FRU_TYPELEN_LEN_MASK); + + list_add_tail(&ci_new->list, custom_fields); + + return 0; +} + static int fru_parse_board(unsigned long addr) { u8 i, type; @@ -179,9 +202,10 @@ static int fru_parse_board(unsigned long addr) data = (u8 *)&fru_data.brd.manufacturer_type_len; /* Record max structure limit not to write data over allocated space */ - limit = (u8 *)&fru_data.brd + sizeof(struct fru_board_data); + limit = (u8 *)&fru_data.brd + sizeof(struct fru_board_data) - + sizeof(struct fru_custom_field_node *); - for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) { + for (i = 0; ; i++, data += FRU_INFO_FIELD_LEN_MAX) { len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code, &type); /* @@ -190,11 +214,14 @@ static int fru_parse_board(unsigned long addr) if (len == -EINVAL) break; - /* Stop when amount of chars is more then fields to record */ - if (data + len > limit) - break; - /* This record type/len field */ - *data++ = *(u8 *)addr; + if (i < FRU_BOARD_AREA_TOTAL_FIELDS) { + /* Stop when length is more then fields to record */ + if (data + len > limit) + break; + + /* This record type/len field */ + *data++ = *(u8 *)addr; + } /* Add offset to match data */ addr += 1; @@ -203,10 +230,23 @@ static int fru_parse_board(unsigned long addr) if (!len) continue; - /* Record data field */ - memcpy(data, (u8 *)addr, len); - term = data + (u8)len; - *term = 0; + if (i < FRU_BOARD_AREA_TOTAL_FIELDS) { + /* Record data field */ + memcpy(data, (u8 *)addr, len); + term = data + (u8)len; + *term = 0; + } else { + struct list_head *custom_fields; + + custom_fields = &fru_data.brd.custom_fields; + + /* Add a custom info field */ + if (fru_append_custom_info(addr - 1, custom_fields)) { + fru_delete_custom_fields(custom_fields); + return -EINVAL; + } + } + addr += len; } @@ -219,34 +259,52 @@ static int fru_parse_board(unsigned long addr) return 0; } +static void fru_delete_multirecs(struct list_head *multi_recs) +{ + struct fru_multirec_node *node, *next; + + list_for_each_entry_safe(node, next, multi_recs, list) { + list_del(&node->list); + kfree(node); + } +} + +static int fru_append_multirec(unsigned long addr, + struct list_head *multi_recs) +{ + struct fru_multirec_info *mr_src = (struct fru_multirec_info *)addr; + struct fru_multirec_node *mr_new; + + mr_new = kzalloc(sizeof(*mr_new), GFP_KERNEL); + if (!mr_new) + return -ENOMEM; + + memcpy(&mr_new->info.hdr, (void *)&mr_src->hdr, sizeof(mr_src->hdr)); + memcpy(&mr_new->info.data, (void *)mr_src->data, mr_src->hdr.len); + + list_add_tail(&mr_new->list, multi_recs); + + 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; + struct fru_multirec_hdr *mr_hdr; - debug("%s: multirec addr %lx\n", __func__, addr); + debug("%s: multirec addr %lx\n", __func__, (ulong)addr); do { - memcpy(&mrc.rec_type, (void *)addr, hdr_len); - - checksum = fru_checksum((u8 *)addr, hdr_len); - if (checksum) { + if (fru_checksum((u8 *)addr, hdr_len)) { 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; + fru_append_multirec(addr, &fru_data.multi_recs); - 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)); + mr_hdr = (struct fru_multirec_hdr *)addr; + addr += mr_hdr->len + hdr_len; + } while (!(mr_hdr->type & FRU_LAST_REC)); return 0; } @@ -255,7 +313,6 @@ 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) { @@ -264,33 +321,28 @@ int fru_capture(unsigned long addr) } hdr = (struct fru_common_hdr *)addr; + fru_delete_custom_fields(&fru_data.brd.custom_fields); + fru_delete_multirecs(&fru_data.multi_recs); memset((void *)&fru_data, 0, sizeof(fru_data)); - memcpy((void *)&fru_data, (void *)hdr, - sizeof(struct fru_common_hdr)); + INIT_LIST_HEAD(&fru_data.brd.custom_fields); + INIT_LIST_HEAD(&fru_data.multi_recs); + memcpy((void *)&fru_data, (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); - } + if (hdr->off_board) + fru_parse_board(addr + fru_cal_area_len(hdr->off_board)); - env_set_hex("fru_addr", addr); + if (hdr->off_multirec) + fru_parse_multirec(addr + fru_cal_area_len(hdr->off_multirec)); - if (hdr->off_multirec) { - multirec_addr += fru_cal_area_len(hdr->off_multirec); - fru_parse_multirec(multirec_addr); - } + env_set_hex("fru_addr", (ulong)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", @@ -301,12 +353,15 @@ static int fru_display_board(struct fru_board_data *brd, int verbose) static const char * const boardinfo[] = { "Manufacturer Name", "Product Name", - "Serial No", + "Serial Number", "Part Number", "File ID", - /* Xilinx spec */ - "Revision Number", }; + struct fru_custom_field_node *node; + u32 time = 0; + u8 *data; + u8 type; + int len; if (verbose) { printf("*****BOARD INFO*****\n"); @@ -358,7 +413,32 @@ static int fru_display_board(struct fru_board_data *brd, int verbose) debug("Unsupported type %x\n", type); } - data += FRU_BOARD_MAX_LEN; + data += FRU_INFO_FIELD_LEN_MAX; + } + + list_for_each_entry(node, &brd->custom_fields, list) { + printf(" Custom Type/Length: 0x%x\n", node->info.type_len); + print_hex_dump_bytes(" ", DUMP_PREFIX_OFFSET, node->info.data, + node->info.type_len & + FRU_TYPELEN_LEN_MASK); + } + + return 0; +} + +static int fru_display_multirec(struct list_head *multi_recs, int verbose) +{ + struct fru_multirec_node *node; + + if (verbose) + printf("*****MULTIRECORDS*****\n"); + + list_for_each_entry(node, multi_recs, list) { + printf("Type ID: 0x%x, Type: 0x%x Length: %d\n", + node->info.hdr.rec_type, node->info.hdr.type, + node->info.hdr.len); + print_hex_dump_bytes(" ", DUMP_PREFIX_OFFSET, node->info.data, + node->info.hdr.len); } return 0; @@ -404,6 +484,8 @@ static void fru_display_common_hdr(struct fru_common_hdr *hdr, int verbose) int fru_display(int verbose) { + int ret; + if (!fru_data.captured) { printf("FRU data not available please run fru parse\n"); return -EINVAL; @@ -411,5 +493,14 @@ int fru_display(int verbose) fru_display_common_hdr(&fru_data.hdr, verbose); - return fru_display_board(&fru_data.brd, verbose); + ret = fru_display_board(&fru_data.brd, verbose); + if (ret) + return ret; + + return fru_display_multirec(&fru_data.multi_recs, verbose); +} + +const struct fru_table *fru_get_fru_data(void) +{ + return &fru_data; } From patchwork Thu Aug 25 16:42:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jae Hyun Yoo X-Patchwork-Id: 1670340 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=pULjo2gU; 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 ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MD87T710nz1yg7 for ; Fri, 26 Aug 2022 02:49:09 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CCE40848A6; Thu, 25 Aug 2022 18:48:53 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.b="pULjo2gU"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 577D384881; Thu, 25 Aug 2022 18:48:48 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id F309D84896 for ; Thu, 25 Aug 2022 18:48:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=quic_jaehyoo@quicinc.com Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27PCro0k000903; Thu, 25 Aug 2022 16:48:20 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=q9DqDF/bTKsOMxAoMIXoFJCKRTp1AeFO7ceutkRZ4rk=; b=pULjo2gUO+BVLqlMltWNmc/NP/r0P+zXTL98etlvoCyKNYCq9CjwaeNWMVD99ZksHT97 Qb9jSUU3zeGepfxpmMu6WOPK/tpcymPoDzbmBivj9OSqaGqJToqv+Bbd36ChhnJ2kV29 fGNxMKCR3ywjWbmAwxqArEsfzRe1gzenJJYYjoPqqSajpzV7LYmf450I4Y6fP5AzTf/E Q19ylIOhv479Zc0LXQ9uAlQ9XaeWAMdyKgCytmlk9oUbeRN704FJenhJfTT1w5K10WM/ 0d+c68HiGsUAWkPP/GGqe/P3dEb0ueEmqn/JrNmqWeyFTnGzS2Jk9NtozD2DaJYpuqLG qg== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j64h7j80n-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:48:20 +0000 Received: from pps.filterd (NALASPPMTA02.qualcomm.com [127.0.0.1]) by NALASPPMTA02.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGfYn9009051; Thu, 25 Aug 2022 16:43:19 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 3j60ettyb2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:19 +0000 Received: from NALASPPMTA02.qualcomm.com (NALASPPMTA02.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27PGhJeI012290; Thu, 25 Aug 2022 16:43:19 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 27PGhJnV012287 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:19 +0000 Received: from maru.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Thu, 25 Aug 2022 09:43:18 -0700 From: Jae Hyun Yoo To: Michal Simek , Ovidiu Panait , Simon Glass , Mario Six , Masahisa Kojima , =?utf-8?q?Pali_Roh=C3=A1r?= , Heinrich Schuchardt , Ashok Reddy Soma , "Thomas Huth" , Huang Jianan , Chris Morgan , Roland Gaudig , Patrick Delaunay , Alexandru Gagniuc CC: Jamie Iles , Graeme Gregory , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Jae Hyun Yoo , Subject: [PATCH v4 2/6] cmd: fru: move FRU handling support to common region Date: Thu, 25 Aug 2022 09:42:41 -0700 Message-ID: <20220825164245.1606958-3-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> References: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: g5IhKENGZX9M3odDYVPw5PwslExldr8c X-Proofpoint-GUID: g5IhKENGZX9M3odDYVPw5PwslExldr8c X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-25_08,2022-08-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 spamscore=0 clxscore=1015 priorityscore=1501 lowpriorityscore=0 malwarescore=0 phishscore=0 mlxscore=0 bulkscore=0 adultscore=0 mlxlogscore=999 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208250063 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean From: Graeme Gregory The FRU handling was added as a Xilinx board dependent support but it is also useful for other boards too, so this commit moves the FRU handling support to the common region so that it can be enabled by CONFIG_CMD_FRU. Signed-off-by: Graeme Gregory Signed-off-by: Jae Hyun Yoo --- Changes from v3: * None. Changes from v2: * None. Changes from v1: * Split out the custom field and multi-record handling part as a seperate patch. (Michal) * Moved fru_ops.c to lib. (Heinrich) * Added what does FRU stand for. (Heinrich) Changes from RFC: * Made FRU typecode string table as a generic and sharable table. (Michal) * Made OEM multirecord parsing call happen only on customizable type IDs. (Michal) * Added manufacturer custom board info fields parsing flow. (Michal) board/xilinx/Kconfig | 8 -------- board/xilinx/common/Makefile | 3 --- board/xilinx/common/board.c | 3 +-- cmd/Kconfig | 8 ++++++++ cmd/Makefile | 1 + {board/xilinx/common => cmd}/fru.c | 3 +-- {board/xilinx/common => include}/fru.h | 0 lib/Makefile | 1 + {board/xilinx/common => lib}/fru_ops.c | 3 +-- 9 files changed, 13 insertions(+), 17 deletions(-) rename {board/xilinx/common => cmd}/fru.c (99%) rename {board/xilinx/common => include}/fru.h (100%) rename {board/xilinx/common => lib}/fru_ops.c (99%) diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig index 17880661736d..110706b20fa3 100644 --- a/board/xilinx/Kconfig +++ b/board/xilinx/Kconfig @@ -74,11 +74,3 @@ 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 cdc3c9677432..e33baaae1159 100644 --- a/board/xilinx/common/Makefile +++ b/board/xilinx/common/Makefile @@ -8,6 +8,3 @@ obj-y += board.o ifndef CONFIG_ARCH_ZYNQ obj-$(CONFIG_DISPLAY_CPUINFO) += cpu-info.o endif -ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o -endif diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index e979f0176273..e58b11d7f757 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -25,8 +26,6 @@ #include #include -#include "fru.h" - #if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) struct efi_fw_image fw_images[] = { #if defined(XILINX_BOOT_IMAGE_GUID) diff --git a/cmd/Kconfig b/cmd/Kconfig index 211ebe9c8783..29b2e11e1247 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1063,6 +1063,14 @@ config CMD_FPGAD fpga_get_reg() function. This functions similarly to the 'md' command. +config CMD_FRU + bool "FRU information for product" + help + This option enables FRU (Field Replaceable Unit) 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. + config CMD_FUSE bool "fuse - support for the fuse subssystem" help diff --git a/cmd/Makefile b/cmd/Makefile index 6e87522b62e8..58e353611a5a 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_CMD_SQUASHFS) += sqfs.o obj-$(CONFIG_CMD_FLASH) += flash.o obj-$(CONFIG_CMD_FPGA) += fpga.o obj-$(CONFIG_CMD_FPGAD) += fpgad.o +obj-$(CONFIG_CMD_FRU) += fru.o obj-$(CONFIG_CMD_FS_GENERIC) += fs.o obj-$(CONFIG_CMD_FUSE) += fuse.o obj-$(CONFIG_CMD_GETTIME) += gettime.o diff --git a/board/xilinx/common/fru.c b/cmd/fru.c similarity index 99% rename from board/xilinx/common/fru.c rename to cmd/fru.c index 0d72911df04d..2ec5012af5ac 100644 --- a/board/xilinx/common/fru.c +++ b/cmd/fru.c @@ -7,10 +7,9 @@ #include #include #include +#include #include -#include "fru.h" - static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { diff --git a/board/xilinx/common/fru.h b/include/fru.h similarity index 100% rename from board/xilinx/common/fru.h rename to include/fru.h diff --git a/lib/Makefile b/lib/Makefile index e3deb1528794..ef8933ae3aee 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -39,6 +39,7 @@ obj-y += crc16-ccitt.o obj-$(CONFIG_ERRNO_STR) += errno_str.o obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o +obj-$(CONFIG_CMD_FRU) += fru_ops.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o diff --git a/board/xilinx/common/fru_ops.c b/lib/fru_ops.c similarity index 99% rename from board/xilinx/common/fru_ops.c rename to lib/fru_ops.c index 8291e347716b..3fe06fe430f2 100644 --- a/board/xilinx/common/fru_ops.c +++ b/lib/fru_ops.c @@ -7,14 +7,13 @@ #include #include #include +#include #include #include #include #include #include -#include "fru.h" - struct fru_table fru_data __section(".data") = { .brd.custom_fields = LIST_HEAD_INIT(fru_data.brd.custom_fields), .multi_recs = LIST_HEAD_INIT(fru_data.multi_recs), From patchwork Thu Aug 25 16:42:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jae Hyun Yoo X-Patchwork-Id: 1670337 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=lziVHE5x; 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 ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MD81j04JCz1yhN for ; Fri, 26 Aug 2022 02:44:07 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B299F84881; Thu, 25 Aug 2022 18:43:57 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.b="lziVHE5x"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0425384880; Thu, 25 Aug 2022 18:43:56 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2951C84880 for ; Thu, 25 Aug 2022 18:43:53 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=quic_jaehyoo@quicinc.com Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27PFCkBD026089; Thu, 25 Aug 2022 16:43:22 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=ciQcyrZYndKccLmqUioPwcaAdaQMYuAy8gmNMFBXFeU=; b=lziVHE5x/FtmErC2IBR6OFF8LUaczNYv5JfPWcx2ta0KA5OOF8IauXnNKN89/J0rhy5L esLmkXawAzBnGnpQbiNKzW34nMA+V3TLXTfM5SLfCD8DYKWdDLGamMTbMybixYRdYHvM OnEqHGZMFhvyXqou48F0Net0b5wnUsKZ5x10C0ZAtCJWG7UVAj6OwU2zNB42oJvf9WH3 J9mxT/6075miDvGl+qhyquL+Oxia4PzcRafCU9NsgMOZS4QbbHv949rnkpGCNo+iOiDh OHPvAItncLTGWwldfq3nJ/ixNwBh/fryYILlOUDTeZHeiQSw7ZSv5YawWEyAqM25PrKk VQ== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j5w5jkanb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:22 +0000 Received: from pps.filterd (NALASPPMTA04.qualcomm.com [127.0.0.1]) by NALASPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGhLAc008705; Thu, 25 Aug 2022 16:43:21 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA04.qualcomm.com (PPS) with ESMTPS id 3j5b19fk0a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:21 +0000 Received: from NALASPPMTA04.qualcomm.com (NALASPPMTA04.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27PGeROo004178; Thu, 25 Aug 2022 16:43:21 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (PPS) with ESMTPS id 27PGhKgG008699 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:21 +0000 Received: from maru.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Thu, 25 Aug 2022 09:43:19 -0700 From: Jae Hyun Yoo To: Michal Simek , Ovidiu Panait , Simon Glass , Mario Six , Masahisa Kojima , =?utf-8?q?Pali_Roh=C3=A1r?= , Heinrich Schuchardt , Ashok Reddy Soma , "Thomas Huth" , Huang Jianan , Chris Morgan , Roland Gaudig , Patrick Delaunay , Alexandru Gagniuc CC: Jamie Iles , Graeme Gregory , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Jae Hyun Yoo , Subject: [PATCH v4 3/6] cmd: fru: fix a sandbox segfault issue Date: Thu, 25 Aug 2022 09:42:42 -0700 Message-ID: <20220825164245.1606958-4-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> References: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: rS50wdGxayxJkRExwH1HYrynZXUIismZ X-Proofpoint-GUID: rS50wdGxayxJkRExwH1HYrynZXUIismZ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-25_08,2022-08-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=969 impostorscore=0 suspectscore=0 adultscore=0 priorityscore=1501 clxscore=1015 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208250062 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean This command doesn't work with sandbox because direct memory access causes a segfault error. Fix it up using map_sysmem(). Signed-off-by: Jae Hyun Yoo Reviewed-by: Simon Glass --- Changes from v3: * None. Changes from v2: * Added a 'Reviewed-by' tag. (Simon) Changes from v1: * Newly added in v2. board/xilinx/common/board.c | 2 +- cmd/fru.c | 19 ++++++++++++++++--- include/fru.h | 4 ++-- lib/fru_ops.c | 17 ++++++++--------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index e58b11d7f757..3292083c5250 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -241,7 +241,7 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name, goto end; } - fru_capture((unsigned long)fru_content); + fru_capture(fru_content); if (gd->flags & GD_FLG_RELOC || (_DEBUG && CONFIG_IS_ENABLED(DTB_RESELECT))) { printf("Xilinx I2C FRU format at %s:\n", name); ret = fru_display(0); diff --git a/cmd/fru.c b/cmd/fru.c index 2ec5012af5ac..b2cadbec9780 100644 --- a/cmd/fru.c +++ b/cmd/fru.c @@ -9,12 +9,15 @@ #include #include #include +#include static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long addr; + const void *buf; char *endp; + int ret; if (argc < cmdtp->maxargs) return CMD_RET_USAGE; @@ -23,7 +26,11 @@ static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc, if (*argv[1] == 0 || *endp != 0) return -1; - return fru_capture(addr); + buf = map_sysmem(addr, 0); + ret = fru_capture(buf); + unmap_sysmem(buf); + + return ret; } static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc, @@ -37,13 +44,19 @@ static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long addr; + const void *buf; + int ret; if (argc < cmdtp->maxargs) return CMD_RET_USAGE; - addr = hextoul(argv[2], NULL); + addr = hextoul(argv[3], NULL); + + buf = map_sysmem(addr, 0); + ret = fru_generate(buf, argc - 3, argv + 3); + unmap_sysmem(buf); - return fru_generate(addr, argc - 3, argv + 3); + return ret; } static struct cmd_tbl cmd_fru_sub[] = { diff --git a/include/fru.h b/include/fru.h index 41655864dbf5..b158b80b5866 100644 --- a/include/fru.h +++ b/include/fru.h @@ -107,8 +107,8 @@ struct fru_table { #define FRU_TYPELEN_TYPE_ASCII8 3 int fru_display(int verbose); -int fru_capture(unsigned long addr); -int fru_generate(unsigned long addr, int argc, char *const argv[]); +int fru_capture(const void *addr); +int fru_generate(const void *addr, int argc, char *const argv[]); u8 fru_checksum(u8 *addr, u8 len); int fru_check_type_len(u8 type_len, u8 language, u8 *type); const struct fru_table *fru_get_fru_data(void); diff --git a/lib/fru_ops.c b/lib/fru_ops.c index 3fe06fe430f2..a25ebccd110d 100644 --- a/lib/fru_ops.c +++ b/lib/fru_ops.c @@ -91,7 +91,7 @@ static u8 fru_gen_type_len(u8 *addr, char *name) return 1 + len; } -int fru_generate(unsigned long addr, int argc, char *const argv[]) +int fru_generate(const void *addr, int argc, char *const argv[]) { struct fru_common_hdr *header = (struct fru_common_hdr *)addr; struct fru_board_info_header *board_info; @@ -155,8 +155,8 @@ int fru_generate(unsigned long addr, int argc, char *const argv[]) debug("checksum %x(addr %x)\n", *member, len); - env_set_hex("fru_addr", addr); - env_set_hex("filesize", (unsigned long)member - addr + 1); + env_set_hex("fru_addr", (ulong)addr); + env_set_hex("filesize", (ulong)member - (ulong)addr + 1); return 0; } @@ -171,7 +171,7 @@ static void fru_delete_custom_fields(struct list_head *custom_fields) } } -static int fru_append_custom_info(unsigned long addr, +static int fru_append_custom_info(const void *addr, struct list_head *custom_fields) { struct fru_custom_info *info = (struct fru_custom_info *)addr; @@ -190,7 +190,7 @@ static int fru_append_custom_info(unsigned long addr, return 0; } -static int fru_parse_board(unsigned long addr) +static int fru_parse_board(const void *addr) { u8 i, type; int len; @@ -268,8 +268,7 @@ static void fru_delete_multirecs(struct list_head *multi_recs) } } -static int fru_append_multirec(unsigned long addr, - struct list_head *multi_recs) +static int fru_append_multirec(const void *addr, struct list_head *multi_recs) { struct fru_multirec_info *mr_src = (struct fru_multirec_info *)addr; struct fru_multirec_node *mr_new; @@ -286,7 +285,7 @@ static int fru_append_multirec(unsigned long addr, return 0; } -static int fru_parse_multirec(unsigned long addr) +static int fru_parse_multirec(const void *addr) { u8 hdr_len = sizeof(struct fru_multirec_hdr); struct fru_multirec_hdr *mr_hdr; @@ -308,7 +307,7 @@ static int fru_parse_multirec(unsigned long addr) return 0; } -int fru_capture(unsigned long addr) +int fru_capture(const void *addr) { struct fru_common_hdr *hdr; u8 checksum = 0; From patchwork Thu Aug 25 16:42:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jae Hyun Yoo X-Patchwork-Id: 1670342 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=CS43IaIW; 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 ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MD87v5Cwjz1yg7 for ; Fri, 26 Aug 2022 02:49:31 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 36E958489D; Thu, 25 Aug 2022 18:49:19 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.b="CS43IaIW"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9B887848B2; Thu, 25 Aug 2022 18:49:17 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 735D3848AF for ; Thu, 25 Aug 2022 18:49:12 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=quic_jaehyoo@quicinc.com Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGllG7010904; Thu, 25 Aug 2022 16:48:23 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=15faSwk0Xu/2Yb7QWbbEiRCm0ix2r98dxA9rtzkbAYg=; b=CS43IaIWnb36Cdd/4W7MWFdzQ05ffwtRaOIq+lLZfmeEovpZcuP3UoLdPKa1w4vPMZ7K hcMunjA+CE1HZEP7tlNpwBFHjgUR6Wcoqcz0z/uBaxsEBzLf54+IrRc7CccwolFtOiWy VJl7z5b5WvApFh8g9JezqNodNC6RdYkuDQyaY+UAa+/KVeNpv7/yuMEk23VORcdW77Tl YQrbKq9K1JW1KL7CVxNIIeSwa6OlExpg3bBkDxTWDsilaE2VLjOd6JCzcAwI3L9ldlRM o8BtVxKgthRowvImPxZSVuvLf0yFcQAWwBkUKF2/58+hqMF6NhVqvv2R0RIrj8/+1nsg yQ== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j60ettv35-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:48:23 +0000 Received: from pps.filterd (NALASPPMTA02.qualcomm.com [127.0.0.1]) by NALASPPMTA02.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGhM8u012350; Thu, 25 Aug 2022 16:43:22 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 3j60ettybc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:22 +0000 Received: from NALASPPMTA02.qualcomm.com (NALASPPMTA02.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27PGhMes012342; Thu, 25 Aug 2022 16:43:22 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 27PGhMUE012341 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:22 +0000 Received: from maru.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Thu, 25 Aug 2022 09:43:20 -0700 From: Jae Hyun Yoo To: Michal Simek , Ovidiu Panait , Simon Glass , Mario Six , Masahisa Kojima , =?utf-8?q?Pali_Roh=C3=A1r?= , Heinrich Schuchardt , Ashok Reddy Soma , "Thomas Huth" , Huang Jianan , Chris Morgan , Roland Gaudig , Patrick Delaunay , Alexandru Gagniuc CC: Jamie Iles , Graeme Gregory , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Jae Hyun Yoo , Subject: [PATCH v4 4/6] cmd: fru: add product info area parsing support Date: Thu, 25 Aug 2022 09:42:43 -0700 Message-ID: <20220825164245.1606958-5-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> References: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: pkkCE8L_LTe9KS5A5KKMVuRC2GWqcZj1 X-Proofpoint-ORIG-GUID: pkkCE8L_LTe9KS5A5KKMVuRC2GWqcZj1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-25_08,2022-08-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 lowpriorityscore=0 mlxscore=0 clxscore=1015 impostorscore=0 mlxlogscore=999 priorityscore=1501 bulkscore=0 adultscore=0 phishscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208250063 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean Add product info area parsing support. Custom board fields can be added dynamically using linked list so that each board support can utilize them in their own custom way. Signed-off-by: Jae Hyun Yoo --- Changes from v3: * None. Changes from v2: * Changed 'struct fru_board_info_member' to 'struct fru_common_info_member'. Changes from v1: * Refactored using linked list instead of calling a custom parsing callback. Changes from RFC: * Added manufacturer custom product info fields parsing flow. cmd/fru.c | 28 ++++-- include/fru.h | 34 ++++++- lib/fru_ops.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 286 insertions(+), 20 deletions(-) diff --git a/cmd/fru.c b/cmd/fru.c index b2cadbec9780..42bdaae09449 100644 --- a/cmd/fru.c +++ b/cmd/fru.c @@ -43,11 +43,22 @@ static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc, static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + int (*fru_generate)(const void *addr, int argc, char *const argv[]); unsigned long addr; const void *buf; - int ret; + int ret, maxargs; + + if (!strncmp(argv[2], "-b", 3)) { + fru_generate = fru_board_generate; + maxargs = cmdtp->maxargs + FRU_BOARD_AREA_TOTAL_FIELDS; + } else if (!strncmp(argv[2], "-p", 3)) { + fru_generate = fru_product_generate; + maxargs = cmdtp->maxargs + FRU_PRODUCT_AREA_TOTAL_FIELDS; + } else { + return CMD_RET_USAGE; + } - if (argc < cmdtp->maxargs) + if (argc < maxargs) return CMD_RET_USAGE; addr = hextoul(argv[3], NULL); @@ -62,7 +73,7 @@ static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc, 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, "", ""), + U_BOOT_CMD_MKENT(generate, 4, 0, do_fru_generate, "", ""), }; static int do_fru(struct cmd_tbl *cmdtp, int flag, int argc, @@ -90,11 +101,16 @@ 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" - " [custom ...] - Generate FRU\n" - " format with board info area filled based on\n" + "fru generate -b \n" + " [custom ...] - Generate FRU\n" + " format with board info area filled based on\n" " parameters. is pointing to place where FRU is\n" " generated.\n" + "fru generate -p \n" + " \n" + " [custom ...] - Generate FRU format with\n" + " product info area filled based on parameters. \n" + " is pointing to place where FRU is generated.\n" ; #endif diff --git a/include/fru.h b/include/fru.h index b158b80b5866..2b19033a3843 100644 --- a/include/fru.h +++ b/include/fru.h @@ -31,7 +31,13 @@ struct fru_board_info_header { u8 time[3]; } __packed; -struct fru_board_info_member { +struct fru_product_info_header { + u8 ver; + u8 len; + u8 lang_code; +} __packed; + +struct fru_common_info_member { u8 type_len; u8 *name; } __packed; @@ -64,6 +70,27 @@ struct fru_board_data { struct list_head custom_fields; }; +struct fru_product_data { + u8 ver; + u8 len; + u8 lang_code; + u8 manufacturer_type_len; + u8 manufacturer_name[FRU_INFO_FIELD_LEN_MAX]; + u8 product_name_type_len; + u8 product_name[FRU_INFO_FIELD_LEN_MAX]; + u8 part_number_type_len; + u8 part_number[FRU_INFO_FIELD_LEN_MAX]; + u8 version_number_type_len; + u8 version_number[FRU_INFO_FIELD_LEN_MAX]; + u8 serial_number_type_len; + u8 serial_number[FRU_INFO_FIELD_LEN_MAX]; + u8 asset_number_type_len; + u8 asset_number[FRU_INFO_FIELD_LEN_MAX]; + u8 file_id_type_len; + u8 file_id[FRU_INFO_FIELD_LEN_MAX]; + struct list_head custom_fields; +}; + struct fru_multirec_hdr { u8 rec_type; u8 type; @@ -85,6 +112,7 @@ struct fru_multirec_node { struct fru_table { struct fru_common_hdr hdr; struct fru_board_data brd; + struct fru_product_data prd; struct list_head multi_recs; bool captured; }; @@ -102,13 +130,15 @@ struct fru_table { /* This should be minimum of fields */ #define FRU_BOARD_AREA_TOTAL_FIELDS 5 +#define FRU_PRODUCT_AREA_TOTAL_FIELDS 7 #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(const void *addr); -int fru_generate(const void *addr, int argc, char *const argv[]); +int fru_board_generate(const void *addr, int argc, char *const argv[]); +int fru_product_generate(const void *addr, int argc, char *const argv[]); u8 fru_checksum(u8 *addr, u8 len); int fru_check_type_len(u8 type_len, u8 language, u8 *type); const struct fru_table *fru_get_fru_data(void); diff --git a/lib/fru_ops.c b/lib/fru_ops.c index a25ebccd110d..978d5f8e8a19 100644 --- a/lib/fru_ops.c +++ b/lib/fru_ops.c @@ -16,9 +16,18 @@ struct fru_table fru_data __section(".data") = { .brd.custom_fields = LIST_HEAD_INIT(fru_data.brd.custom_fields), + .prd.custom_fields = LIST_HEAD_INIT(fru_data.prd.custom_fields), .multi_recs = LIST_HEAD_INIT(fru_data.multi_recs), }; +static const char * const fru_typecode_str[] = { + "Binary/Unspecified", + "BCD plus", + "6-bit ASCII", + "8-bit ASCII", + "2-byte UNICODE" +}; + static u16 fru_cal_area_len(u8 len) { return len * FRU_COMMON_HDR_LEN_MULTIPLIER; @@ -77,9 +86,9 @@ int fru_check_type_len(u8 type_len, u8 language, u8 *type) static u8 fru_gen_type_len(u8 *addr, char *name) { int len = strlen(name); - struct fru_board_info_member *member; + struct fru_common_info_member *member; - member = (struct fru_board_info_member *)addr; + member = (struct fru_common_info_member *)addr; member->type_len = FRU_TYPELEN_TYPE_ASCII8 << FRU_TYPELEN_TYPE_SHIFT; member->type_len |= len; @@ -91,7 +100,7 @@ static u8 fru_gen_type_len(u8 *addr, char *name) return 1 + len; } -int fru_generate(const void *addr, int argc, char *const argv[]) +int fru_board_generate(const void *addr, int argc, char *const argv[]) { struct fru_common_hdr *header = (struct fru_common_hdr *)addr; struct fru_board_info_header *board_info; @@ -161,6 +170,74 @@ int fru_generate(const void *addr, int argc, char *const argv[]) return 0; } +int fru_product_generate(const void *addr, int argc, char *const argv[]) +{ + struct fru_common_hdr *header = (struct fru_common_hdr *)addr; + struct fru_product_info_header *product_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 = 0; /* not present */ + header->off_product = (sizeof(*header)) / 8; /* Starting offset 8 */ + 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 */ + product_info = (void *)((u8 *)header + sizeof(*header)); + + debug("header %lx, product_info %lx\n", (ulong)header, + (ulong)product_info); + + product_info->ver = 1; /* 1.0 spec */ + product_info->lang_code = 0; /* English */ + + /* Member fields are just after board_info header */ + member = (u8 *)product_info + sizeof(*product_info); + + while (--argc > 0 && ++argv) { + len = fru_gen_type_len(member, *argv); + member += len; + } + + *member++ = 0xc1; /* Indication of no more fields */ + + len = member - (u8 *)product_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; + } + + product_info->len = len / 8; /* Size in multiples of 8 bytes */ + + *member = 0; /* Clear before calculation */ + *member = 0 - fru_checksum((u8 *)product_info, len); + + debug("checksum %x(addr %x)\n", *member, len); + + env_set_hex("fru_addr", (ulong)addr); + env_set_hex("filesize", (ulong)member - (ulong)addr + 1); + + return 0; +} + static void fru_delete_custom_fields(struct list_head *custom_fields) { struct fru_custom_field_node *node, *next; @@ -258,6 +335,74 @@ static int fru_parse_board(const void *addr) return 0; } +static int fru_parse_product(const void *addr) +{ + u8 i, type; + int len; + u8 *data, *term, *limit; + + memcpy(&fru_data.prd.ver, (void *)addr, 6); + addr += 3; + data = (u8 *)&fru_data.prd.manufacturer_type_len; + + /* Record max structure limit not to write data over allocated space */ + limit = (u8 *)&fru_data.prd + sizeof(struct fru_product_data) - + sizeof(struct fru_custom_field_node *); + + for (i = 0; ; i++, data += FRU_INFO_FIELD_LEN_MAX) { + len = fru_check_type_len(*(u8 *)addr, fru_data.prd.lang_code, + &type); + /* + * Stop cature if it end of fields + */ + if (len == -EINVAL) + break; + + if (i < FRU_PRODUCT_AREA_TOTAL_FIELDS) { + /* Stop when length is more then fields to record */ + if (data + len > limit) + 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; + + if (i < FRU_PRODUCT_AREA_TOTAL_FIELDS) { + /* Record data field */ + memcpy(data, (u8 *)addr, len); + term = data + (u8)len; + *term = 0; + } else { + struct list_head *custom_fields; + + custom_fields = &fru_data.prd.custom_fields; + + /* Add a custom info field */ + if (fru_append_custom_info(addr - 1, custom_fields)) { + fru_delete_custom_fields(custom_fields); + return -EINVAL; + } + } + + addr += len; + } + + if (i < FRU_PRODUCT_AREA_TOTAL_FIELDS) { + printf("Product area require minimum %d fields\n", + FRU_PRODUCT_AREA_TOTAL_FIELDS); + return -EINVAL; + } + + return 0; +} + static void fru_delete_multirecs(struct list_head *multi_recs) { struct fru_multirec_node *node, *next; @@ -320,9 +465,11 @@ int fru_capture(const void *addr) hdr = (struct fru_common_hdr *)addr; fru_delete_custom_fields(&fru_data.brd.custom_fields); + fru_delete_custom_fields(&fru_data.prd.custom_fields); fru_delete_multirecs(&fru_data.multi_recs); memset((void *)&fru_data, 0, sizeof(fru_data)); INIT_LIST_HEAD(&fru_data.brd.custom_fields); + INIT_LIST_HEAD(&fru_data.prd.custom_fields); INIT_LIST_HEAD(&fru_data.multi_recs); memcpy((void *)&fru_data, (void *)hdr, sizeof(struct fru_common_hdr)); @@ -331,6 +478,9 @@ int fru_capture(const void *addr) if (hdr->off_board) fru_parse_board(addr + fru_cal_area_len(hdr->off_board)); + if (hdr->off_product) + fru_parse_product(addr + fru_cal_area_len(hdr->off_product)); + if (hdr->off_multirec) fru_parse_multirec(addr + fru_cal_area_len(hdr->off_multirec)); @@ -341,13 +491,6 @@ int fru_capture(const void *addr) static int fru_display_board(struct fru_board_data *brd, int verbose) { - 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", @@ -389,9 +532,9 @@ static int fru_display_board(struct fru_board_data *brd, int verbose) 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]); + debug("Type code: %s\n", fru_typecode_str[type]); else - debug("Type code: %s\n", typecode[type + 1]); + debug("Type code: %s\n", fru_typecode_str[type + 1]); if (!len) { debug("%s not found\n", boardinfo[i]); @@ -424,6 +567,79 @@ static int fru_display_board(struct fru_board_data *brd, int verbose) return 0; } +static int fru_display_product(struct fru_product_data *prd, int verbose) +{ + static const char * const productinfo[] = { + "Manufacturer Name", + "Product Name", + "Part Number", + "Version Number", + "Serial Number", + "Asset Number", + "File ID", + }; + struct fru_custom_field_node *node; + u8 *data; + u8 type; + int len; + + if (verbose) { + printf("*****PRODUCT INFO*****\n"); + printf("Version:%d\n", fru_version(prd->ver)); + printf("Product Area Length:%d\n", fru_cal_area_len(prd->len)); + } + + if (fru_check_language(prd->lang_code)) + return -EINVAL; + + data = (u8 *)&prd->manufacturer_type_len; + + for (u8 i = 0; i < (sizeof(productinfo) / sizeof(*productinfo)); i++) { + len = fru_check_type_len(*data++, prd->lang_code, + &type); + if (len == -EINVAL) { + printf("**** EOF for Product Area ****\n"); + break; + } + + if (type <= FRU_TYPELEN_TYPE_ASCII8 && + (prd->lang_code == FRU_LANG_CODE_ENGLISH || + prd->lang_code == FRU_LANG_CODE_ENGLISH_1)) + debug("Type code: %s\n", fru_typecode_str[type]); + else + debug("Type code: %s\n", fru_typecode_str[type + 1]); + + if (!len) { + debug("%s not found\n", productinfo[i]); + continue; + } + + switch (type) { + case FRU_TYPELEN_TYPE_BINARY: + debug("Length: %d\n", len); + printf(" %s: 0x%x\n", productinfo[i], *data); + break; + case FRU_TYPELEN_TYPE_ASCII8: + debug("Length: %d\n", len); + printf(" %s: %s\n", productinfo[i], data); + break; + default: + debug("Unsupported type %x\n", type); + } + + data += FRU_INFO_FIELD_LEN_MAX; + } + + list_for_each_entry(node, &prd->custom_fields, list) { + printf(" Custom Type/Length: 0x%x\n", node->info.type_len); + print_hex_dump_bytes(" ", DUMP_PREFIX_OFFSET, node->info.data, + node->info.type_len & + FRU_TYPELEN_LEN_MASK); + } + + return 0; +} + static int fru_display_multirec(struct list_head *multi_recs, int verbose) { struct fru_multirec_node *node; @@ -495,6 +711,10 @@ int fru_display(int verbose) if (ret) return ret; + ret = fru_display_product(&fru_data.prd, verbose); + if (ret) + return ret; + return fru_display_multirec(&fru_data.multi_recs, verbose); } From patchwork Thu Aug 25 16:42:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jae Hyun Yoo X-Patchwork-Id: 1670348 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=b2fAwYn4; 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 ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MD8YX14MSz1yhQ for ; Fri, 26 Aug 2022 03:08:16 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 26FC1845F1; Thu, 25 Aug 2022 19:08:11 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.b="b2fAwYn4"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2066B84886; Thu, 25 Aug 2022 19:08:09 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5619C845F0 for ; Thu, 25 Aug 2022 19:08:05 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=quic_jaehyoo@quicinc.com Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27PBLdx0003633; Thu, 25 Aug 2022 17:07:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=dX4vD8tjm0sIM0H7kkWDxKzAGxAxyiH0OOiP9YG4kTc=; b=b2fAwYn4HxOiRaoIUK8g0R4rSGe3sD/CFPn20OshTqtXcUzikRqa4xWRmSjPlQlJkN4Y PtEYkX5xEbsLEtosCTBJO7aQTqPtHZBh3h5OES6uzkdCkrFRlOoSWtkkOieJTRU/H2tx 4BY8Q7JIBUekplj1wG1gjTr93j9L/Cgqy3YvgzRKw9nupvf7MDfREXCQlUsHop7bKh46 RXTovvTlAu9NqYVxlk+bugmzhI6yOi4QQOGijNfwdyhAtA3Dn1AOzjqduQpK3awsoVbI 36rVcA+cq/XVQVWngsRMv7DUpyw0GejM+NjoNASwaP0Hyfm9nTw2vRvOkaV6p0dfkttg Eg== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j6399jk2e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 17:07:41 +0000 Received: from pps.filterd (NALASPPMTA02.qualcomm.com [127.0.0.1]) by NALASPPMTA02.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGhN7n012386; Thu, 25 Aug 2022 16:43:23 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 3j60ettybh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:23 +0000 Received: from NALASPPMTA02.qualcomm.com (NALASPPMTA02.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27PGfETV008522; Thu, 25 Aug 2022 16:43:23 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 27PGhNEx012367 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:23 +0000 Received: from maru.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Thu, 25 Aug 2022 09:43:22 -0700 From: Jae Hyun Yoo To: Michal Simek , Ovidiu Panait , Simon Glass , Mario Six , Masahisa Kojima , =?utf-8?q?Pali_Roh=C3=A1r?= , Heinrich Schuchardt , Ashok Reddy Soma , "Thomas Huth" , Huang Jianan , Chris Morgan , Roland Gaudig , Patrick Delaunay , Alexandru Gagniuc CC: Jamie Iles , Graeme Gregory , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Jae Hyun Yoo , Subject: [PATCH v4 5/6] doc: fru: add documentation for the fru command and APIs Date: Thu, 25 Aug 2022 09:42:44 -0700 Message-ID: <20220825164245.1606958-6-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> References: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: GWq8vGsgNYyt3I71OF5bVCwE6SDHGTgV X-Proofpoint-ORIG-GUID: GWq8vGsgNYyt3I71OF5bVCwE6SDHGTgV X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-25_08,2022-08-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 phishscore=0 impostorscore=0 mlxlogscore=999 spamscore=0 lowpriorityscore=0 adultscore=0 mlxscore=0 malwarescore=0 suspectscore=0 clxscore=1015 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208250064 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean Add a usage document for the 'fru' u-boot command. Add kerneldocs for . Signed-off-by: Jae Hyun Yoo --- Changes from v3: * None. Changes from v2: * Added kerneldocs to 'include/fru.h'. (Simon) Changes from v1: * Newly added in v2. (Heinrich) doc/usage/cmd/fru.rst | 144 +++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + include/fru.h | 182 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 doc/usage/cmd/fru.rst diff --git a/doc/usage/cmd/fru.rst b/doc/usage/cmd/fru.rst new file mode 100644 index 000000000000..d65bbc6dcbba --- /dev/null +++ b/doc/usage/cmd/fru.rst @@ -0,0 +1,144 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +fru command +=========== + +Synopsis +-------- + +:: + + fru capture + fru display + fru generate -b [ ...] + fru generate -p [ ...] + +Description +----------- + +The *fru* commands is used to generate, capture and display FRU (Field +Replaceable Unit) information data. + +Capture +~~~~~~~ + +The *fru capture* command parses and captures FRU configuration table at +a specified address. + + addr + memory address which FRU configuration table is stored. + +Display +~~~~~~~ + +The *fru display* command displays FRU information that is parsed using +fru capture command. + +Generate +~~~~~~~~ + +The *fru generate* command generates a FRU configuration table which has Board +or Product Info Area using the given field parameters. + + -b + generate FRU which has board info area. + + addr + memory address which FRU configuration table will be stored. + + manufacturer + board manufacturer string. + + board name + board product name string. + + serial number + board serial number string. + + serial number + board serial number string. + + part number + board part number string. + + file id + FRU File ID string. The FRU File version field is a pre-defined + field provided as a manufacturing aid for verifying the file that + was used during manufacture or field update to load the FRU + information. The content is manufacturer-specific. + + custom + additional custom board info area fields, if any. + + -p + generate FRU which has product info area. + + addr + memory address which FRU configuration table will be stored. + + manufacturer + product manufacturer string. + + board name + product name string. + + part number + product part/model number string. + + version number + product version number string. + + serial number + product serial number string. + + asset number + asset tag. + + file id + FRU File ID string. The FRU File version field is a pre-defined + field provided as a manufacturing aid for verifying the file that + was used during manufacture or field update to load the FRU + information. The content is manufacturer-specific. + + custom + additional custom product info area fields, if any. + +Example +------- + +:: + + => fru generate -b 90000000 abc def ghi jkl mno prs tuv wxy + => fru capture 90000000 + => fru display + *****COMMON HEADER***** + Version:1 + *** No Internal Area *** + *** No Chassis Info Area *** + Board Area Offset:8 + *** No Product Info Area *** + *** No MultiRecord Area *** + *****BOARD INFO***** + Version:1 + Board Area Length:40 + Time in Minutes from 0:00hrs 1/1/96: 0 + Manufacturer Name: abc + Product Name: def + Serial Number: ghi + Part Number: jkl + File ID: mno + Custom Type/Length: 0xc3 + 00000000: 70 72 73 prs + Custom Type/Length: 0xc3 + 00000000: 74 75 76 tuv + Custom Type/Length: 0xc3 + 00000000: 77 78 79 wxy + *****PRODUCT INFO***** + Version:0 + Product Area Length:0 + *****MULTIRECORDS***** + +Configuration +------------- + +The fru command is only available if CONFIG_CMD_FRU=y. diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 28f9683a3e6f..e96a16356307 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -45,6 +45,7 @@ Shell commands cmd/fatload cmd/fdt cmd/for + cmd/fru cmd/gpio cmd/load cmd/loadm diff --git a/include/fru.h b/include/fru.h index 2b19033a3843..1d11fd1a5964 100644 --- a/include/fru.h +++ b/include/fru.h @@ -10,6 +10,21 @@ #include +/** + * struct fru_common_hdr - FRU common header + * + * @version: Common header format version + * @off_internal: Internal use area starting offset + * @off_chassis: Chassis info area starting offset + * @off_board: Board area starting offset + * @off_product: Product info area starting offset + * @off_multirec: MultiRecord area starting offset + * @pad: PAD, write as 00h + * @crc: Common header checksum (zero checksum) + * + * Offsets are all in multiples of 8 bytes). 00h indicates that the area is not + * present. + */ struct fru_common_hdr { u8 version; u8 off_internal; @@ -24,6 +39,17 @@ struct fru_common_hdr { #define FRU_INFO_FIELD_LEN_MAX 32 #define FRU_MULTIREC_DATA_LEN_MAX 255 +/** + * struct fru_board_info_header - Board info area header + * + * @ver: Board area format version + * @len: Board area length (in multiples of 8 bytes) + * @lang_code: Language code + * @time: Mfg. date / time + * Number of minutes from 0:00 hrs 1/1/96. + * LSbyte first (little endian) + * 00_00_00h = unspecified + */ struct fru_board_info_header { u8 ver; u8 len; @@ -31,27 +57,71 @@ struct fru_board_info_header { u8 time[3]; } __packed; +/** + * struct fru_product_info_header - Product info area header + * + * @ver: Product area format version + * @len: Product area length (in multiples of 8 bytes) + * @lang_code: Language code + */ struct fru_product_info_header { u8 ver; u8 len; u8 lang_code; } __packed; +/** + * struct fru_common_info_member - FRU common info member + * + * @type_len: type/length byte + * @name: Member information bytes + */ struct fru_common_info_member { u8 type_len; u8 *name; } __packed; +/** + * struct fru_custom_info - Custom info field + * + * @type_len: Type/length byte + * @data: Custom information bytes + */ struct fru_custom_info { u8 type_len; u8 data[FRU_INFO_FIELD_LEN_MAX]; } __packed; +/** + * struct fru_custom_field_node - Linked list head for Custom info fields + * + * @list: Linked list head + * @info: Custom info field of the node + */ struct fru_custom_field_node { struct list_head list; struct fru_custom_info info; }; +/** + * struct fru_board_data - Board info area + * + * @ver: Board area format version + * @len: Board area length (in multiples of 8 bytes) + * @lang_code: Language code + * @time: Mfg. date / time + * @manufacturer_type_len: Type/length byte + * @manufacturer_name: Board manufacturer name + * @product_name_type_len: Type/length byte + * @product_name: Board product name + * @serial_number_type_len: Type/length byte + * @serial_number: Board serial number + * @part_number_type_len: Type/length byte + * @part_number: Board part number + * @file_id_type_len: Type/length byte + * @file_id: FRU file ID + * @custom_fields: Linked list head for Custom info fields + */ struct fru_board_data { u8 ver; u8 len; @@ -70,6 +140,28 @@ struct fru_board_data { struct list_head custom_fields; }; +/** + * struct fru_product_data - Product info area + * + * @ver: Product area format version + * @len: Product area length (in multiples of 8 bytes) + * @lang_code: Language code + * @manufacturer_type_len: Type/length byte + * @manufacturer_name: Product manufacturer name + * @product_name_type_len: Type/length byte + * @product_name: Product name + * @part_number_type_len: Type/length byte + * @part_number: Product part number + * @version_number_type_len: Type/length byte + * @version_number: Product version number + * @serial_number_type_len: Type/length byte + * @serial_number: Product serial number + * @asset_number_type_len: Type/length byte + * @asset_number: Product asset number + * @file_id_type_len: Type/length byte + * @file_id: FRU file ID + * @custom_fields: Linked list head for Custom info fields + */ struct fru_product_data { u8 ver; u8 len; @@ -91,6 +183,15 @@ struct fru_product_data { struct list_head custom_fields; }; +/** + * struct fru_multirec_hdr - MultiRecord area header + * + * @rec_type: Product area format version + * @type: Product area length (in multiples of 8 bytes) + * @len: Language code + * @csum: Type/length byte + * @hdr_csum: Product manufacturer name + */ struct fru_multirec_hdr { u8 rec_type; u8 type; @@ -99,16 +200,37 @@ struct fru_multirec_hdr { u8 hdr_csum; } __packed; +/** + * struct fru_multirec_info - MultiRecord info field + * + * @hdr: MultiRecord area header + * @data: MultiRecord information bytes + */ struct fru_multirec_info { struct fru_multirec_hdr hdr; u8 data[FRU_MULTIREC_DATA_LEN_MAX]; } __packed; +/** + * struct fru_multirec_node - Linked list head for MultiRecords + * + * @list: Linked list head + * @info: MultiRecord info field of the node + */ struct fru_multirec_node { struct list_head list; struct fru_multirec_info info; }; +/** + * struct fru_table - FRU table storage + * + * @hdr: FRU common header + * @brd: Board info + * @prd: Product info + * @multi_recs: MultiRecords + * @captured: TRUE when this table is captured and parsed + */ struct fru_table { struct fru_common_hdr hdr; struct fru_board_data brd; @@ -135,12 +257,72 @@ struct fru_table { #define FRU_TYPELEN_TYPE_BINARY 0 #define FRU_TYPELEN_TYPE_ASCII8 3 +/** + * fru_display() - display captured FRU information + * + * @verbose: Enable (1) verbose output or not (0) + * + * Returns 0 on success or a negative error code. + */ int fru_display(int verbose); + +/** + * fru_display() - parse and capture FRU configuration table + * + * @addr: Address where the FRU configuration table is stored + * + * Returns 0 on success or a negative error code. + */ int fru_capture(const void *addr); + +/** + * fru_board_generate() - generate FRU which has board info area + * + * @addr: Address to store generated FRU configuration table at + * @argc: Length of @argv + * @argv: Vector of arguments. See doc/usage/fru.rst for more details + * + * Returns 0 on success or a negative error code. + */ int fru_board_generate(const void *addr, int argc, char *const argv[]); + +/** + * fru_product_generate() - generate FRU which has product info area + * + * @addr: Address to store generated FRU configuration table at + * @argc: Length of @argv + * @argv: Vector of arguments. See doc/usage/fru.rst for more details + * + * Returns 0 on success or a negative error code. + */ int fru_product_generate(const void *addr, int argc, char *const argv[]); + +/** + * fru_checksum() - calculate checksum of FRU info + * + * @addr: Address of the FRU info data source + * @len: Length of the FRU info data + * + * Returns a calculated checksum. + */ u8 fru_checksum(u8 *addr, u8 len); + +/** + * fru_check_type_len() - check and parse type/len byte + * + * @type_len: Type/len byte + * @language: Language code byte + * @type: Pointer to a variable to store parsed type + * + * Returns length of the type, -EINVAL on the FRU_TYPELEN_EOF type + */ int fru_check_type_len(u8 type_len, u8 language, u8 *type); + +/** + * fru_get_fru_data() - get pointer to captured FRU info table + * + * Returns pointer to captured FRU table + */ const struct fru_table *fru_get_fru_data(void); #endif /* FRU_H */ From patchwork Thu Aug 25 16:42:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jae Hyun Yoo X-Patchwork-Id: 1670341 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=euMLxPCH; 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 ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MD87j2kh6z1yg7 for ; Fri, 26 Aug 2022 02:49:21 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 72FD68489E; Thu, 25 Aug 2022 18:48:59 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.b="euMLxPCH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D1E46848A5; Thu, 25 Aug 2022 18:48:52 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B143284881 for ; Thu, 25 Aug 2022 18:48:49 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=quic_jaehyoo@quicinc.com Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27PBLn6N021062; Thu, 25 Aug 2022 16:48:26 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=KFJMjbCyrjFYfR3VrTQgxV3oSzNC6B+0C6UsBLl9cb8=; b=euMLxPCH4t0IO8iQRq1++9YXkPj6uW1KHv/eqT++eC4HeQdXm+eXgoYPtGC9YvPEALOA APhhuhcivgSNU/AJh4+VFGUwiqLvFILDsaIQvJOISCs69O3KraR9NRdv1td9fByx2Vqp kQlhbh0fXMN64EINUFxkvFCi9pz5r+Pq/3aVJapUugGJqtjhwyMyful7bNmPjaaT6PZO pedT+9DfJr6u0M1FemRRXvTLuxXBzdykaTCCWrEltXDJCKeKvBIVdwb7vE8icTPGrbMJ xkNYpZBscEMIMbhWsDon/a6I0r9yIAPXx4WJjO6SsnK94q5+CB8HV+4UjzkqGLgbe3kU aA== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j644ntb2q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:48:26 +0000 Received: from pps.filterd (NALASPPMTA03.qualcomm.com [127.0.0.1]) by NALASPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27PGhPO5018373; Thu, 25 Aug 2022 16:43:25 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 3j47bn72q7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:25 +0000 Received: from NALASPPMTA03.qualcomm.com (NALASPPMTA03.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27PGcZBX011965; Thu, 25 Aug 2022 16:43:25 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 27PGhP2R018361 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 25 Aug 2022 16:43:25 +0000 Received: from maru.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Thu, 25 Aug 2022 09:43:23 -0700 From: Jae Hyun Yoo To: Michal Simek , Ovidiu Panait , Simon Glass , Mario Six , Masahisa Kojima , =?utf-8?q?Pali_Roh=C3=A1r?= , Heinrich Schuchardt , Ashok Reddy Soma , "Thomas Huth" , Huang Jianan , Chris Morgan , Roland Gaudig , Patrick Delaunay , Alexandru Gagniuc CC: Jamie Iles , Graeme Gregory , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Jae Hyun Yoo , Subject: [PATCH v4 6/6] test: cmd: fru: add unit test for the fru command Date: Thu, 25 Aug 2022 09:42:45 -0700 Message-ID: <20220825164245.1606958-7-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> References: <20220825164245.1606958-1-quic_jaehyoo@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: ev_czutv_1Kk7qaV86rdaolt0wxweKVM X-Proofpoint-GUID: ev_czutv_1Kk7qaV86rdaolt0wxweKVM X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-25_08,2022-08-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 lowpriorityscore=0 malwarescore=0 spamscore=0 clxscore=1015 adultscore=0 phishscore=0 suspectscore=0 impostorscore=0 mlxscore=0 bulkscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208250063 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.6 at phobos.denx.de X-Virus-Status: Clean Add test cases for the fru command. Signed-off-by: Jae Hyun Yoo Reviewed-by: Simon Glass --- Changes from v3: * Added a 'Reviewed-by' tag. (Simon) Changes from v2: * Newly added in v3. (Simon) include/test/suites.h | 1 + test/cmd/Makefile | 1 + test/cmd/fru.c | 84 +++++++++++++++++++++++++++++++++++++++++++ test/cmd_ut.c | 6 ++++ 4 files changed, 92 insertions(+) create mode 100644 test/cmd/fru.c diff --git a/include/test/suites.h b/include/test/suites.h index 44025ccecd6f..1d4a8c3e4a66 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -39,6 +39,7 @@ int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_fru(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); diff --git a/test/cmd/Makefile b/test/cmd/Makefile index c331757425ea..5995384dad91 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -8,6 +8,7 @@ endif obj-y += mem.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o obj-$(CONFIG_CMD_FDT) += fdt.o +obj-$(CONFIG_CMD_FRU) += fru.o obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o obj-$(CONFIG_CMD_PINMUX) += pinmux.o diff --git a/test/cmd/fru.c b/test/cmd/fru.c new file mode 100644 index 000000000000..fa560622cf0b --- /dev/null +++ b/test/cmd/fru.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Executes tests for fru command + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#define FRU_TEST(_name, _flags) UNIT_TEST(_name, _flags, fru_test) + +#define CMD_FRU_TEST_SRC_BUF_SIZE 1024 + +static const char cmd_gen_b[] = + "fru generate -b %08lx abcd efgh ijkl mnop qrst uvwx"; +static const char cmd_gen_p[] = + "fru generate -p %08lx abcd efgh ijkl mnop qrst uvwx yz01 2345"; + +static const char cmd_capture[] = "fru capture %08lx"; + +static int fru_test_board(struct unit_test_state *uts) +{ + u8 fru_src[CMD_FRU_TEST_SRC_BUF_SIZE]; + int i; + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf(cmd_gen_b, (ulong)map_to_sysmem(fru_src))); + ut_assertok(run_commandf(cmd_capture, (ulong)map_to_sysmem(fru_src))); + ut_assertok(run_command("fru display", 0)); + for (i = 0; i < 11; i++) + ut_assert_skipline(); + ut_assert_nextline(" Manufacturer Name: abcd"); + ut_assert_nextline(" Product Name: efgh"); + ut_assert_nextline(" Serial Number: ijkl"); + ut_assert_nextline(" Part Number: mnop"); + ut_assert_nextline(" File ID: qrst"); + ut_assert_nextline(" Custom Type/Length: 0xc4"); + ut_assert_nextline(" 00000000: 75 76 77 78 uvwx"); + for (i = 0; i < 4; i++) + ut_assert_skipline(); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FRU_TEST(fru_test_board, UT_TESTF_CONSOLE_REC); + +static int fru_test_product(struct unit_test_state *uts) +{ + u8 fru_src[CMD_FRU_TEST_SRC_BUF_SIZE]; + int i; + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf(cmd_gen_p, (ulong)map_to_sysmem(fru_src))); + ut_assertok(run_commandf(cmd_capture, (ulong)map_to_sysmem(fru_src))); + ut_assertok(run_command("fru display", 0)); + for (i = 0; i < 14; i++) + ut_assert_skipline(); + ut_assert_nextline(" Manufacturer Name: abcd"); + ut_assert_nextline(" Product Name: efgh"); + ut_assert_nextline(" Part Number: ijkl"); + ut_assert_nextline(" Version Number: mnop"); + ut_assert_nextline(" Serial Number: qrst"); + ut_assert_nextline(" Asset Number: uvwx"); + ut_assert_nextline(" File ID: yz01"); + ut_assert_nextline(" Custom Type/Length: 0xc4"); + ut_assert_nextline(" 00000000: 32 33 34 35 2345"); + ut_assert_skipline(); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FRU_TEST(fru_test_product, UT_TESTF_CONSOLE_REC); + +int do_ut_fru(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(fru_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(fru_test); + + return cmd_ut_category("fru", "fru_test_", tests, n_ents, argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 3789c6b784c0..4c163da8176c 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -80,6 +80,9 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_CMD_LOADM U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""), #endif +#ifdef CONFIG_CMD_FRU + U_BOOT_CMD_MKENT(fru, CONFIG_SYS_MAXARGS, 1, do_ut_fru, "", ""), +#endif }; static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc, @@ -167,6 +170,9 @@ static char ut_help_text[] = #endif #ifdef CONFIG_CMD_LOADM "ut loadm [test-name]- test of parameters and load memory blob\n" +#endif +#ifdef CONFIG_CMD_FRU + "ut fru [test-name] - test of the fru command\n" #endif ; #endif /* CONFIG_SYS_LONGHELP */