]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
0fa2cac4 KS |
2 | /* This program is free software; you can redistribute it and/or modify it |
3 | * under the terms of the GNU Lesser General Public License as published by | |
4 | * the Free Software Foundation; either version 2.1 of the License, or | |
5 | * (at your option) any later version. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, but | |
8 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
10 | * Lesser General Public License for more details. | |
11 | * | |
12 | * Copyright (C) 2015 Kay Sievers <kay@vrfy.org> | |
13 | */ | |
14 | ||
15 | #include <efi.h> | |
16 | #include <efilib.h> | |
17 | ||
8110e144 | 18 | #include "disk.h" |
37fa3690 | 19 | #include "graphics.h" |
0fa2cac4 | 20 | #include "linux.h" |
d4cbada2 MG |
21 | #include "measure.h" |
22 | #include "pe.h" | |
cf0fbc49 TA |
23 | #include "splash.h" |
24 | #include "util.h" | |
0fa2cac4 KS |
25 | |
26 | /* magic string to find in the binary image */ | |
948aaa7c | 27 | static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " PACKAGE_VERSION " ####"; |
0fa2cac4 KS |
28 | |
29 | static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; | |
30 | ||
31 | EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { | |
32 | EFI_LOADED_IMAGE *loaded_image; | |
0fa2cac4 KS |
33 | CHAR8 *b; |
34 | UINTN size; | |
35 | BOOLEAN secure = FALSE; | |
36 | CHAR8 *sections[] = { | |
37 | (UINT8 *)".cmdline", | |
38 | (UINT8 *)".linux", | |
39 | (UINT8 *)".initrd", | |
37fa3690 | 40 | (UINT8 *)".splash", |
0fa2cac4 KS |
41 | NULL |
42 | }; | |
43 | UINTN addrs[ELEMENTSOF(sections)-1] = {}; | |
44 | UINTN offs[ELEMENTSOF(sections)-1] = {}; | |
45 | UINTN szs[ELEMENTSOF(sections)-1] = {}; | |
46 | CHAR8 *cmdline = NULL; | |
47 | UINTN cmdline_len; | |
8110e144 | 48 | CHAR16 uuid[37]; |
0fa2cac4 KS |
49 | EFI_STATUS err; |
50 | ||
51 | InitializeLib(image, sys_table); | |
52 | ||
53 | err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, | |
54 | image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); | |
55 | if (EFI_ERROR(err)) { | |
56 | Print(L"Error getting a LoadedImageProtocol handle: %r ", err); | |
57 | uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); | |
58 | return err; | |
59 | } | |
60 | ||
0fa2cac4 KS |
61 | if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) { |
62 | if (*b > 0) | |
63 | secure = TRUE; | |
64 | FreePool(b); | |
65 | } | |
d4cbada2 | 66 | err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs); |
0fa2cac4 KS |
67 | if (EFI_ERROR(err)) { |
68 | Print(L"Unable to locate embedded .linux section: %r ", err); | |
69 | uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); | |
70 | return err; | |
71 | } | |
72 | ||
73 | if (szs[0] > 0) | |
74 | cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]); | |
75 | ||
76 | cmdline_len = szs[0]; | |
77 | ||
78 | /* if we are not in secure boot mode, accept a custom command line and replace the built-in one */ | |
293b1673 | 79 | if (!secure && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions != 0) { |
0fa2cac4 KS |
80 | CHAR16 *options; |
81 | CHAR8 *line; | |
82 | UINTN i; | |
83 | ||
84 | options = (CHAR16 *)loaded_image->LoadOptions; | |
85 | cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8); | |
86 | line = AllocatePool(cmdline_len); | |
87 | for (i = 0; i < cmdline_len; i++) | |
88 | line[i] = options[i]; | |
89 | cmdline = line; | |
92ed3bb4 | 90 | |
349cc4a5 | 91 | #if ENABLE_TPM |
7db5706e | 92 | /* Try to log any options to the TPM, especially manually edited options */ |
92ed3bb4 HH |
93 | err = tpm_log_event(SD_TPM_PCR, |
94 | (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions, | |
95 | loaded_image->LoadOptionsSize, loaded_image->LoadOptions); | |
96 | if (EFI_ERROR(err)) { | |
97 | Print(L"Unable to add image options measurement: %r", err); | |
522aa9f5 | 98 | uefi_call_wrapper(BS->Stall, 1, 200 * 1000); |
92ed3bb4 HH |
99 | } |
100 | #endif | |
0fa2cac4 KS |
101 | } |
102 | ||
8110e144 KS |
103 | /* export the device path this image is started from */ |
104 | if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) | |
105 | efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); | |
106 | ||
37fa3690 KS |
107 | if (szs[3] > 0) |
108 | graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL); | |
109 | ||
0fa2cac4 KS |
110 | err = linux_exec(image, cmdline, cmdline_len, |
111 | (UINTN)loaded_image->ImageBase + addrs[1], | |
112 | (UINTN)loaded_image->ImageBase + addrs[2], szs[2]); | |
113 | ||
37fa3690 | 114 | graphics_mode(FALSE); |
0fa2cac4 KS |
115 | Print(L"Execution of embedded linux image failed: %r\n", err); |
116 | uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); | |
117 | return err; | |
118 | } |