Skip to content

Prepare to support UKIs - #523

Draft
arnaldo2792 wants to merge 5 commits into
bottlerocket-os:developfrom
arnaldo2792:uki-support/kernel-kit
Draft

Prepare to support UKIs#523
arnaldo2792 wants to merge 5 commits into
bottlerocket-os:developfrom
arnaldo2792:uki-support/kernel-kit

Conversation

@arnaldo2792

@arnaldo2792 arnaldo2792 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Description of changes:

This series prepares the kernel kit to support Unified Kernel Images.

The first commit in the series prevents grub from being used with a variant that opt-in to use the new UKI format, and makes it provide the %{_cross_os}bootloader(efi) capability.

The second commit in the series prepares an extra copy of the shim that looks for systemd-boot instead of GRUB, and re-structures the spec to resolve either subpackage depending on the features enabled for the variant.

The remaining commits in the series drop a patch to don't measure PCR9 in the kernel. systemd-boot triggering PCR9 measurements in the kernel, but this patch prevented the kernel from actually updating the PCR. The side-effect is that in GRUB-based AMIs, PCR9 measurements will be as follows:

  • in x86_64, no changes, as the kernel lacks the support to measure PCR9 with GRUB
  • in aarch64, two PCR9 measurements: the kernel measures the cmdline once and user space measures again, with the updated parameters provided by bootconfig.

Testing done:

Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

Provide the bootloader(efi) RPM capability so newer versions of
twoliter and the core kit, which support UKI, can depend on it to
select GRUB as the EFI bootloader.

Conflict with the uki-image feature, since UKI images require
systemd-boot instead of GRUB.

Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
Split shim into two subpackages: one that chain-loads GRUB (installed
at the current location, for backwards compatibility) and a new one
that chain-loads systemd-boot instead.

Older versions of twoliter don't understand the 'uki-image' feature,
so the GRUB subpackage's requirements are left unrestricted to remain
installable there. To prevent it from being pulled in on UKI images
with newer twoliter versions, it instead conflicts with the
uki-image feature; the systemd-boot subpackage conflicts with
no-uki-image accordingly.

Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
The patch prevented systemd-boot from measuring PCR9

Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
The patch prevented systemd-boot from measuring PCR9

Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
The patch prevented systemd-boot from measuring PCR9

Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
Comment thread packages/shim/shim.spec
Comment on lines +33 to +34
# Avoid explicit image-feature(no-uki-image) requires for backwards compatibility
# The conflict is enough for now to prevent installing GRUB when UKIs are used

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Avoid explicit image-feature(no-uki-image) requires for backwards compatibility
# The conflict is enough for now to prevent installing GRUB when UKIs are used

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually wrote this one comment. Usually, we do the strong Requires and Conflicts, but in this case I avoided the Requires for a reason - don't require downstreams to bump their twoliter version if they take this kernel kit.

Comment thread packages/shim/shim.spec
Comment on lines +6 to +7
%global systemd_boot_efi_image systemd-boot%{_cross_efi_arch}.efi
%global shim_systemd_boot_efi_image shim-systemd-boot%{_cross_efi_arch}.efi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like you could interpolate these variables e.g.

%global shim_systemd_boot_efi_image shim-%{systemd_boot_efi_image}

Comment thread packages/shim/shim.spec
# Install grub-chaining shim at the default boot path, for backwards
# compatibility with image builds that expect to find it there.
find %{_builddir}/build-grub -name '%{shim_efi_image}' -exec \
cp {} "%{buildroot}%{efidir}/%{boot_efi_image}" \;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason these all changed from mv to cp? And no longer rm -rf %{buildroot}%{_datadir} ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm -f is no longer needed because we don't do the direct install anymore. re cp mv, nothing in particular, I can revert back if you feel strongly about this.

Comment thread packages/shim/shim.spec
Comment on lines +36 to +46
Provides: %{name}(shim-efi) = 1:
Conflicts: %{_cross_os}image-feature(uki-image)

%description grub
%{summary}.

%package systemd-boot
Summary: Shim built to chain-load systemd-boot
Requires: %{name}
Requires: %{_cross_os}image-feature(uki-image)
Provides: %{name}(shim-efi) = 0:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Epoch-only Provides: %{name}(shim-efi) = N: is non-idiomatic and not load-bearing

Both subpackages declare a versioned virtual provide with only an Epoch and an empty version string:

  • shim-grub: Provides: %{name}(shim-efi) = 1: (line 36)
  • shim-systemd-boot: Provides: %{name}(shim-efi) = 0: (line 46)

The base package has an unversioned Requires: %{name}(shim-efi) (line 26).

