1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 static void efi_unload_image(EFI_HANDLE
*h
) {
11 (void) BS
->UnloadImage(*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
= BS
->LoadImage(FALSE
, parent_image
, path
, NULL
, 0, &image
);
38 return log_error_status_stall(err
, L
"Failed to load image %s: %r", fname
, err
);
40 err
= BS
->HandleProtocol(image
, &LoadedImageProtocol
, (void **)&loaded_image
);
42 return log_error_status_stall(err
, L
"Failed to find protocol in driver image s: %r", fname
, err
);
44 if (loaded_image
->ImageCodeType
!= EfiBootServicesCode
&&
45 loaded_image
->ImageCodeType
!= EfiRuntimeServicesCode
)
46 return log_error_status_stall(EFI_INVALID_PARAMETER
, L
"Image %s is not a driver, refusing: %r", fname
);
48 err
= BS
->StartImage(image
, NULL
, NULL
);
50 return log_error_status_stall(err
, L
"Failed to start image %s: %r", fname
, err
);
56 static EFI_STATUS
reconnect(void) {
57 _cleanup_freepool_ EFI_HANDLE
*handles
= NULL
;
61 /* Reconnects all handles, so that any loaded drivers can take effect. */
63 err
= BS
->LocateHandleBuffer(AllHandles
, NULL
, NULL
, &n_handles
, &handles
);
65 return log_error_status_stall(err
, L
"Failed to get list of handles: %r", err
);
67 for (UINTN i
= 0; i
< n_handles
; i
++) {
68 err
= BS
->ConnectController(handles
[i
], NULL
, NULL
, TRUE
);
69 if (err
== EFI_NOT_FOUND
) /* No drivers for this handle */
72 log_error_status_stall(err
, L
"Failed to reconnect handle %u, ignoring: %r", i
, err
);
78 EFI_STATUS
load_drivers(
79 EFI_HANDLE parent_image
,
80 EFI_LOADED_IMAGE
*loaded_image
,
81 EFI_FILE_HANDLE root_dir
) {
83 _cleanup_(FileHandleClosep
) EFI_FILE_HANDLE drivers_dir
= NULL
;
84 _cleanup_freepool_ EFI_FILE_INFO
*dirent
= NULL
;
85 UINTN dirent_size
= 0, n_succeeded
= 0;
90 L
"\\EFI\\systemd\\drivers",
92 if (err
== EFI_NOT_FOUND
)
95 return log_error_status_stall(err
, L
"Failed to open \\EFI\\systemd\\drivers: %r", err
);
98 err
= readdir_harder(drivers_dir
, &dirent
, &dirent_size
);
100 return log_error_status_stall(err
, L
"Failed to read extra directory of loaded image: %r", err
);
101 if (!dirent
) /* End of directory */
104 if (dirent
->FileName
[0] == '.')
106 if (dirent
->Attribute
& EFI_FILE_DIRECTORY
)
108 if (!endswith_no_case(dirent
->FileName
, EFI_MACHINE_TYPE_NAME L
".efi"))
111 err
= load_one_driver(parent_image
, loaded_image
, dirent
->FileName
);