From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Wed, 07 Jun 2023 14:16:37 +0200 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by lore.white.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6s5e-00EJu9-Hh for lore@lore.pengutronix.de; Wed, 07 Jun 2023 14:16:37 +0200 Received: from localhost ([127.0.0.1] helo=metis.ext.pengutronix.de) by metis.ext.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1q6s5Z-00067R-EF; Wed, 07 Jun 2023 14:16:33 +0200 Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1q6s5X-00065J-6D; Wed, 07 Jun 2023 14:16:31 +0200 Received: from [2a0a:edc0:0:1101:1d::54] (helo=dude05.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1q6s5W-005jmF-Fs; Wed, 07 Jun 2023 14:16:30 +0200 Received: from afa by dude05.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1q6s5V-00DNCn-Ln; Wed, 07 Jun 2023 14:16:29 +0200 From: Ahmad Fatoum To: oss-tools@pengutronix.de Date: Wed, 7 Jun 2023 14:16:28 +0200 Message-Id: <20230607121628.3180139-9-a.fatoum@pengutronix.de> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230607121628.3180139-1-a.fatoum@pengutronix.de> References: <20230607121628.3180139-1-a.fatoum@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [OSS-Tools] [PATCH v2 8/8] state: allow lookup of barebox state partition by Type GUID X-BeenThere: oss-tools@pengutronix.de X-Mailman-Version: 2.1.29 Precedence: list List-Id: Pengutronix Public Open-Source-Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "OSS-Tools" X-SA-Exim-Connect-IP: 127.0.0.1 X-SA-Exim-Mail-From: oss-tools-bounces@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false The backend device tree property so far always pointed at a partition. Let's allow pointing it at GPT storage devices directly and lookup the correct barebox state partition by the well-known type GUID: 4778ed65-bf42-45fa-9c5b-287a1dc4aab1 The implementation is not as neat as hoped for, because lifetime for barebox cdev and libudev udev_device are quite different and libdt doesn't yet get the latter right. Once we make sure not to leak libudev objects and add cdev_unref stubs to barebox, this can be further simplified by sticking the struct udev_device into struct cdev and determining extra information on demand. Signed-off-by: Ahmad Fatoum --- src/barebox-state/state.c | 20 +++++++++ src/dt/dt.h | 4 ++ src/libdt-utils.sym | 2 + src/libdt.c | 94 ++++++++++++++++++++++++++++++++++++++- src/linux/uuid.h | 24 ++++++++++ src/state.h | 4 ++ 6 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/linux/uuid.h diff --git a/src/barebox-state/state.c b/src/barebox-state/state.c index 29e04c3d7ea8..41256d79e3c2 100644 --- a/src/barebox-state/state.c +++ b/src/barebox-state/state.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -592,6 +593,8 @@ static char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size) } #endif +static guid_t barebox_state_partition_guid = BAREBOX_STATE_PARTITION_GUID; + /* * state_new_from_node - create a new state instance from a device_node * @@ -638,6 +641,23 @@ struct state *state_new_from_node(struct device_node *node, bool readonly) goto out_release_state; } + /* Is the backend referencing an on-disk partitionable block device? */ + if (cdev_is_block_disk(cdev)) { + cdev = cdev_find_child_by_gpt_typeuuid(cdev, &barebox_state_partition_guid); + if (IS_ERR(cdev)) { + ret = -EINVAL; + goto out_release_state; + } + + pr_debug("%s: backend GPT partition looked up via PartitionTypeGUID\n", + node->full_name); + } + + state->backend_path = cdev_to_devpath(cdev, &offset, &size); + + pr_debug("%s: backend resolved to %s %lld %zu\n", node->full_name, + state->backend_path, (long long)offset, size); + state->backend_reproducible_name = of_get_reproducible_name(partition_node); ret = of_property_read_string(node, "backend-type", &backend_type); diff --git a/src/dt/dt.h b/src/dt/dt.h index f8bd3e56efed..f20f5680fc6c 100644 --- a/src/dt/dt.h +++ b/src/dt/dt.h @@ -5,6 +5,7 @@ #include
#include
#include +#include /* Default string compare functions */ #define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2)) @@ -234,6 +235,9 @@ int of_get_devicepath(struct device_node *partition_node, char **devnode, off_t struct cdev *of_cdev_find(struct device_node *partition_node); char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size); +bool cdev_is_block_disk(struct cdev *cdev); +struct cdev *cdev_find_child_by_gpt_typeuuid(struct cdev *cdev, guid_t *typeuuid); + #define for_each_node_by_name(dn, name) \ for (dn = of_find_node_by_name(NULL, name); dn; \ dn = of_find_node_by_name(dn, name)) diff --git a/src/libdt-utils.sym b/src/libdt-utils.sym index f95c74305fb0..636c3461e490 100644 --- a/src/libdt-utils.sym +++ b/src/libdt-utils.sym @@ -36,6 +36,8 @@ global: of_get_devicepath; of_cdev_find; cdev_to_devpath; + cdev_is_block_disk; + cdev_find_child_by_gpt_typeuuid; of_get_next_available_child; of_get_parent; of_get_property; diff --git a/src/libdt.c b/src/libdt.c index a55bc9b8d27d..5022bc7c7804 100644 --- a/src/libdt.c +++ b/src/libdt.c @@ -30,12 +30,15 @@ #include #include #include +#include #include struct cdev { char *devpath; off_t offset; size_t size; + bool is_gpt_partitioned; + bool is_block_disk; }; static int pr_level = 5; @@ -2288,8 +2291,13 @@ static int cdev_from_block_device(struct udev_device *dev, } } - if (best_match) + if (best_match) { + const char *part_type; + cdev->devpath = strdup(udev_device_get_devnode(best_match)); + part_type = udev_device_get_property_value(best_match, "ID_PART_TABLE_TYPE"); + cdev->is_gpt_partitioned = part_type && !strcmp(part_type, "gpt"); + } udev_enumerate_unref(enumerate); udev_unref(udev); @@ -2526,6 +2534,8 @@ static int __of_cdev_find(struct device_node *partition_node, struct cdev *cdev) cdev->offset = 0; cdev->size = 0; + cdev->is_gpt_partitioned = false; + cdev->is_block_disk = false; /* * simplest case: This nodepath can directly be translated into @@ -2541,6 +2551,11 @@ static int __of_cdev_find(struct device_node *partition_node, struct cdev *cdev) if (!udev_parse_mtd(dev, &cdev->devpath, &cdev->size)) return 0; + if (!cdev_from_block_device(dev, cdev)) { + cdev->is_block_disk = true; + return 0; + } + /* * If we find a udev_device but couldn't classify it above, * it's an error. Falling through would mean to handle it as a @@ -2720,3 +2735,80 @@ char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size) *size = cdev->size; return cdev->devpath; } + +static struct udev_device *udev_from_devpath(struct udev *udev, + const char *devpath) +{ + char syspath[64]; + struct stat st; + const char *type; + int ret; + + ret = stat(devpath, &st); + if (ret) + return NULL; + + if (S_ISBLK(st.st_mode)) + type = "block"; + else if (S_ISCHR(st.st_mode)) + type = "char"; + else + return NULL; + + if (major(st.st_rdev) == 0) + return NULL; + + snprintf(syspath, sizeof(syspath), "/sys/dev/%s/%u:%u", + type, major(st.st_rdev), minor(st.st_rdev)); + + return udev_device_new_from_syspath(udev, syspath); +} + +struct cdev *cdev_find_child_by_gpt_typeuuid(struct cdev *cdev, guid_t *typeuuid) +{ + struct cdev *new = ERR_PTR(-ENOENT); + struct udev_device *parent, *child; + struct udev *udev; + u64 size; + int ret; + + + if (!cdev->is_gpt_partitioned) + return ERR_PTR(-EINVAL); + + udev = udev_new(); + if (!udev) + return ERR_PTR(-ENOMEM); + + parent = udev_from_devpath(udev, cdev->devpath); + if (!parent) + goto udev_unref; + + child = of_find_device_by_uuid(parent, typeuuid->str, true); + if (!child) + goto udev_unref_parent; + + ret = udev_device_parse_sysattr_u64(child, "size", &size); + if (ret) + goto udev_unref_child; + + new = xzalloc(sizeof(*new)); + + new->offset = 0; + new->size = size * 512; + new->devpath = strdup(udev_device_get_devnode(child)); + +udev_unref_child: + udev_device_unref(child); +udev_unref_parent: + udev_device_unref(parent); +udev_unref: + udev_unref(udev); + + return new; +} + +bool cdev_is_block_disk(struct cdev *cdev) +{ + return cdev->is_block_disk; +} diff --git a/src/linux/uuid.h b/src/linux/uuid.h new file mode 100644 index 000000000000..1bc7cfc94040 --- /dev/null +++ b/src/linux/uuid.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Pengutronix, Ahmad Fatoum + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _LINUX_UUID_H_ +#define _LINUX_UUID_H_ + +#define UUID_STRING_LEN 36 + +/* We only do string comparisons anyway */ +typedef struct { const char str[UUID_STRING_LEN + 1]; } guid_t; + +#define GUID_INIT(str) { str } + +#endif diff --git a/src/state.h b/src/state.h index d98b781c2089..889df43b5780 100644 --- a/src/state.h +++ b/src/state.h @@ -2,6 +2,7 @@ #define __STATE_H #include +#include struct state; @@ -55,4 +56,7 @@ static inline int state_read_mac(struct state *state, const char *name, u8 *buf) #endif /* #if IS_ENABLED(CONFIG_STATE) / #else */ +#define BAREBOX_STATE_PARTITION_GUID \ + GUID_INIT("4778ed65-bf42-45fa-9c5b-287a1dc4aab1") + #endif /* __STATE_H */ -- 2.39.2