From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: oss-tools@pengutronix.de
Subject: [OSS-Tools] [PATCH v2 8/8] state: allow lookup of barebox state partition by Type GUID
Date: Wed, 7 Jun 2023 14:16:28 +0200 [thread overview]
Message-ID: <20230607121628.3180139-9-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20230607121628.3180139-1-a.fatoum@pengutronix.de>
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 <a.fatoum@pengutronix.de>
---
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 <crc.h>
#include <linux/err.h>
#include <linux/list.h>
+#include <linux/uuid.h>
#include <linux/mtd/mtd-abi.h>
#include <malloc.h>
@@ -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 <dt/list.h>
#include <dt/common.h>
#include <asm/byteorder.h>
+#include <linux/uuid.h>
/* 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 <fcntl.h>
#include <unistd.h>
#include <libudev.h>
+#include <sys/sysmacros.h>
#include <dt.h>
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 <a.fatoum@pengutronix.de>
+ *
+ * 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 <of.h>
+#include <linux/uuid.h>
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
next prev parent reply other threads:[~2023-06-07 12:16 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-07 12:16 [OSS-Tools] [PATCH v2 0/8] " Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 1/8] state: backend: direct: open block device in read-only mode if possible Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 2/8] libdt: factor out u64 sysattr parsing into helper Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 3/8] libdt: drop broken if-branch Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 4/8] libdt: factor out __of_cdev_find helper Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 5/8] libdt: use block device partition instead of parent if found Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 6/8] state: align with barebox use of of_cdev_find Ahmad Fatoum
2023-06-07 12:16 ` [OSS-Tools] [PATCH v2 7/8] libdt: use of_find_device_by_uuid for partuuid lookup Ahmad Fatoum
2023-06-07 12:16 ` Ahmad Fatoum [this message]
2023-06-12 11:52 ` [OSS-Tools] [PATCH v2 0/8] state: allow lookup of barebox state partition by Type GUID Ahmad Fatoum
2023-07-03 12:23 ` Roland Hieber
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230607121628.3180139-9-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=oss-tools@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox