From patchwork Tue Oct 11 10:03:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 13003806 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2C8ECC433FE for ; Tue, 11 Oct 2022 10:05:15 +0000 (UTC) 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:References:In-Reply-To: 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: List-Owner; bh=gezJcpgMti5TFxyQ8ZQYR1X/3+zO2SVkcl2yI1NdN1k=; b=1WyehgCF3tK5nK Gcx8jY7q0qDmdM6DGkL5T4JJ4jAtOBDyksFHH/D5CLC8Lg37SSp98d1uxiLW0cvcFWsU4jhf73J0a rjhZGfUjMTm+6j7ut8vU3G/8FsoJwna4GQEOifnotRNb02Q5QkTdN/e5LW6XmHv/CyzWw7Fv4kWVY 01mHFwZGMWBxOpQLEUz/utRwPjUkDoMSPu8OaJPSnb8Fuidlh+rA7QVa/GoELQCAMId1zv/HgX6id UFzHEbp5CIKGSzbN5dOjZUyb4qiVebA3rUhvrKF0xmgj280iFqiQGS5YrcFpA4cLPkcxFOn04J6re ob7gLa+0INp2j1nCGSHg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oiC7M-003wEJ-B7; Tue, 11 Oct 2022 10:04:08 +0000 Received: from mail-ej1-x62d.google.com ([2a00:1450:4864:20::62d]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oiC76-003w9R-ES; Tue, 11 Oct 2022 10:03:54 +0000 Received: by mail-ej1-x62d.google.com with SMTP id d26so23137615eje.10; Tue, 11 Oct 2022 03:03:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6r9TR6k7ZFnpYRrQ79w4enoBrUyIdRGewHutjKTPK0c=; b=dit3LHF+DkfIOR2jPB98pCnX5hBg2tdQYKlOSSnzZwUddl2fl8cHYDeZJpUO9A4Aw/ Af1C5cwxE5Q7nDLsh8IxLaXYaKJsMiSJGko8AJIB7p2FCiz6Y5Ye/uuADYF+EAGaljkZ 4sHPGDDV6V9B5carYU3TAuQTxOgUDlgYqmscEIax3d7+v0Fr9gFsdTdmCPtX0l0nrNR3 zamYQt+nYWT1XzLaSHw5OFuD/LqFwbunGbhVl+vUC5/UJrqSdNtXlTR6Qng6cHsnEF5Y JKEM2E36Tl2Rf+I0Ev7tvP53V3Dkbm4npeiVyV5qj9gTVNmmT2X4lAosMLgoyHSzWkKN gMtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6r9TR6k7ZFnpYRrQ79w4enoBrUyIdRGewHutjKTPK0c=; b=k8B1q4BaWQ5smL0zVLdKubpp0RxlUrswintGVX3h6BWCIAZanOPRuLmBay1j9rrU3S FhgeRGMWmy2urqgk4KjOqbOrxUszLHpwmQ0g+BHITJGdD4YLdMEr17QYCZIUPcsLqBZc 8sa7Nw8UElrdRYQ2lPn0Dc421xQ+73yCgSzsmvXVBwMdi0lkogr0xMh9LV4Unzap3Oz+ cxygQpjJbt49w8aPCCgkypes7UwVtXuUTqoJNQF3g+Tx+2kED4vpWUrSDFNGa097+zH0 UxcQZhDhTD2jkrJvG5w8az7BG+f7B8VcY+Gnhyb77hiBo21/CZxX4g95WGu8A9j8wY5E B7fg== X-Gm-Message-State: ACrzQf23Pm2bwmLytu+3RjtJSpF1K6ZsXhxGlz+AL3xeseB7vb+H2IdM 9e0QtQNHT9yH3MoaOhdWxuI= X-Google-Smtp-Source: AMsMyM6gizhUse19Na7gK9CEfRA28qIOD56HDJigggh7Xg6DDqwtaArMlhx4ISEVp6zi9p7QQUvsgQ== X-Received: by 2002:a17:907:1c1a:b0:78d:426c:2828 with SMTP id nc26-20020a1709071c1a00b0078d426c2828mr18691133ejc.331.1665482629474; Tue, 11 Oct 2022 03:03:49 -0700 (PDT) Received: from localhost.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id o8-20020a170906768800b00780ab5a9116sm4597749ejm.211.2022.10.11.03.03.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Oct 2022 03:03:49 -0700 (PDT) From: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, Florian Fainelli , Hauke Mehrtens , bcm-kernel-feedback-list@broadcom.com, John Crispin , =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , Sergio Paracuellos , linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org, =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= Subject: [PATCH 2/2] mtd: parsers: add TP-Link SafeLoader partitions table parser Date: Tue, 11 Oct 2022 12:03:33 +0200 Message-Id: <20221011100333.32536-2-zajec5@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221011100333.32536-1-zajec5@gmail.com> References: <20221011100333.32536-1-zajec5@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221011_030352_516427_FDC3EA01 X-CRM114-Status: GOOD ( 22.40 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Rafał Miłecki This parser deals with most TP-Link home routers. It reads info about partitions and registers them in the MTD subsystem. Signed-off-by: Rafał Miłecki --- drivers/mtd/parsers/Kconfig | 15 +++ drivers/mtd/parsers/Makefile | 1 + drivers/mtd/parsers/tplink_safeloader.c | 150 ++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/mtd/parsers/tplink_safeloader.c diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index aaa06050c9bc..c258ba2a3a6f 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -123,6 +123,21 @@ config MTD_AFS_PARTS for your particular device. It won't happen automatically. The 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. +config MTD_PARSER_TPLINK_SAFELOADER + tristate "TP-Link Safeloader partitions parser" + depends on MTD && (ARCH_BCM_5301X || ATH79 || SOC_MT7620 || SOC_MT7621 || COMPILE_TEST) + help + TP-Link home routers use flash partitions to store various data. Info + about flash space layout is stored in a partitions table using a + custom ASCII-based format. + + That format was first found in devices with SafeLoader bootloader and + was named after it. Later it was adapted to CFE and U-Boot + bootloaders. + + This driver reads partitions table, parses it and creates MTD + partitions. + config MTD_PARSER_TRX tristate "Parser for TRX format partitions" depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST) diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index 23fa4de4016f..0e70b621a1d8 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -10,6 +10,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o obj-$(CONFIG_MTD_AFS_PARTS) += afs.o +obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o diff --git a/drivers/mtd/parsers/tplink_safeloader.c b/drivers/mtd/parsers/tplink_safeloader.c new file mode 100644 index 000000000000..7317d1faabbb --- /dev/null +++ b/drivers/mtd/parsers/tplink_safeloader.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright © 2022 Rafał Miłecki + */ + +#include +#include +#include +#include +#include +#include + +#define TPLINK_SAFELOADER_DATA_OFFSET 4 +#define TPLINK_SAFELOADER_MAX_PARTS 32 + +struct safeloader_cmn_header { + __be32 size; + uint32_t unused; +} __packed; + +static void *mtd_parser_tplink_safeloader_read_table(struct mtd_info *mtd) +{ + struct safeloader_cmn_header hdr; + struct device_node *np; + size_t bytes_read; + size_t offset; + size_t size; + char *buf; + int err; + + np = mtd_get_of_node(mtd); + if (mtd_is_partition(mtd)) + of_node_get(np); + else + np = of_get_child_by_name(np, "partitions"); + + if (of_property_read_u32(np, "partitions-table-offset", &offset)) { + pr_err("Failed to get partitions table offset\n"); + goto err_put; + } + + err = mtd_read(mtd, offset, sizeof(hdr), &bytes_read, (uint8_t *)&hdr); + if (err && !mtd_is_bitflip(err)) { + pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset); + goto err_put; + } + + size = be32_to_cpu(hdr.size); + + buf = kmalloc(size + 1, GFP_KERNEL); + if (!buf) + goto err_put; + + err = mtd_read(mtd, offset + sizeof(hdr), size, &bytes_read, buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset + sizeof(hdr)); + goto err_kfree; + } + + buf[size - 1] = '\0'; + + of_node_put(np); + + return buf; + +err_kfree: + kfree(buf); +err_put: + of_node_put(np); + return NULL; +} + +static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct mtd_partition *parts; + char name[65]; + size_t offset; + size_t bytes; + char *buf; + int idx; + int err; + + parts = kcalloc(TPLINK_SAFELOADER_MAX_PARTS, sizeof(*parts), GFP_KERNEL); + if (!parts) { + err = -ENOMEM; + goto err_out; + } + + buf = mtd_parser_tplink_safeloader_read_table(mtd); + if (!buf) { + err = -ENOENT; + goto err_out; + } + + for (idx = 0, offset = TPLINK_SAFELOADER_DATA_OFFSET; + idx < TPLINK_SAFELOADER_MAX_PARTS && + sscanf(buf + offset, "partition %64s base 0x%llx size 0x%llx%n\n", + name, &parts[idx].offset, &parts[idx].size, &bytes) == 3; + idx++, offset += bytes + 1) { + parts[idx].name = kstrdup(name, GFP_KERNEL); + if (!parts[idx].name) { + err = -ENOMEM; + goto err_free; + } + } + + if (idx == TPLINK_SAFELOADER_MAX_PARTS) + pr_warn("Reached maximum number of partitions!\n"); + + kfree(buf); + + *pparts = parts; + + return idx; + +err_free: + for (idx -= 1; idx >= 0; idx--) + kfree(parts[idx].name); +err_out: + return err; +}; + +static void mtd_parser_tplink_safeloader_cleanup(const struct mtd_partition *pparts, + int nr_parts) +{ + int i; + + for (i = 0; i < nr_parts; i++) + kfree(pparts[i].name); + + kfree(pparts); +} + +static const struct of_device_id mtd_parser_tplink_safeloader_of_match_table[] = { + { .compatible = "tplink,safeloader-partitions" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mtd_parser_tplink_safeloader_of_match_table); + +static struct mtd_part_parser mtd_parser_tplink_safeloader = { + .parse_fn = mtd_parser_tplink_safeloader_parse, + .cleanup = mtd_parser_tplink_safeloader_cleanup, + .name = "tplink-safeloader", + .of_match_table = mtd_parser_tplink_safeloader_of_match_table, +}; +module_mtd_part_parser(mtd_parser_tplink_safeloader); + +MODULE_LICENSE("GPL");