]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/efi/stub.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / boot / efi / stub.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <efi.h>
4 #include <efilib.h>
5
6 #include "disk.h"
7 #include "graphics.h"
8 #include "linux.h"
9 #include "measure.h"
10 #include "pe.h"
11 #include "splash.h"
12 #include "util.h"
13
14 /* magic string to find in the binary image */
15 static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####";
16
17 static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
18
19 EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
20 EFI_LOADED_IMAGE *loaded_image;
21 _cleanup_freepool_ CHAR8 *b = NULL;
22 UINTN size;
23 BOOLEAN secure = FALSE;
24 CHAR8 *sections[] = {
25 (UINT8 *)".cmdline",
26 (UINT8 *)".linux",
27 (UINT8 *)".initrd",
28 (UINT8 *)".splash",
29 NULL
30 };
31 UINTN addrs[ELEMENTSOF(sections)-1] = {};
32 UINTN offs[ELEMENTSOF(sections)-1] = {};
33 UINTN szs[ELEMENTSOF(sections)-1] = {};
34 CHAR8 *cmdline = NULL;
35 UINTN cmdline_len;
36 CHAR16 uuid[37];
37 EFI_STATUS err;
38
39 InitializeLib(image, sys_table);
40
41 err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
42 image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
43 if (EFI_ERROR(err)) {
44 Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
45 uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
46 return err;
47 }
48
49 if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
50 if (*b > 0)
51 secure = TRUE;
52
53 err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
54 if (EFI_ERROR(err)) {
55 Print(L"Unable to locate embedded .linux section: %r ", err);
56 uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
57 return err;
58 }
59
60 if (szs[0] > 0)
61 cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]);
62
63 cmdline_len = szs[0];
64
65 /* if we are not in secure boot mode, accept a custom command line and replace the built-in one */
66 if (!secure && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) {
67 CHAR16 *options;
68 CHAR8 *line;
69 UINTN i;
70
71 options = (CHAR16 *)loaded_image->LoadOptions;
72 cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
73 line = AllocatePool(cmdline_len);
74 for (i = 0; i < cmdline_len; i++)
75 line[i] = options[i];
76 cmdline = line;
77
78 #if ENABLE_TPM
79 /* Try to log any options to the TPM, especially manually edited options */
80 err = tpm_log_event(SD_TPM_PCR,
81 (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
82 loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
83 if (EFI_ERROR(err)) {
84 Print(L"Unable to add image options measurement: %r", err);
85 uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
86 }
87 #endif
88 }
89
90 /* export the device path this image is started from */
91 if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
92 efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
93
94 /* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */
95 if (efivar_get_raw(&global_guid, L"LoaderImageIdentifier", &b, &size) != EFI_SUCCESS) {
96 _cleanup_freepool_ CHAR16 *s;
97
98 s = DevicePathToStr(loaded_image->FilePath);
99 efivar_set(L"LoaderImageIdentifier", s, FALSE);
100 }
101
102 /* if LoaderFirmwareInfo is not set, let's set it */
103 if (efivar_get_raw(&global_guid, L"LoaderFirmwareInfo", &b, &size) != EFI_SUCCESS) {
104 _cleanup_freepool_ CHAR16 *s;
105
106 s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
107 efivar_set(L"LoaderFirmwareInfo", s, FALSE);
108 }
109
110 /* ditto for LoaderFirmwareType */
111 if (efivar_get_raw(&global_guid, L"LoaderFirmwareType", &b, &size) != EFI_SUCCESS) {
112 _cleanup_freepool_ CHAR16 *s;
113
114 s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
115 efivar_set(L"LoaderFirmwareType", s, FALSE);
116 }
117
118 /* add StubInfo */
119 if (efivar_get_raw(&global_guid, L"StubInfo", &b, &size) != EFI_SUCCESS)
120 efivar_set(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE);
121
122 if (szs[3] > 0)
123 graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL);
124
125 err = linux_exec(image, cmdline, cmdline_len,
126 (UINTN)loaded_image->ImageBase + addrs[1],
127 (UINTN)loaded_image->ImageBase + addrs[2], szs[2]);
128
129 graphics_mode(FALSE);
130 Print(L"Execution of embedded linux image failed: %r\n", err);
131 uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
132 return err;
133 }