]> code.delx.au - refind/blob - EfiLib/BdsConnect.c
Improvements to refind-mkdefault, including packaging files.
[refind] / EfiLib / BdsConnect.c
1 /** @file
2 BDS Lib functions which relate with connect the device
3
4 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Platform.h"
16
17
18 EFI_STATUS ScanDeviceHandles(EFI_HANDLE ControllerHandle,
19 UINTN *HandleCount,
20 EFI_HANDLE **HandleBuffer,
21 UINT32 **HandleType)
22 {
23 EFI_STATUS Status;
24 UINTN HandleIndex;
25 EFI_GUID **ProtocolGuidArray;
26 UINTN ArrayCount;
27 UINTN ProtocolIndex;
28 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
29 UINTN OpenInfoCount;
30 UINTN OpenInfoIndex;
31 UINTN ChildIndex;
32
33 *HandleCount = 0;
34 *HandleBuffer = NULL;
35 *HandleType = NULL;
36
37 //
38 // Retrieve the list of all handles from the handle database
39 //
40 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, HandleCount, HandleBuffer);
41 if (EFI_ERROR (Status)) goto Error;
42
43 *HandleType = AllocatePool (*HandleCount * sizeof (UINT32));
44 if (*HandleType == NULL) goto Error;
45
46 for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
47 (*HandleType)[HandleIndex] = EFI_HANDLE_TYPE_UNKNOWN;
48 //
49 // Retrieve the list of all the protocols on each handle
50 //
51 Status = gBS->ProtocolsPerHandle (
52 (*HandleBuffer)[HandleIndex],
53 &ProtocolGuidArray,
54 &ArrayCount
55 );
56 if (!EFI_ERROR (Status)) {
57 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++)
58 {
59
60 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid))
61 {
62 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_IMAGE_HANDLE;
63 }
64
65 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid))
66 {
67 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE;
68 }
69
70 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid))
71 {
72 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE;
73 }
74
75 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid))
76 {
77 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE;
78 }
79
80 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid))
81 {
82 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE;
83 }
84
85 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) )
86 {
87 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE;
88 }
89
90 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid))
91 {
92 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DEVICE_HANDLE;
93 }
94
95 //
96 // Retrieve the list of agents that have opened each protocol
97 //
98 Status = gBS->OpenProtocolInformation (
99 (*HandleBuffer)[HandleIndex],
100 ProtocolGuidArray[ProtocolIndex],
101 &OpenInfo,
102 &OpenInfoCount
103 );
104 if (!EFI_ERROR (Status)) {
105
106 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
107
108 if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle)
109 {
110 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER)
111 {
112 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++)
113 {
114 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle)
115 {
116 (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER;
117 }
118 }
119 }
120
121 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
122 {
123 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_PARENT_HANDLE;
124 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++)
125 {
126 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle)
127 {
128 (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER;
129 }
130 }
131 }
132 }
133 }
134
135 FreePool (OpenInfo);
136 }
137 }
138
139 FreePool (ProtocolGuidArray);
140 }
141 }
142
143 return EFI_SUCCESS;
144
145 Error:
146 if (*HandleType != NULL) {
147 FreePool (*HandleType);
148 }
149
150 if (*HandleBuffer != NULL) {
151 FreePool (*HandleBuffer);
152 }
153
154 *HandleCount = 0;
155 *HandleBuffer = NULL;
156 *HandleType = NULL;
157
158 return Status;
159 }
160
161
162
163 EFI_STATUS BdsLibConnectMostlyAllEfi()
164 {
165 EFI_STATUS Status;
166 UINTN AllHandleCount;
167 EFI_HANDLE *AllHandleBuffer;
168 UINTN Index;
169 UINTN HandleCount;
170 EFI_HANDLE *HandleBuffer;
171 UINT32 *HandleType;
172 UINTN HandleIndex;
173 BOOLEAN Parent;
174 BOOLEAN Device;
175 EFI_PCI_IO_PROTOCOL* PciIo;
176 PCI_TYPE00 Pci;
177
178
179 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &AllHandleCount, &AllHandleBuffer);
180 if (CheckError(Status, L"locating handle buffer"))
181 return Status;
182
183 for (Index = 0; Index < AllHandleCount; Index++)
184 {
185 Status = ScanDeviceHandles(AllHandleBuffer[Index], &HandleCount, &HandleBuffer, &HandleType);
186
187 if (EFI_ERROR (Status))
188 goto Done;
189
190 Device = TRUE;
191
192 if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE)
193 Device = FALSE;
194 if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE)
195 Device = FALSE;
196
197 if (Device)
198 {
199 Parent = FALSE;
200 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++)
201 {
202 if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE)
203 Parent = TRUE;
204 }
205
206 if (!Parent)
207 {
208 if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE)
209 {
210 Status = gBS->HandleProtocol (AllHandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);
211 if (!EFI_ERROR (Status))
212 {
213 Status = PciIo->Pci.Read (PciIo,EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
214 if (!EFI_ERROR (Status))
215 {
216 if(IS_PCI_VGA(&Pci)==TRUE)
217 {
218 gBS->DisconnectController(AllHandleBuffer[Index], NULL, NULL);
219 }
220 }
221 }
222 Status = gBS->ConnectController(AllHandleBuffer[Index], NULL, NULL, TRUE);
223 }
224 }
225 }
226
227 FreePool (HandleBuffer);
228 FreePool (HandleType);
229 }
230
231 Done:
232 FreePool (AllHandleBuffer);
233 return Status;
234 }
235
236
237
238 /**
239 Connects all drivers to all controllers.
240 This function make sure all the current system driver will manage
241 the correspoinding controllers if have. And at the same time, make
242 sure all the system controllers have driver to manage it if have.
243
244 **/
245 VOID
246 EFIAPI
247 BdsLibConnectAllDriversToAllControllers (
248 VOID
249 )
250 {
251 EFI_STATUS Status;
252
253 do {
254 //
255 // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
256 //
257 //BdsLibConnectAllEfi ();
258 BdsLibConnectMostlyAllEfi ();
259
260 //
261 // Check to see if it's possible to dispatch an more DXE drivers.
262 // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
263 // If anything is Dispatched Status == EFI_SUCCESS and we will try
264 // the connect again.
265 //
266 Status = gDS->Dispatch ();
267
268 } while (!EFI_ERROR (Status));
269
270 }