@@ -1298,6 +1298,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
{ EFI_LOADER_FEATURE_ENTRY_ONESHOT, "One-shot entry control" },
|
||||
{ EFI_LOADER_FEATURE_XBOOTLDR, "Support for XBOOTLDR partition" },
|
||||
{ EFI_LOADER_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" },
|
||||
{ EFI_LOADER_FEATURE_LOAD_DRIVER, "Load drop-in drivers" },
|
||||
};
|
||||
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "console.h"
|
||||
#include "devicetree.h"
|
||||
#include "disk.h"
|
||||
#include "drivers.h"
|
||||
#include "efi-loader-features.h"
|
||||
#include "graphics.h"
|
||||
#include "linux.h"
|
||||
@@ -2428,6 +2429,7 @@ static VOID export_variables(
|
||||
EFI_LOADER_FEATURE_BOOT_COUNTING |
|
||||
EFI_LOADER_FEATURE_XBOOTLDR |
|
||||
EFI_LOADER_FEATURE_RANDOM_SEED |
|
||||
EFI_LOADER_FEATURE_LOAD_DRIVER |
|
||||
0;
|
||||
|
||||
_cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
|
||||
@@ -2538,6 +2540,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
return log_error_status_stall(err, L"Error installing security policy: %r", err);
|
||||
}
|
||||
|
||||
(VOID) load_drivers(image, loaded_image, root_dir);
|
||||
|
||||
config_load_all_entries(&config, loaded_image, loaded_image_path, root_dir);
|
||||
|
||||
if (config.entry_count == 0) {
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "drivers.h"
|
||||
#include "util.h"
|
||||
|
||||
static VOID efi_unload_image(EFI_HANDLE *h) {
|
||||
if (*h)
|
||||
(VOID) uefi_call_wrapper(BS->UnloadImage, 1, *h);
|
||||
}
|
||||
|
||||
static EFI_STATUS load_one_driver(
|
||||
EFI_HANDLE parent_image,
|
||||
EFI_LOADED_IMAGE *loaded_image,
|
||||
const CHAR16 *fname) {
|
||||
|
||||
_cleanup_(efi_unload_image) EFI_HANDLE image = NULL;
|
||||
_cleanup_freepool_ EFI_DEVICE_PATH *path = NULL;
|
||||
_cleanup_freepool_ CHAR16 *spath = NULL;
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(parent_image);
|
||||
assert(loaded_image);
|
||||
assert(fname);
|
||||
|
||||
spath = PoolPrint(L"\\EFI\\systemd\\drivers\\%s", fname);
|
||||
if (!spath)
|
||||
return log_oom();
|
||||
|
||||
path = FileDevicePath(loaded_image->DeviceHandle, spath);
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
err = uefi_call_wrapper(
|
||||
BS->LoadImage, 6,
|
||||
FALSE,
|
||||
parent_image,
|
||||
path,
|
||||
NULL, 0,
|
||||
&image);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Failed to load image %s: %r", fname, err);
|
||||
|
||||
err = uefi_call_wrapper(
|
||||
BS->HandleProtocol, 3,
|
||||
image,
|
||||
&LoadedImageProtocol,
|
||||
(VOID **)&loaded_image);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Failed to find protocol in driver image s: %r", fname, err);
|
||||
|
||||
if (loaded_image->ImageCodeType != EfiBootServicesCode &&
|
||||
loaded_image->ImageCodeType != EfiRuntimeServicesCode)
|
||||
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Image %s is not a driver, refusing: %r", fname);
|
||||
|
||||
err = uefi_call_wrapper(
|
||||
BS->StartImage, 3,
|
||||
image,
|
||||
NULL,
|
||||
NULL);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Failed to start image %s: %r", fname, err);
|
||||
|
||||
TAKE_PTR(image);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS reconnect(VOID) {
|
||||
_cleanup_freepool_ EFI_HANDLE *handles = NULL;
|
||||
UINTN n_handles = 0;
|
||||
EFI_STATUS err;
|
||||
|
||||
/* Reconnects all handles, so that any loaded drivers can take effect. */
|
||||
|
||||
err = uefi_call_wrapper(
|
||||
BS->LocateHandleBuffer, 5,
|
||||
AllHandles,
|
||||
NULL,
|
||||
NULL,
|
||||
&n_handles,
|
||||
&handles);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
|
||||
|
||||
for (UINTN i = 0; i < n_handles; i++) {
|
||||
err = uefi_call_wrapper(
|
||||
BS->ConnectController, 4,
|
||||
handles[i],
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE);
|
||||
if (err == EFI_NOT_FOUND) /* No drivers for this handle */
|
||||
continue;
|
||||
if (EFI_ERROR(err))
|
||||
log_error_status_stall(err, L"Failed to reconnect handle %u, ignoring: %r", i, err);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS load_drivers(
|
||||
EFI_HANDLE parent_image,
|
||||
EFI_LOADED_IMAGE *loaded_image,
|
||||
EFI_FILE_HANDLE root_dir) {
|
||||
|
||||
_cleanup_(FileHandleClosep) EFI_FILE_HANDLE drivers_dir = NULL;
|
||||
_cleanup_freepool_ EFI_FILE_INFO *dirent = NULL;
|
||||
_cleanup_freepool_ EFI_DEVICE_PATH *path = NULL;
|
||||
UINTN dirent_size = 0, n_succeeded = 0;
|
||||
EFI_STATUS err;
|
||||
|
||||
err = open_directory(
|
||||
root_dir,
|
||||
L"\\EFI\\systemd\\drivers",
|
||||
&drivers_dir);
|
||||
if (err == EFI_NOT_FOUND)
|
||||
return EFI_SUCCESS;
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Failed to open \\EFI\\systemd\\drivers: %r", err);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_freepool_ CHAR16 *d = NULL;
|
||||
|
||||
err = readdir_harder(drivers_dir, &dirent, &dirent_size);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Failed to read extra directory of loaded image: %r", err);
|
||||
if (!dirent) /* End of directory */
|
||||
break;
|
||||
|
||||
if (dirent->FileName[0] == '.')
|
||||
continue;
|
||||
if (dirent->Attribute & EFI_FILE_DIRECTORY)
|
||||
continue;
|
||||
if (!endswith_no_case(dirent->FileName, EFI_MACHINE_TYPE_NAME L".efi"))
|
||||
continue;
|
||||
|
||||
err = load_one_driver(parent_image, loaded_image, dirent->FileName);
|
||||
if (EFI_ERROR(err))
|
||||
continue;
|
||||
|
||||
n_succeeded++;
|
||||
}
|
||||
|
||||
if (n_succeeded > 0)
|
||||
(VOID) reconnect();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
EFI_STATUS load_drivers(
|
||||
EFI_HANDLE parent_image,
|
||||
EFI_LOADED_IMAGE *loaded_image,
|
||||
EFI_FILE_HANDLE root_dir);
|
||||
@@ -5,6 +5,7 @@ efi_headers = files('''
|
||||
cpio.h
|
||||
devicetree.h
|
||||
disk.h
|
||||
drivers.h
|
||||
graphics.h
|
||||
linux.h
|
||||
measure.h
|
||||
@@ -31,6 +32,7 @@ systemd_boot_sources = '''
|
||||
boot.c
|
||||
console.c
|
||||
devicetree.c
|
||||
drivers.c
|
||||
random-seed.c
|
||||
sha256.c
|
||||
shim.c
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
#define EFI_LOADER_FEATURE_BOOT_COUNTING (UINT64_C(1) << 4)
|
||||
#define EFI_LOADER_FEATURE_XBOOTLDR (UINT64_C(1) << 5)
|
||||
#define EFI_LOADER_FEATURE_RANDOM_SEED (UINT64_C(1) << 6)
|
||||
#define EFI_LOADER_FEATURE_LOAD_DRIVER (UINT64_C(1) << 7)
|
||||
|
||||
Reference in New Issue
Block a user