From: Frieder Schrempf <[email protected]> The RAUC bootmeth uses any MMC device on which the boot partition of a slot holds a filesystem and the root partition exists. This also matches devices with a different layout, for example a single-system image or a standard distro installed to eMMC. The bootmeth then claims such a device and creates and saves its BOOT_ORDER and BOOT_x_LEFT variables in the environment, which makes it difficult to run BOOTMETH_RAUC alongside other bootmeths.
Add CONFIG_BOOTMETH_RAUC_PART_NAMES to set the expected names of the boot and root partitions of each slot, in the same format as CONFIG_BOOTMETH_RAUC_PARTITIONS. If set, a slot only counts if its partitions carry these names. As only GPT provides partition names, this also rejects MBR devices. The option is empty by default, which keeps the current behaviour. Assisted-by: LLM Signed-off-by: Frieder Schrempf <[email protected]> --- boot/Kconfig | 13 +++++++++ boot/bootmeth_rauc.c | 68 ++++++++++++++++++++++++++++++++++++++++---- doc/develop/bootstd/rauc.rst | 7 +++++ 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/boot/Kconfig b/boot/Kconfig index 8fcdc36c931..5f89c9d86fa 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -968,6 +968,19 @@ config BOOTMETH_RAUC_PARTITIONS The first value in pair is for the boot partition and second for the root partition. +config BOOTMETH_RAUC_PART_NAMES + string "RAUC boot and root partition names" + default "" + help + Sets the expected names of the boot and root partitions of each slot, + for example "boot_a,root_a boot_b,root_b". The format is the same as + for BOOTMETH_RAUC_PARTITIONS, with names instead of indexes, and each + pair belongs to the slot at the same position. + + A device is only used if at least one slot's partitions carry these + names. Partition names are only available on GPT, so this rejects + MBR devices. Leave this empty to not check the names. + config BOOTMETH_RAUC_DEFAULT_TRIES int "RAUC slot default tries" default 3 diff --git a/boot/bootmeth_rauc.c b/boot/bootmeth_rauc.c index 3bb9a2ace3d..ff2e2d48145 100644 --- a/boot/bootmeth_rauc.c +++ b/boot/bootmeth_rauc.c @@ -37,11 +37,15 @@ static const char * const script_names[] = { "boot.scr", "boot.scr.uimg", NULL } * @name The slot name * @boot_part The boot partition number on disk * @root_part The root partition number on disk + * @boot_part_name The expected boot partition name, or NULL to not check it + * @root_part_name The expected root partition name, or NULL to not check it */ struct distro_rauc_slot { char *name; int boot_part; int root_part; + char *boot_part_name; + char *root_part_name; }; /** @@ -54,14 +58,20 @@ struct distro_rauc_priv { struct distro_rauc_slot **slots; }; +static void distro_rauc_slot_free(struct distro_rauc_slot *slot) +{ + free(slot->name); + free(slot->boot_part_name); + free(slot->root_part_name); + free(slot); +} + static void distro_rauc_priv_free(struct distro_rauc_priv *priv) { int i; - for (i = 0; priv->slots[i]; i++) { - free(priv->slots[i]->name); - free(priv->slots[i]); - } + for (i = 0; priv->slots[i]; i++) + distro_rauc_slot_free(priv->slots[i]); free(priv->slots); free(priv); } @@ -88,6 +98,19 @@ static struct distro_rauc_slot *get_slot(struct distro_rauc_priv *priv, return NULL; } +static bool distro_rauc_part_name_ok(struct blk_desc *desc, int part, + const char *name) +{ + struct disk_partition info; + + if (!name) + return true; + if (part_get_info(desc, part, &info)) + return false; + + return !strcmp((char *)info.name, name); +} + static int distro_rauc_check(struct udevice *dev, struct bootflow_iter *iter) { /* @@ -138,6 +161,11 @@ static int distro_rauc_scan_parts(struct bootflow *bflow) ret = part_get_info(desc, slot->root_part, &fs_info); if (ret) continue; + if (!distro_rauc_part_name_ok(desc, slot->boot_part, + slot->boot_part_name) || + !distro_rauc_part_name_ok(desc, slot->root_part, + slot->root_part_name)) + continue; slot_found = true; } } @@ -164,6 +192,8 @@ static int distro_rauc_read_bootflow(struct udevice *dev, struct bootflow *bflow char *boot_order_cursor; char boot_left[BOOT_LEFT_LEN]; char *parts; + char *part_names = NULL; + char *part_names_cursor; /* Get RAUC variables or set their default values */ boot_order = env_get("BOOT_ORDER"); @@ -211,8 +241,14 @@ static int distro_rauc_read_bootflow(struct udevice *dev, struct bootflow *bflow ret = log_msg_ret("buf", -ENOMEM); goto rauc_read_bootflow_err; } + part_names = strdup(CONFIG_BOOTMETH_RAUC_PART_NAMES); + if (!part_names) { + ret = log_msg_ret("buf", -ENOMEM); + goto rauc_read_bootflow_err; + } partitions_cursor = partitions; + part_names_cursor = part_names; boot_order_cursor = boot_order_copy; for (i = 1; (parts = strsep(&partitions_cursor, " ")) && @@ -234,11 +270,29 @@ static int distro_rauc_read_bootflow(struct udevice *dev, struct bootflow *bflow } s->boot_part = simple_strtoul(strsep(&parts, ","), NULL, 10); s->root_part = simple_strtoul(strsep(&parts, ","), NULL, 10); + if (CONFIG_BOOTMETH_RAUC_PART_NAMES[0]) { + char *names = strsep(&part_names_cursor, " "); + char *boot_name = names ? strsep(&names, ",") : NULL; + char *root_name = names ? strsep(&names, ",") : NULL; + + if (!boot_name || !*boot_name || !root_name || !*root_name) { + log_err("ERROR: No partition names for slot %s\n", slot); + distro_rauc_slot_free(s); + ret = log_msg_ret("names", -EINVAL); + goto rauc_read_bootflow_err; + } + s->boot_part_name = strdup(boot_name); + s->root_part_name = strdup(root_name); + if (!s->boot_part_name || !s->root_part_name) { + distro_rauc_slot_free(s); + ret = log_msg_ret("buf", -ENOMEM); + goto rauc_read_bootflow_err; + } + } new_slots = realloc(priv->slots, (i + 1) * sizeof(struct distro_rauc_slot)); if (!new_slots) { - free(s->name); - free(s); + distro_rauc_slot_free(s); ret = log_msg_ret("buf", -ENOMEM); goto rauc_read_bootflow_err; } @@ -257,6 +311,7 @@ static int distro_rauc_read_bootflow(struct udevice *dev, struct bootflow *bflow free(boot_order_copy); free(partitions); + free(part_names); return 0; @@ -265,6 +320,7 @@ rauc_read_bootflow_err: bflow->bootmeth_priv = NULL; free(boot_order_copy); free(partitions); + free(part_names); return ret; } diff --git a/doc/develop/bootstd/rauc.rst b/doc/develop/bootstd/rauc.rst index 5afd705dcb1..dfbe010a60f 100644 --- a/doc/develop/bootstd/rauc.rst +++ b/doc/develop/bootstd/rauc.rst @@ -14,6 +14,13 @@ filesystem each. The partition numbers must be specified with the following syntax: ``1,2 3,4``, where 1 and 3 are the slots' boot partition and 2 and 4 the slots' root partition. +Optionally, ``CONFIG_BOOTMETH_RAUC_PART_NAMES`` gives the expected GPT +partition names in the same format, for example +``boot_a,root_a boot_b,root_b``. The bootmeth then only uses a device if the +partitions of at least one slot carry these names. This prevents it from +claiming devices with a different layout which happen to have a filesystem in +the first partition. If empty, the names are not checked. + Each pair of boot and rootfs partition form a "slot". The default order in which available slots are tried is set through ``CONFIG_BOOTMETH_RAUC_BOOT_ORDER``, with the left one tried first. -- 2.56.0
