| Message ID | 20260402202616.3177283-1-pavel@loebl.cz |
|---|---|
| State | New |
| Headers | show |
| Series | [RFC] uki.bbclass: add multi-profile UKI support | expand |
On Thu, 2026-04-02 at 22:25 +0200, Pavel Löbl wrote: > Allow generating multi-profile UKI [1]. This is quite usefull for > dual slot A/B deploymets with secureboot active. > > Currently only .cmdline sections are supported. But can be easily > extended with others. > > [1] https://uapi-group.org/specifications/specs/unified_kernel_image/#multi-profile-ukis > > Signed-off-by: Pavel Löbl <pavel@loebl.cz> > --- > meta/classes-recipe/uki.bbclass | 48 +++++++++++++++++++++++++++++---- > 1 file changed, 43 insertions(+), 5 deletions(-) > > diff --git a/meta/classes-recipe/uki.bbclass b/meta/classes-recipe/uki.bbclass > index d16f3c95561e..c2d21304c793 100644 > --- a/meta/classes-recipe/uki.bbclass > +++ b/meta/classes-recipe/uki.bbclass > @@ -59,6 +59,17 @@ > # - see efi-uki-bootdisk.wks.in how to create ESP partition which hosts systemd-boot, > # config file(s) for systemd-boot and the UKI binaries. > # > +# - to generate multi-profile UKI (currently only supports .cmdline section) > +# > +# UKI_PROFILE[0] = "TITLE=Recovery boot" > +# UKI_PROFILE_CMDLINE[0] = "rootwait recovery" > +# > +# UKI_PROFILE[1] = "TITLE=Boot from slot A" > +# UKI_PROFILE_CMDLINE[1] = "rootwait root=LABEL=root_a" > +# > +# UKI_PROFILE[2] = "TITLE=Boot from slot B" > +# UKI_PROFILE_CMDLINE[2] = "rootwait root=LABEL=root_b" > +# Hi Pavel, thanks for the RFC. To make things easier to debug and to follow existing conventions, I'd suggest: UKI_PROFILES = "slot_a slot_b recovery" UKI_PROFILES[recovery] = "TITLE=Recovery boot" UKI_PROFILE_CMDLINE[recovery] = "rootwait recovery" UKI_PROFILES[slot_a] = "TITLE=Boot from slot A" UKI_PROFILE_CMDLINE[slot_a] = "rootwait root=LABEL=root_a" UKI_PROFILES[slot_b] = "TITLE=Boot from slot B" UKI_PROFILE_CMDLINE[slot_b] = "rootwait root=LABEL=root_b" See the uboot-config class [1] for an example of this pattern. [1]: https://docs.yoctoproject.org/ref-manual/classes.html#uboot-config If typical usage will always have `TITLE=...` for each UKI profile, you could also use a UKI_PROFILE_TITLE[profile] variable to make things clearer. Best regards,
On Fri, Apr 03, 2026 at 08:47:17AM +0100, Paul Barker wrote: > On Thu, 2026-04-02 at 22:25 +0200, Pavel L�bl wrote: > > Allow generating multi-profile UKI [1]. This is quite usefull for > > dual slot A/B deploymets with secureboot active. > > > > Currently only .cmdline sections are supported. But can be easily > > extended with others. > > > > [1] https://uapi-group.org/specifications/specs/unified_kernel_image/#multi-profile-ukis > > > > Signed-off-by: Pavel L�bl <pavel@loebl.cz> > > --- > > meta/classes-recipe/uki.bbclass | 48 +++++++++++++++++++++++++++++---- > > 1 file changed, 43 insertions(+), 5 deletions(-) > > > > diff --git a/meta/classes-recipe/uki.bbclass b/meta/classes-recipe/uki.bbclass > > index d16f3c95561e..c2d21304c793 100644 > > --- a/meta/classes-recipe/uki.bbclass > > +++ b/meta/classes-recipe/uki.bbclass > > @@ -59,6 +59,17 @@ > > # - see efi-uki-bootdisk.wks.in how to create ESP partition which hosts systemd-boot, > > # config file(s) for systemd-boot and the UKI binaries. > > # > > +# - to generate multi-profile UKI (currently only supports .cmdline section) > > +# > > +# UKI_PROFILE[0] = "TITLE=Recovery boot" > > +# UKI_PROFILE_CMDLINE[0] = "rootwait recovery" > > +# > > +# UKI_PROFILE[1] = "TITLE=Boot from slot A" > > +# UKI_PROFILE_CMDLINE[1] = "rootwait root=LABEL=root_a" > > +# > > +# UKI_PROFILE[2] = "TITLE=Boot from slot B" > > +# UKI_PROFILE_CMDLINE[2] = "rootwait root=LABEL=root_b" > > +# > > Hi Pavel, thanks for the RFC. > > To make things easier to debug and to follow existing conventions, I'd > suggest: > > UKI_PROFILES = "slot_a slot_b recovery" > > UKI_PROFILES[recovery] = "TITLE=Recovery boot" > UKI_PROFILE_CMDLINE[recovery] = "rootwait recovery" > > UKI_PROFILES[slot_a] = "TITLE=Boot from slot A" > UKI_PROFILE_CMDLINE[slot_a] = "rootwait root=LABEL=root_a" > > UKI_PROFILES[slot_b] = "TITLE=Boot from slot B" > UKI_PROFILE_CMDLINE[slot_b] = "rootwait root=LABEL=root_b" > Hi Paul, the idea was to use the same indexes as firmware will be passing to stub. As multi-profile UKI only supports numerical ones (actually it's just the order in which they appear in PE32 binary). In your example user would have to pass @0 from firmware to select slot_a, @1 for slot_b and @2 for recovery. I have no issues with that, just wanted to make that clear. Regards, Pavel > > Best regards, > > -- > Paul Barker >
diff --git a/meta/classes-recipe/uki.bbclass b/meta/classes-recipe/uki.bbclass index d16f3c95561e..c2d21304c793 100644 --- a/meta/classes-recipe/uki.bbclass +++ b/meta/classes-recipe/uki.bbclass @@ -59,6 +59,17 @@ # - see efi-uki-bootdisk.wks.in how to create ESP partition which hosts systemd-boot, # config file(s) for systemd-boot and the UKI binaries. # +# - to generate multi-profile UKI (currently only supports .cmdline section) +# +# UKI_PROFILE[0] = "TITLE=Recovery boot" +# UKI_PROFILE_CMDLINE[0] = "rootwait recovery" +# +# UKI_PROFILE[1] = "TITLE=Boot from slot A" +# UKI_PROFILE_CMDLINE[1] = "rootwait root=LABEL=root_a" +# +# UKI_PROFILE[2] = "TITLE=Boot from slot B" +# UKI_PROFILE_CMDLINE[2] = "rootwait root=LABEL=root_b" +# DEPENDS += "\ os-release \ @@ -109,21 +120,46 @@ python do_uki() { import glob import bb.process - # base ukify command, can be extended if needed - ukify_cmd = d.getVar('UKIFY_CMD') + def generate_profiles(ukify_cmd): + join_profiles = "" + profile_num = 0 + while (profile := d.getVarFlag("UKI_PROFILE", str(profile_num))): + ukify_cmd += " --profile='%s'" % (profile) + + cmdline = d.getVarFlag("UKI_PROFILE_CMDLINE", str(profile_num)) + if cmdline: + ukify_cmd += " --cmdline='%s'" % (cmdline) + + profile_file = "%s/uki-profile%s.efi" % (d.getVar('DEPLOY_DIR_IMAGE') , profile_num) + ukify_cmd += " --output=%s" % (profile_file) + join_profiles += " --join-profile=%s" % (profile_file) + + bb.debug(2, "uki: running command: %s" % (ukify_cmd)) + out, err = bb.process.run(ukify_cmd, shell=True) + bb.debug(2, "%s\n%s" % (out, err)) + + profile_num += 1 + + return join_profiles + deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE') + # base ukify command, can be extended if needed + ukify_common_cmd = d.getVar('UKIFY_CMD') + # architecture target_arch = d.getVar('EFI_ARCH') if target_arch: - ukify_cmd += " --efi-arch %s" % (target_arch) + ukify_common_cmd += " --efi-arch %s" % (target_arch) - # systemd stubs + # systemd stubs, required even for UKI profile generation stub = "%s/linux%s.efi.stub" % (d.getVar('DEPLOY_DIR_IMAGE'), target_arch) if not os.path.exists(stub): bb.fatal(f"ERROR: cannot find {stub}.") - ukify_cmd += " --stub %s" % (stub) + ukify_common_cmd += " --stub %s" % (stub) + + ukify_cmd = ukify_common_cmd # initrd uki_fstype = d.getVar("INITRAMFS_FSTYPES").split()[0] @@ -185,6 +221,8 @@ python do_uki() { if cert: ukify_cmd += " --secureboot-certificate='%s'" % (cert) + ukify_cmd += generate_profiles(ukify_common_cmd) + # custom output UKI filename output = " --output=%s/%s" % (d.getVar('DEPLOY_DIR_IMAGE'), d.getVar('UKI_FILENAME')) ukify_cmd += " %s" % (output)
Allow generating multi-profile UKI [1]. This is quite usefull for dual slot A/B deploymets with secureboot active. Currently only .cmdline sections are supported. But can be easily extended with others. [1] https://uapi-group.org/specifications/specs/unified_kernel_image/#multi-profile-ukis Signed-off-by: Pavel Löbl <pavel@loebl.cz> --- meta/classes-recipe/uki.bbclass | 48 +++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-)