]>
Commit | Line | Data |
---|---|---|
93e3992d | 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( | |
25ca163d | 342 | IN UINT8 HostControllerPI, |
93e3992d | 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) | |
93e3992d | 363 | && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP) |
93e3992d | 364 | )) { |
365 | return EFI_INVALID_PARAMETER; | |
366 | } | |
367 | ||
368 | if (HostControllerPI != 0xFF && | |
369 | HostControllerPI != 0x00 && | |
370 | HostControllerPI != 0x20) { | |
371 | return EFI_INVALID_PARAMETER; | |
372 | } | |
373 | ||
374 | // | |
375 | // Find the usb host controller firstly, then connect with the remaining device path | |
376 | // | |
377 | AtLeastOneConnected = FALSE; | |
378 | Status = gBS->LocateHandleBuffer ( | |
379 | ByProtocol, | |
380 | &gEfiPciIoProtocolGuid, | |
381 | NULL, | |
382 | &HandleArrayCount, | |
383 | &HandleArray | |
384 | ); | |
385 | if (!EFI_ERROR (Status)) { | |
386 | for (Index = 0; Index < HandleArrayCount; Index++) { | |
387 | Status = gBS->HandleProtocol ( | |
388 | HandleArray[Index], | |
389 | &gEfiPciIoProtocolGuid, | |
390 | (VOID **)&PciIo | |
391 | ); | |
392 | if (!EFI_ERROR (Status)) { | |
393 | // | |
394 | // Check whether the Pci device is the wanted usb host controller | |
395 | // | |
396 | Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); | |
397 | if (!EFI_ERROR (Status)) { | |
398 | if ((PCI_CLASS_SERIAL == Class[2]) && | |
399 | (PCI_CLASS_SERIAL_USB == Class[1])) { | |
400 | if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) { | |
401 | Status = gBS->ConnectController ( | |
402 | HandleArray[Index], | |
403 | NULL, | |
404 | RemainingDevicePath, | |
405 | FALSE | |
406 | ); | |
407 | if (!EFI_ERROR(Status)) { | |
408 | AtLeastOneConnected = TRUE; | |
409 | } | |
410 | } | |
411 | } | |
412 | } | |
413 | } | |
414 | } | |
415 | ||
416 | if (AtLeastOneConnected) { | |
417 | return EFI_SUCCESS; | |
418 | } | |
419 | } | |
420 | ||
421 | return EFI_NOT_FOUND; | |
422 | } |