blob: 0e5f369b957cf248927adf067e65694dfc4dd1ae [file] [log] [blame]
Lorenz Brun35fcf032023-06-29 04:15:58 +02001From a8004bca64e697bf8f39af63c4325fbc9b507e48 Mon Sep 17 00:00:00 2001
2From: Lorenz Brun <lorenz@monogon.tech>
3Date: Thu, 29 Jun 2023 03:54:01 +0200
4Subject: [PATCH] Implement filename-based A/B slot handling
5
6---
7 src/boot/efi/stub.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
8 1 file changed, 66 insertions(+)
9
10diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
11index dad0f61335..88eda7e0e7 100644
12--- a/src/boot/efi/stub.c
13+++ b/src/boot/efi/stub.c
14@@ -5,6 +5,8 @@
15
16 #include "cpio.h"
17 #include "disk.h"
18+#include "efibind.h"
19+#include "efidevp.h"
20 #include "graphics.h"
21 #include "linux.h"
22 #include "measure.h"
23@@ -13,6 +15,31 @@
24 #include "splash.h"
25 #include "util.h"
26
27+// From picolibc under BSD-3-Clause (c) 2018 Arm Ltd.
28+/* Small and efficient strstr implementation. */
29+char * strstr (const char *hs, const char *ne)
30+{
31+ UINTN i;
32+ int c = ne[0];
33+
34+ if (c == 0)
35+ return (char*)hs;
36+
37+ for ( ; hs[0] != '\0'; hs++)
38+ {
39+ if (hs[0] != c)
40+ continue;
41+ for (i = 1; ne[i] != 0; i++)
42+ if (hs[i] != ne[i])
43+ break;
44+ if (ne[i] == '\0')
45+ return (char*)hs;
46+ }
47+
48+ return NULL;
49+}
50+
51+
52 /* magic string to find in the binary image */
53 static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####";
54
55@@ -180,6 +207,45 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
56 cmdline_len = szs[SECTION_CMDLINE];
57 }
58
59+ /* Extract last FILEPATH element from image path to check file name */
60+ CHAR16 *last_file_path = NULL;
61+ EFI_DEVICE_PATH *current_path_elem = loaded_image->FilePath;
62+ while (current_path_elem != NULL && !IsDevicePathEnd(current_path_elem)) {
63+ if (DevicePathType(current_path_elem) == MEDIA_DEVICE_PATH &&
64+ current_path_elem->SubType == MEDIA_FILEPATH_DP) {
65+ last_file_path = ((FILEPATH_DEVICE_PATH*)current_path_elem)->PathName;
66+ }
67+ current_path_elem = NextDevicePathNode(current_path_elem);
68+ }
69+ /* Check slot based on suffix of the last FILE_PATH value */
70+ CHAR8 slot = 'A';
71+ const CHAR16 suffix_a[] = L"boot-a.efi";
72+ const CHAR16 suffix_b[] = L"boot-b.efi";
73+ const UINTN suffix_len = (sizeof(suffix_a)/sizeof(CHAR16))-1;
74+ if (last_file_path != NULL) {
75+ UINTN plen = StrLen(last_file_path);
76+ if (suffix_len > plen) {
77+ // TODO: Log
78+ } else if (StriCmp(suffix_a, last_file_path + (plen-suffix_len)) == 0) {
79+ slot = 'A';
80+ } else if (StriCmp(suffix_b, last_file_path + (plen-suffix_len)) == 0) {
81+ slot = 'B';
82+ } else {
83+ // TODO: Log
84+ }
85+ }
86+ Print(L"Booting into Slot %c\n", slot);
87+ /* Replace METROPOLIS-SYSTEM-X with the correct slot */
88+ const char slot_identifier[] = "METROPOLIS-SYSTEM-X";
89+ const UINTN slot_id_len = (sizeof(slot_identifier)/sizeof(char))-1;
90+ if (cmdline != NULL) {
91+ CHAR8 *rest_ptr = cmdline;
92+ while((rest_ptr = strstr(rest_ptr, slot_identifier))) {
93+ rest_ptr[slot_id_len-1] = slot;
94+ rest_ptr += slot_id_len;
95+ }
96+ }
97+
98 /* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */
99 if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 &&
100 *(CHAR16 *) loaded_image->LoadOptions > 0x1F) {
101--
1022.40.1
103