]>
Commit | Line | Data |
---|---|---|
dccded55 ER |
1 | From: Emanuele Rocca <ema@debian.org> |
2 | Date: Fri, 31 Mar 2023 12:38:52 +0200 | |
3 | Subject: Cherry-pick parts of "Load arm with SB enabled." | |
4 | ||
5 | Fix Secure Boot on arm64 by cherry-picking the relevant parts of upstream patch | |
6 | "Load arm with SB enabled." | |
7 | ||
8 | Signed-off-by: Emanuele Rocca <ema@debian.org> | |
9 | ||
10 | Origin: vendor, https://github.com/rhboot/grub2/commit/2786ab864cf00c15123320671f653e9a36ba12b4 | |
11 | --- | |
12 | ||
effc8001 | 13 | Index: grub.git/grub-core/loader/arm64/linux.c |
dccded55 | 14 | =================================================================== |
effc8001 SM |
15 | --- grub.git.orig/grub-core/loader/arm64/linux.c |
16 | +++ grub.git/grub-core/loader/arm64/linux.c | |
dccded55 ER |
17 | @@ -16,6 +16,7 @@ |
18 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
20 | ||
21 | +#include <grub/cache.h> | |
22 | #include <grub/charset.h> | |
23 | #include <grub/command.h> | |
24 | #include <grub/err.h> | |
25 | @@ -33,6 +34,7 @@ | |
26 | #include <grub/i18n.h> | |
27 | #include <grub/lib/cmdline.h> | |
28 | #include <grub/verify.h> | |
29 | +#include <grub/efi/sb.h> | |
30 | ||
31 | GRUB_MOD_LICENSE ("GPLv3+"); | |
32 | ||
33 | @@ -41,6 +43,7 @@ static int loaded; | |
34 | ||
35 | static void *kernel_addr; | |
36 | static grub_uint64_t kernel_size; | |
37 | +static grub_uint32_t handover_offset; | |
38 | ||
39 | static char *linux_args; | |
40 | static grub_uint32_t cmdline_size; | |
41 | @@ -48,6 +51,15 @@ static grub_uint32_t cmdline_size; | |
42 | static grub_addr_t initrd_start; | |
43 | static grub_addr_t initrd_end; | |
44 | ||
45 | +struct grub_arm64_linux_pe_header | |
46 | +{ | |
47 | + grub_uint32_t magic; | |
48 | + struct grub_pe32_coff_header coff; | |
49 | + struct grub_pe64_optional_header opt; | |
50 | +}; | |
51 | + | |
52 | +typedef void (*handover_func) (void *, grub_efi_system_table_t *); | |
53 | + | |
54 | grub_err_t | |
55 | grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) | |
56 | { | |
57 | @@ -64,7 +76,8 @@ grub_arch_efi_linux_check_image (struct | |
58 | static grub_err_t | |
59 | finalize_params_linux (void) | |
60 | { | |
61 | - int node, retval; | |
62 | + grub_efi_loaded_image_t *loaded_image = NULL; | |
63 | + int node, retval, len; | |
64 | ||
65 | void *fdt; | |
66 | ||
67 | @@ -99,6 +112,27 @@ finalize_params_linux (void) | |
68 | if (grub_fdt_install() != GRUB_ERR_NONE) | |
69 | goto failure; | |
70 | ||
71 | + grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", | |
72 | + fdt); | |
73 | + | |
74 | + /* Convert command line to UCS-2 */ | |
75 | + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); | |
76 | + if (!loaded_image) { | |
77 | + grub_dprintf ("linux", "Error loading image with grub_efi_get_loaded_image()\n"); | |
78 | + goto failure; | |
79 | + } | |
80 | + | |
81 | + loaded_image->load_options_size = len = | |
82 | + (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); | |
83 | + loaded_image->load_options = | |
84 | + grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); | |
85 | + if (!loaded_image->load_options) | |
86 | + return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); | |
87 | + | |
88 | + loaded_image->load_options_size = | |
89 | + 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, | |
90 | + (grub_uint8_t *) linux_args, len, NULL); | |
91 | + | |
92 | return GRUB_ERR_NONE; | |
93 | ||
94 | failure: | |
effc8001 | 95 | @@ -116,6 +150,39 @@ grub_arch_efi_linux_boot_image (grub_add |
dccded55 | 96 | grub_efi_loaded_image_t *loaded_image; |
dccded55 ER |
97 | int len; |
98 | ||
effc8001 SM |
99 | +#ifdef __aarch64__ /* SB only enabled for arm64 */ |
100 | + handover_func hf; | |
101 | + | |
dccded55 ER |
102 | + if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED) { |
103 | + grub_dprintf ("linux", "GRUB_EFI_SECUREBOOT_MODE enabled\n"); | |
104 | + /* | |
105 | + * Since the EFI loader is not calling the LoadImage() and StartImage() | |
106 | + * services for loading the kernel and booting respectively, it has to | |
107 | + * set the Loaded Image base address. | |
108 | + */ | |
109 | + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); | |
110 | + if (loaded_image) { | |
111 | + loaded_image->image_base = kernel_addr; | |
112 | + grub_dprintf ("linux", "Loaded Image base address set to %p\n", kernel_addr); | |
113 | + } | |
114 | + else | |
115 | + grub_dprintf ("linux", "Loaded Image base address could not be set\n"); | |
116 | + | |
117 | + grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p\n", | |
118 | + kernel_addr, (void *)(grub_efi_uintn_t)handover_offset); | |
119 | + | |
120 | + /* Invalidate the instruction cache */ | |
121 | + grub_arch_sync_caches((void *)kernel_addr, kernel_size); | |
122 | + | |
123 | + hf = (handover_func)((char *)kernel_addr + handover_offset); | |
124 | + hf (grub_efi_image_handle, grub_efi_system_table); | |
125 | + | |
126 | + return GRUB_ERR_BUG; | |
127 | + } | |
128 | + | |
129 | + grub_dprintf ("linux", "GRUB_EFI_SECUREBOOT_MODE is NOT enabled\n"); | |
effc8001 | 130 | +#endif |
dccded55 ER |
131 | + |
132 | mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); | |
133 | if (!mempath) | |
134 | return grub_errno; | |
effc8001 | 135 | @@ -285,6 +352,7 @@ grub_cmd_linux (grub_command_t cmd __att |
dccded55 ER |
136 | { |
137 | grub_file_t file = 0; | |
138 | struct linux_arch_kernel_header lh; | |
139 | + struct grub_arm64_linux_pe_header *pe; | |
140 | grub_err_t err; | |
141 | ||
142 | grub_dl_ref (my_mod); | |
effc8001 | 143 | @@ -330,6 +398,9 @@ grub_cmd_linux (grub_command_t cmd __att |
dccded55 ER |
144 | |
145 | grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); | |
146 | ||
147 | + pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); | |
148 | + handover_offset = pe->opt.entry_addr; | |
149 | + | |
150 | cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); | |
151 | linux_args = grub_malloc (cmdline_size); | |
152 | if (!linux_args) |