#include <sys/stat.h>
#include <blkid/blkid.h>
+#include "sd-id128.h"
+#include "gpt.h"
+#include "efivars.h"
#include "udev.h"
-static void print_property(struct udev_device *dev, bool test, const char *name, const char *value)
-{
- char s[265];
+static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) {
+ char s[256];
s[0] = '\0';
} else if (streq(name, "PTTYPE")) {
udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value);
+ } else if (streq(name, "PTUUID")) {
+ udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value);
+
} else if (streq(name, "PART_ENTRY_NAME")) {
blkid_encode_string(value, s, sizeof(s));
udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s);
}
}
-static int probe_superblocks(blkid_probe pr)
-{
+static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool test) {
+
+#if defined(GPT_ROOT_NATIVE) && defined(ENABLE_EFI)
+
+ _cleanup_free_ char *root_id = NULL;
+ bool found_esp = false;
+ blkid_partlist pl;
+ int i, nvals, r;
+
+ assert(pr);
+
+ /* Iterate through the partitions on this disk, and see if the
+ * EFI ESP we booted from is on it. If so, find the first root
+ * disk, and add a property indicating its partition UUID. */
+
+ errno = 0;
+ pl = blkid_probe_get_partitions(pr);
+ if (!pl)
+ return errno ? -errno : -ENOMEM;
+
+ nvals = blkid_partlist_numof_partitions(pl);
+ for (i = 0; i < nvals; i++) {
+ blkid_partition pp;
+ const char *stype, *sid;
+ sd_id128_t type;
+
+ pp = blkid_partlist_get_partition(pl, i);
+ if (!pp)
+ continue;
+
+ sid = blkid_partition_get_uuid(pp);
+ if (!sid)
+ continue;
+
+ stype = blkid_partition_get_type_string(pp);
+ if (!stype)
+ continue;
+
+ if (sd_id128_from_string(stype, &type) < 0)
+ continue;
+
+ if (sd_id128_equal(type, GPT_ESP)) {
+ sd_id128_t id, esp;
+
+ /* We found an ESP, let's see if it matches
+ * the ESP we booted from. */
+
+ if (sd_id128_from_string(sid, &id) < 0)
+ continue;
+
+ r = efi_loader_get_device_part_uuid(&esp);
+ if (r < 0)
+ return r;
+
+ if (sd_id128_equal(id, esp))
+ found_esp = true;
+
+ } else if (sd_id128_equal(type, GPT_ROOT_NATIVE)) {
+
+ /* We found a suitable root partition, let's
+ * remember the first one. */
+
+ if (!root_id) {
+ root_id = strdup(sid);
+ if (!root_id)
+ return -ENOMEM;
+ }
+ }
+ }
+
+ /* We found the ESP on this disk, and also found a root
+ * partition, nice! Let's export its UUID */
+ if (found_esp && root_id)
+ udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id);
+#endif
+
+ return 0;
+}
+
+static int probe_superblocks(blkid_probe pr) {
struct stat st;
int rc;
blkid_probe_enable_partitions(pr, 1);
- if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 &&
+ if (!S_ISCHR(st.st_mode) &&
+ blkid_probe_get_size(pr) <= 1024 * 1440 &&
blkid_probe_is_wholedisk(pr)) {
/*
* check if the small disk is partitioned, if yes then
rc = blkid_do_fullprobe(pr);
if (rc < 0)
- return rc; /* -1 = error, 1 = nothing, 0 = succes */
+ return rc; /* -1 = error, 1 = nothing, 0 = success */
if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0)
return 0; /* partition table detected */
return blkid_do_safeprobe(pr);
}
-static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test)
-{
+static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) {
+ const char *root_partition;
int64_t offset = 0;
bool noraid = false;
- int fd = -1;
+ _cleanup_close_ int fd = -1;
blkid_probe pr;
const char *data;
const char *name;
int nvals;
int i;
- size_t len;
int err = 0;
+ bool is_gpt = false;
static const struct option options[] = {
{ "offset", optional_argument, NULL, 'o' },
if (err < 0)
goto out;
- log_debug("probe %s %sraid offset=%llu\n",
+ log_debug("probe %s %sraid offset=%"PRIu64,
udev_device_get_devnode(dev),
- noraid ? "no" : "", (unsigned long long) offset);
+ noraid ? "no" : "", offset);
err = probe_superblocks(pr);
if (err < 0)
goto out;
+ /* If we are a partition then our parent passed on the root
+ * partition UUID to us */
+ root_partition = udev_device_get_property_value(dev, "ID_PART_GPT_AUTO_ROOT_UUID");
+
nvals = blkid_probe_numof_values(pr);
for (i = 0; i < nvals; i++) {
- if (blkid_probe_get_value(pr, i, &name, &data, &len))
+ if (blkid_probe_get_value(pr, i, &name, &data, NULL))
continue;
- len = strnlen((char *) data, len);
- print_property(dev, test, name, (char *) data);
+
+ print_property(dev, test, name, data);
+
+ /* Is this a disk with GPT partition table? */
+ if (streq(name, "PTTYPE") && streq(data, "gpt"))
+ is_gpt = true;
+
+ /* Is this a partition that matches the root partition
+ * property we inherited from our parent? */
+ if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition))
+ udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1");
}
+ if (is_gpt)
+ find_gpt_root(dev, pr, test);
+
blkid_free_probe(pr);
out:
- if (fd > 0)
- close(fd);
if (err < 0)
return EXIT_FAILURE;
+
return EXIT_SUCCESS;
}