]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
0fa2cac4 KS |
2 | |
3 | #include <efi.h> | |
4 | #include <efilib.h> | |
5 | ||
8110e144 | 6 | #include "disk.h" |
37fa3690 | 7 | #include "graphics.h" |
0fa2cac4 | 8 | #include "linux.h" |
d4cbada2 MG |
9 | #include "measure.h" |
10 | #include "pe.h" | |
cf0fbc49 TA |
11 | #include "splash.h" |
12 | #include "util.h" | |
0fa2cac4 KS |
13 | |
14 | /* magic string to find in the binary image */ | |
681bd2c5 | 15 | static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####"; |
0fa2cac4 KS |
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; | |
a42d7cf1 | 21 | _cleanup_freepool_ CHAR8 *b = NULL; |
0fa2cac4 KS |
22 | UINTN size; |
23 | BOOLEAN secure = FALSE; | |
24 | CHAR8 *sections[] = { | |
25 | (UINT8 *)".cmdline", | |
26 | (UINT8 *)".linux", | |
27 | (UINT8 *)".initrd", | |
37fa3690 | 28 | (UINT8 *)".splash", |
0fa2cac4 KS |
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; | |
8110e144 | 36 | CHAR16 uuid[37]; |
0fa2cac4 KS |
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 | ||
a42d7cf1 | 49 | if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) |
0fa2cac4 KS |
50 | if (*b > 0) |
51 | secure = TRUE; | |
a42d7cf1 | 52 | |
d4cbada2 | 53 | err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs); |
0fa2cac4 KS |
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 */ | |
15720d03 | 66 | if (!secure && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) { |
0fa2cac4 KS |
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; | |
92ed3bb4 | 77 | |
349cc4a5 | 78 | #if ENABLE_TPM |
7db5706e | 79 | /* Try to log any options to the TPM, especially manually edited options */ |
92ed3bb4 | 80 | err = tpm_log_event(SD_TPM_PCR, |
33de6b57 | 81 | (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions, |
92ed3bb4 HH |
82 | loaded_image->LoadOptionsSize, loaded_image->LoadOptions); |
83 | if (EFI_ERROR(err)) { | |
84 | Print(L"Unable to add image options measurement: %r", err); | |
522aa9f5 | 85 | uefi_call_wrapper(BS->Stall, 1, 200 * 1000); |
92ed3bb4 HH |
86 | } |
87 | #endif | |
0fa2cac4 KS |
88 | } |
89 | ||
c8b32d06 LP |
90 | /* Export the device path this image is started from, if it's not set yet */ |
91 | if (efivar_get_raw(&loader_guid, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) | |
92 | if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) | |
93 | efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); | |
8110e144 | 94 | |
19e0e60a | 95 | /* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */ |
8118fb3c | 96 | if (efivar_get_raw(&loader_guid, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) { |
a42d7cf1 ZJS |
97 | _cleanup_freepool_ CHAR16 *s; |
98 | ||
99 | s = DevicePathToStr(loaded_image->FilePath); | |
100 | efivar_set(L"LoaderImageIdentifier", s, FALSE); | |
19e0e60a ДГ |
101 | } |
102 | ||
1aa15def | 103 | /* if LoaderFirmwareInfo is not set, let's set it */ |
8118fb3c | 104 | if (efivar_get_raw(&loader_guid, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) { |
a42d7cf1 ZJS |
105 | _cleanup_freepool_ CHAR16 *s; |
106 | ||
107 | s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); | |
108 | efivar_set(L"LoaderFirmwareInfo", s, FALSE); | |
1aa15def | 109 | } |
a42d7cf1 | 110 | |
1aa15def | 111 | /* ditto for LoaderFirmwareType */ |
8118fb3c | 112 | if (efivar_get_raw(&loader_guid, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) { |
a42d7cf1 ZJS |
113 | _cleanup_freepool_ CHAR16 *s; |
114 | ||
115 | s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); | |
116 | efivar_set(L"LoaderFirmwareType", s, FALSE); | |
1aa15def ДГ |
117 | } |
118 | ||
34412f79 | 119 | /* add StubInfo */ |
8118fb3c | 120 | if (efivar_get_raw(&loader_guid, L"StubInfo", NULL, NULL) != EFI_SUCCESS) |
681bd2c5 | 121 | efivar_set(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE); |
1aa15def | 122 | |
37fa3690 KS |
123 | if (szs[3] > 0) |
124 | graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL); | |
125 | ||
0fa2cac4 KS |
126 | err = linux_exec(image, cmdline, cmdline_len, |
127 | (UINTN)loaded_image->ImageBase + addrs[1], | |
5f7df68c | 128 | (UINTN)loaded_image->ImageBase + addrs[2], szs[2]); |
0fa2cac4 | 129 | |
37fa3690 | 130 | graphics_mode(FALSE); |
0fa2cac4 KS |
131 | Print(L"Execution of embedded linux image failed: %r\n", err); |
132 | uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); | |
133 | return err; | |
134 | } |