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