1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 static VOID
efi_unload_image(EFI_HANDLE
*h
) {
11 (VOID
) uefi_call_wrapper(BS
->UnloadImage
, 1, *h
);
14 static EFI_STATUS
load_one_driver(
15 EFI_HANDLE parent_image
,
16 EFI_LOADED_IMAGE
*loaded_image
,
17 const CHAR16
*fname
) {
19 _cleanup_(efi_unload_image
) EFI_HANDLE image
= NULL
;
20 _cleanup_freepool_ EFI_DEVICE_PATH
*path
= NULL
;
21 _cleanup_freepool_ CHAR16
*spath
= NULL
;
28 spath
= PoolPrint(L
"\\EFI\\systemd\\drivers\\%s", fname
);
32 path
= FileDevicePath(loaded_image
->DeviceHandle
, spath
);
36 err
= uefi_call_wrapper(
44 return log_error_status_stall(err
, L
"Failed to load image %s: %r", fname
, err
);
46 err
= uefi_call_wrapper(
47 BS
->HandleProtocol
, 3,
50 (VOID
**)&loaded_image
);
52 return log_error_status_stall(err
, L
"Failed to find protocol in driver image s: %r", fname
, err
);
54 if (loaded_image
->ImageCodeType
!= EfiBootServicesCode
&&
55 loaded_image
->ImageCodeType
!= EfiRuntimeServicesCode
)
56 return log_error_status_stall(EFI_INVALID_PARAMETER
, L
"Image %s is not a driver, refusing: %r", fname
);
58 err
= uefi_call_wrapper(
64 return log_error_status_stall(err
, L
"Failed to start image %s: %r", fname
, err
);
70 static EFI_STATUS
reconnect(VOID
) {
71 _cleanup_freepool_ EFI_HANDLE
*handles
= NULL
;
75 /* Reconnects all handles, so that any loaded drivers can take effect. */
77 err
= uefi_call_wrapper(
78 BS
->LocateHandleBuffer
, 5,
85 return log_error_status_stall(err
, L
"Failed to get list of handles: %r", err
);
87 for (UINTN i
= 0; i
< n_handles
; i
++) {
88 err
= uefi_call_wrapper(
89 BS
->ConnectController
, 4,
94 if (err
== EFI_NOT_FOUND
) /* No drivers for this handle */
97 log_error_status_stall(err
, L
"Failed to reconnect handle %u, ignoring: %r", i
, err
);
103 EFI_STATUS
load_drivers(
104 EFI_HANDLE parent_image
,
105 EFI_LOADED_IMAGE
*loaded_image
,
106 EFI_FILE_HANDLE root_dir
) {
108 _cleanup_(FileHandleClosep
) EFI_FILE_HANDLE drivers_dir
= NULL
;
109 _cleanup_freepool_ EFI_FILE_INFO
*dirent
= NULL
;
110 _cleanup_freepool_ EFI_DEVICE_PATH
*path
= NULL
;
111 UINTN dirent_size
= 0, n_succeeded
= 0;
114 err
= open_directory(
116 L
"\\EFI\\systemd\\drivers",
118 if (err
== EFI_NOT_FOUND
)
121 return log_error_status_stall(err
, L
"Failed to open \\EFI\\systemd\\drivers: %r", err
);
124 _cleanup_freepool_ CHAR16
*d
= NULL
;
126 err
= readdir_harder(drivers_dir
, &dirent
, &dirent_size
);
128 return log_error_status_stall(err
, L
"Failed to read extra directory of loaded image: %r", err
);
129 if (!dirent
) /* End of directory */
132 if (dirent
->FileName
[0] == '.')
134 if (dirent
->Attribute
& EFI_FILE_DIRECTORY
)
136 if (!endswith_no_case(dirent
->FileName
, EFI_MACHINE_TYPE_NAME L
".efi"))
139 err
= load_one_driver(parent_image
, loaded_image
, dirent
->FileName
);