]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/efi/drivers.c
efi: drop two unused variables
[thirdparty/systemd.git] / src / boot / efi / drivers.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <efi.h>
4 #include <efilib.h>
5
6 #include "drivers.h"
7 #include "util.h"
8
9 static void efi_unload_image(EFI_HANDLE *h) {
10 if (*h)
11 (void) BS->UnloadImage(*h);
12 }
13
14 static EFI_STATUS load_one_driver(
15 EFI_HANDLE parent_image,
16 EFI_LOADED_IMAGE *loaded_image,
17 const CHAR16 *fname) {
18
19 _cleanup_(efi_unload_image) EFI_HANDLE image = NULL;
20 _cleanup_freepool_ EFI_DEVICE_PATH *path = NULL;
21 _cleanup_freepool_ CHAR16 *spath = NULL;
22 EFI_STATUS err;
23
24 assert(parent_image);
25 assert(loaded_image);
26 assert(fname);
27
28 spath = PoolPrint(L"\\EFI\\systemd\\drivers\\%s", fname);
29 if (!spath)
30 return log_oom();
31
32 path = FileDevicePath(loaded_image->DeviceHandle, spath);
33 if (!path)
34 return log_oom();
35
36 err = BS->LoadImage(FALSE, parent_image, path, NULL, 0, &image);
37 if (EFI_ERROR(err))
38 return log_error_status_stall(err, L"Failed to load image %s: %r", fname, err);
39
40 err = BS->HandleProtocol(image, &LoadedImageProtocol, (void **)&loaded_image);
41 if (EFI_ERROR(err))
42 return log_error_status_stall(err, L"Failed to find protocol in driver image s: %r", fname, err);
43
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);
47
48 err = BS->StartImage(image, NULL, NULL);
49 if (EFI_ERROR(err))
50 return log_error_status_stall(err, L"Failed to start image %s: %r", fname, err);
51
52 TAKE_PTR(image);
53 return EFI_SUCCESS;
54 }
55
56 static EFI_STATUS reconnect(void) {
57 _cleanup_freepool_ EFI_HANDLE *handles = NULL;
58 UINTN n_handles = 0;
59 EFI_STATUS err;
60
61 /* Reconnects all handles, so that any loaded drivers can take effect. */
62
63 err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
64 if (EFI_ERROR(err))
65 return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
66
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 */
70 continue;
71 if (EFI_ERROR(err))
72 log_error_status_stall(err, L"Failed to reconnect handle %u, ignoring: %r", i, err);
73 }
74
75 return EFI_SUCCESS;
76 }
77
78 EFI_STATUS load_drivers(
79 EFI_HANDLE parent_image,
80 EFI_LOADED_IMAGE *loaded_image,
81 EFI_FILE_HANDLE root_dir) {
82
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;
86 EFI_STATUS err;
87
88 err = open_directory(
89 root_dir,
90 L"\\EFI\\systemd\\drivers",
91 &drivers_dir);
92 if (err == EFI_NOT_FOUND)
93 return EFI_SUCCESS;
94 if (EFI_ERROR(err))
95 return log_error_status_stall(err, L"Failed to open \\EFI\\systemd\\drivers: %r", err);
96
97 for (;;) {
98 err = readdir_harder(drivers_dir, &dirent, &dirent_size);
99 if (EFI_ERROR(err))
100 return log_error_status_stall(err, L"Failed to read extra directory of loaded image: %r", err);
101 if (!dirent) /* End of directory */
102 break;
103
104 if (dirent->FileName[0] == '.')
105 continue;
106 if (dirent->Attribute & EFI_FILE_DIRECTORY)
107 continue;
108 if (!endswith_no_case(dirent->FileName, EFI_MACHINE_TYPE_NAME L".efi"))
109 continue;
110
111 err = load_one_driver(parent_image, loaded_image, dirent->FileName);
112 if (EFI_ERROR(err))
113 continue;
114
115 n_succeeded++;
116 }
117
118 if (n_succeeded > 0)
119 (void) reconnect();
120
121 return EFI_SUCCESS;
122 }