summaryrefslogtreecommitdiffstats
path: root/debian/patches/arm64-handover-to-kernel-if-sb-enabled.patch
blob: e20d4ad150ac4ccdc86831b0827ffdf4bd9a95cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
From: Emanuele Rocca <ema@debian.org>
Date: Fri, 31 Mar 2023 12:38:52 +0200
Subject: Cherry-pick parts of "Load arm with SB enabled."

Fix Secure Boot on arm64 by cherry-picking the relevant parts of upstream patch
"Load arm with SB enabled."

Signed-off-by: Emanuele Rocca <ema@debian.org>

Origin: vendor, https://github.com/rhboot/grub2/commit/2786ab864cf00c15123320671f653e9a36ba12b4
---

Index: grub.git/grub-core/loader/arm64/linux.c
===================================================================
--- grub.git.orig/grub-core/loader/arm64/linux.c
+++ grub.git/grub-core/loader/arm64/linux.c
@@ -16,6 +16,7 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <grub/cache.h>
 #include <grub/charset.h>
 #include <grub/command.h>
 #include <grub/err.h>
@@ -33,6 +34,7 @@
 #include <grub/i18n.h>
 #include <grub/lib/cmdline.h>
 #include <grub/verify.h>
+#include <grub/efi/sb.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -41,6 +43,7 @@ static int loaded;
 
 static void *kernel_addr;
 static grub_uint64_t kernel_size;
+static grub_uint32_t handover_offset;
 
 static char *linux_args;
 static grub_uint32_t cmdline_size;
@@ -48,6 +51,15 @@ static grub_uint32_t cmdline_size;
 static grub_addr_t initrd_start;
 static grub_addr_t initrd_end;
 
+struct grub_arm64_linux_pe_header
+{
+  grub_uint32_t magic;
+  struct grub_pe32_coff_header coff;
+  struct grub_pe64_optional_header opt;
+};
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *);
+
 grub_err_t
 grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
 {
@@ -64,7 +76,8 @@ grub_arch_efi_linux_check_image (struct
 static grub_err_t
 finalize_params_linux (void)
 {
-  int node, retval;
+  grub_efi_loaded_image_t *loaded_image = NULL;
+  int node, retval, len;
 
   void *fdt;
 
@@ -99,6 +112,27 @@ finalize_params_linux (void)
   if (grub_fdt_install() != GRUB_ERR_NONE)
     goto failure;
 
+  grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+                fdt);
+
+  /* Convert command line to UCS-2 */
+  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+  if (!loaded_image) {
+    grub_dprintf ("linux", "Error loading image with grub_efi_get_loaded_image()\n");
+    goto failure;
+  }
+
+  loaded_image->load_options_size = len =
+    (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
+  loaded_image->load_options =
+    grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+  if (!loaded_image->load_options)
+    return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+
+  loaded_image->load_options_size =
+    2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
+                            (grub_uint8_t *) linux_args, len, NULL);
+
   return GRUB_ERR_NONE;
 
 failure:
@@ -116,6 +150,39 @@ grub_arch_efi_linux_boot_image (grub_add
   grub_efi_loaded_image_t *loaded_image;
   int len;
 
+#ifdef __aarch64__  /* SB only enabled for arm64 */
+  handover_func hf;
+
+  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED) {
+      grub_dprintf ("linux", "GRUB_EFI_SECUREBOOT_MODE enabled\n");
+      /*
+       * Since the EFI loader is not calling the LoadImage() and StartImage()
+       * services for loading the kernel and booting respectively, it has to
+       * set the Loaded Image base address.
+       */
+      loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+      if (loaded_image) {
+        loaded_image->image_base = kernel_addr;
+        grub_dprintf ("linux", "Loaded Image base address set to %p\n", kernel_addr);
+      }
+      else
+        grub_dprintf ("linux", "Loaded Image base address could not be set\n");
+
+      grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p\n",
+                    kernel_addr, (void *)(grub_efi_uintn_t)handover_offset);
+
+      /* Invalidate the instruction cache */
+      grub_arch_sync_caches((void *)kernel_addr, kernel_size);
+
+      hf = (handover_func)((char *)kernel_addr + handover_offset);
+      hf (grub_efi_image_handle, grub_efi_system_table);
+
+      return GRUB_ERR_BUG;
+  }
+
+  grub_dprintf ("linux", "GRUB_EFI_SECUREBOOT_MODE is NOT enabled\n");
+#endif
+
   mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
   if (!mempath)
     return grub_errno;
@@ -285,6 +352,7 @@ grub_cmd_linux (grub_command_t cmd __att
 {
   grub_file_t file = 0;
   struct linux_arch_kernel_header lh;
+  struct grub_arm64_linux_pe_header *pe;
   grub_err_t err;
 
   grub_dl_ref (my_mod);
@@ -330,6 +398,9 @@ grub_cmd_linux (grub_command_t cmd __att
 
   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
 
+  pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+  handover_offset = pe->opt.entry_addr;
+
   cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
   linux_args = grub_malloc (cmdline_size);
   if (!linux_args)