]> code.delx.au - refind/blob - refind/driver_support.c
b8cb8b091839572f0e4b0e4891ecaaae5f4877e3
[refind] / refind / driver_support.c
1 /*
2 * File to implement LibScanHandleDatabase(), which is used by rEFInd's
3 * driver-loading code (inherited from rEFIt), but which has not been
4 * implemented in GNU-EFI and seems to have been dropped from current
5 * versions of the Tianocore library. This function was taken from a git
6 * site with EFI code, but some of the constants it uses were taken from
7 * a more recent EDK2 package (see below for details). The original files
8 * bore the following copyright notice:
9 *
10 * Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
11 * This program and the accompanying materials are licensed and made available under
12 * the terms and conditions of the BSD License that accompanies this distribution.
13 * The full text of the license may be found at
14 * http://opensource.org/licenses/bsd-license.php.
15 *
16 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 *
19 */
20
21 #include "driver_support.h"
22 #include "../include/refit_call_wrapper.h"
23
24 #ifdef __MAKEWITH_GNUEFI
25 // Following "global" constants are from EDK2's AutoGen.c....
26 EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
27 EFI_GUID gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }};
28 EFI_GUID gEfiDriverConfiguration2ProtocolGuid = { 0xBFD7DC1D, 0x24F1, 0x40D9, { 0x82, 0xE7, 0x2E, 0x09, 0xBB, 0x6B, 0x4E, 0xBE }};
29 EFI_GUID gEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
30 EFI_GUID gEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
31 EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x90, 0xD8, 0x5E, 0xD9, 0x00, 0x17, 0x3B, 0x63 }};
32 EFI_GUID gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
33 EFI_GUID gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }};
34 EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
35 #endif
36
37 // Below is from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec;
38 // Seems to have been replaced by ParseHandleDatabaseByRelationshipWithType(), but the latter isn't working for me....
39 EFI_STATUS
40 LibScanHandleDatabase (
41 EFI_HANDLE DriverBindingHandle, OPTIONAL
42 UINT32 *DriverBindingHandleIndex, OPTIONAL
43 EFI_HANDLE ControllerHandle, OPTIONAL
44 UINT32 *ControllerHandleIndex, OPTIONAL
45 UINTN *HandleCount,
46 EFI_HANDLE **HandleBuffer,
47 UINT32 **HandleType
48 )
49
50 {
51 EFI_STATUS Status;
52 UINTN HandleIndex;
53 EFI_GUID **ProtocolGuidArray;
54 UINTN ArrayCount;
55 UINTN ProtocolIndex;
56 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
57 UINTN OpenInfoCount;
58 UINTN OpenInfoIndex;
59 UINTN ChildIndex;
60 BOOLEAN DriverBindingHandleIndexValid;
61 // BOOLEAN ControllerHandleIndexValid;
62
63 DriverBindingHandleIndexValid = FALSE;
64 if (DriverBindingHandleIndex != NULL) {
65 *DriverBindingHandleIndex = 0xffffffff;
66 }
67
68 // ControllerHandleIndexValid = FALSE;
69 if (ControllerHandleIndex != NULL) {
70 *ControllerHandleIndex = 0xffffffff;
71 }
72
73 *HandleCount = 0;
74 *HandleBuffer = NULL;
75 *HandleType = NULL;
76
77 //
78 // Retrieve the list of all handles from the handle database
79 //
80
81 Status = refit_call5_wrapper(BS->LocateHandleBuffer,
82 AllHandles,
83 NULL,
84 NULL,
85 HandleCount,
86 HandleBuffer
87 );
88 if (EFI_ERROR (Status)) {
89 goto Error;
90 }
91
92 *HandleType = AllocatePool (*HandleCount * sizeof (UINT32));
93 if (*HandleType == NULL) {
94 goto Error;
95 }
96
97 for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
98 //
99 // Assume that the handle type is unknown
100 //
101 (*HandleType)[HandleIndex] = EFI_HANDLE_TYPE_UNKNOWN;
102
103 if (DriverBindingHandle != NULL &&
104 DriverBindingHandleIndex != NULL &&
105 (*HandleBuffer)[HandleIndex] == DriverBindingHandle
106 ) {
107 *DriverBindingHandleIndex = (UINT32) HandleIndex;
108 DriverBindingHandleIndexValid = TRUE;
109 }
110
111 if (ControllerHandle != NULL && ControllerHandleIndex != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
112 *ControllerHandleIndex = (UINT32) HandleIndex;
113 // ControllerHandleIndexValid = TRUE;
114 }
115
116 }
117
118 for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
119 //
120 // Retrieve the list of all the protocols on each handle
121 //
122
123 Status = refit_call3_wrapper(BS->ProtocolsPerHandle,
124 (*HandleBuffer)[HandleIndex],
125 &ProtocolGuidArray,
126 &ArrayCount
127 );
128 if (!EFI_ERROR (Status)) {
129
130 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
131
132 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) == 0) {
133 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_IMAGE_HANDLE;
134 }
135
136 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) == 0) {
137 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE;
138 }
139
140 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) == 0) {
141 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE;
142 }
143
144 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) == 0) {
145 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE;
146 }
147
148 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) == 0) {
149 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE;
150 }
151
152 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) == 0) {
153 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DEVICE_HANDLE;
154 }
155 //
156 // Retrieve the list of agents that have opened each protocol
157 //
158
159 Status = refit_call4_wrapper(BS->OpenProtocolInformation,
160 (*HandleBuffer)[HandleIndex],
161 ProtocolGuidArray[ProtocolIndex],
162 &OpenInfo,
163 &OpenInfoCount
164 );
165 if (!EFI_ERROR (Status)) {
166
167 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
168 if (DriverBindingHandle != NULL && OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
169 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
170 //
171 // Mark the device handle as being managed by the driver specified by DriverBindingHandle
172 //
173 (*HandleType)[HandleIndex] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE | EFI_HANDLE_TYPE_CONTROLLER_HANDLE);
174 //
175 // Mark the DriverBindingHandle as being a driver that is managing at least one controller
176 //
177 if (DriverBindingHandleIndexValid) {
178 (*HandleType)[*DriverBindingHandleIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER;
179 }
180 }
181
182 if ((
183 OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
184 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
185 ) {
186 //
187 // Mark the DriverBindingHandle as being a driver that is managing at least one child controller
188 //
189 if (DriverBindingHandleIndexValid) {
190 (*HandleType)[*DriverBindingHandleIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER;
191 }
192 }
193
194 if (ControllerHandle != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
195 if ((
196 OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
197 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
198 ) {
199 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
200 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].ControllerHandle) {
201 (*HandleType)[ChildIndex] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE | EFI_HANDLE_TYPE_CHILD_HANDLE);
202 }
203 }
204 }
205 }
206 }
207
208 if (DriverBindingHandle == NULL && OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
209 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
210 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
211 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
212 (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER;
213 }
214 }
215 }
216
217 if ((
218 OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
219 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
220 ) {
221 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_PARENT_HANDLE;
222 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
223 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
224 (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER;
225 }
226 }
227 }
228 }
229 }
230
231 MyFreePool (OpenInfo);
232 }
233 }
234
235 MyFreePool (ProtocolGuidArray);
236 }
237 }
238
239 return EFI_SUCCESS;
240
241 Error:
242 MyFreePool (*HandleType);
243 MyFreePool (*HandleBuffer);
244
245 *HandleCount = 0;
246 *HandleBuffer = NULL;
247 *HandleType = NULL;
248
249 return Status;
250 } /* EFI_STATUS LibScanHandleDatabase() */