From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BE2DCC38159 for ; Wed, 18 Jan 2023 14:38:46 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6FD63855FD; Wed, 18 Jan 2023 15:38:44 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=amd.com header.i=@amd.com header.b="y8ND9h8w"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3380385602; Wed, 18 Jan 2023 15:38:43 +0100 (CET) Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10on2050.outbound.protection.outlook.com [40.107.92.50]) (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 8E7B08481F for ; Wed, 18 Jan 2023 15:38:39 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=michal.simek@amd.com ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gEGGCFJQdow2Z1GUmmStygHB07oOdaWhIZFbQMocfBGJRJc5V2rhwl/i1Ass1Xp70qm4lEW1KpxeRnE6hDSZ/RFhiu12aysvQxoNKboy/E3tpJ6KtXVyMYXOUAWyyotMBoz2C6sWDzQgn9ae/KEYFFYNbafg/UFDPyBb8XTD9H1WNOO/ASTwFfp2QinZmU6We1TuB5rmIqWoxWX945rIY6McD5ToHvbBqHBhZIMXGlrJQK7W+AQNbvYobQzwFQZn0glEKkJ6pd8VDb1mChqWAzlRkfI6hG8xdREF+zhOWzo9GSwBQRUBZg8Q1QCn5ZVoZkXJRrVE7GbJUzHNFOWXCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=K3RyreIFs3yzK+JtgCxLp1a0pHcsysuSOv+32gkaeKA=; b=Ucl67a5dhdIJv71WjlTDHifxyo2ugBxiRDr62ibJIgcJXSmfQc8v3HAq33O2DsPcDGC2J/vYdM/cdQ5cQBRoMiD3uAyHoou9zOz3HRE10ubW/l6gaickmafdzu8RqPuht5SNM/7qBb33IdglUkDg5s+LOlsKn4RW8ULX3exQgg3DofpgBR3NYmI2jA2ZwUewdBkgbYPZhLs8wnc5hbv+WQPbGY3a4fOZtmbLVQdn1GiZEN18qdlBr4zLSGO1cQZ0reMN9MKm+CAwQ9kuDsvXaX9LsksDEjU/2p/uSLYAoPyPXArh+iBDa3jSP7BWsEokk44xG/jsfzG9etyK5LbBaw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=gmail.com smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=K3RyreIFs3yzK+JtgCxLp1a0pHcsysuSOv+32gkaeKA=; b=y8ND9h8wZ8dw2HaO4TRld1lLCN3f81EuFMDxXgfAbD4wWL3non8FKpS74pSMZxuES8oSXsC4GmIlKvQ3xhHTb9hK2/nieYhxqBZMgXCcAmc0R7t5+4accj/CtPQjGk+hIU9kMIic51iP/lJiq0DUFUKBQSRkGSOlaDuf3kwTagY= Received: from BN9PR03CA0912.namprd03.prod.outlook.com (2603:10b6:408:107::17) by DM4PR12MB5309.namprd12.prod.outlook.com (2603:10b6:5:390::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6002.24; Wed, 18 Jan 2023 14:38:36 +0000 Received: from BN8NAM11FT027.eop-nam11.prod.protection.outlook.com (2603:10b6:408:107:cafe::96) by BN9PR03CA0912.outlook.office365.com (2603:10b6:408:107::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6002.19 via Frontend Transport; Wed, 18 Jan 2023 14:38:35 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN8NAM11FT027.mail.protection.outlook.com (10.13.177.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6002.24 via Frontend Transport; Wed, 18 Jan 2023 14:38:35 +0000 Received: from [10.254.241.50] (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Wed, 18 Jan 2023 08:38:31 -0600 Message-ID: Date: Wed, 18 Jan 2023 15:38:28 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Content-Language: en-US To: Jassi Brar , CC: , , , , , , , Masami Hiramatsu , Jassi Brar References: <20230109010601.578439-1-jaswinder.singh@linaro.org> <20230109010717.578564-1-jaswinder.singh@linaro.org> From: Michal Simek Subject: Re: [PATCHv3 5/5] tools: Add mkfwumdata tool for FWU metadata image In-Reply-To: <20230109010717.578564-1-jaswinder.singh@linaro.org> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN8NAM11FT027:EE_|DM4PR12MB5309:EE_ X-MS-Office365-Filtering-Correlation-Id: 7c695e9f-30a1-4cb7-0491-08daf961ae65 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Mp02puSMB1tMHGqd0sT9QHVr2OZE8E36Ddv7wBZsU/P/0fCLDRlK2LOHXy+PT37oOXhkJI2gjT56EGiX/z0rX83DH0ws0Vf46Mjv2SNuh2DINNosKRiNf2Krzcx158d/WbqcjIjU+E1ekEJanpfw+6z+XqQ9Gv3TaumaPlskfeNgDgq+Vx1Dbehk4ZVf07rc3GNAyMs8hLpYyPCq9xY+6KVeT46dnhofSgbCEgaTZL6xKGpcQOBRhClwSyLG2dwAw3ec2D3edanTaoi8ZcX6oxf6Hii4aWsKEqz+JMHg7ha09/JVX/nXmntIDBHX7GUS0NNv4CxDxG/6uRlhEvZVHDJAu7i5jrxi+g5S83HGmHmMbrGvxqUain6iV3aFiDwR23dPrVL6N+F99ySNnKyvQBIZTHVVBFeXOpxM5+wrduLi+RsgvaVx5UkEEIGHWoGR4Si/lZHMEAws4e5LSHHUIsWXpxfL632Zu9oJUi8Js5OCG8EO5wwucDMcVAdNNxWVHenv+NQNgUy9gHzUWDyDUvLA4uj44zY/izaGTgnO/L+URtqT93GstlukUwXZ+Cj/4PhSa07knZrqp0C5p3QBUVxKaA2775QmyHuvM/9DCKXidR+q9GzxrcVR43dudB1JELDrQSD/zHt2fV1hS6sAKxwJ02zi29SdikMtY/nUiU5TkS5U3a6cRvc4MVEtHO2TmaaFm7NlpIuqtA4z/5GOBTzxQ0027WKilczy7CrbpU4HAcEkneX8z4sYY5ATbnXXn/y73mEP1LmE0Car5tUfOA== X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(376002)(136003)(39860400002)(346002)(396003)(451199015)(46966006)(36840700001)(40470700004)(31686004)(356005)(86362001)(44832011)(70206006)(70586007)(30864003)(7416002)(2906002)(8936002)(5660300002)(82740400003)(81166007)(36860700001)(31696002)(316002)(16576012)(54906003)(110136005)(6666004)(47076005)(426003)(53546011)(478600001)(36756003)(82310400005)(8676002)(40480700001)(4326008)(41300700001)(186003)(336012)(16526019)(83380400001)(2616005)(40460700003)(26005)(43740500002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jan 2023 14:38:35.8721 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7c695e9f-30a1-4cb7-0491-08daf961ae65 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT027.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB5309 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 On 1/9/23 02:07, Jassi Brar wrote: > From: Masami Hiramatsu > > Add 'mkfwumdata' tool to generate FWU metadata image for the meta-data > partition to be used in A/B Update imeplementation. > > Signed-off-by: Masami Hiramatsu > Signed-off-by: Sughosh Ganu > Signed-off-by: Jassi Brar > --- ./scripts/checkpatch.pl --strict tools/mkfwumdata.c CHECK: 'Endianess' may be misspelled - perhaps 'Endianness'? #32: FILE: tools/mkfwumdata.c:32: +/* TODO: Endianess conversion may be required for some arch. */ ^^^^^^^^^ ERROR: do not initialise statics to 0 #68: FILE: tools/mkfwumdata.c:68: +static int active_bank = 0; ERROR: do not initialise statics to false #70: FILE: tools/mkfwumdata.c:70: +static bool __use_guid = false; ERROR: code indent should use tabs where possible #234: FILE: tools/mkfwumdata.c:234: + mobj->size - sizeof(uint32_t));$ CHECK: Alignment should match open parenthesis #234: FILE: tools/mkfwumdata.c:234: + mdata->crc32 = crc32(0, (const unsigned char *)&mdata->version, + mobj->size - sizeof(uint32_t)); WARNING: please, no spaces at the start of a line #234: FILE: tools/mkfwumdata.c:234: + mobj->size - sizeof(uint32_t));$ total: 3 errors, 1 warnings, 2 checks, 326 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. NOTE: Whitespace errors detected. You may wish to use scripts/cleanpatch or scripts/cleanfile > tools/Kconfig | 9 ++ > tools/Makefile | 4 + > tools/mkfwumdata.c | 326 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 339 insertions(+) > create mode 100644 tools/mkfwumdata.c This is good but actually I can't see any example how you use this tool on your board. It would be good to list it in documentation you have written in previous patch. > > diff --git a/tools/Kconfig b/tools/Kconfig > index 539708f277..6e23f44d55 100644 > --- a/tools/Kconfig > +++ b/tools/Kconfig > @@ -157,4 +157,13 @@ config LUT_SEQUENCE > help > Look Up Table Sequence > > +config TOOLS_MKFWUMDATA > + bool "Build mkfwumdata command" > + default y if FWU_MULTI_BANK_UPDATE > + help > + This command allows users to create a raw image of the FWU > + metadata for initial installation of the FWU multi bank > + update on the board. The installation method depends on > + the platform. > + > endmenu > diff --git a/tools/Makefile b/tools/Makefile > index 26be0a7ba2..024d6c8eca 100644 > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -255,6 +255,10 @@ HOSTLDLIBS_mkeficapsule += \ > $(shell pkg-config --libs uuid 2> /dev/null || echo "-luuid") > hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule > > +mkfwumdata-objs := mkfwumdata.o lib/crc32.o > +HOSTLDLIBS_mkfwumdata += -luuid > +hostprogs-$(CONFIG_TOOLS_MKFWUMDATA) += mkfwumdata > + > # We build some files with extra pedantic flags to try to minimize things > # that won't build on some weird host compiler -- though there are lots of > # exceptions for files that aren't complaint. > diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c > new file mode 100644 > index 0000000000..e0b6702039 > --- /dev/null > +++ b/tools/mkfwumdata.c > @@ -0,0 +1,326 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (c) 2023, Linaro Limited > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* This will dynamically allocate the fwu_mdata */ > +#define CONFIG_FWU_NUM_BANKS 0 > +#define CONFIG_FWU_NUM_IMAGES_PER_BANK 0 > + > +/* Since we can not include fwu.h, redefine version here. */ > +#define FWU_MDATA_VERSION 1 > + > +typedef uint8_t u8; > +typedef int16_t s16; > +typedef uint16_t u16; > +typedef uint32_t u32; > +typedef uint64_t u64; > + > +#include > + > +/* TODO: Endianess conversion may be required for some arch. */ > + > +static const char *opts_short = "b:i:a:p:gh"; > + > +static struct option options[] = { > + {"banks", required_argument, NULL, 'b'}, > + {"images", required_argument, NULL, 'i'}, > + {"guid", required_argument, NULL, 'g'}, > + {"active-bank", required_argument, NULL, 'a'}, > + {"previous-bank", required_argument, NULL, 'p'}, > + {"help", no_argument, NULL, 'h'}, > + {NULL, 0, NULL, 0}, > +}; > + > +static void print_usage(void) > +{ > + fprintf(stderr, "Usage: mkfwumdata [options] \n"); > + fprintf(stderr, "Options:\n" > + "\t-i, --images Number of images\n" > + "\t-b, --banks Number of banks\n" > + "\t-a, --active-bank Active bank\n" > + "\t-p, --previous-bank Previous active bank\n" > + "\t-g, --guid Use GUID instead of UUID\n" > + "\t-h, --help print a help message\n" > + ); > + fprintf(stderr, " UUIDs list syntax:\n" > + "\t ,,\n" > + "\t images uuid list syntax:\n" > + "\t\t img_uuid_00,img_uuid_01...img_uuid_0b,\n" > + "\t\t img_uuid_10,img_uuid_11...img_uuid_1b,\n" > + "\t\t ...,\n" > + "\t\t img_uuid_i0,img_uuid_i1...img_uuid_ib,\n" > + "\t\t where 'b' and 'i' are number of banks and numbder of images in a bank respectively.\n" typo And personally \t\t is already nice indentation that you don't need to use additional spaces. And last line would be good to fit to 80 char limit. > + ); > +} > + > +static int active_bank = 0; > +static int previous_bank = INT_MAX; /* unset */ > +static bool __use_guid = false; > + > +struct fwu_mdata_object { > + size_t images; > + size_t banks; > + size_t size; > + struct fwu_mdata *mdata; > +}; > + > +struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) static? > +{ > + struct fwu_mdata_object *mobj; > + > + mobj = calloc(1, sizeof(*mobj)); > + if (!mobj) > + return NULL; > + > + mobj->size = sizeof(struct fwu_mdata) + > + (sizeof(struct fwu_image_entry) + > + sizeof(struct fwu_image_bank_info) * banks) * images; > + mobj->images = images; > + mobj->banks = banks; > + > + mobj->mdata = calloc(1, mobj->size); > + if (!mobj->mdata) { > + free(mobj); > + return NULL; > + } > + > + return mobj; > +} > + > +struct fwu_image_entry *fwu_get_image(struct fwu_mdata_object *mobj, size_t idx) static? > +{ > + size_t offset; > + > + offset = sizeof(struct fwu_mdata) + > + (sizeof(struct fwu_image_entry) + > + sizeof(struct fwu_image_bank_info) * mobj->banks) * idx; > + > + return (struct fwu_image_entry *)((char *)mobj->mdata + offset); > +} > + > +struct fwu_image_bank_info *fwu_get_bank(struct fwu_mdata_object *mobj, > + size_t img_idx, size_t bnk_idx) static? > +{ > + size_t offset; > + > + offset = sizeof(struct fwu_mdata) + > + (sizeof(struct fwu_image_entry) + > + sizeof(struct fwu_image_bank_info) * mobj->banks) * img_idx + > + sizeof(struct fwu_image_entry) + > + sizeof(struct fwu_image_bank_info) * bnk_idx; > + > + return (struct fwu_image_bank_info *)((char *)mobj->mdata + offset); > +} > + > +/** > + * convert_uuid_to_guid() - convert UUID to GUID > + * @buf: UUID binary > + * > + * UUID and GUID have the same data structure, but their binary > + * formats are different due to the endianness. See lib/uuid.c. > + * Since uuid_parse() can handle only UUID, this function must > + * be called to get correct data for GUID when parsing a string. > + * > + * The correct data will be returned in @buf. > + */ > +void convert_uuid_to_guid(unsigned char *buf) static? > +{ > + unsigned char c; > + > + c = buf[0]; > + buf[0] = buf[3]; > + buf[3] = c; > + c = buf[1]; > + buf[1] = buf[2]; > + buf[2] = c; > + > + c = buf[4]; > + buf[4] = buf[5]; > + buf[5] = c; > + > + c = buf[6]; > + buf[6] = buf[7]; > + buf[7] = c; if this is just endian convertion isn't there any standard function which you can just call. > +} > + > +int uuid_guid_parse(char *uuidstr, unsigned char *uuid) static > +{ > + int ret; > + > + ret = uuid_parse(uuidstr, uuid); > + if (ret < 0) > + return ret; > + > + if (__use_guid) > + convert_uuid_to_guid(uuid); > + > + return ret; > +} > + > +int fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, > + size_t idx, char *uuids) static - fix it everywhere. > +{ > + struct fwu_image_entry *image = fwu_get_image(mobj, idx); > + struct fwu_image_bank_info *bank; > + char *p = uuids, *uuid; > + int i; > + > + if (!image) > + return -ENOENT; > + > + /* Image location UUID */ > + uuid = strsep(&p, ","); > + if (!uuid) > + return -EINVAL; > + > + if (strcmp(uuid, "0") && > + uuid_guid_parse(uuid, (unsigned char *)&image->location_uuid) < 0) > + return -EINVAL; > + > + /* Image type UUID */ > + uuid = strsep(&p, ","); > + if (!uuid) > + return -EINVAL; > + > + if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_uuid) < 0) > + return -EINVAL; > + > + /* Fill bank image-UUID */ > + for (i = 0; i < mobj->banks; i++) { > + bank = fwu_get_bank(mobj, idx, i); > + if (!bank) > + return -ENOENT; > + bank->accepted = 1; > + uuid = strsep(&p, ","); > + if (!uuid) > + return -EINVAL; > + > + if (strcmp(uuid, "0") && > + uuid_guid_parse(uuid, (unsigned char *)&bank->image_uuid) < 0) > + return -EINVAL; > + } > + return 0; > +} > + > +/* Caller must ensure that @uuids[] has @mobj->images entries. */ > +int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) > +{ > + struct fwu_mdata *mdata = mobj->mdata; > + int i, ret; > + > + mdata->version = FWU_MDATA_VERSION; > + mdata->active_index = active_bank; > + mdata->previous_active_index = previous_bank; > + > + for (i = 0; i < mobj->images; i++) { > + ret = fwu_parse_fill_image_uuid(mobj, i, uuids[i]); > + if (ret < 0) > + return ret; > + } > + > + mdata->crc32 = crc32(0, (const unsigned char *)&mdata->version, > + mobj->size - sizeof(uint32_t)); > + > + return 0; > +} > + > +int fwu_make_mdata(size_t images, size_t banks, char *uuids[], char *output) > +{ > + struct fwu_mdata_object *mobj; > + FILE *file; > + int ret; > + > + mobj = fwu_alloc_mdata(images, banks); > + if (!mobj) > + return -ENOMEM; > + > + ret = fwu_parse_fill_uuids(mobj, uuids); > + if (ret < 0) > + goto done_make; > + > + file = fopen(output, "w"); > + if (!file) { > + ret = -errno; > + goto done_make; > + } > + > + ret = fwrite(mobj->mdata, mobj->size, 1, file); > + if (ret != mobj->size) > + ret = -errno; > + else > + ret = 0; > + > + fclose(file); > + > +done_make: > + free(mobj->mdata); > + free(mobj); > + > + return ret; > +} > + > +int main(int argc, char *argv[]) > +{ > + unsigned long banks = 0, images = 0; > + int c, ret; > + > + do { > + c = getopt_long(argc, argv, opts_short, options, NULL); > + switch (c) { > + case 'h': > + print_usage(); > + return 0; > + case 'b': > + banks = strtoul(optarg, NULL, 0); > + break; > + case 'i': > + images = strtoul(optarg, NULL, 0); > + break; > + case 'g': > + __use_guid = true; > + break; > + case 'p': > + previous_bank = strtoul(optarg, NULL, 0); > + break; > + case 'a': > + active_bank = strtoul(optarg, NULL, 0); > + break; > + } > + } while (c != -1); > + > + if (!banks || !images) { > + fprintf(stderr, "Error: The number of banks and images must not be 0.\n"); > + return -EINVAL; > + } > + > + /* This command takes UUIDs * images and output file. */ > + if (optind + images + 1 != argc) { > + fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n"); > + print_usage(); > + return -ERANGE; > + } > + > + if (previous_bank == INT_MAX) { > + /* set to the earlier bank in round-robin scheme */ > + previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1; > + } > + > + ret = fwu_make_mdata(images, banks, argv + optind, argv[argc - 1]); > + if (ret < 0) > + fprintf(stderr, "Error: Failed to parse and write image: %s\n", > + strerror(-ret)); > + > + return ret; > +} M