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:
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.
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.
21 #include "driver_support.h"
22 #include "../include/refit_call_wrapper.h"
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 }};
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....
40 LibScanHandleDatabase (
41 EFI_HANDLE DriverBindingHandle
, OPTIONAL
42 UINT32
*DriverBindingHandleIndex
, OPTIONAL
43 EFI_HANDLE ControllerHandle
, OPTIONAL
44 UINT32
*ControllerHandleIndex
, OPTIONAL
46 EFI_HANDLE
**HandleBuffer
,
53 EFI_GUID
**ProtocolGuidArray
;
56 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
60 BOOLEAN DriverBindingHandleIndexValid
;
61 // BOOLEAN ControllerHandleIndexValid;
63 DriverBindingHandleIndexValid
= FALSE
;
64 if (DriverBindingHandleIndex
!= NULL
) {
65 *DriverBindingHandleIndex
= 0xffffffff;
68 // ControllerHandleIndexValid = FALSE;
69 if (ControllerHandleIndex
!= NULL
) {
70 *ControllerHandleIndex
= 0xffffffff;
78 // Retrieve the list of all handles from the handle database
81 Status
= refit_call5_wrapper(BS
->LocateHandleBuffer
,
88 if (EFI_ERROR (Status
)) {
92 *HandleType
= AllocatePool (*HandleCount
* sizeof (UINT32
));
93 if (*HandleType
== NULL
) {
97 for (HandleIndex
= 0; HandleIndex
< *HandleCount
; HandleIndex
++) {
99 // Assume that the handle type is unknown
101 (*HandleType
)[HandleIndex
] = EFI_HANDLE_TYPE_UNKNOWN
;
103 if (DriverBindingHandle
!= NULL
&&
104 DriverBindingHandleIndex
!= NULL
&&
105 (*HandleBuffer
)[HandleIndex
] == DriverBindingHandle
107 *DriverBindingHandleIndex
= (UINT32
) HandleIndex
;
108 DriverBindingHandleIndexValid
= TRUE
;
111 if (ControllerHandle
!= NULL
&& ControllerHandleIndex
!= NULL
&& (*HandleBuffer
)[HandleIndex
] == ControllerHandle
) {
112 *ControllerHandleIndex
= (UINT32
) HandleIndex
;
113 // ControllerHandleIndexValid = TRUE;
118 for (HandleIndex
= 0; HandleIndex
< *HandleCount
; HandleIndex
++) {
120 // Retrieve the list of all the protocols on each handle
123 Status
= refit_call3_wrapper(BS
->ProtocolsPerHandle
,
124 (*HandleBuffer
)[HandleIndex
],
128 if (!EFI_ERROR (Status
)) {
130 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
132 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiLoadedImageProtocolGuid
) == 0) {
133 (*HandleType
)[HandleIndex
] |= EFI_HANDLE_TYPE_IMAGE_HANDLE
;
136 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverBindingProtocolGuid
) == 0) {
137 (*HandleType
)[HandleIndex
] |= EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE
;
140 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverConfigurationProtocolGuid
) == 0) {
141 (*HandleType
)[HandleIndex
] |= EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE
;
144 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverDiagnosticsProtocolGuid
) == 0) {
145 (*HandleType
)[HandleIndex
] |= EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE
;
148 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiComponentNameProtocolGuid
) == 0) {
149 (*HandleType
)[HandleIndex
] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE
;
152 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDevicePathProtocolGuid
) == 0) {
153 (*HandleType
)[HandleIndex
] |= EFI_HANDLE_TYPE_DEVICE_HANDLE
;
156 // Retrieve the list of agents that have opened each protocol
159 Status
= refit_call4_wrapper(BS
->OpenProtocolInformation
,
160 (*HandleBuffer
)[HandleIndex
],
161 ProtocolGuidArray
[ProtocolIndex
],
165 if (!EFI_ERROR (Status
)) {
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
) {
171 // Mark the device handle as being managed by the driver specified by DriverBindingHandle
173 (*HandleType
)[HandleIndex
] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE
| EFI_HANDLE_TYPE_CONTROLLER_HANDLE
);
175 // Mark the DriverBindingHandle as being a driver that is managing at least one controller
177 if (DriverBindingHandleIndexValid
) {
178 (*HandleType
)[*DriverBindingHandleIndex
] |= EFI_HANDLE_TYPE_DEVICE_DRIVER
;
183 OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
184 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
187 // Mark the DriverBindingHandle as being a driver that is managing at least one child controller
189 if (DriverBindingHandleIndexValid
) {
190 (*HandleType
)[*DriverBindingHandleIndex
] |= EFI_HANDLE_TYPE_BUS_DRIVER
;
194 if (ControllerHandle
!= NULL
&& (*HandleBuffer
)[HandleIndex
] == ControllerHandle
) {
196 OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
197 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
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
);
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
;
218 OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
219 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
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
;
235 FreePool (ProtocolGuidArray
);
242 if (*HandleType
!= NULL
) {
243 FreePool (*HandleType
);
246 if (*HandleBuffer
!= NULL
) {
247 FreePool (*HandleBuffer
);
251 *HandleBuffer
= NULL
;
255 } /* EFI_STATUS LibScanHandleDatabase() */