summaryrefslogtreecommitdiffstats
path: root/src/boot/efi/stub.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/efi/stub.c')
-rw-r--r--src/boot/efi/stub.c98
1 files changed, 61 insertions, 37 deletions
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index 0d9df7e..9aa605b 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -26,28 +26,27 @@ DECLARE_NOALLOC_SECTION(".sdmagic", "#### LoaderInfo: systemd-stub " GIT_VERSION
DECLARE_SBAT(SBAT_STUB_SECTION_TEXT);
-static EFI_STATUS combine_initrd(
- EFI_PHYSICAL_ADDRESS initrd_base, size_t initrd_size,
- const void * const extra_initrds[], const size_t extra_initrd_sizes[], size_t n_extra_initrds,
+/* Combine initrds by concatenation in memory */
+static EFI_STATUS combine_initrds(
+ const void * const initrds[], const size_t initrd_sizes[], size_t n_initrds,
Pages *ret_initr_pages, size_t *ret_initrd_size) {
- size_t n;
+ size_t n = 0;
assert(ret_initr_pages);
assert(ret_initrd_size);
- /* Combines four initrds into one, by simple concatenation in memory */
-
- n = ALIGN4(initrd_size); /* main initrd might not be padded yet */
-
- for (size_t i = 0; i < n_extra_initrds; i++) {
- if (!extra_initrds[i])
+ for (size_t i = 0; i < n_initrds; i++) {
+ if (!initrds[i])
continue;
- if (n > SIZE_MAX - extra_initrd_sizes[i])
+ /* some initrds (the ones from UKI sections) need padding,
+ * pad all to be safe */
+ size_t initrd_size = ALIGN4(initrd_sizes[i]);
+ if (n > SIZE_MAX - initrd_size)
return EFI_OUT_OF_RESOURCES;
- n += extra_initrd_sizes[i];
+ n += initrd_size;
}
_cleanup_pages_ Pages pages = xmalloc_pages(
@@ -56,27 +55,21 @@ static EFI_STATUS combine_initrd(
EFI_SIZE_TO_PAGES(n),
UINT32_MAX /* Below 4G boundary. */);
uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr);
- if (initrd_base != 0) {
+ for (size_t i = 0; i < n_initrds; i++) {
+ if (!initrds[i])
+ continue;
+
size_t pad;
- /* Order matters, the real initrd must come first, since it might include microcode updates
- * which the kernel only looks for in the first cpio archive */
- p = mempcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
+ p = mempcpy(p, initrds[i], initrd_sizes[i]);
- pad = ALIGN4(initrd_size) - initrd_size;
+ pad = ALIGN4(initrd_sizes[i]) - initrd_sizes[i];
if (pad > 0) {
memzero(p, pad);
p += pad;
}
}
- for (size_t i = 0; i < n_extra_initrds; i++) {
- if (!extra_initrds[i])
- continue;
-
- p = mempcpy(p, extra_initrds[i], extra_initrd_sizes[i]);
- }
-
assert(PHYSICAL_ADDRESS_TO_POINTER(pages.addr + n) == p);
*ret_initr_pages = pages;
@@ -91,6 +84,7 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
EFI_STUB_FEATURE_REPORT_BOOT_PARTITION | /* We set LoaderDevicePartUUID */
EFI_STUB_FEATURE_PICK_UP_CREDENTIALS | /* We pick up credentials from the boot partition */
EFI_STUB_FEATURE_PICK_UP_SYSEXTS | /* We pick up system extensions from the boot partition */
+ EFI_STUB_FEATURE_PICK_UP_CONFEXTS | /* We pick up configuration extensions from the boot partition */
EFI_STUB_FEATURE_THREE_PCRS | /* We can measure kernel image, parameters and sysext */
EFI_STUB_FEATURE_RANDOM_SEED | /* We pass a random seed to the kernel */
EFI_STUB_FEATURE_CMDLINE_ADDONS | /* We pick up .cmdline addons */
@@ -497,20 +491,20 @@ static EFI_STATUS load_addons(
}
static EFI_STATUS run(EFI_HANDLE image) {
- _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
- size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
+ _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *confext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
+ size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, confext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL;
char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL;
_cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL;
- size_t linux_size, initrd_size, dt_size, n_dts_addons_global = 0, n_dts_addons_uki = 0;
- EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base;
+ size_t linux_size, initrd_size, ucode_size, dt_size, n_dts_addons_global = 0, n_dts_addons_uki = 0;
+ EFI_PHYSICAL_ADDRESS linux_base, initrd_base, ucode_base, dt_base;
_cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
_cleanup_free_ char16_t *cmdline = NULL, *cmdline_addons_global = NULL, *cmdline_addons_uki = NULL;
int sections_measured = -1, parameters_measured = -1;
_cleanup_free_ char *uname = NULL;
- bool sysext_measured = false, m;
+ bool sysext_measured = false, confext_measured = false, m;
uint64_t loader_features = 0;
EFI_STATUS err;
@@ -660,8 +654,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
export_variables(loaded_image);
if (pack_cpio(loaded_image,
- NULL,
+ /* dropin_dir= */ NULL,
u".cred",
+ /* exclude_suffix= */ NULL,
".extra/credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
@@ -675,6 +670,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
if (pack_cpio(loaded_image,
u"\\loader\\credentials",
u".cred",
+ /* exclude_suffix= */ NULL,
".extra/global_credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
@@ -686,8 +682,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
if (pack_cpio(loaded_image,
- NULL,
- u".raw",
+ /* dropin_dir= */ NULL,
+ u".raw", /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
+ u".confext.raw", /* … but then exclude *.confext.raw again */
".extra/sysext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
@@ -698,6 +695,20 @@ static EFI_STATUS run(EFI_HANDLE image) {
&m) == EFI_SUCCESS)
sysext_measured = m;
+ if (pack_cpio(loaded_image,
+ /* dropin_dir= */ NULL,
+ u".confext.raw",
+ /* exclude_suffix= */ NULL,
+ ".extra/confext",
+ /* dir_mode= */ 0555,
+ /* access_mode= */ 0444,
+ /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
+ u"Configuration extension initrd",
+ &confext_initrd,
+ &confext_initrd_size,
+ &m) == EFI_SUCCESS)
+ confext_measured = m;
+
dt_size = szs[UNIFIED_SECTION_DTB];
dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0;
@@ -728,6 +739,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelParameters", TPM2_PCR_KERNEL_CONFIG, 0);
if (sysext_measured)
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDSysExts", TPM2_PCR_SYSEXTS, 0);
+ if (confext_measured)
+ (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDConfExts", TPM2_PCR_KERNEL_CONFIG, 0);
/* If the PCR signature was embedded in the PE image, then let's wrap it in a cpio and also pass it
* to the kernel, so that it can be read from /.extra/tpm2-pcr-signature.json. Note that this section
@@ -772,26 +785,36 @@ static EFI_STATUS run(EFI_HANDLE image) {
initrd_size = szs[UNIFIED_SECTION_INITRD];
initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0;
+ ucode_size = szs[UNIFIED_SECTION_UCODE];
+ ucode_base = ucode_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_UCODE] : 0;
+
_cleanup_pages_ Pages initrd_pages = {};
- if (credential_initrd || global_credential_initrd || sysext_initrd || pcrsig_initrd || pcrpkey_initrd) {
- /* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
- err = combine_initrd(
- initrd_base, initrd_size,
+ if (ucode_base || credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) {
+ /* If we have generated initrds dynamically or there is a microcode initrd, combine them with the built-in initrd. */
+ err = combine_initrds(
(const void*const[]) {
+ /* Microcode must always be first as kernel only scans uncompressed cpios
+ * and later initrds might be compressed. */
+ PHYSICAL_ADDRESS_TO_POINTER(ucode_base),
+ PHYSICAL_ADDRESS_TO_POINTER(initrd_base),
credential_initrd,
global_credential_initrd,
sysext_initrd,
+ confext_initrd,
pcrsig_initrd,
pcrpkey_initrd,
},
(const size_t[]) {
+ ucode_size,
+ initrd_size,
credential_initrd_size,
global_credential_initrd_size,
sysext_initrd_size,
+ confext_initrd_size,
pcrsig_initrd_size,
pcrpkey_initrd_size,
},
- 5,
+ 8,
&initrd_pages, &initrd_size);
if (err != EFI_SUCCESS)
return err;
@@ -802,6 +825,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd = mfree(credential_initrd);
global_credential_initrd = mfree(global_credential_initrd);
sysext_initrd = mfree(sysext_initrd);
+ confext_initrd = mfree(confext_initrd);
pcrsig_initrd = mfree(pcrsig_initrd);
pcrpkey_initrd = mfree(pcrpkey_initrd);
}