mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-29 18:19:02 +00:00
f9a70a20c5
Backport BLOCK OF support patch merged upstream and refresh pending BLOCK patches. This is a new way to declare partition table for BLOCK device (eMMC currently supported) with the use of DTS. Current pending patch are adapted to not cause regression with current downstream implementation of a similar functionality. Also enable the new OF_PARTITION config by default. Link: https://github.com/openwrt/openwrt/pull/16663 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
201 lines
6.2 KiB
Diff
201 lines
6.2 KiB
Diff
From 884555b557e5e6d41c866e2cd8d7b32f50ec974b Mon Sep 17 00:00:00 2001
|
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
|
Date: Thu, 3 Oct 2024 00:11:45 +0200
|
|
Subject: [PATCH 5/5] block: add support for partition table defined in OF
|
|
|
|
Add support for partition table defined in Device Tree. Similar to how
|
|
it's done with MTD, add support for defining a fixed partition table in
|
|
device tree.
|
|
|
|
A common scenario for this is fixed block (eMMC) embedded devices that
|
|
have no MBR or GPT partition table to save storage space. Bootloader
|
|
access the block device with absolute address of data.
|
|
|
|
This is to complete the functionality with an equivalent implementation
|
|
with providing partition table with bootargs, for case where the booargs
|
|
can't be modified and tweaking the Device Tree is the only solution to
|
|
have an usabe partition table.
|
|
|
|
The implementation follow the fixed-partitions parser used on MTD
|
|
devices where a "partitions" node is expected to be declared with
|
|
"fixed-partitions" compatible in the OF node of the disk device
|
|
(mmc-card for eMMC for example) and each child node declare a label
|
|
and a reg with offset and size. If label is not declared, the node name
|
|
is used as fallback. Eventually is also possible to declare the read-only
|
|
property to flag the partition as read-only.
|
|
|
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
|
Link: https://lore.kernel.org/r/20241002221306.4403-6-ansuelsmth@gmail.com
|
|
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
|
---
|
|
block/partitions/Kconfig | 9 ++++
|
|
block/partitions/Makefile | 1 +
|
|
block/partitions/check.h | 1 +
|
|
block/partitions/core.c | 3 ++
|
|
block/partitions/of.c | 110 ++++++++++++++++++++++++++++++++++++++
|
|
5 files changed, 124 insertions(+)
|
|
create mode 100644 block/partitions/of.c
|
|
|
|
--- a/block/partitions/Kconfig
|
|
+++ b/block/partitions/Kconfig
|
|
@@ -270,4 +270,13 @@ config CMDLINE_PARTITION
|
|
Say Y here if you want to read the partition table from bootargs.
|
|
The format for the command line is just like mtdparts.
|
|
|
|
+config OF_PARTITION
|
|
+ bool "Device Tree partition support" if PARTITION_ADVANCED
|
|
+ depends on OF
|
|
+ help
|
|
+ Say Y here if you want to enable support for partition table
|
|
+ defined in Device Tree. (mainly for eMMC)
|
|
+ The format for the device tree node is just like MTD fixed-partition
|
|
+ schema.
|
|
+
|
|
endmenu
|
|
--- a/block/partitions/Makefile
|
|
+++ b/block/partitions/Makefile
|
|
@@ -12,6 +12,7 @@ obj-$(CONFIG_CMDLINE_PARTITION) += cmdli
|
|
obj-$(CONFIG_MAC_PARTITION) += mac.o
|
|
obj-$(CONFIG_LDM_PARTITION) += ldm.o
|
|
obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
|
|
+obj-$(CONFIG_OF_PARTITION) += of.o
|
|
obj-$(CONFIG_OSF_PARTITION) += osf.o
|
|
obj-$(CONFIG_SGI_PARTITION) += sgi.o
|
|
obj-$(CONFIG_SUN_PARTITION) += sun.o
|
|
--- a/block/partitions/check.h
|
|
+++ b/block/partitions/check.h
|
|
@@ -62,6 +62,7 @@ int karma_partition(struct parsed_partit
|
|
int ldm_partition(struct parsed_partitions *state);
|
|
int mac_partition(struct parsed_partitions *state);
|
|
int msdos_partition(struct parsed_partitions *state);
|
|
+int of_partition(struct parsed_partitions *state);
|
|
int osf_partition(struct parsed_partitions *state);
|
|
int sgi_partition(struct parsed_partitions *state);
|
|
int sun_partition(struct parsed_partitions *state);
|
|
--- a/block/partitions/core.c
|
|
+++ b/block/partitions/core.c
|
|
@@ -43,6 +43,9 @@ static int (*const check_part[])(struct
|
|
#ifdef CONFIG_CMDLINE_PARTITION
|
|
cmdline_partition,
|
|
#endif
|
|
+#ifdef CONFIG_OF_PARTITION
|
|
+ of_partition, /* cmdline have priority to OF */
|
|
+#endif
|
|
#ifdef CONFIG_EFI_PARTITION
|
|
efi_partition, /* this must come before msdos */
|
|
#endif
|
|
--- /dev/null
|
|
+++ b/block/partitions/of.c
|
|
@@ -0,0 +1,110 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+
|
|
+#include <linux/blkdev.h>
|
|
+#include <linux/major.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/string.h>
|
|
+#include "check.h"
|
|
+
|
|
+static int validate_of_partition(struct device_node *np, int slot)
|
|
+{
|
|
+ u64 offset, size;
|
|
+ int len;
|
|
+
|
|
+ const __be32 *reg = of_get_property(np, "reg", &len);
|
|
+ int a_cells = of_n_addr_cells(np);
|
|
+ int s_cells = of_n_size_cells(np);
|
|
+
|
|
+ /* Make sure reg len match the expected addr and size cells */
|
|
+ if (len / sizeof(*reg) != a_cells + s_cells)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Validate offset conversion from bytes to sectors */
|
|
+ offset = of_read_number(reg, a_cells);
|
|
+ if (offset % SECTOR_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Validate size conversion from bytes to sectors */
|
|
+ size = of_read_number(reg + a_cells, s_cells);
|
|
+ if (!size || size % SECTOR_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void add_of_partition(struct parsed_partitions *state, int slot,
|
|
+ struct device_node *np)
|
|
+{
|
|
+ struct partition_meta_info *info;
|
|
+ char tmp[sizeof(info->volname) + 4];
|
|
+ const char *partname;
|
|
+ int len;
|
|
+
|
|
+ const __be32 *reg = of_get_property(np, "reg", &len);
|
|
+ int a_cells = of_n_addr_cells(np);
|
|
+ int s_cells = of_n_size_cells(np);
|
|
+
|
|
+ /* Convert bytes to sector size */
|
|
+ u64 offset = of_read_number(reg, a_cells) / SECTOR_SIZE;
|
|
+ u64 size = of_read_number(reg + a_cells, s_cells) / SECTOR_SIZE;
|
|
+
|
|
+ put_partition(state, slot, offset, size);
|
|
+
|
|
+ if (of_property_read_bool(np, "read-only"))
|
|
+ state->parts[slot].flags |= ADDPART_FLAG_READONLY;
|
|
+
|
|
+ /*
|
|
+ * Follow MTD label logic, search for label property,
|
|
+ * fallback to node name if not found.
|
|
+ */
|
|
+ info = &state->parts[slot].info;
|
|
+ partname = of_get_property(np, "label", &len);
|
|
+ if (!partname)
|
|
+ partname = of_get_property(np, "name", &len);
|
|
+ strscpy(info->volname, partname, sizeof(info->volname));
|
|
+
|
|
+ snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
|
|
+ strlcat(state->pp_buf, tmp, PAGE_SIZE);
|
|
+}
|
|
+
|
|
+int of_partition(struct parsed_partitions *state)
|
|
+{
|
|
+ struct device *ddev = disk_to_dev(state->disk);
|
|
+ struct device_node *np;
|
|
+ int slot;
|
|
+
|
|
+ struct device_node *partitions_np = of_node_get(ddev->of_node);
|
|
+
|
|
+ if (!partitions_np ||
|
|
+ !of_device_is_compatible(partitions_np, "fixed-partitions"))
|
|
+ return 0;
|
|
+
|
|
+ slot = 1;
|
|
+ /* Validate parition offset and size */
|
|
+ for_each_child_of_node(partitions_np, np) {
|
|
+ if (validate_of_partition(np, slot)) {
|
|
+ of_node_put(np);
|
|
+ of_node_put(partitions_np);
|
|
+
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ slot++;
|
|
+ }
|
|
+
|
|
+ slot = 1;
|
|
+ for_each_child_of_node(partitions_np, np) {
|
|
+ if (slot >= state->limit) {
|
|
+ of_node_put(np);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ add_of_partition(state, slot, np);
|
|
+
|
|
+ slot++;
|
|
+ }
|
|
+
|
|
+ strlcat(state->pp_buf, "\n", PAGE_SIZE);
|
|
+
|
|
+ return 1;
|
|
+}
|