The normal RPM syntax is NAME = [EPOCH:]VERSION[-RELEASE]. = 1: with an empty version is parseable by rpm (Epoch=1, Version="") but:

  1. The unversioned Requires in the base does not consider the Epoch at all — either subpackage satisfies it. So the Epoch never participates in dependency resolution for this Requires.
  2. Subpackage selection is actually driven by the Conflicts/Requires: image-feature(...) rules, not by the Epoch. The epoch-only versioning implies a tie-break mechanism that isn't actually load-bearing.
  3. If in the future both subpackages become eligible under some variant, the well-formedness of = 1: vs = 0: becomes depsolver-dependent.

Suggested fix: either drop the versioned Provides entirely and rely on the image-feature Conflicts/Requires (which are what really determine selection today), or make it well-formed and document the intent, e.g.:

Provides: %{name}(shim-efi) = 1:%{version}-%{release}
...
Provides: %{name}(shim-efi) = 0:%{version}-%{release}

with a comment explaining it is a tie-breaker for the shim-grub default.

Confidence: ~70%.

Comment thread packages/shim/shim.spec
Comment on lines +97 to +98
find %{_builddir}/build-grub -name '%{mokm_efi_image}' -exec \
cp {} "%{buildroot}%{efidir}/%{mokm_efi_image}" \;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] MokManager is copied only from build-grub but shipped in the base package

%install copies mm*.efi exclusively out of the build-grub tree, and the resulting file is packaged in the base %files list (line 104), which is installed alongside both subpackages.

Concerns:

  1. Asymmetric build coupling. MokManager doesn't depend on DEFAULT_LOADER, so both build trees produce it. Sourcing it only from build-grub couples the base package to that specific build. If a follow-up PR conditionally disables the grub build for UKI-only variants (e.g., wraps lines 77, 80-81 in %if !%{uki_only}), the base %files list still references %{efidir}/%{mokm_efi_image} and the build breaks non-obviously.
  2. find … -exec cp doesn't signal 'no match'. find returns 0 whether or not it matched. If the grub build silently stops producing mm*.efi in the future, the failure surfaces later at %files ("File not found") rather than at the copy step.

Suggested fix: either copy mm*.efi from build-systemd-boot (identical bits, decoupled from the grub build) or add a brief comment stating that MokManager is loader-independent and either build tree is acceptable, e.g.:

# MokManager is not affected by DEFAULT_LOADER; either build tree is fine.
find %{_builddir}/build-grub -name '%{mokm_efi_image}' -exec \
  cp {} "%{buildroot}%{efidir}/%{mokm_efi_image}" \;

Confidence: ~60%.

Comment thread packages/shim/shim.spec
Comment on lines +31 to +50
%package grub
Summary: Shim built to chain-load GRUB
# Avoid explicit image-feature(no-uki-image) requires for backwards compatibility
# The conflict is enough for now to prevent installing GRUB when UKIs are used
Requires: %{name}
Provides: %{name}(shim-efi) = 1:
Conflicts: %{_cross_os}image-feature(uki-image)

%description grub
%{summary}.

%package systemd-boot
Summary: Shim built to chain-load systemd-boot
Requires: %{name}
Requires: %{_cross_os}image-feature(uki-image)
Provides: %{name}(shim-efi) = 0:
Conflicts: %{_cross_os}image-feature(no-uki-image)

%description systemd-boot
%{summary}.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] shim-grub and shim-systemd-boot have no explicit mutual Conflicts

The two subpackages are designed to be mutually exclusive, but nothing in the spec directly prevents co-installation. Mutual exclusion is only enforced transitively through the image-feature(...) Requires/Conflicts:

  • shim-grub Conflicts image-feature(uki-image) (line 37)
  • shim-systemd-boot Requires image-feature(uki-image) (line 45) and Conflicts image-feature(no-uki-image) (line 47)

The two subpackages install into disjoint paths (bootXX.efi vs shim-systemd-bootXX.efi), so RPM sees no file conflict either.

Scenario: a variant recipe that lists both Requires: shim-grub and Requires: shim-systemd-boot (dual-boot image or copy/paste error) will resolve without any RPM-level signal. The resulting image ships both loaders and boot behavior is then only determined by whatever bootXX.efi the firmware/UKI configuration points at.

If the intent really is "exactly one", encoding it in the spec is stronger than delegating it to image-feature discipline in downstream recipes.

Suggested fix: add mutual Conflicts to make the invariant explicit:

%package grub
...
Conflicts: %{name}-systemd-boot
Conflicts: %{_cross_os}image-feature(uki-image)

%package systemd-boot
...
Conflicts: %{name}-grub
Conflicts: %{_cross_os}image-feature(no-uki-image)

Alternatively, document in a comment that mutual exclusion is intentionally delegated to image-feature declarations upstream of this spec.

Confidence: ~55%.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants