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