]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/boot/efi/boot.c
Merge pull request #13953 from SpencerMichaels/systemd-boot-efistub-id-fix
[thirdparty/systemd.git] / src / boot / efi / boot.c
index fd0c972951f9ff282c03fa837a1a360a86a94ccd..84293364b47eb03fd23cd0bed99d04bec966c520 100644 (file)
@@ -32,7 +32,7 @@ enum loader_type {
 };
 
 typedef struct {
-        CHAR16 *id; /* The identifier for this entry (note that this id is not necessarily unique though!) */
+        CHAR16 *id; /* The unique identifier for this entry */
         CHAR16 *title_show;
         CHAR16 *title;
         CHAR16 *version;
@@ -515,7 +515,6 @@ static BOOLEAN menu_run(
         BOOLEAN exit = FALSE;
         BOOLEAN run = TRUE;
         BOOLEAN wait = FALSE;
-        BOOLEAN cleared_screen = FALSE;
 
         graphics_mode(FALSE);
         uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
@@ -527,16 +526,13 @@ static BOOLEAN menu_run(
 
         if (config->console_mode_change != CONSOLE_MODE_KEEP) {
                 err = console_set_mode(&config->console_mode, config->console_mode_change);
-                if (!EFI_ERROR(err))
-                        cleared_screen = TRUE;
-        }
-
-        if (!cleared_screen)
+                if (EFI_ERROR(err)) {
+                        uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+                        Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
+                }
+        } else
                 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
 
-        if (config->console_mode_change != CONSOLE_MODE_KEEP && EFI_ERROR(err))
-                Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
-
         err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
         if (EFI_ERROR(err)) {
                 x_max = 80;
@@ -1304,6 +1300,7 @@ static VOID config_entry_bump_counters(
 static VOID config_entry_add_from_file(
                 Config *config,
                 EFI_HANDLE *device,
+                EFI_FILE *root_dir,
                 CHAR16 *path,
                 CHAR16 *file,
                 CHAR8 *content,
@@ -1313,7 +1310,8 @@ static VOID config_entry_add_from_file(
         CHAR8 *line;
         UINTN pos = 0;
         CHAR8 *key, *value;
-        UINTN len;
+        EFI_STATUS err;
+        EFI_FILE_HANDLE handle;
         _cleanup_freepool_ CHAR16 *initrd = NULL;
 
         entry = AllocatePool(sizeof(ConfigEntry));
@@ -1410,6 +1408,14 @@ static VOID config_entry_add_from_file(
                 return;
         }
 
+        /* check existence */
+        err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, entry->loader, EFI_FILE_MODE_READ, 0ULL);
+        if (EFI_ERROR(err)) {
+                config_entry_free(entry);
+                return;
+        }
+        uefi_call_wrapper(handle->Close, 1, handle);
+
         /* add initrd= to options */
         if (entry->type == LOADER_LINUX && initrd) {
                 if (entry->options) {
@@ -1424,10 +1430,6 @@ static VOID config_entry_add_from_file(
 
         entry->device = device;
         entry->id = StrDuplicate(file);
-        len = StrLen(entry->id);
-        /* remove ".conf" */
-        if (len > 5)
-                entry->id[len - 5] = '\0';
         StrLwr(entry->id);
 
         config_add_entry(config, entry);
@@ -1507,7 +1509,7 @@ static VOID config_load_entries(
 
                         err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
                         if (!EFI_ERROR(err))
-                                config_entry_add_from_file(config, device, L"\\loader\\entries", f->FileName, content, loaded_image_path);
+                                config_entry_add_from_file(config, device, root_dir, L"\\loader\\entries", f->FileName, content, loaded_image_path);
                 }
                 uefi_call_wrapper(entries_dir->Close, 1, entries_dir);
         }
@@ -1768,7 +1770,8 @@ static ConfigEntry *config_entry_add_loader(
                 CHAR16 *id,
                 CHAR16 key,
                 CHAR16 *title,
-                CHAR16 *loader) {
+                CHAR16 *loader,
+                CHAR16 *version) {
 
         ConfigEntry *entry;
 
@@ -1776,6 +1779,7 @@ static ConfigEntry *config_entry_add_loader(
         *entry = (ConfigEntry) {
                 .type = type,
                 .title = StrDuplicate(title),
+                .version = StrDuplicate(version),
                 .device = device,
                 .loader = StrDuplicate(loader),
                 .id = StrDuplicate(id),
@@ -1833,7 +1837,7 @@ static BOOLEAN config_entry_add_loader_auto(
                 return FALSE;
         uefi_call_wrapper(handle->Close, 1, handle);
 
-        entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, id, key, title, loader);
+        entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, id, key, title, loader, NULL);
         if (!entry)
                 return FALSE;
 
@@ -1901,10 +1905,12 @@ static VOID config_entry_add_linux(
                 CHAR8 *line;
                 UINTN pos = 0;
                 CHAR8 *key, *value;
+                CHAR16 *os_name_pretty = NULL;
                 CHAR16 *os_name = NULL;
                 CHAR16 *os_id = NULL;
                 CHAR16 *os_version = NULL;
-                CHAR16 *os_build = NULL;
+                CHAR16 *os_version_id = NULL;
+                CHAR16 *os_build_id = NULL;
 
                 err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf);
                 if (bufsize == 0 || EFI_ERROR(err))
@@ -1920,6 +1926,8 @@ static VOID config_entry_add_linux(
                         continue;
                 if (StriCmp(f->FileName + len - 4, L".efi") != 0)
                         continue;
+                if (StrnCmp(f->FileName, L"auto-", 5) == 0)
+                        continue;
 
                 /* look for .osrel and .cmdline sections in the .efi binary */
                 err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
@@ -1933,6 +1941,12 @@ static VOID config_entry_add_linux(
                 /* read properties from the embedded os-release file */
                 while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
                         if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) {
+                                FreePool(os_name_pretty);
+                                os_name_pretty = stra_to_str(value);
+                                continue;
+                        }
+
+                        if (strcmpa((CHAR8 *)"NAME", key) == 0) {
                                 FreePool(os_name);
                                 os_name = stra_to_str(value);
                                 continue;
@@ -1950,20 +1964,27 @@ static VOID config_entry_add_linux(
                                 continue;
                         }
 
+                        if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) {
+                                FreePool(os_version_id);
+                                os_version_id = stra_to_str(value);
+                                continue;
+                        }
+
                         if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) {
-                                FreePool(os_build);
-                                os_build = stra_to_str(value);
+                                FreePool(os_build_id);
+                                os_build_id = stra_to_str(value);
                                 continue;
                         }
                 }
 
-                if (os_name && os_id && (os_version || os_build)) {
-                        _cleanup_freepool_ CHAR16 *conf = NULL, *path = NULL;
+                if ((os_name_pretty || os_name) && os_id && (os_version || os_version_id || os_build_id)) {
+                        _cleanup_freepool_ CHAR16 *path = NULL;
 
-                        conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build);
                         path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
 
-                        entry = config_entry_add_loader(config, device, LOADER_LINUX, conf, 'l', os_name, path);
+                        entry = config_entry_add_loader(config, device, LOADER_LINUX, f->FileName, 'l',
+                                                        os_name_pretty ? : (os_name ? : os_id), path,
+                                                        os_version ? : (os_version_id ? : os_build_id));
 
                         FreePool(content);
                         content = NULL;
@@ -1982,10 +2003,12 @@ static VOID config_entry_add_linux(
                         config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi");
                 }
 
+                FreePool(os_name_pretty);
                 FreePool(os_name);
                 FreePool(os_id);
                 FreePool(os_version);
-                FreePool(os_build);
+                FreePool(os_version_id);
+                FreePool(os_build_id);
                 FreePool(content);
         }
 
@@ -2446,6 +2469,12 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 UINT64 key;
 
                 err = console_key_read(&key, FALSE);
+
+                if (err == EFI_NOT_READY) {
+                        uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
+                        err = console_key_read(&key, FALSE);
+                }
+
                 if (!EFI_ERROR(err)) {
                         INT16 idx;