]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/boot/efi/boot.c
build-sys: use #if Y instead of #ifdef Y everywhere
[thirdparty/systemd.git] / src / boot / efi / boot.c
index dde0c41744e27586d0a881db9c692967aa538a45..12176f1fe0c5911e4c56e64e8f7fbeeda646be72 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
 #include <efi.h>
 #include <efilib.h>
 
-#include "util.h"
 #include "console.h"
-#include "graphics.h"
-#include "pefile.h"
 #include "disk.h"
+#include "graphics.h"
 #include "linux.h"
+#include "measure.h"
+#include "pe.h"
+#include "shim.h"
+#include "util.h"
 
 #ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI
 #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL
 #endif
 
 /* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " VERSION " ####";
+static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " PACKAGE_VERSION " ####";
 
 static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
 
@@ -70,16 +70,14 @@ typedef struct {
         BOOLEAN no_editor;
 } Config;
 
-static VOID cursor_left(UINTN *cursor, UINTN *first)
-{
+static VOID cursor_left(UINTN *cursor, UINTN *first) {
         if ((*cursor) > 0)
                 (*cursor)--;
         else if ((*first) > 0)
                 (*first)--;
 }
 
-static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len)
-{
+static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) {
         if ((*cursor)+1 < x_max)
                 (*cursor)++;
         else if ((*first) + (*cursor) < len)
@@ -366,7 +364,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
         uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
         uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
 
-        Print(L"systemd-boot version:   " VERSION "\n");
+        Print(L"systemd-boot version:   " PACKAGE_VERSION "\n");
         Print(L"architecture:           " EFI_MACHINE_TYPE_NAME "\n");
         Print(L"loaded image:           %s\n", loaded_image_path);
         Print(L"UEFI specification:     %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
@@ -386,6 +384,9 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
                 FreePool(b);
         }
 
+        if (shim_loaded())
+                Print(L"Shim:                   present\n");
+
         if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
                 Print(L"OsIndicationsSupported: %d\n", (UINT64)*b);
                 FreePool(b);
@@ -784,7 +785,7 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, CHAR16 *load
                         break;
 
                 case KEYPRESS(0, 0, 'v'):
-                        status = PoolPrint(L"systemd-boot " VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
+                        status = PoolPrint(L"systemd-boot " PACKAGE_VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
                                            ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff,
                                            ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
                         break;
@@ -856,13 +857,11 @@ static VOID config_entry_free(ConfigEntry *entry) {
         FreePool(entry->options);
 }
 
-static BOOLEAN is_digit(CHAR16 c)
-{
+static BOOLEAN is_digit(CHAR16 c) {
         return (c >= '0') && (c <= '9');
 }
 
-static UINTN c_order(CHAR16 c)
-{
+static UINTN c_order(CHAR16 c) {
         if (c == '\0')
                 return 0;
         if (is_digit(c))
@@ -873,8 +872,7 @@ static UINTN c_order(CHAR16 c)
                 return c + 0x10000;
 }
 
-static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2)
-{
+static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) {
         CHAR16 *os1 = s1;
         CHAR16 *os2 = s2;
 
@@ -1140,13 +1138,11 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
         config_add_entry(config, entry);
 }
 
-static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
-        EFI_FILE_HANDLE entries_dir;
-        EFI_STATUS err;
+static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
         CHAR8 *content = NULL;
         UINTN sec;
         UINTN len;
-        UINTN i;
+        EFI_STATUS err;
 
         len = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content);
         if (len > 0)
@@ -1159,6 +1155,11 @@ static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir,
                 config->timeout_sec = sec;
         } else
                 config->timeout_sec_efivar = -1;
+}
+
+static VOID config_load_entries(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
+        EFI_FILE_HANDLE entries_dir;
+        EFI_STATUS err;
 
         err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL);
         if (!EFI_ERROR(err)) {
@@ -1195,8 +1196,11 @@ static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir,
                 }
                 uefi_call_wrapper(entries_dir->Close, 1, entries_dir);
         }
+}
+
+static VOID config_sort_entries(Config *config) {
+        UINTN i;
 
-        /* sort entries after version number */
         for (i = 1; i < config->entry_count; i++) {
                 BOOLEAN more;
                 UINTN k;
@@ -1482,7 +1486,7 @@ static VOID config_entry_add_osx(Config *config) {
                         root = LibOpenRoot(handles[i]);
                         if (!root)
                                 continue;
-                        found = config_entry_add_loader_auto(config, handles[i], root, NULL, L"auto-osx", 'a', L"OS X",
+                        found = config_entry_add_loader_auto(config, handles[i], root, NULL, L"auto-osx", 'a', L"macOS",
                                                              L"\\System\\Library\\CoreServices\\boot.efi");
                         uefi_call_wrapper(root->Close, 1, root);
                         if (found)
@@ -1539,7 +1543,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
                                 continue;
 
                         /* look for .osrel and .cmdline sections in the .efi binary */
-                        err = pefile_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
+                        err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
                         if (EFI_ERROR(err))
                                 continue;
 
@@ -1645,6 +1649,17 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con
                 }
                 loaded_image->LoadOptions = options;
                 loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16);
+
+#if ENABLE_TPM
+                /* Try to log any options to the TPM, especially to catch manually edited options */
+                err = tpm_log_event(SD_TPM_PCR,
+                                    (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
+                                    loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
+                if (EFI_ERROR(err)) {
+                        Print(L"Unable to add image options measurement: %r", err);
+                        uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
+                }
+#endif
         }
 
         efivar_set_time_usec(L"LoaderTimeExecUSec", 0);
@@ -1706,7 +1721,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         InitializeLib(image, sys_table);
         init_usec = time_usec();
         efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
-        efivar_set(L"LoaderInfo", L"systemd-boot " VERSION, FALSE);
+        efivar_set(L"LoaderInfo", L"systemd-boot " PACKAGE_VERSION, FALSE);
         s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
         efivar_set(L"LoaderFirmwareInfo", s, FALSE);
         FreePool(s);
@@ -1733,17 +1748,32 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 return EFI_LOAD_ERROR;
         }
 
+        if (secure_boot_enabled() && shim_loaded()) {
+                err = security_policy_install();
+                if (EFI_ERROR(err)) {
+                        Print(L"Error installing security policy: %r ", err);
+                        uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+                        return err;
+                }
+        }
 
         /* the filesystem path to this image, to prevent adding ourselves to the menu */
         loaded_image_path = DevicePathToStr(loaded_image->FilePath);
         efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
 
-        /* scan "\loader\entries\*.conf" files */
         ZeroMem(&config, sizeof(Config));
-        config_load(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
+        config_load_defaults(&config, root_dir);
 
-        /* if we find some well-known loaders, add them to the end of the list */
+        /* scan /EFI/Linux/ directory */
         config_entry_add_linux(&config, loaded_image, root_dir);
+
+        /* scan /loader/entries/\*.conf files */
+        config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
+
+        /* sort entries after version number */
+        config_sort_entries(&config);
+
+        /* if we find some well-known loaders, add them to the end of the list */
         config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
                                      L"auto-windows", 'w', L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
         config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
@@ -1768,7 +1798,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
 
         config_title_generate(&config);
 
-        /* select entry by configured pattern or EFI LoaderDefaultEntry= variable*/
+        /* select entry by configured pattern or EFI LoaderDefaultEntry= variable */
         config_default_entry_select(&config);
 
         /* if no configured entry to select from was found, enable the menu */