1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "device-path-util.h"
5 #include "devicetree.h"
9 #include "part-discovery.h"
11 #include "proto/shell-parameters.h"
12 #include "random-seed.h"
14 #include "secure-boot.h"
23 /* magic string to find in the binary image */
24 _used_
_section_(".sdmagic") static const char magic
[] = "#### LoaderInfo: systemd-stub " GIT_VERSION
" ####";
26 DECLARE_SBAT(SBAT_STUB_SECTION_TEXT
);
28 static EFI_STATUS
combine_initrd(
29 EFI_PHYSICAL_ADDRESS initrd_base
, size_t initrd_size
,
30 const void * const extra_initrds
[], const size_t extra_initrd_sizes
[], size_t n_extra_initrds
,
31 Pages
*ret_initr_pages
, size_t *ret_initrd_size
) {
35 assert(ret_initr_pages
);
36 assert(ret_initrd_size
);
38 /* Combines four initrds into one, by simple concatenation in memory */
40 n
= ALIGN4(initrd_size
); /* main initrd might not be padded yet */
42 for (size_t i
= 0; i
< n_extra_initrds
; i
++) {
43 if (!extra_initrds
[i
])
46 if (n
> SIZE_MAX
- extra_initrd_sizes
[i
])
47 return EFI_OUT_OF_RESOURCES
;
49 n
+= extra_initrd_sizes
[i
];
52 _cleanup_pages_ Pages pages
= xmalloc_pages(
56 UINT32_MAX
/* Below 4G boundary. */);
57 uint8_t *p
= PHYSICAL_ADDRESS_TO_POINTER(pages
.addr
);
58 if (initrd_base
!= 0) {
61 /* Order matters, the real initrd must come first, since it might include microcode updates
62 * which the kernel only looks for in the first cpio archive */
63 p
= mempcpy(p
, PHYSICAL_ADDRESS_TO_POINTER(initrd_base
), initrd_size
);
65 pad
= ALIGN4(initrd_size
) - initrd_size
;
72 for (size_t i
= 0; i
< n_extra_initrds
; i
++) {
73 if (!extra_initrds
[i
])
76 p
= mempcpy(p
, extra_initrds
[i
], extra_initrd_sizes
[i
]);
79 assert(PHYSICAL_ADDRESS_TO_POINTER(pages
.addr
+ n
) == p
);
81 *ret_initr_pages
= pages
;
88 static void export_variables(EFI_LOADED_IMAGE_PROTOCOL
*loaded_image
) {
89 static const uint64_t stub_features
=
90 EFI_STUB_FEATURE_REPORT_BOOT_PARTITION
| /* We set LoaderDevicePartUUID */
91 EFI_STUB_FEATURE_PICK_UP_CREDENTIALS
| /* We pick up credentials from the boot partition */
92 EFI_STUB_FEATURE_PICK_UP_SYSEXTS
| /* We pick up system extensions from the boot partition */
93 EFI_STUB_FEATURE_THREE_PCRS
| /* We can measure kernel image, parameters and sysext */
94 EFI_STUB_FEATURE_RANDOM_SEED
| /* We pass a random seed to the kernel */
95 EFI_STUB_FEATURE_CMDLINE_ADDONS
| /* We pick up .cmdline addons */
96 EFI_STUB_FEATURE_CMDLINE_SMBIOS
| /* We support extending kernel cmdline from SMBIOS Type #11 */
101 /* Export the device path this image is started from, if it's not set yet */
102 if (efivar_get_raw(MAKE_GUID_PTR(LOADER
), u
"LoaderDevicePartUUID", NULL
, NULL
) != EFI_SUCCESS
) {
103 _cleanup_free_ char16_t
*uuid
= disk_get_part_uuid(loaded_image
->DeviceHandle
);
105 efivar_set(MAKE_GUID_PTR(LOADER
), u
"LoaderDevicePartUUID", uuid
, 0);
108 /* If LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from the
109 * UEFI firmware without any boot loader, and hence set the LoaderImageIdentifier ourselves. Note
110 * that some boot chain loaders neither set LoaderImageIdentifier nor make FilePath available to us,
111 * in which case there's simple nothing to set for us. (The UEFI spec doesn't really say who's wrong
112 * here, i.e. whether FilePath may be NULL or not, hence handle this gracefully and check if FilePath
113 * is non-NULL explicitly.) */
114 if (efivar_get_raw(MAKE_GUID_PTR(LOADER
), u
"LoaderImageIdentifier", NULL
, NULL
) != EFI_SUCCESS
&&
115 loaded_image
->FilePath
) {
116 _cleanup_free_ char16_t
*s
= NULL
;
117 if (device_path_to_str(loaded_image
->FilePath
, &s
) == EFI_SUCCESS
)
118 efivar_set(MAKE_GUID_PTR(LOADER
), u
"LoaderImageIdentifier", s
, 0);
121 /* if LoaderFirmwareInfo is not set, let's set it */
122 if (efivar_get_raw(MAKE_GUID_PTR(LOADER
), u
"LoaderFirmwareInfo", NULL
, NULL
) != EFI_SUCCESS
) {
123 _cleanup_free_ char16_t
*s
= NULL
;
124 s
= xasprintf("%ls %u.%02u", ST
->FirmwareVendor
, ST
->FirmwareRevision
>> 16, ST
->FirmwareRevision
& 0xffff);
125 efivar_set(MAKE_GUID_PTR(LOADER
), u
"LoaderFirmwareInfo", s
, 0);
128 /* ditto for LoaderFirmwareType */
129 if (efivar_get_raw(MAKE_GUID_PTR(LOADER
), u
"LoaderFirmwareType", NULL
, NULL
) != EFI_SUCCESS
) {
130 _cleanup_free_ char16_t
*s
= NULL
;
131 s
= xasprintf("UEFI %u.%02u", ST
->Hdr
.Revision
>> 16, ST
->Hdr
.Revision
& 0xffff);
132 efivar_set(MAKE_GUID_PTR(LOADER
), u
"LoaderFirmwareType", s
, 0);
136 /* add StubInfo (this is one is owned by the stub, hence we unconditionally override this with our
138 (void) efivar_set(MAKE_GUID_PTR(LOADER
), u
"StubInfo", u
"systemd-stub " GIT_VERSION
, 0);
140 (void) efivar_set_uint64_le(MAKE_GUID_PTR(LOADER
), u
"StubFeatures", stub_features
, 0);
143 static bool use_load_options(
144 EFI_HANDLE stub_image
,
145 EFI_LOADED_IMAGE_PROTOCOL
*loaded_image
,
150 assert(loaded_image
);
153 /* We only allow custom command lines if we aren't in secure boot or if no cmdline was baked into
155 * We also don't allow it if we are in confidential vms and secureboot is on. */
156 if (secure_boot_enabled() && (have_cmdline
|| is_confidential_vm()))
159 /* We also do a superficial check whether first character of passed command line
160 * is printable character (for compat with some Dell systems which fill in garbage?). */
161 if (loaded_image
->LoadOptionsSize
< sizeof(char16_t
) || ((char16_t
*) loaded_image
->LoadOptions
)[0] <= 0x1F)
164 /* The UEFI shell registers EFI_SHELL_PARAMETERS_PROTOCOL onto images it runs. This lets us know that
165 * LoadOptions starts with the stub binary path which we want to strip off. */
166 EFI_SHELL_PARAMETERS_PROTOCOL
*shell
;
167 if (BS
->HandleProtocol(stub_image
, MAKE_GUID_PTR(EFI_SHELL_PARAMETERS_PROTOCOL
), (void **) &shell
)
169 /* Not running from EFI shell, use entire LoadOptions. Note that LoadOptions is a void*, so
170 * it could be anything! */
171 *ret
= xstrndup16(loaded_image
->LoadOptions
, loaded_image
->LoadOptionsSize
/ sizeof(char16_t
));
172 mangle_stub_cmdline(*ret
);
177 /* No arguments were provided? Then we fall back to built-in cmdline. */
180 /* Assemble the command line ourselves without our stub path. */
181 *ret
= xstrdup16(shell
->Argv
[1]);
182 for (size_t i
= 2; i
< shell
->Argc
; i
++) {
183 _cleanup_free_ char16_t
*old
= *ret
;
184 *ret
= xasprintf("%ls %ls", old
, shell
->Argv
[i
]);
187 mangle_stub_cmdline(*ret
);
191 static EFI_STATUS
load_addons_from_dir(
193 const char16_t
*prefix
,
196 size_t *n_allocated
) {
198 _cleanup_(file_closep
) EFI_FILE
*extra_dir
= NULL
;
199 _cleanup_free_ EFI_FILE_INFO
*dirent
= NULL
;
200 size_t dirent_size
= 0;
209 err
= open_directory(root
, prefix
, &extra_dir
);
210 if (err
== EFI_NOT_FOUND
)
211 /* No extra subdir, that's totally OK */
213 if (err
!= EFI_SUCCESS
)
214 return log_error_status(err
, "Failed to open addons directory '%ls': %m", prefix
);
217 _cleanup_free_ char16_t
*d
= NULL
;
219 err
= readdir(extra_dir
, &dirent
, &dirent_size
);
220 if (err
!= EFI_SUCCESS
)
221 return log_error_status(err
, "Failed to read addons directory of loaded image: %m");
222 if (!dirent
) /* End of directory */
225 if (dirent
->FileName
[0] == '.')
227 if (FLAGS_SET(dirent
->Attribute
, EFI_FILE_DIRECTORY
))
229 if (!is_ascii(dirent
->FileName
))
231 if (strlen16(dirent
->FileName
) > 255) /* Max filename size on Linux */
233 if (!endswith_no_case(dirent
->FileName
, u
".addon.efi"))
236 d
= xstrdup16(dirent
->FileName
);
238 if (*n_items
+ 2 > *n_allocated
) {
239 /* We allocate 16 entries at a time, as a matter of optimization */
240 if (*n_items
> (SIZE_MAX
/ sizeof(uint16_t)) - 16) /* Overflow check, just in case */
243 size_t m
= *n_items
+ 16;
244 *items
= xrealloc(*items
, *n_allocated
* sizeof(uint16_t *), m
* sizeof(uint16_t *));
248 (*items
)[(*n_items
)++] = TAKE_PTR(d
);
249 (*items
)[*n_items
] = NULL
; /* Let's always NUL terminate, to make freeing via strv_free() easy */
256 static EFI_STATUS
cmdline_append_and_measure_addons(
257 EFI_HANDLE stub_image
,
258 EFI_LOADED_IMAGE_PROTOCOL
*loaded_image
,
259 const char16_t
*prefix
,
261 bool *ret_parameters_measured
,
262 char16_t
**cmdline_append
) {
264 _cleanup_(strv_freep
) char16_t
**items
= NULL
;
265 _cleanup_(file_closep
) EFI_FILE
*root
= NULL
;
266 _cleanup_free_ char16_t
*buffer
= NULL
;
267 size_t n_items
= 0, n_allocated
= 0;
271 assert(loaded_image
);
273 assert(ret_parameters_measured
);
274 assert(cmdline_append
);
276 if (!loaded_image
->DeviceHandle
)
279 err
= open_volume(loaded_image
->DeviceHandle
, &root
);
280 if (err
== EFI_UNSUPPORTED
)
281 /* Error will be unsupported if the bootloader doesn't implement the file system protocol on
282 * its file handles. */
284 if (err
!= EFI_SUCCESS
)
285 return log_error_status(err
, "Unable to open root directory: %m");
287 err
= load_addons_from_dir(root
, prefix
, &items
, &n_items
, &n_allocated
);
288 if (err
!= EFI_SUCCESS
)
292 return EFI_SUCCESS
; /* Empty directory */
294 /* Now, sort the files we found, to make this uniform and stable (and to ensure the TPM measurements
295 * are not dependent on read order) */
296 sort_pointer_array((void**) items
, n_items
, (compare_pointer_func_t
) strcmp16
);
298 for (size_t i
= 0; i
< n_items
; i
++) {
299 size_t addrs
[_UNIFIED_SECTION_MAX
] = {}, szs
[_UNIFIED_SECTION_MAX
] = {};
300 _cleanup_free_ EFI_DEVICE_PATH
*addon_path
= NULL
;
301 _cleanup_(unload_imagep
) EFI_HANDLE addon
= NULL
;
302 EFI_LOADED_IMAGE_PROTOCOL
*loaded_addon
= NULL
;
303 _cleanup_free_ char16_t
*addon_spath
= NULL
;
305 addon_spath
= xasprintf("%ls\\%ls", prefix
, items
[i
]);
306 err
= make_file_device_path(loaded_image
->DeviceHandle
, addon_spath
, &addon_path
);
307 if (err
!= EFI_SUCCESS
)
308 return log_error_status(err
, "Error making device path for %ls: %m", addon_spath
);
310 /* By using shim_load_image, we cover both the case where the PE files are signed with MoK
311 * and with DB, and running with or without shim. */
312 err
= shim_load_image(stub_image
, addon_path
, &addon
);
313 if (err
!= EFI_SUCCESS
) {
314 log_error_status(err
,
315 "Failed to read '%ls' from '%ls', ignoring: %m",
321 err
= BS
->HandleProtocol(addon
,
322 MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL
),
323 (void **) &loaded_addon
);
324 if (err
!= EFI_SUCCESS
)
325 return log_error_status(err
, "Failed to find protocol in %ls: %m", items
[i
]);
327 err
= pe_memory_locate_sections(loaded_addon
->ImageBase
, unified_sections
, addrs
, szs
);
328 if (err
!= EFI_SUCCESS
|| szs
[UNIFIED_SECTION_CMDLINE
] == 0) {
329 if (err
== EFI_SUCCESS
)
331 log_error_status(err
,
332 "Unable to locate embedded .cmdline section in %ls, ignoring: %m",
337 /* We want to enforce that addons are not UKIs, i.e.: they must not embed a kernel. */
338 if (szs
[UNIFIED_SECTION_LINUX
] > 0) {
339 log_error_status(EFI_INVALID_PARAMETER
, "%ls is a UKI, not an addon, ignoring: %m", items
[i
]);
343 /* Also enforce that, in case it is specified, .uname matches as a quick way to allow
344 * enforcing compatibility with a specific UKI only */
345 if (uname
&& szs
[UNIFIED_SECTION_UNAME
] > 0 &&
347 (char *)loaded_addon
->ImageBase
+ addrs
[UNIFIED_SECTION_UNAME
],
348 szs
[UNIFIED_SECTION_UNAME
])) {
349 log_error(".uname mismatch between %ls and UKI, ignoring", items
[i
]);
353 _cleanup_free_ char16_t
*tmp
= TAKE_PTR(buffer
),
354 *extra16
= xstrn8_to_16((char *)loaded_addon
->ImageBase
+ addrs
[UNIFIED_SECTION_CMDLINE
],
355 szs
[UNIFIED_SECTION_CMDLINE
]);
356 buffer
= xasprintf("%ls%ls%ls", strempty(tmp
), isempty(tmp
) ? u
"" : u
" ", extra16
);
359 mangle_stub_cmdline(buffer
);
361 if (!isempty(buffer
)) {
362 _cleanup_free_ char16_t
*tmp
= TAKE_PTR(*cmdline_append
);
365 (void) tpm_log_load_options(buffer
, &m
);
366 *ret_parameters_measured
= m
;
368 *cmdline_append
= xasprintf("%ls%ls%ls", strempty(tmp
), isempty(tmp
) ? u
"" : u
" ", buffer
);
374 static EFI_STATUS
run(EFI_HANDLE image
) {
375 _cleanup_free_
void *credential_initrd
= NULL
, *global_credential_initrd
= NULL
, *sysext_initrd
= NULL
, *pcrsig_initrd
= NULL
, *pcrpkey_initrd
= NULL
;
376 size_t credential_initrd_size
= 0, global_credential_initrd_size
= 0, sysext_initrd_size
= 0, pcrsig_initrd_size
= 0, pcrpkey_initrd_size
= 0;
377 size_t linux_size
, initrd_size
, dt_size
;
378 EFI_PHYSICAL_ADDRESS linux_base
, initrd_base
, dt_base
;
379 _cleanup_(devicetree_cleanup
) struct devicetree_state dt_state
= {};
380 EFI_LOADED_IMAGE_PROTOCOL
*loaded_image
;
381 size_t addrs
[_UNIFIED_SECTION_MAX
] = {}, szs
[_UNIFIED_SECTION_MAX
] = {};
382 _cleanup_free_ char16_t
*cmdline
= NULL
;
383 int sections_measured
= -1, parameters_measured
= -1;
384 _cleanup_free_
char *uname
= NULL
;
385 bool sysext_measured
= false, m
;
386 uint64_t loader_features
= 0;
389 err
= BS
->HandleProtocol(image
, MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL
), (void **) &loaded_image
);
390 if (err
!= EFI_SUCCESS
)
391 return log_error_status(err
, "Error getting a LoadedImageProtocol handle: %m");
393 if (efivar_get_uint64_le(MAKE_GUID_PTR(LOADER
), u
"LoaderFeatures", &loader_features
) != EFI_SUCCESS
||
394 !FLAGS_SET(loader_features
, EFI_LOADER_FEATURE_RANDOM_SEED
)) {
395 _cleanup_(file_closep
) EFI_FILE
*esp_dir
= NULL
;
397 err
= partition_open(MAKE_GUID_PTR(ESP
), loaded_image
->DeviceHandle
, NULL
, &esp_dir
);
398 if (err
== EFI_SUCCESS
) /* Non-fatal on failure, so that we still boot without it. */
399 (void) process_random_seed(esp_dir
);
402 err
= pe_memory_locate_sections(loaded_image
->ImageBase
, unified_sections
, addrs
, szs
);
403 if (err
!= EFI_SUCCESS
|| szs
[UNIFIED_SECTION_LINUX
] == 0) {
404 if (err
== EFI_SUCCESS
)
406 return log_error_status(err
, "Unable to locate embedded .linux section: %m");
409 /* Measure all "payload" of this PE image into a separate PCR (i.e. where nothing else is written
410 * into so far), so that we have one PCR that we can nicely write policies against because it
411 * contains all static data of this image, and thus can be easily be pre-calculated. */
412 for (UnifiedSection section
= 0; section
< _UNIFIED_SECTION_MAX
; section
++) {
414 if (!unified_section_measure(section
)) /* shall not measure? */
417 if (szs
[section
] == 0) /* not found */
422 /* First measure the name of the section */
423 (void) tpm_log_event_ascii(
424 TPM2_PCR_KERNEL_BOOT
,
425 POINTER_TO_PHYSICAL_ADDRESS(unified_sections
[section
]),
426 strsize8(unified_sections
[section
]), /* including NUL byte */
427 unified_sections
[section
],
430 sections_measured
= sections_measured
< 0 ? m
: (sections_measured
&& m
);
432 /* Then measure the data of the section */
433 (void) tpm_log_event_ascii(
434 TPM2_PCR_KERNEL_BOOT
,
435 POINTER_TO_PHYSICAL_ADDRESS(loaded_image
->ImageBase
) + addrs
[section
],
437 unified_sections
[section
],
440 sections_measured
= sections_measured
< 0 ? m
: (sections_measured
&& m
);
443 /* After we are done, set an EFI variable that tells userspace this was done successfully, and encode
444 * in it which PCR was used. */
445 if (sections_measured
> 0)
446 (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER
), u
"StubPcrKernelImage", TPM2_PCR_KERNEL_BOOT
, 0);
448 /* Show splash screen as early as possible */
449 graphics_splash((const uint8_t*) loaded_image
->ImageBase
+ addrs
[UNIFIED_SECTION_SPLASH
], szs
[UNIFIED_SECTION_SPLASH
]);
451 if (szs
[UNIFIED_SECTION_UNAME
] > 0)
452 uname
= xstrndup8((char *)loaded_image
->ImageBase
+ addrs
[UNIFIED_SECTION_UNAME
],
453 szs
[UNIFIED_SECTION_UNAME
]);
455 if (use_load_options(image
, loaded_image
, szs
[UNIFIED_SECTION_CMDLINE
] > 0, &cmdline
)) {
456 /* Let's measure the passed kernel command line into the TPM. Note that this possibly
457 * duplicates what we already did in the boot menu, if that was already used. However, since
458 * we want the boot menu to support an EFI binary, and want to this stub to be usable from
459 * any boot menu, let's measure things anyway. */
461 (void) tpm_log_load_options(cmdline
, &m
);
462 parameters_measured
= m
;
463 } else if (szs
[UNIFIED_SECTION_CMDLINE
] > 0) {
464 cmdline
= xstrn8_to_16(
465 (char *) loaded_image
->ImageBase
+ addrs
[UNIFIED_SECTION_CMDLINE
],
466 szs
[UNIFIED_SECTION_CMDLINE
]);
467 mangle_stub_cmdline(cmdline
);
470 /* If we have any extra command line to add via PE addons, load them now and append, and
471 * measure the additions separately, after the embedded options, but before the smbios ones,
472 * so that the order is reversed from "most hardcoded" to "most dynamic". The global addons are
473 * loaded first, and the image-specific ones later, for the same reason. */
474 err
= cmdline_append_and_measure_addons(
481 if (err
!= EFI_SUCCESS
)
482 log_error_status(err
, "Error loading global addons, ignoring: %m");
483 parameters_measured
= parameters_measured
< 0 ? m
: (parameters_measured
&& m
);
485 _cleanup_free_ char16_t
*dropin_dir
= get_extra_dir(loaded_image
->FilePath
);
486 err
= cmdline_append_and_measure_addons(
493 if (err
!= EFI_SUCCESS
)
494 log_error_status(err
, "Error loading UKI-specific addons, ignoring: %m");
495 parameters_measured
= parameters_measured
< 0 ? m
: (parameters_measured
&& m
);
497 /* SMBIOS OEM Strings data is controlled by the host admin and not covered
498 * by the VM attestation, so MUST NOT be trusted when in a confidential VM */
499 if (!is_confidential_vm()) {
500 const char *extra
= smbios_find_oem_string("io.systemd.stub.kernel-cmdline-extra");
502 _cleanup_free_ char16_t
*tmp
= TAKE_PTR(cmdline
), *extra16
= xstr8_to_16(extra
);
503 cmdline
= xasprintf("%ls %ls", tmp
, extra16
);
505 /* SMBIOS strings are measured in PCR1, but we also want to measure them in our specific
506 * PCR12, as firmware-owned PCRs are very difficult to use as they'll contain unpredictable
507 * measurements that are not under control of the machine owner. */
509 (void) tpm_log_load_options(extra16
, &m
);
510 parameters_measured
= parameters_measured
< 0 ? m
: (parameters_measured
&& m
);
514 export_variables(loaded_image
);
516 if (pack_cpio(loaded_image
,
519 ".extra/credentials",
520 /* dir_mode= */ 0500,
521 /* access_mode= */ 0400,
522 /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG
,
523 u
"Credentials initrd",
525 &credential_initrd_size
,
527 parameters_measured
= parameters_measured
< 0 ? m
: (parameters_measured
&& m
);
529 if (pack_cpio(loaded_image
,
530 u
"\\loader\\credentials",
532 ".extra/global_credentials",
533 /* dir_mode= */ 0500,
534 /* access_mode= */ 0400,
535 /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG
,
536 u
"Global credentials initrd",
537 &global_credential_initrd
,
538 &global_credential_initrd_size
,
540 parameters_measured
= parameters_measured
< 0 ? m
: (parameters_measured
&& m
);
542 if (pack_cpio(loaded_image
,
546 /* dir_mode= */ 0555,
547 /* access_mode= */ 0444,
548 /* tpm_pcr= */ TPM2_PCR_SYSEXTS
,
549 u
"System extension initrd",
555 if (parameters_measured
> 0)
556 (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER
), u
"StubPcrKernelParameters", TPM2_PCR_KERNEL_CONFIG
, 0);
558 (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER
), u
"StubPcrInitRDSysExts", TPM2_PCR_SYSEXTS
, 0);
560 /* If the PCR signature was embedded in the PE image, then let's wrap it in a cpio and also pass it
561 * to the kernel, so that it can be read from /.extra/tpm2-pcr-signature.json. Note that this section
562 * is not measured, neither as raw section (see above), nor as cpio (here), because it is the
563 * signature of expected PCR values, i.e. its input are PCR measurements, and hence it shouldn't
564 * itself be input for PCR measurements. */
565 if (szs
[UNIFIED_SECTION_PCRSIG
] > 0)
566 (void) pack_cpio_literal(
567 (uint8_t*) loaded_image
->ImageBase
+ addrs
[UNIFIED_SECTION_PCRSIG
],
568 szs
[UNIFIED_SECTION_PCRSIG
],
570 u
"tpm2-pcr-signature.json",
571 /* dir_mode= */ 0555,
572 /* access_mode= */ 0444,
573 /* tpm_pcr= */ UINT32_MAX
,
574 /* tpm_description= */ NULL
,
577 /* ret_measured= */ NULL
);
579 /* If the public key used for the PCR signatures was embedded in the PE image, then let's wrap it in
580 * a cpio and also pass it to the kernel, so that it can be read from
581 * /.extra/tpm2-pcr-public-key.pem. This section is already measure above, hence we won't measure the
583 if (szs
[UNIFIED_SECTION_PCRPKEY
] > 0)
584 (void) pack_cpio_literal(
585 (uint8_t*) loaded_image
->ImageBase
+ addrs
[UNIFIED_SECTION_PCRPKEY
],
586 szs
[UNIFIED_SECTION_PCRPKEY
],
588 u
"tpm2-pcr-public-key.pem",
589 /* dir_mode= */ 0555,
590 /* access_mode= */ 0444,
591 /* tpm_pcr= */ UINT32_MAX
,
592 /* tpm_description= */ NULL
,
594 &pcrpkey_initrd_size
,
595 /* ret_measured= */ NULL
);
597 linux_size
= szs
[UNIFIED_SECTION_LINUX
];
598 linux_base
= POINTER_TO_PHYSICAL_ADDRESS(loaded_image
->ImageBase
) + addrs
[UNIFIED_SECTION_LINUX
];
600 initrd_size
= szs
[UNIFIED_SECTION_INITRD
];
601 initrd_base
= initrd_size
!= 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image
->ImageBase
) + addrs
[UNIFIED_SECTION_INITRD
] : 0;
603 dt_size
= szs
[UNIFIED_SECTION_DTB
];
604 dt_base
= dt_size
!= 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image
->ImageBase
) + addrs
[UNIFIED_SECTION_DTB
] : 0;
606 _cleanup_pages_ Pages initrd_pages
= {};
607 if (credential_initrd
|| global_credential_initrd
|| sysext_initrd
|| pcrsig_initrd
|| pcrpkey_initrd
) {
608 /* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
609 err
= combine_initrd(
610 initrd_base
, initrd_size
,
611 (const void*const[]) {
613 global_credential_initrd
,
619 credential_initrd_size
,
620 global_credential_initrd_size
,
626 &initrd_pages
, &initrd_size
);
627 if (err
!= EFI_SUCCESS
)
630 initrd_base
= initrd_pages
.addr
;
632 /* Given these might be large let's free them explicitly, quickly. */
633 credential_initrd
= mfree(credential_initrd
);
634 global_credential_initrd
= mfree(global_credential_initrd
);
635 sysext_initrd
= mfree(sysext_initrd
);
636 pcrsig_initrd
= mfree(pcrsig_initrd
);
637 pcrpkey_initrd
= mfree(pcrpkey_initrd
);
641 err
= devicetree_install_from_memory(
642 &dt_state
, PHYSICAL_ADDRESS_TO_POINTER(dt_base
), dt_size
);
643 if (err
!= EFI_SUCCESS
)
644 log_error_status(err
, "Error loading embedded devicetree: %m");
647 err
= linux_exec(image
, cmdline
,
648 PHYSICAL_ADDRESS_TO_POINTER(linux_base
), linux_size
,
649 PHYSICAL_ADDRESS_TO_POINTER(initrd_base
), initrd_size
);
650 graphics_mode(false);
654 DEFINE_EFI_MAIN_FUNCTION(run
, "systemd-stub", /*wait_for_debugger=*/false);