From patchwork Sun Oct 16 10:40:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 615424 Delivered-To: patch@linaro.org Received: by 2002:a17:522:c983:b0:460:3032:e3c4 with SMTP id kr3csp1348766pvb; Sun, 16 Oct 2022 03:43:25 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5+YYxV9Oz6b0ZNoGKhVK+67c0c/IwtuvdNIuzs1X+syjMwfFqrFnIyOW3VrWCBQRQIbJB6 X-Received: by 2002:a17:903:41d1:b0:184:e955:abf4 with SMTP id u17-20020a17090341d100b00184e955abf4mr6662416ple.123.1665917005142; Sun, 16 Oct 2022 03:43:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665917005; cv=none; d=google.com; s=arc-20160816; b=OKtBq+HY2K7hg1RniV6ZB743R6rnf/wSO/IPEhUA9MUQuBgwFc4MmJFluFCui56aFd JveHP6grBglIzyx1xENjvYdwbHuD72gJFA1NnEZjOdx/DT4a8PotPzcQAhUIxNAb3aq3 o7QB3ti9IUpubmMpZfbHcKPp4YgFkaUmKyUPvDIiQjlCialJIB28tE3i/n/ohKLv+d0w 9bETOXE8MMU9aPsSC/zKqXgGk7GW4roh8tgeHrpNM8cKtusxYvTmVmaE47rBnD4aeW0/ +9McxzCP9jToQVTGkPvlms2J6r7/9kVvyeWYos2URFKkclb9e5VFtIIbS7vmKRDzg013 ZbqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:sender:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :mime-version:message-id:date:subject:cc:to:from:dkim-signature :dkim-signature; bh=tTZjrl8urIoxztDJCP0tfSFTDljIaFDbJMGoS7l5yEE=; b=Go9fIcKmOVkGTXKkrVFJDSsXekDW/b7GbbbUs0FvONQ/2kr0aXSbkp3GaClniHdvpP RG2c7YGKRJgHoj14GFgTO2KklRuCwJkbcSQhECpcpXfGG+8TGulZuyHk3jV5sXJw4Qe4 pwgqe/pNcD02HbYY9Ham9T77Y4t3WcI75KsJkwQnSY/Uw75vvx9ZoParIKSRW6nphu2n hMv/U/pyKPg4zl/cJSEgRY7eMOPzE+aep3hL556unv/NJIubpF4Ai4q0bImHudw4qZvl hccJpf+d9Phd45GDM36hJsRY2r/ZlkNliP06uPPkhaEphHfoBSBgp0iERQNNUuI3NqjY DXSQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.infradead.org header.s=bombadil.20210309 header.b=wAulhziS; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=csIkLxh0; spf=pass (google.com: best guess record for domain of linux-mtd-bounces+patch=linaro.org@lists.infradead.org designates 2607:7c80:54:3::133 as permitted sender) smtp.mailfrom="linux-mtd-bounces+patch=linaro.org@lists.infradead.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2607:7c80:54:3::133]) by mx.google.com with ESMTPS id y12-20020a170902700c00b0018273316ce0si8382856plk.511.2022.10.16.03.43.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Oct 2022 03:43:25 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-mtd-bounces+patch=linaro.org@lists.infradead.org designates 2607:7c80:54:3::133 as permitted sender) client-ip=2607:7c80:54:3::133; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.infradead.org header.s=bombadil.20210309 header.b=wAulhziS; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=csIkLxh0; spf=pass (google.com: best guess record for domain of linux-mtd-bounces+patch=linaro.org@lists.infradead.org designates 2607:7c80:54:3::133 as permitted sender) smtp.mailfrom="linux-mtd-bounces+patch=linaro.org@lists.infradead.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=tTZjrl8urIoxztDJCP0tfSFTDljIaFDbJMGoS7l5yEE=; b=wAulhziSMlo3qN f7riBC2/6VUEzryeVmWz0QEFnUWDN+Gbk+u3/r1EYl0gKYzb3qe4FrMzvkX00plZod2RxHW/N7Vkw Z07sJtPCWc4rVxgGjxI5xChLBl/xh/62uMtc25W8VzOrG76cN3YtZuGlEraPjGR7k5P3gfDfc6npX RbmO2rf/VwdhNemulfKufSSi2EiMUQiVlKJsZ+lsczOx4KRg/F3yMq8bb+0NuVukC981ArO4LrXQZ zOw12gyp6PjgkV8PJw+NnTCqivfCQf5Wi7svTN2AotgW953ytJgXHAi2+6xSpkm/Jwoemx9IHEcko DWiBIv+5ZwQiL5yJXdGw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ok16G-0014Af-6D; Sun, 16 Oct 2022 10:42:32 +0000 Received: from mail-lf1-x12b.google.com ([2a00:1450:4864:20::12b]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1ok16C-00147g-3N for linux-mtd@lists.infradead.org; Sun, 16 Oct 2022 10:42:30 +0000 Received: by mail-lf1-x12b.google.com with SMTP id b1so13514480lfs.7 for ; Sun, 16 Oct 2022 03:42:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=UcY3JOQPBN9UnBwaCusrlGVYYrWXocP7ZuQCKOwvOZE=; b=csIkLxh0b72uq+OjkZ6Kex3+3Hyz5ztvoWonMtkSCAvBg64ChvwkYWTcOVvHyaJrhR nX9cvdQdUzpHQyp6M5XHg5XBBU8beJ2BxQj4Kd74Em9sO1aZa0WzZ8GWXxj9SpY5vund CiX+C87Bk+NNBrWkm8HhIGTW8bgSQdn26yJksBwiArsSgp/gVgC7zmKbP856pLRqVfUf IWbBigrgOpzW6T3keT/LC4Zd1RkL8zQqhP4RU4r8fV2ZBpTdkGd+b+3HUq5/rMWpGTAG 1IHndjs5Ntp53yF9wqTINPBY64FJT+OuRRkIrEaSwO1lxNLQCNgpxd/roGf/pDur8V8x g+Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=UcY3JOQPBN9UnBwaCusrlGVYYrWXocP7ZuQCKOwvOZE=; b=RP/ObNMmIT9zH1YU15+669eeD8ahMq33Sce6foZ7p+hjVeLyCrefWp+Fv8OFnrvpOK IAZ0grEZrHmuMojpW+e+8tDmrip0fdXixFAogm+7af/M55I+fMHZRGOWdPyJOL4rY8AU RkAGuTsSgFN+sDH6c3699MtuPuGrs9guriSgiG7YWr2WuEQNvdK2V7fbLUl08U5PkrIG d+L392+Ag2t+y6n5Bj1qB1EcC4eQuiiD/rmo/DEFrseCIecoR+hpUsZk0Q6teTVBkVsu Un13STIgV0WBZPOONU87yyPkIVBPPvMMISfRw7FYsfutb3y4odcuj55S6OI85DXhplfT kMtg== X-Gm-Message-State: ACrzQf1dWVTuLkk63JVSVGcAyGbHiVotmXtKpn5g4N3LvrD3VKnCEoIA rjQ8YbNfHEn/00bR1/nSFYZiIg== X-Received: by 2002:a05:6512:1156:b0:4a2:7e51:b3e0 with SMTP id m22-20020a056512115600b004a27e51b3e0mr2282009lfg.118.1665916943607; Sun, 16 Oct 2022 03:42:23 -0700 (PDT) Received: from localhost.localdomain (c-fdcc225c.014-348-6c756e10.bbcust.telenor.se. [92.34.204.253]) by smtp.gmail.com with ESMTPSA id i4-20020a2ea364000000b0026dfedff58csm1087457ljn.99.2022.10.16.03.42.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Oct 2022 03:42:23 -0700 (PDT) From: Linus Walleij To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra Cc: linux-mtd@lists.infradead.org, Linus Walleij , =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= , Hauke Mehrtens Subject: [PATCH] mtd: parsers: trx: Rewrite partition parsing Date: Sun, 16 Oct 2022 12:40:17 +0200 Message-Id: <20221016104017.2695989-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.37.3 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221016_034228_245237_E17CC6C8 X-CRM114-Status: GOOD ( 38.43 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: The TRX parser has never been fully implemented, the commit splitting it out of the bcm47xx parser says "There is still some place for improvement". Here are some improvements: 1. First partition includes TRX header offset: Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:12b listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+patch=linaro.org@lists.infradead.org The TRX parser has never been fully implemented, the commit splitting it out of the bcm47xx parser says "There is still some place for improvement". Here are some improvements: 1. First partition includes TRX header offset: The parser can currently produce output like this: 0x00000000001c-0x000000280000 : "linux" mtd: partition "linux" doesn't start on an erase/write block boundary -- force read-only This is because the TRX header is not included into the partition, while it should be: the vendor code does this, and when replacing the kernel in flash we certainly want to write it along with a new TRX tag as well. Right now we cannot replace it from within Linux due to this limitation. 2. Scan for several TRX headers Currently only the first flash block is scanned for a TRX header, but several flashes have multiple TRX headers each with up to 3 partitions. 3. Determine extents of the data (rootfs) partition. While still a bit hacky (just scanning forward for UBI magic) we check where the rootfs volume actually ends, and do not assume it fills the rest of the flash memory. 4. Add free space as a separate partition. Before this I could not mount my UBI rootfs because the rootfs gets too big: all remaining space will put into the second detected partition so the UBI partition has the wrong size and will not attach. After this patch it mounts just fine. Vendor code partition detection (D-Link DWL-8610AP): Creating 5 MTD partitions on "brcmnand": 0x000000000000-0x000002800000 : "linux" 0x000000280000-0x000002800000 : "rootfs" 0x000002800000-0x000005000000 : "linux2" 0x000002a80000-0x000005000000 : "rootfs2" 0x000005000000-0x000008000000 : "jffs2" Before this patch: Creating 2 MTD partitions on "brcmnand.0": 0x00000000001c-0x000000280000 : "linux" mtd: partition "linux" doesn't start on an erase/write block boundary -- force read-only 0x000000280000-0x000008000000 : "ubi" After this patch: 5 trx partitions found on MTD device brcmnand.0 Creating 5 MTD partitions on "brcmnand.0": 0x000000000000-0x000000280000 : "linux" 0x000000280000-0x000002800000 : "ubi" 0x000002800000-0x000002a80000 : "linux2" 0x000002a80000-0x000005000000 : "ubi2" 0x000005000000-0x000008000000 : "free" Cc: Rafał Miłecki Cc: Hauke Mehrtens Signed-off-by: Linus Walleij --- drivers/mtd/parsers/parser_trx.c | 289 +++++++++++++++++++++++++------ 1 file changed, 232 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/parsers/parser_trx.c b/drivers/mtd/parsers/parser_trx.c index 4814cf218e17..aa088fa039d1 100644 --- a/drivers/mtd/parsers/parser_trx.c +++ b/drivers/mtd/parsers/parser_trx.c @@ -3,6 +3,7 @@ * Parser for TRX format partitions * * Copyright (C) 2012 - 2017 Rafał Miłecki + * Copyright (C) 2022 Linus Walleij */ #include @@ -10,7 +11,13 @@ #include #include -#define TRX_PARSER_MAX_PARTS 4 +/* Maximum number of TRX headers that can be found in a flash */ +#define TRX_PARSER_MAX_TRX 4 +/* + * Maximum number of partitions that can be found in total in a flash + * 3 offsets and free space = 4. + */ +#define TRX_PARSER_MAX_PARTS (TRX_PARSER_MAX_TRX * 4) /* Magics */ #define TRX_MAGIC 0x30524448 @@ -25,26 +32,193 @@ struct trx_header { uint32_t offset[3]; } __packed; -static const char *parser_trx_data_part_name(struct mtd_info *master, - size_t offset) +static void parser_trx_dump_trx(struct trx_header *trx) +{ + pr_debug("TRX at %08x\n", (u32)trx); + pr_debug(" MAGIC %08x\n", trx->magic); + pr_debug(" LENGTH %08x\n", trx->length); + pr_debug(" CRC32 %08x\n", trx->crc32); + pr_debug(" FLAGS %04x\n", trx->flags); + pr_debug(" VERSION %04x\n", trx->version); + pr_debug(" OFFSET[0] %08x\n", trx->offset[0]); + pr_debug(" OFFSET[1] %08x\n", trx->offset[1]); + pr_debug(" OFFSET[2] %08x\n", trx->offset[2]); +} + +static int parser_trx_data_part_name_and_extents(struct mtd_info *mtd, + uint64_t start, uint64_t end, int trx_index, + const char **out_name, uint64_t *out_size) { - uint32_t buf; + uint32_t blocksize = mtd->erasesize; size_t bytes_read; + uint64_t offset; + uint64_t size; + uint32_t magic; + uint32_t tmp; + char *name; int err; - err = mtd_read(master, offset, sizeof(buf), &bytes_read, - (uint8_t *)&buf); + err = mtd_read(mtd, start, sizeof(magic), &bytes_read, (uint8_t *)&magic); if (err && !mtd_is_bitflip(err)) { - pr_err("mtd_read error while parsing (offset: 0x%zX): %d\n", - offset, err); - goto out_default; + pr_err("mtd_read error while parsing (offset: 0x%08llx): %d\n", + offset, err); + magic = 0x0; + } + + /* Here other data partion types can be added as needed */ + switch (magic) { + case UBI_EC_MAGIC: + name = "ubi"; + break; + default: + magic = 0x0; + name = "rootfs"; + break; + } + + /* First partion is just "name", second is "name2" etc */ + if (trx_index > 0) { + name = kasprintf(GFP_KERNEL, "%s%d", name, trx_index + 1); + if (!name) + return -ENOMEM; } - if (buf == UBI_EC_MAGIC) - return "ubi"; + /* + * Attempt to determine extents, first assume it is + * the rest of the TRX partition, then scan to check. + */ + size = end - start; + if (magic == 0x0) + goto out_no_scan; + + for (offset = start; offset <= end - blocksize; + offset += blocksize) { + err = mtd_read(mtd, offset, sizeof(tmp), &bytes_read, (uint8_t *)&tmp); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%08llx): %d\n", + offset, err); + break; + } + if (tmp != magic) { + size = offset - start; + break; + } + } -out_default: - return "rootfs"; +out_no_scan: + *out_name = name; + *out_size = size; + + return 0; +} + +static uint64_t parser_trx_get_offset(uint64_t start, struct trx_header *trx, int i) +{ + /* Include the TRX header into the first partition */ + if ((i == 0) && (trx->offset[i] == sizeof(struct trx_header))) + return start; + return start + trx->offset[i]; +} + +static uint64_t parser_trx_get_size(uint64_t start, uint64_t end, struct trx_header *trx, int i) +{ + uint64_t this_offset; + uint64_t next_offset; + uint64_t retsz; + + /* + * Get the size from the next offset if that is > 0, else we assume + * we are the last partition in the TRX partition block, and then we + * use the rest of the available size. + */ + this_offset = parser_trx_get_offset(start, trx, i); + if ((i < 2) && (trx->offset[i + 1] > 0)) + next_offset = parser_trx_get_offset(start, trx, i + 1); + else + next_offset = end; + + retsz = next_offset - this_offset; + pr_debug("size of trx partion %d is %08llx\n", i, retsz); + + return retsz; +} + +static const char *parser_trx_get_partname(const char *basename, int trx_index) +{ + if (trx_index == 0) + return basename; + return kasprintf(GFP_KERNEL, "%s%d", basename, trx_index + 1); +} + +/* + * This adds all the partitions found in a TRX partition block, which means + * up to three individual partitions. Returns number of added partitions. + */ +static int parser_trx_add_trx_partition(struct mtd_info *mtd, struct trx_header *trx, + int trx_index, uint64_t start, uint64_t end, + struct mtd_partition *parts, + int curr_part) +{ + struct mtd_partition *part; + bool has_loader = false; + uint64_t last_end; + int i = 0; + int ret; + + parser_trx_dump_trx(trx); + + /* We have an LZMA loader partition if there is an address in offset[2] */ + if (trx->offset[2]) + has_loader = true; + + if (has_loader) { + part = &parts[curr_part + i]; + part->name = parser_trx_get_partname("loader", trx_index); + if (!part->name) + return -ENOMEM; + part->offset = parser_trx_get_offset(start, trx, i); + part->size = parser_trx_get_size(start, end, trx, i); + i++; + } + + if (trx->offset[i]) { + part = &parts[curr_part + i]; + part->name = parser_trx_get_partname("linux", trx_index); + if (!part->name) + return -ENOMEM; + part->offset = parser_trx_get_offset(start, trx, i); + part->size = parser_trx_get_size(start, end, trx, i); + i++; + } + + if (trx->offset[i]) { + part = &parts[curr_part + i]; + part->offset = parser_trx_get_offset(start, trx, i); + part->size = parser_trx_get_size(start, end, trx, i); + ret = parser_trx_data_part_name_and_extents(mtd, part->offset, end, trx_index, + &part->name, &part->size); + if (ret) + return ret; + i++; + } + + /* + * If there is free space after the last TRX add this as a separate + * partition. This happens when the data partition parser finds less than + * the space up until the end sector. + */ + last_end = part->offset + part->size; + if (last_end < end) { + part = &parts[curr_part + i]; + part->offset = last_end; + part->size = end - last_end; + part->name = "free"; + i++; + } + + pr_debug("Added %d partitions\n", i); + + return i; } static int parser_trx_parse(struct mtd_info *mtd, @@ -53,70 +227,71 @@ static int parser_trx_parse(struct mtd_info *mtd, { struct device_node *np = mtd_get_of_node(mtd); struct mtd_partition *parts; - struct mtd_partition *part; - struct trx_header trx; + struct trx_header trxs[TRX_PARSER_MAX_TRX]; + uint64_t trx_offsets[TRX_PARSER_MAX_TRX]; + struct trx_header *trx; size_t bytes_read; - uint8_t curr_part = 0, i = 0; + int curr_part = 0; + int found_trx = 0; + int i; + uint64_t offset; + uint32_t blocksize = mtd->erasesize; uint32_t trx_magic = TRX_MAGIC; - int err; + int ret; /* Get different magic from device tree if specified */ - err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic); - if (err != 0 && err != -EINVAL) - pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err); + ret = of_property_read_u32(np, "brcm,trx-magic", &trx_magic); + if (ret && ret != -EINVAL) + pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", ret); parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), GFP_KERNEL); if (!parts) return -ENOMEM; - err = mtd_read(mtd, 0, sizeof(trx), &bytes_read, (uint8_t *)&trx); - if (err) { - pr_err("MTD reading error: %d\n", err); - kfree(parts); - return err; - } + for (offset = 0; offset <= mtd->size - blocksize; + offset += blocksize) { - if (trx.magic != trx_magic) { - kfree(parts); - return -ENOENT; - } + trx = &trxs[found_trx]; + ret = mtd_read(mtd, offset, sizeof(*trx), &bytes_read, (u_char *)trx); + if (ret) { + pr_err("MTD reading error: %d\n", ret); + goto out_free_parts; + } - /* We have LZMA loader if there is address in offset[2] */ - if (trx.offset[2]) { - part = &parts[curr_part++]; - part->name = "loader"; - part->offset = trx.offset[i]; - i++; - } + if (trx->magic != trx_magic) + continue; - if (trx.offset[i]) { - part = &parts[curr_part++]; - part->name = "linux"; - part->offset = trx.offset[i]; - i++; - } + trx_offsets[found_trx] = offset; - if (trx.offset[i]) { - part = &parts[curr_part++]; - part->name = parser_trx_data_part_name(mtd, trx.offset[i]); - part->offset = trx.offset[i]; - i++; + found_trx++; } - /* - * Assume that every partition ends at the beginning of the one it is - * followed by. - */ - for (i = 0; i < curr_part; i++) { - u64 next_part_offset = (i < curr_part - 1) ? - parts[i + 1].offset : mtd->size; + for (i = 0; i < found_trx; i++) { + uint64_t start; + uint64_t end; - parts[i].size = next_part_offset - parts[i].offset; + trx = &trxs[i]; + start = trx_offsets[i]; + if (i < (found_trx - 1)) + end = trx_offsets[i + 1]; + else + end = mtd->size; + + ret = parser_trx_add_trx_partition(mtd, trx, i, start, end, + parts, curr_part); + if (ret < 0) + goto out_free_parts; + + curr_part += ret; } *pparts = parts; - return i; + return curr_part; + +out_free_parts: + kfree(parts); + return ret; }; static const struct of_device_id mtd_parser_trx_of_match_table[] = {