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