]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/GenericBdsLib/BdsConnect.c
UEFI HII: Merge UEFI HII support changes from branch.
[mirror_edk2.git] / MdeModulePkg / Library / GenericBdsLib / BdsConnect.c
1 /** @file
2
3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 BdsConnect.c
15
16 Abstract:
17
18 BDS Lib functions which relate with connect the device
19
20
21 **/
22
23 #include "InternalBdsLib.h"
24
25
26 /**
27 This function will connect all the system driver to controller
28 first, and then special connect the default console, this make
29 sure all the system controller avialbe and the platform default
30 console connected.
31
32 None
33
34 @return None
35
36 **/
37 VOID
38 BdsLibConnectAll (
39 VOID
40 )
41 {
42 //
43 // Connect the platform console first
44 //
45 BdsLibConnectAllDefaultConsoles ();
46
47 //
48 // Generic way to connect all the drivers
49 //
50 BdsLibConnectAllDriversToAllControllers ();
51
52 //
53 // Here we have the assumption that we have already had
54 // platform default console
55 //
56 BdsLibConnectAllDefaultConsoles ();
57 }
58
59
60 /**
61 This function will connect all the system drivers to all controllers
62 first, and then connect all the console devices the system current
63 have. After this we should get all the device work and console avariable
64 if the system have console device.
65
66 None
67
68 @return None
69
70 **/
71 VOID
72 BdsLibGenericConnectAll (
73 VOID
74 )
75 {
76 //
77 // Most generic way to connect all the drivers
78 //
79 BdsLibConnectAllDriversToAllControllers ();
80 BdsLibConnectAllConsoles ();
81 }
82
83
84 /**
85 This function will create all handles associate with every device
86 path node. If the handle associate with one device path node can not
87 be created success, then still give one chance to do the dispatch,
88 which load the missing drivers if possible.
89
90 @param DevicePathToConnect The device path which will be connected, it can be
91 a multi-instance device path
92
93 @retval EFI_SUCCESS All handles associate with every device path node
94 have been created
95 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
96 @retval EFI_NOT_FOUND Create the handle associate with one device path
97 node failed
98
99 **/
100 EFI_STATUS
101 BdsLibConnectDevicePath (
102 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect
103 )
104 {
105 EFI_STATUS Status;
106 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
107 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
108 EFI_DEVICE_PATH_PROTOCOL *Instance;
109 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
110 EFI_DEVICE_PATH_PROTOCOL *Next;
111 EFI_HANDLE Handle;
112 EFI_HANDLE PreviousHandle;
113 UINTN Size;
114
115 if (DevicePathToConnect == NULL) {
116 return EFI_SUCCESS;
117 }
118
119 DevicePath = DuplicateDevicePath (DevicePathToConnect);
120 CopyOfDevicePath = DevicePath;
121 if (DevicePath == NULL) {
122 return EFI_OUT_OF_RESOURCES;
123 }
124
125 do {
126 //
127 // The outer loop handles multi instance device paths.
128 // Only console variables contain multiple instance device paths.
129 //
130 // After this call DevicePath points to the next Instance
131 //
132 Instance = GetNextDevicePathInstance (&DevicePath, &Size);
133 Next = Instance;
134 while (!IsDevicePathEndType (Next)) {
135 Next = NextDevicePathNode (Next);
136 }
137
138 SetDevicePathEndNode (Next);
139
140 //
141 // Start the real work of connect with RemainingDevicePath
142 //
143 PreviousHandle = NULL;
144 do {
145 //
146 // Find the handle that best matches the Device Path. If it is only a
147 // partial match the remaining part of the device path is returned in
148 // RemainingDevicePath.
149 //
150 RemainingDevicePath = Instance;
151 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
152
153 if (!EFI_ERROR (Status)) {
154 if (Handle == PreviousHandle) {
155 //
156 // If no forward progress is made try invoking the Dispatcher.
157 // A new FV may have been added to the system an new drivers
158 // may now be found.
159 // Status == EFI_SUCCESS means a driver was dispatched
160 // Status == EFI_NOT_FOUND means no new drivers were dispatched
161 //
162 Status = gDS->Dispatch ();
163 }
164
165 if (!EFI_ERROR (Status)) {
166 PreviousHandle = Handle;
167 //
168 // Connect all drivers that apply to Handle and RemainingDevicePath,
169 // the Recursive flag is FALSE so only one level will be expanded.
170 //
171 // Do not check the connect status here, if the connect controller fail,
172 // then still give the chance to do dispatch, because partial
173 // RemainingDevicepath may be in the new FV
174 //
175 // 1. If the connect fail, RemainingDevicepath and handle will not
176 // change, so next time will do the dispatch, then dispatch's status
177 // will take effect
178 // 2. If the connect success, the RemainingDevicepath and handle will
179 // change, then avoid the dispatch, we have chance to continue the
180 // next connection
181 //
182 gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
183 }
184 }
185 //
186 // Loop until RemainingDevicePath is an empty device path
187 //
188 } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
189
190 } while (DevicePath != NULL);
191
192 if (CopyOfDevicePath != NULL) {
193 gBS->FreePool (CopyOfDevicePath);
194 }
195 //
196 // All handle with DevicePath exists in the handle database
197 //
198 return Status;
199 }
200
201
202 /**
203 This function will connect all current system handles recursively. The
204 connection will finish until every handle's child handle created if it have.
205
206 None
207
208 @retval EFI_SUCCESS All handles and it's child handle have been
209 connected
210 @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
211
212 **/
213 EFI_STATUS
214 BdsLibConnectAllEfi (
215 VOID
216 )
217 {
218 EFI_STATUS Status;
219 UINTN HandleCount;
220 EFI_HANDLE *HandleBuffer;
221 UINTN Index;
222
223 Status = gBS->LocateHandleBuffer (
224 AllHandles,
225 NULL,
226 NULL,
227 &HandleCount,
228 &HandleBuffer
229 );
230 if (EFI_ERROR (Status)) {
231 return Status;
232 }
233
234 for (Index = 0; Index < HandleCount; Index++) {
235 Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
236 }
237
238 gBS->FreePool (HandleBuffer);
239
240 return EFI_SUCCESS;
241 }
242
243
244 /**
245 This function will disconnect all current system handles. The disconnection
246 will finish until every handle have been disconnected.
247
248 None
249
250 @retval EFI_SUCCESS All handles have been disconnected
251 @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
252
253 **/
254 EFI_STATUS
255 BdsLibDisconnectAllEfi (
256 VOID
257 )
258 {
259 EFI_STATUS Status;
260 UINTN HandleCount;
261 EFI_HANDLE *HandleBuffer;
262 UINTN Index;
263
264 //
265 // Disconnect all
266 //
267 Status = gBS->LocateHandleBuffer (
268 AllHandles,
269 NULL,
270 NULL,
271 &HandleCount,
272 &HandleBuffer
273 );
274 if (EFI_ERROR (Status)) {
275 return Status;
276 }
277
278 for (Index = 0; Index < HandleCount; Index++) {
279 Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
280 }
281
282 gBS->FreePool (HandleBuffer);
283
284 return EFI_SUCCESS;
285 }
286
287
288 /**
289 Connects all drivers to all controllers.
290 This function make sure all the current system driver will manage
291 the correspoinding controllers if have. And at the same time, make
292 sure all the system controllers have driver to manage it if have.
293
294 None
295
296 @return None
297
298 **/
299 VOID
300 BdsLibConnectAllDriversToAllControllers (
301 VOID
302 )
303 {
304 EFI_STATUS Status;
305
306 do {
307 //
308 // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
309 //
310 BdsLibConnectAllEfi ();
311
312 //
313 // Check to see if it's possible to dispatch an more DXE drivers.
314 // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
315 // If anything is Dispatched Status == EFI_SUCCESS and we will try
316 // the connect again.
317 //
318 Status = gDS->Dispatch ();
319
320 } while (!EFI_ERROR (Status));
321
322 }
323
324
325 /**
326 Connect the specific Usb device which match the short form device path,
327 and whose bus is determined by Host Controller (Uhci or Ehci)
328
329 @param HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci
330 (0xFF)
331 @param RemainingDevicePath a short-form device path that starts with the first
332 element being a USB WWID or a USB Class device
333 path
334
335 @return EFI_INVALID_PARAMETER
336 @return EFI_SUCCESS
337 @return EFI_NOT_FOUND
338
339 **/
340 EFI_STATUS
341 BdsLibConnectUsbDevByShortFormDP(
342 IN CHAR8 HostControllerPI,
343 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
344 )
345 {
346 EFI_STATUS Status;
347 EFI_HANDLE *HandleArray;
348 UINTN HandleArrayCount;
349 UINTN Index;
350 EFI_PCI_IO_PROTOCOL *PciIo;
351 UINT8 Class[3];
352 BOOLEAN AtLeastOneConnected;
353
354 //
355 // Check the passed in parameters
356 //
357 if (RemainingDevicePath == NULL) {
358 return EFI_INVALID_PARAMETER;
359 }
360
361 if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||
362 ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)
363 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
364 && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)
365 #endif
366 )) {
367 return EFI_INVALID_PARAMETER;
368 }
369
370 if (HostControllerPI != 0xFF &&
371 HostControllerPI != 0x00 &&
372 HostControllerPI != 0x20) {
373 return EFI_INVALID_PARAMETER;
374 }
375
376 //
377 // Find the usb host controller firstly, then connect with the remaining device path
378 //
379 AtLeastOneConnected = FALSE;
380 Status = gBS->LocateHandleBuffer (
381 ByProtocol,
382 &gEfiPciIoProtocolGuid,
383 NULL,
384 &HandleArrayCount,
385 &HandleArray
386 );
387 if (!EFI_ERROR (Status)) {
388 for (Index = 0; Index < HandleArrayCount; Index++) {
389 Status = gBS->HandleProtocol (
390 HandleArray[Index],
391 &gEfiPciIoProtocolGuid,
392 (VOID **)&PciIo
393 );
394 if (!EFI_ERROR (Status)) {
395 //
396 // Check whether the Pci device is the wanted usb host controller
397 //
398 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
399 if (!EFI_ERROR (Status)) {
400 if ((PCI_CLASS_SERIAL == Class[2]) &&
401 (PCI_CLASS_SERIAL_USB == Class[1])) {
402 if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {
403 Status = gBS->ConnectController (
404 HandleArray[Index],
405 NULL,
406 RemainingDevicePath,
407 FALSE
408 );
409 if (!EFI_ERROR(Status)) {
410 AtLeastOneConnected = TRUE;
411 }
412 }
413 }
414 }
415 }
416 }
417
418 if (AtLeastOneConnected) {
419 return EFI_SUCCESS;
420 }
421 }
422
423 return EFI_NOT_FOUND;
424 }