From patchwork Tue Aug 23 21:52:54 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: 1669473 X-Patchwork-Delegate: monstr@monstr.eu 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=U6VASCR/; 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) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MC30M6J6yz1ygc for ; Wed, 24 Aug 2022 07:54:11 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 78660842E0; Tue, 23 Aug 2022 23:53: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="U6VASCR/"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 008B884810; Tue, 23 Aug 2022 23:53:45 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-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 A38DD83FFF for ; Tue, 23 Aug 2022 23:53:40 +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 27NLd55M003389; Tue, 23 Aug 2022 21:53:16 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=E7vuOZCVAR0u2i8pdugPL5+6jyP9YQ08Ye7WATcrk/Y=; b=U6VASCR/UYCzgz2WbcjFrvSpdczKLbwyKaUOtdzhgTeCXfVZZzQ9M0Izo4XQ1Q9LeZhH yK3pZ3e+PJzOtAZh1wI/eTkk0emqJR3p7KQvPoclmti2HGV++2g9P1DS+1f2lc7LCg7H jpUqfv2PkVq4EdL+cWFUy+1Dy3C9yDuJF+oMVlG5qY2EHd13lVt0FJQ5B/ajea2qjb22 oOc9pIg/Yj13Bwiy9nI0hXuRt/P/7Cs+BNUgFsUUYQ1hSTeEcCzN2I6HNb9km6RxQoGc TQZwYQB2hus86wu3jVUltG+dJzT3RR9gtlgzhalYLKMpGua1vSHmxDe//LVwsWrH6OQi Mw== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pk8utu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:16 +0000 Received: from pps.filterd (NALASPPMTA05.qualcomm.com [127.0.0.1]) by NALASPPMTA05.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTP id 27NLrFhF015095; Tue, 23 Aug 2022 21:53:15 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA05.qualcomm.com (PPS) with ESMTPS id 3j4dvgdbmw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:15 +0000 Received: from NALASPPMTA05.qualcomm.com (NALASPPMTA05.qualcomm.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 27NLrF55015089; Tue, 23 Aug 2022 21:53:15 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA05.qualcomm.com (PPS) with ESMTPS id 27NLrFeZ015087 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:15 +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; Tue, 23 Aug 2022 14:53:13 -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 v3 1/7] xilinx: common: refactor FRU handling support Date: Tue, 23 Aug 2022 14:52:54 -0700 Message-ID: <20220823215300.1485789-2-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: GSFzpzzqHFBoS9WdNNA0zL9snlnOUy3k X-Proofpoint-GUID: GSFzpzzqHFBoS9WdNNA0zL9snlnOUy3k 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 mlxlogscore=999 bulkscore=0 mlxscore=0 adultscore=0 spamscore=0 priorityscore=1501 suspectscore=0 phishscore=0 malwarescore=0 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 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 | 228 ++++++++++++++++++++++++---------- 4 files changed, 264 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..e005ecae21fa 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 Tue Aug 23 21:52:55 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: 1669471 X-Patchwork-Delegate: monstr@monstr.eu 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=EkXBIY1w; 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 4MC3043mLCz1ygc for ; Wed, 24 Aug 2022 07:53:54 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7D94F814B6; Tue, 23 Aug 2022 23:53:42 +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="EkXBIY1w"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C7F7E84314; Tue, 23 Aug 2022 23:53:41 +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 C276D80F4E for ; Tue, 23 Aug 2022 23:53:38 +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 27NLatGv022994; Tue, 23 Aug 2022 21:53:18 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=PsJA7qSegIe1MxC+74dUiBAZSlAujgD8vw/JHC8xZhI=; b=EkXBIY1waRhQ6DqY/JQYxoi5G5bF2S/7ynMC3MGmX0f6BzAYkyf8h7plM1EF7ayvrkRI 40aDrkw8cli6++v6Xsb4H7n3aCbBPbfy5rOMS2kcgmHFRIMlP4w3xLnMlP1aIWuUe1et Yv/sATGVNTmG2eSaRorvCOub7jKetZY5cbKuVGruxyoJYsqqigtpZdJ3g/TMWa7wtmmy TUhiVmxIy71efhABAez6SFlq1lX0U173YNiwRqLNphCNrm4M+fWsml26OrdjkIOOIUF6 boI4qzTol2LuOICR0GLkW36sgEHf2wdh3WJ1ZUJ6Dpc69/3Tb6gAL3q6zMBRmfq+5i7C Rg== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pkruph-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:18 +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 27NLrHLv030506; Tue, 23 Aug 2022 21:53:17 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 3j46u0y0un-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:16 +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 27NLrG2E030501; Tue, 23 Aug 2022 21:53:16 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 27NLrG8s030500 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:16 +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; Tue, 23 Aug 2022 14:53:15 -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 v3 2/7] cmd: fru: move FRU handling support to common region Date: Tue, 23 Aug 2022 14:52:55 -0700 Message-ID: <20220823215300.1485789-3-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: BCeyqxYuUGedlOXbEPHJy3ojbiobKhDn X-Proofpoint-GUID: BCeyqxYuUGedlOXbEPHJy3ojbiobKhDn 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 mlxscore=0 adultscore=0 mlxlogscore=999 phishscore=0 spamscore=0 suspectscore=0 impostorscore=0 malwarescore=0 priorityscore=1501 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 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 e005ecae21fa..c0360f219c37 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 Tue Aug 23 21:52:56 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: 1669474 X-Patchwork-Delegate: monstr@monstr.eu 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=SinE5VnH; 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 4MC30X3814z1ygc for ; Wed, 24 Aug 2022 07:54:20 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CFCF38483F; Tue, 23 Aug 2022 23:53:54 +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="SinE5VnH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3F6DB83FFF; Tue, 23 Aug 2022 23:53:46 +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 E183F83F69 for ; Tue, 23 Aug 2022 23:53:42 +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 (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27NLWQhK027250; Tue, 23 Aug 2022 21:53:19 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=VrHJbPX3eyG2GKFkRoVsALnAJFiT+7n+7ePTqzABXGE=; b=SinE5VnHbnQHXhvVj5MN3yWMQ2jXlzitXonKf4EYJO8Ai2pEVtGhXIlAc2vQNqmEBYCz VYPc//x5UK7lc2YnfQu6sJWQjb1rScpzHQVkKTcsutX7wbFiv8fMnf3SsQGoX/tW7wg2 /YlF9DziXoJFofkxXr8qd6d6o+UFRUViCXsFoNm0KKfvoqBSoXv+mD73B8mYw5ueQqgv 6Lz/TpmD97rpfTYOmYG2hCFNDNrrZD3pdGsQ9Qom8SwEHQT4Kb1lVVSsbj5kJIb1oxBg ocEdlirdb22urJEFhHrwwBvsntM+iskcK/cGufUGo5YbnXsgC09QT4xmuGY06dAx/QX4 pA== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pqgutw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:19 +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 27NLrIwY030551; Tue, 23 Aug 2022 21:53:18 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 3j46u0y0v3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:18 +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 27NLrIPS030543; Tue, 23 Aug 2022 21:53:18 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 27NLrIpm030542 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53: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; Tue, 23 Aug 2022 14:53: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 v3 3/7] cmd: fru: fix a sandbox segfault issue Date: Tue, 23 Aug 2022 14:52:56 -0700 Message-ID: <20220823215300.1485789-4-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: LpNWwQCRAUubV0dcgjZ3hrzBXhe_OnhM X-Proofpoint-GUID: LpNWwQCRAUubV0dcgjZ3hrzBXhe_OnhM 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 bulkscore=0 phishscore=0 mlxlogscore=954 clxscore=1015 malwarescore=0 lowpriorityscore=0 impostorscore=0 suspectscore=0 spamscore=0 mlxscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 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 c0360f219c37..6ed1388b2fc8 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 Tue Aug 23 21:52:57 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: 1669476 X-Patchwork-Delegate: monstr@monstr.eu 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=ALe81VXI; 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 4MC30y3xH0z1ygc for ; Wed, 24 Aug 2022 07:54:42 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 41F378484F; Tue, 23 Aug 2022 23:54:00 +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="ALe81VXI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7349080F4E; Tue, 23 Aug 2022 23:53: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 4AE7284314 for ; Tue, 23 Aug 2022 23:53: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 (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27NLUvw4025762; Tue, 23 Aug 2022 21:53:21 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=ugTVN+MwRrV0QEPsTTqyonofFYgS0Ezeh8Kyx8PnBtI=; b=ALe81VXIqTqLjPH6Am3MqpnZGuJIgFfjO67li5w3KH77VaLYAokvl8w4B3Jwa/V7OXZ6 c9yMmBKxapikZcPhQwmhjnmZYvX0Nfj6I98VfRr7dB8ASaXOTwtrl4/yAkGmOwM2YG5q fyUhP9s2USTd/aFWs0zgv5ZoHMzKeATKYbAxX7coxUJZo2WI2mYoKKPJs8Z546Qbuh1x Ecll5H+I6+RSDCwgwQGky3urcUEoQP+QaEkU63MhN63h+4bZclwHENjqez1D8FvusSYb B4TZrI4esFMD+LH2qUQ3ypvXdH5AYhRsVHWcj1X1BDskykmwcXbMSQN3jaR3dtX74HmI pQ== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pj0ucy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:20 +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 27NLrKNd003621; Tue, 23 Aug 2022 21:53:20 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 3j47bmxw2g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:20 +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 27NLrJap003613; Tue, 23 Aug 2022 21:53:19 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 27NLrJlI003612 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53: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; Tue, 23 Aug 2022 14:53: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 v3 4/7] cmd: fru: add product info area parsing support Date: Tue, 23 Aug 2022 14:52:57 -0700 Message-ID: <20220823215300.1485789-5-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: _lckl51sTWqNZZfFpqXSaB9PVUasNOZW X-Proofpoint-ORIG-GUID: _lckl51sTWqNZZfFpqXSaB9PVUasNOZW 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 lowpriorityscore=0 clxscore=1015 impostorscore=0 malwarescore=0 phishscore=0 mlxlogscore=999 spamscore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 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 6ed1388b2fc8..b6197d3e250f 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 Tue Aug 23 21:52:58 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: 1669478 X-Patchwork-Delegate: monstr@monstr.eu 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=fs7d21CU; 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 4MC31N0bP9z1ygc for ; Wed, 24 Aug 2022 07:55:04 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CE5E184855; Tue, 23 Aug 2022 23:54:06 +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="fs7d21CU"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 12ECA847FC; Tue, 23 Aug 2022 23:53:50 +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 2F51F842E0 for ; Tue, 23 Aug 2022 23:53:46 +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 27NGj3O5030644; Tue, 23 Aug 2022 21:53: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=9QAqzCKzJgZhe+4Cd2XywLWBa8P2foCf23xW4oYnxyI=; b=fs7d21CU20wJryw1y35Qon7io/oG4VEfRU8BMQLCQ7RQb3yEbKNvJpIjR0wfRsFLUUr2 PHcT5DchrF7scHAxqGC6+A6TpEXQmN8b7YIoVzaIP3wG4FXFmpWutRbLBqfp1W8LQn+f yFQT+tArlwqiKH6I82Gya6MeaUjGqrt0Px1vElVbIkIMzKfmUuP9rdScQ10OrJuyAxZa SLxGafaIqip0e+UGY14YhnmLxx5lXBR8SjmGRm9vmyhlcPXmp0KtEOuwM5IOOORoObvu MnO7oIvy6X3GNhOEPK5bjeG8ALH/Z0NAxQt8TKOVOB4CvAsxGgI6Op+PWvAyKsZfkQtB 3g== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pk8uma-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:21 +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 27NLrLVd003639; Tue, 23 Aug 2022 21:53:21 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 3j47bmxw2q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:21 +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 27NLrLWr003631; Tue, 23 Aug 2022 21:53:21 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (PPS) with ESMTPS id 27NLrLUW003630 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53: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; Tue, 23 Aug 2022 14:53: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 v3 5/7] doc: fru: add documentation for the fru command and APIs Date: Tue, 23 Aug 2022 14:52:58 -0700 Message-ID: <20220823215300.1485789-6-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: Weelm8moV84BiFmJncNjkyHNH8M3AWbl X-Proofpoint-ORIG-GUID: Weelm8moV84BiFmJncNjkyHNH8M3AWbl 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 lowpriorityscore=0 adultscore=0 priorityscore=1501 malwarescore=0 bulkscore=0 phishscore=0 impostorscore=0 mlxlogscore=999 spamscore=0 suspectscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 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 Tue Aug 23 21:52:59 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: 1669475 X-Patchwork-Delegate: monstr@monstr.eu 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=AY/2K3lU; 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 4MC30m0HBfz1ygc for ; Wed, 24 Aug 2022 07:54:32 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 148A884847; Tue, 23 Aug 2022 23:53:58 +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="AY/2K3lU"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 99B0E844B5; Tue, 23 Aug 2022 23:53: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 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 7B08E845A8 for ; Tue, 23 Aug 2022 23:53: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 (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27NLmBAQ001978; Tue, 23 Aug 2022 21:53:24 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=VLqDQ++1jGwWJU4nwbszJhhTbDSnH+hEhUdcgWUEfjs=; b=AY/2K3lUE37zfaW/pGwE4qzoqFLbzNNYCHdgUrYMpPJMw2Rm5SztvEAZOlqM3CpqrJy6 NiWZmEbjg/w3+lQ77JCTlH6xNCuNv9NBW7/yhQqSHM/y3Qo5HpE+yPwUH1LVEmqFG2s1 sO4Q3YqdKSoA7IVCSWu2cIGsjHIEi3KSswVEYMb0bARC0Uq66886OPfe96JVCXU//rYB Wgv9Cw8bvIMv1sUTx/eHagmh2RRoIS7Bhg+VlriSE7Cek5+loyBJntB7idSES5ElEw0/ pnKsjXmnBBaULRmciiAaSSH8TQdN82qFZ4sFdTbnnn5kUaW/546FRQpJ9j1KRfyVNOQe YA== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pq8ug8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53: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 27NLrMjn030575; Tue, 23 Aug 2022 21:53:22 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 3j46u0y0vb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53: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 27NLrMJT030567; Tue, 23 Aug 2022 21:53:22 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (PPS) with ESMTPS id 27NLrM8s030566 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53: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; Tue, 23 Aug 2022 14:53:21 -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 v3 6/7] test: py: fru: add a test for the fru command Date: Tue, 23 Aug 2022 14:52:59 -0700 Message-ID: <20220823215300.1485789-7-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: r31DIFpTV4q95_hI_MR-tgTSP-ivCcfX X-Proofpoint-GUID: r31DIFpTV4q95_hI_MR-tgTSP-ivCcfX 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 mlxlogscore=999 bulkscore=0 phishscore=0 spamscore=0 impostorscore=0 clxscore=1015 adultscore=0 malwarescore=0 mlxscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 simple test for the 'fru' command. Signed-off-by: Jae Hyun Yoo --- Changes from v2: * Added CONFIG_CMD_FRU=y only into the sandbox_defconfig. (Simon) Changes from v1: * Newly added in v2. (Heinrich) configs/sandbox_defconfig | 1 + test/py/tests/test_fru.py | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 test/py/tests/test_fru.py diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index eba7bcbb483b..293e39706cf2 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -115,6 +115,7 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_SQUASHFS=y CONFIG_CMD_MTDPARTS=y CONFIG_CMD_STACKPROTECTOR_TEST=y +CONFIG_CMD_FRU=y CONFIG_MAC_PARTITION=y CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y diff --git a/test/py/tests/test_fru.py b/test/py/tests/test_fru.py new file mode 100644 index 000000000000..e5e1d7d00639 --- /dev/null +++ b/test/py/tests/test_fru.py @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + +import pytest +import u_boot_utils + +@pytest.mark.buildconfigspec('cmd_fru') +def test_fru_board(u_boot_console): + """Test that fru command generates and captures board FRU information as + expected.""" + + ram_base = u_boot_utils.find_ram_base(u_boot_console) + addr = '0x%x' % ram_base + expected_response = 'rc:0' + response = u_boot_console.run_command('fru generate -b ' + addr + ' abcd efgh ijkl mnop qrst uvwx; echo rc:$?') + assert(expected_response in response) + response = u_boot_console.run_command('fru capture ' + addr + '; echo rc:$?') + assert(expected_response in response) + response = u_boot_console.run_command('fru display') + assert('Manufacturer Name: abcd' in response) + assert('Product Name: efgh' in response) + assert('Serial Number: ijkl' in response) + assert('Part Number: mnop' in response) + assert('File ID: qrst' in response) + assert('Custom Type/Length: 0xc4' in response) + +@pytest.mark.buildconfigspec('cmd_fru') +def test_fru_product(u_boot_console): + """Test that fru command generates and captures product FRU information as + expected.""" + + ram_base = u_boot_utils.find_ram_base(u_boot_console) + addr = '0x%x' % ram_base + expected_response = 'rc:0' + response = u_boot_console.run_command('fru generate -p ' + addr + ' abcd efgh ijkl mnop qrst uvwx yz01 2345; echo rc:$?') + assert(expected_response in response) + response = u_boot_console.run_command('fru capture ' + addr + '; echo rc:$?') + assert(expected_response in response) + response = u_boot_console.run_command('fru display') + assert('Manufacturer Name: abcd' in response) + assert('Product Name: efgh' in response) + assert('Part Number: ijkl' in response) + assert('Version Number: mnop' in response) + assert('Serial Number: qrst' in response) + assert('Asset Number: uvwx' in response) + assert('File ID: yz01' in response) + assert('Custom Type/Length: 0xc4' in response) From patchwork Tue Aug 23 21:53:00 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: 1669477 X-Patchwork-Delegate: monstr@monstr.eu 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=f15E0Pzk; 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 4MC3191y08z1ygc for ; Wed, 24 Aug 2022 07:54:53 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7A10284856; Tue, 23 Aug 2022 23:54:04 +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="f15E0Pzk"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C1A8A8483E; Tue, 23 Aug 2022 23:53:49 +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 AC61A847FC for ; Tue, 23 Aug 2022 23:53: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 (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27NKTZAu022208; Tue, 23 Aug 2022 21:53:25 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=ZjqK8iCnuFEYpYzY2ka79XKxjYH+1Nl/UjsPmkAucCA=; b=f15E0PzkDBPzwl+6/Jga6LhMv4JxmCWlqfXVbnTNP+rqmRJzI+0cmF7k+b5r9FspKImr c8YjJSBmwCWljhkhUOH7E7vA92PsCyDtlzxr7u+9MbYJB1XcFlteloObUWx7zlOMLBC7 PBqwPM6wNPf2ZCZroZr4r60WecdcGl0m/hH2rrGrFkY1sFo1FtZoytN7/kVtqdt7vno0 y8LLuyNxteMtSMImrk3ICcj1W3r/C4ARPjLeIc4sR0FNrXUHcmDDGWtbxx2dIkOMqIZU 1rDTtinT0oGbl1Am358p5m+a9P4ttduPXYDFWVjBr2+1IVMhfTWDoOaY65apPK5G3Xu3 Cg== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3j52pkrupn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:25 +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 27NLrOi9001763; Tue, 23 Aug 2022 21:53:24 GMT Received: from pps.reinject (localhost [127.0.0.1]) by NALASPPMTA04.qualcomm.com (PPS) with ESMTPS id 3j2rpkvc5u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:24 +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 27NLrONu001758; Tue, 23 Aug 2022 21:53:24 GMT Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA04.qualcomm.com (PPS) with ESMTPS id 27NLrNa1001755 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 23 Aug 2022 21:53:24 +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; Tue, 23 Aug 2022 14:53: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 v3 7/7] test: cmd: fru: add unit test for the fru command Date: Tue, 23 Aug 2022 14:53:00 -0700 Message-ID: <20220823215300.1485789-8-quic_jaehyoo@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220823215300.1485789-1-quic_jaehyoo@quicinc.com> References: <20220823215300.1485789-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: HnA2_AH0qc0UwwqHffjGA8DVS7qkqQkB X-Proofpoint-GUID: HnA2_AH0qc0UwwqHffjGA8DVS7qkqQkB 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-23_09,2022-08-22_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 mlxscore=0 adultscore=0 mlxlogscore=999 phishscore=0 spamscore=0 suspectscore=0 impostorscore=0 malwarescore=0 priorityscore=1501 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208230082 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 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 */