]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
0fa2cac4 KS |
2 | |
3 | #include <efi.h> | |
4 | #include <efilib.h> | |
5 | ||
845707aa | 6 | #include "cpio.h" |
33bc9b75 | 7 | #include "devicetree.h" |
8110e144 | 8 | #include "disk.h" |
37fa3690 | 9 | #include "graphics.h" |
0fa2cac4 | 10 | #include "linux.h" |
d4cbada2 | 11 | #include "measure.h" |
0a1d8ac7 | 12 | #include "part-discovery.h" |
d4cbada2 | 13 | #include "pe.h" |
0a1d8ac7 | 14 | #include "random-seed.h" |
ce0f078f | 15 | #include "secure-boot.h" |
cf0fbc49 | 16 | #include "splash.h" |
aa323c09 | 17 | #include "tpm-pcr.h" |
cf0fbc49 | 18 | #include "util.h" |
0fa2cac4 KS |
19 | |
20 | /* magic string to find in the binary image */ | |
2ccd5986 | 21 | _used_ _section_(".sdmagic") static const char magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####"; |
0fa2cac4 | 22 | |
845707aa LP |
23 | static EFI_STATUS combine_initrd( |
24 | EFI_PHYSICAL_ADDRESS initrd_base, UINTN initrd_size, | |
23002b45 | 25 | const void * const extra_initrds[], const size_t extra_initrd_sizes[], size_t n_extra_initrds, |
09173c91 | 26 | Pages *ret_initr_pages, UINTN *ret_initrd_size) { |
845707aa | 27 | |
845707aa LP |
28 | UINTN n; |
29 | ||
09173c91 | 30 | assert(ret_initr_pages); |
845707aa LP |
31 | assert(ret_initrd_size); |
32 | ||
f3b6f333 | 33 | /* Combines four initrds into one, by simple concatenation in memory */ |
845707aa | 34 | |
b4e7df4a | 35 | n = ALIGN4(initrd_size); /* main initrd might not be padded yet */ |
845707aa | 36 | |
23002b45 LP |
37 | for (size_t i = 0; i < n_extra_initrds; i++) { |
38 | if (!extra_initrds[i]) | |
39 | continue; | |
f3b6f333 | 40 | |
23002b45 | 41 | if (n > UINTN_MAX - extra_initrd_sizes[i]) |
845707aa LP |
42 | return EFI_OUT_OF_RESOURCES; |
43 | ||
23002b45 | 44 | n += extra_initrd_sizes[i]; |
845707aa LP |
45 | } |
46 | ||
09173c91 | 47 | _cleanup_pages_ Pages pages = xmalloc_pages( |
845707aa LP |
48 | AllocateMaxAddress, |
49 | EfiLoaderData, | |
50 | EFI_SIZE_TO_PAGES(n), | |
09173c91 JJ |
51 | UINT32_MAX /* Below 4G boundary. */); |
52 | uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr); | |
845707aa LP |
53 | if (initrd_base != 0) { |
54 | UINTN pad; | |
55 | ||
56 | /* Order matters, the real initrd must come first, since it might include microcode updates | |
57 | * which the kernel only looks for in the first cpio archive */ | |
515581d6 | 58 | p = mempcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size); |
845707aa | 59 | |
b4e7df4a | 60 | pad = ALIGN4(initrd_size) - initrd_size; |
845707aa | 61 | if (pad > 0) { |
bbc1f2ea | 62 | memset(p, 0, pad); |
845707aa LP |
63 | p += pad; |
64 | } | |
65 | } | |
66 | ||
23002b45 LP |
67 | for (size_t i = 0; i < n_extra_initrds; i++) { |
68 | if (!extra_initrds[i]) | |
69 | continue; | |
70 | ||
71 | p = mempcpy(p, extra_initrds[i], extra_initrd_sizes[i]); | |
72 | } | |
845707aa | 73 | |
09173c91 | 74 | assert(PHYSICAL_ADDRESS_TO_POINTER(pages.addr + n) == p); |
845707aa | 75 | |
09173c91 | 76 | *ret_initr_pages = pages; |
845707aa | 77 | *ret_initrd_size = n; |
09173c91 | 78 | pages.n_pages = 0; |
845707aa LP |
79 | |
80 | return EFI_SUCCESS; | |
81 | } | |
82 | ||
b30a43df | 83 | static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) { |
46d33672 LP |
84 | static const uint64_t stub_features = |
85 | EFI_STUB_FEATURE_REPORT_BOOT_PARTITION | /* We set LoaderDevicePartUUID */ | |
86 | EFI_STUB_FEATURE_PICK_UP_CREDENTIALS | /* We pick up credentials from the boot partition */ | |
87 | EFI_STUB_FEATURE_PICK_UP_SYSEXTS | /* We pick up system extensions from the boot partition */ | |
88 | EFI_STUB_FEATURE_THREE_PCRS | /* We can measure kernel image, parameters and sysext */ | |
0a1d8ac7 | 89 | EFI_STUB_FEATURE_RANDOM_SEED | /* We pass a random seed to the kernel */ |
46d33672 LP |
90 | 0; |
91 | ||
3639d1b0 | 92 | char16_t uuid[37]; |
5a186322 LP |
93 | |
94 | assert(loaded_image); | |
95 | ||
96 | /* Export the device path this image is started from, if it's not set yet */ | |
19f08504 | 97 | if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) |
5a186322 | 98 | if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) |
19f08504 | 99 | efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", uuid, 0); |
5a186322 LP |
100 | |
101 | /* If LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from the | |
102 | * UEFI firmware without any boot loader, and hence set the LoaderImageIdentifier ourselves. Note | |
103 | * that some boot chain loaders neither set LoaderImageIdentifier nor make FilePath available to us, | |
104 | * in which case there's simple nothing to set for us. (The UEFI spec doesn't really say who's wrong | |
105 | * here, i.e. whether FilePath may be NULL or not, hence handle this gracefully and check if FilePath | |
106 | * is non-NULL explicitly.) */ | |
19f08504 | 107 | if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS && |
5a186322 | 108 | loaded_image->FilePath) { |
3639d1b0 | 109 | _cleanup_free_ char16_t *s = NULL; |
616a80fe | 110 | if (device_path_to_str(loaded_image->FilePath, &s) == EFI_SUCCESS) |
19f08504 | 111 | efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", s, 0); |
5a186322 LP |
112 | } |
113 | ||
114 | /* if LoaderFirmwareInfo is not set, let's set it */ | |
19f08504 | 115 | if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) { |
3639d1b0 | 116 | _cleanup_free_ char16_t *s = NULL; |
2f3c3b0b | 117 | s = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); |
19f08504 | 118 | efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", s, 0); |
5a186322 LP |
119 | } |
120 | ||
121 | /* ditto for LoaderFirmwareType */ | |
19f08504 | 122 | if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) { |
3639d1b0 | 123 | _cleanup_free_ char16_t *s = NULL; |
2f3c3b0b | 124 | s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); |
19f08504 | 125 | efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", s, 0); |
5a186322 LP |
126 | } |
127 | ||
46d33672 | 128 | |
24120e40 LP |
129 | /* add StubInfo (this is one is owned by the stub, hence we unconditionally override this with our |
130 | * own data) */ | |
19f08504 | 131 | (void) efivar_set(MAKE_GUID_PTR(LOADER), u"StubInfo", u"systemd-stub " GIT_VERSION, 0); |
46d33672 | 132 | |
19f08504 | 133 | (void) efivar_set_uint64_le(MAKE_GUID_PTR(LOADER), u"StubFeatures", stub_features, 0); |
5a186322 LP |
134 | } |
135 | ||
b17f3b3d JJ |
136 | static bool use_load_options( |
137 | EFI_HANDLE stub_image, | |
138 | EFI_LOADED_IMAGE_PROTOCOL *loaded_image, | |
139 | bool have_cmdline, | |
140 | char16_t **ret) { | |
141 | ||
142 | assert(stub_image); | |
143 | assert(loaded_image); | |
144 | assert(ret); | |
145 | ||
146 | /* We only allow custom command lines if we aren't in secure boot or if no cmdline was baked into | |
147 | * the stub image. */ | |
148 | if (secure_boot_enabled() && have_cmdline) | |
149 | return false; | |
150 | ||
151 | /* We also do a superficial check whether first character of passed command line | |
152 | * is printable character (for compat with some Dell systems which fill in garbage?). */ | |
153 | if (loaded_image->LoadOptionsSize < sizeof(char16_t) || ((char16_t *) loaded_image->LoadOptions)[0] <= 0x1F) | |
154 | return false; | |
155 | ||
156 | /* The UEFI shell registers EFI_SHELL_PARAMETERS_PROTOCOL onto images it runs. This lets us know that | |
157 | * LoadOptions starts with the stub binary path which we want to strip off. */ | |
158 | EFI_SHELL_PARAMETERS_PROTOCOL *shell; | |
19f08504 | 159 | if (BS->HandleProtocol(stub_image, MAKE_GUID_PTR(EFI_SHELL_PARAMETERS_PROTOCOL), (void **) &shell) |
b17f3b3d JJ |
160 | != EFI_SUCCESS) { |
161 | /* Not running from EFI shell, use entire LoadOptions. Note that LoadOptions is a void*, so | |
162 | * it could be anything! */ | |
163 | *ret = xstrndup16(loaded_image->LoadOptions, loaded_image->LoadOptionsSize / sizeof(char16_t)); | |
164 | mangle_stub_cmdline(*ret); | |
165 | return true; | |
166 | } | |
167 | ||
168 | if (shell->Argc < 2) | |
169 | /* No arguments were provided? Then we fall back to built-in cmdline. */ | |
170 | return false; | |
171 | ||
172 | /* Assemble the command line ourselves without our stub path. */ | |
173 | *ret = xstrdup16(shell->Argv[1]); | |
174 | for (size_t i = 2; i < shell->Argc; i++) { | |
175 | _cleanup_free_ char16_t *old = *ret; | |
2f3c3b0b | 176 | *ret = xasprintf("%ls %ls", old, shell->Argv[i]); |
b17f3b3d JJ |
177 | } |
178 | ||
179 | mangle_stub_cmdline(*ret); | |
180 | return true; | |
181 | } | |
182 | ||
31a131bb | 183 | static EFI_STATUS run(EFI_HANDLE image) { |
23002b45 | 184 | _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL; |
927ebebe JJ |
185 | size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0; |
186 | size_t linux_size, initrd_size, dt_size; | |
33bc9b75 MR |
187 | EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base; |
188 | _cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {}; | |
b30a43df | 189 | EFI_LOADED_IMAGE_PROTOCOL *loaded_image; |
927ebebe JJ |
190 | size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {}; |
191 | _cleanup_free_ char16_t *cmdline = NULL; | |
72c97c19 | 192 | int sections_measured = -1, parameters_measured = -1; |
de7ad6d4 | 193 | bool sysext_measured = false, m; |
0a1d8ac7 | 194 | uint64_t loader_features = 0; |
0fa2cac4 KS |
195 | EFI_STATUS err; |
196 | ||
12f32748 JJ |
197 | err = BS->OpenProtocol( |
198 | image, | |
19f08504 JJ |
199 | MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL), |
200 | (void **) &loaded_image, | |
12f32748 JJ |
201 | image, |
202 | NULL, | |
203 | EFI_OPEN_PROTOCOL_GET_PROTOCOL); | |
2a5e4fe4 | 204 | if (err != EFI_SUCCESS) |
c2c62035 | 205 | return log_error_status(err, "Error getting a LoadedImageProtocol handle: %m"); |
0fa2cac4 | 206 | |
19f08504 | 207 | if (efivar_get_uint64_le(MAKE_GUID_PTR(LOADER), u"LoaderFeatures", &loader_features) != EFI_SUCCESS || |
0a1d8ac7 JD |
208 | !FLAGS_SET(loader_features, EFI_LOADER_FEATURE_RANDOM_SEED)) { |
209 | _cleanup_(file_closep) EFI_FILE *esp_dir = NULL; | |
210 | ||
19f08504 | 211 | err = partition_open(MAKE_GUID_PTR(ESP), loaded_image->DeviceHandle, NULL, &esp_dir); |
0a1d8ac7 JD |
212 | if (err == EFI_SUCCESS) /* Non-fatal on failure, so that we still boot without it. */ |
213 | (void) process_random_seed(esp_dir); | |
214 | } | |
215 | ||
6017eee9 LP |
216 | err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, addrs, szs); |
217 | if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) { | |
2a5e4fe4 | 218 | if (err == EFI_SUCCESS) |
65ff3d26 | 219 | err = EFI_NOT_FOUND; |
c2c62035 | 220 | return log_error_status(err, "Unable to locate embedded .linux section: %m"); |
65ff3d26 | 221 | } |
0fa2cac4 | 222 | |
72c97c19 LP |
223 | /* Measure all "payload" of this PE image into a separate PCR (i.e. where nothing else is written |
224 | * into so far), so that we have one PCR that we can nicely write policies against because it | |
225 | * contains all static data of this image, and thus can be easily be pre-calculated. */ | |
6017eee9 | 226 | for (UnifiedSection section = 0; section < _UNIFIED_SECTION_MAX; section++) { |
df7ee6f8 LP |
227 | |
228 | if (!unified_section_measure(section)) /* shall not measure? */ | |
229 | continue; | |
72c97c19 LP |
230 | |
231 | if (szs[section] == 0) /* not found */ | |
232 | continue; | |
233 | ||
df7ee6f8 LP |
234 | m = false; |
235 | ||
72c97c19 LP |
236 | /* First measure the name of the section */ |
237 | (void) tpm_log_event_ascii( | |
238 | TPM_PCR_INDEX_KERNEL_IMAGE, | |
6017eee9 LP |
239 | POINTER_TO_PHYSICAL_ADDRESS(unified_sections[section]), |
240 | strsize8(unified_sections[section]), /* including NUL byte */ | |
241 | unified_sections[section], | |
72c97c19 LP |
242 | &m); |
243 | ||
244 | sections_measured = sections_measured < 0 ? m : (sections_measured && m); | |
245 | ||
246 | /* Then measure the data of the section */ | |
247 | (void) tpm_log_event_ascii( | |
248 | TPM_PCR_INDEX_KERNEL_IMAGE, | |
249 | POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[section], | |
250 | szs[section], | |
6017eee9 | 251 | unified_sections[section], |
72c97c19 LP |
252 | &m); |
253 | ||
254 | sections_measured = sections_measured < 0 ? m : (sections_measured && m); | |
255 | } | |
256 | ||
257 | /* After we are done, set an EFI variable that tells userspace this was done successfully, and encode | |
258 | * in it which PCR was used. */ | |
259 | if (sections_measured > 0) | |
19f08504 | 260 | (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelImage", TPM_PCR_INDEX_KERNEL_IMAGE, 0); |
72c97c19 | 261 | |
94b81afb | 262 | /* Show splash screen as early as possible */ |
957dfcc9 | 263 | graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_SPLASH], szs[UNIFIED_SECTION_SPLASH]); |
94b81afb | 264 | |
b17f3b3d | 265 | if (use_load_options(image, loaded_image, szs[UNIFIED_SECTION_CMDLINE] > 0, &cmdline)) { |
e6e24af5 LP |
266 | /* Let's measure the passed kernel command line into the TPM. Note that this possibly |
267 | * duplicates what we already did in the boot menu, if that was already used. However, since | |
268 | * we want the boot menu to support an EFI binary, and want to this stub to be usable from | |
269 | * any boot menu, let's measure things anyway. */ | |
599fe002 | 270 | m = false; |
927ebebe | 271 | (void) tpm_log_load_options(cmdline, &m); |
599fe002 | 272 | parameters_measured = m; |
927ebebe JJ |
273 | } else if (szs[UNIFIED_SECTION_CMDLINE] > 0) { |
274 | cmdline = xstrn8_to_16( | |
275 | (char *) loaded_image->ImageBase + addrs[UNIFIED_SECTION_CMDLINE], | |
276 | szs[UNIFIED_SECTION_CMDLINE]); | |
277 | mangle_stub_cmdline(cmdline); | |
0fa2cac4 KS |
278 | } |
279 | ||
5a186322 | 280 | export_variables(loaded_image); |
1aa15def | 281 | |
599fe002 LP |
282 | if (pack_cpio(loaded_image, |
283 | NULL, | |
284 | L".cred", | |
285 | ".extra/credentials", | |
286 | /* dir_mode= */ 0500, | |
287 | /* access_mode= */ 0400, | |
d84bdadb | 288 | /* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS, |
599fe002 LP |
289 | L"Credentials initrd", |
290 | &credential_initrd, | |
291 | &credential_initrd_size, | |
292 | &m) == EFI_SUCCESS) | |
293 | parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m); | |
294 | ||
295 | if (pack_cpio(loaded_image, | |
296 | L"\\loader\\credentials", | |
297 | L".cred", | |
298 | ".extra/global_credentials", | |
299 | /* dir_mode= */ 0500, | |
300 | /* access_mode= */ 0400, | |
d84bdadb | 301 | /* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS, |
599fe002 LP |
302 | L"Global credentials initrd", |
303 | &global_credential_initrd, | |
304 | &global_credential_initrd_size, | |
305 | &m) == EFI_SUCCESS) | |
306 | parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m); | |
f3b6f333 | 307 | |
de7ad6d4 LP |
308 | if (pack_cpio(loaded_image, |
309 | NULL, | |
310 | L".raw", | |
311 | ".extra/sysext", | |
312 | /* dir_mode= */ 0555, | |
313 | /* access_mode= */ 0444, | |
d84bdadb | 314 | /* tpm_pcr= */ TPM_PCR_INDEX_INITRD_SYSEXTS, |
de7ad6d4 LP |
315 | L"System extension initrd", |
316 | &sysext_initrd, | |
317 | &sysext_initrd_size, | |
318 | &m) == EFI_SUCCESS) | |
319 | sysext_measured = m; | |
599fe002 LP |
320 | |
321 | if (parameters_measured > 0) | |
19f08504 | 322 | (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelParameters", TPM_PCR_INDEX_KERNEL_PARAMETERS, 0); |
de7ad6d4 | 323 | if (sysext_measured) |
19f08504 | 324 | (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDSysExts", TPM_PCR_INDEX_INITRD_SYSEXTS, 0); |
845707aa | 325 | |
23002b45 LP |
326 | /* If the PCR signature was embedded in the PE image, then let's wrap it in a cpio and also pass it |
327 | * to the kernel, so that it can be read from /.extra/tpm2-pcr-signature.json. Note that this section | |
328 | * is not measured, neither as raw section (see above), nor as cpio (here), because it is the | |
5dcb9c3c | 329 | * signature of expected PCR values, i.e. its input are PCR measurements, and hence it shouldn't |
23002b45 LP |
330 | * itself be input for PCR measurements. */ |
331 | if (szs[UNIFIED_SECTION_PCRSIG] > 0) | |
332 | (void) pack_cpio_literal( | |
333 | (uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRSIG], | |
334 | szs[UNIFIED_SECTION_PCRSIG], | |
335 | ".extra", | |
336 | L"tpm2-pcr-signature.json", | |
337 | /* dir_mode= */ 0555, | |
338 | /* access_mode= */ 0444, | |
d84bdadb | 339 | /* tpm_pcr= */ UINT32_MAX, |
23002b45 LP |
340 | /* tpm_description= */ NULL, |
341 | &pcrsig_initrd, | |
342 | &pcrsig_initrd_size, | |
343 | /* ret_measured= */ NULL); | |
344 | ||
345 | /* If the public key used for the PCR signatures was embedded in the PE image, then let's wrap it in | |
346 | * a cpio and also pass it to the kernel, so that it can be read from | |
347 | * /.extra/tpm2-pcr-public-key.pem. This section is already measure above, hence we won't measure the | |
348 | * cpio. */ | |
349 | if (szs[UNIFIED_SECTION_PCRPKEY] > 0) | |
350 | (void) pack_cpio_literal( | |
351 | (uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRPKEY], | |
352 | szs[UNIFIED_SECTION_PCRPKEY], | |
353 | ".extra", | |
354 | L"tpm2-pcr-public-key.pem", | |
355 | /* dir_mode= */ 0555, | |
356 | /* access_mode= */ 0444, | |
d84bdadb | 357 | /* tpm_pcr= */ UINT32_MAX, |
23002b45 LP |
358 | /* tpm_description= */ NULL, |
359 | &pcrpkey_initrd, | |
360 | &pcrpkey_initrd_size, | |
361 | /* ret_measured= */ NULL); | |
362 | ||
6017eee9 LP |
363 | linux_size = szs[UNIFIED_SECTION_LINUX]; |
364 | linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_LINUX]; | |
5b5d365d | 365 | |
6017eee9 LP |
366 | initrd_size = szs[UNIFIED_SECTION_INITRD]; |
367 | initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0; | |
37fa3690 | 368 | |
6017eee9 LP |
369 | dt_size = szs[UNIFIED_SECTION_DTB]; |
370 | dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0; | |
33bc9b75 | 371 | |
09173c91 | 372 | _cleanup_pages_ Pages initrd_pages = {}; |
64650de7 | 373 | if (credential_initrd || global_credential_initrd || sysext_initrd || pcrsig_initrd || pcrpkey_initrd) { |
845707aa LP |
374 | /* If we have generated initrds dynamically, let's combine them with the built-in initrd. */ |
375 | err = combine_initrd( | |
376 | initrd_base, initrd_size, | |
23002b45 LP |
377 | (const void*const[]) { |
378 | credential_initrd, | |
379 | global_credential_initrd, | |
380 | sysext_initrd, | |
381 | pcrsig_initrd, | |
382 | pcrpkey_initrd, | |
383 | }, | |
384 | (const size_t[]) { | |
385 | credential_initrd_size, | |
386 | global_credential_initrd_size, | |
387 | sysext_initrd_size, | |
388 | pcrsig_initrd_size, | |
389 | pcrpkey_initrd_size, | |
390 | }, | |
391 | 5, | |
09173c91 | 392 | &initrd_pages, &initrd_size); |
2a5e4fe4 | 393 | if (err != EFI_SUCCESS) |
845707aa LP |
394 | return err; |
395 | ||
09173c91 JJ |
396 | initrd_base = initrd_pages.addr; |
397 | ||
845707aa | 398 | /* Given these might be large let's free them explicitly, quickly. */ |
f3b6f333 AV |
399 | credential_initrd = mfree(credential_initrd); |
400 | global_credential_initrd = mfree(global_credential_initrd); | |
401 | sysext_initrd = mfree(sysext_initrd); | |
23002b45 LP |
402 | pcrsig_initrd = mfree(pcrsig_initrd); |
403 | pcrpkey_initrd = mfree(pcrpkey_initrd); | |
845707aa | 404 | } |
0fa2cac4 | 405 | |
33bc9b75 MR |
406 | if (dt_size > 0) { |
407 | err = devicetree_install_from_memory( | |
408 | &dt_state, PHYSICAL_ADDRESS_TO_POINTER(dt_base), dt_size); | |
2a5e4fe4 | 409 | if (err != EFI_SUCCESS) |
c2c62035 | 410 | log_error_status(err, "Error loading embedded devicetree: %m"); |
33bc9b75 MR |
411 | } |
412 | ||
927ebebe | 413 | err = linux_exec(image, cmdline, |
dc467928 | 414 | PHYSICAL_ADDRESS_TO_POINTER(linux_base), linux_size, |
a6089431 | 415 | PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size); |
e5a1b8f9 | 416 | graphics_mode(false); |
a529d818 | 417 | return err; |
0fa2cac4 | 418 | } |
6ac54809 | 419 | |
31a131bb | 420 | DEFINE_EFI_MAIN_FUNCTION(run, "systemd-stub", /*wait_for_debugger=*/false); |
1d278ad7 JJ |
421 | |
422 | /* See comment in boot.c. */ | |
423 | EFI_STATUS _entry(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) { | |
424 | return efi_main(image, system_table); | |
425 | } |