]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmConnect.c
1 /** @file
2 Library functions which relate with connecting the device.
3
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "InternalBm.h"
10
11 /**
12 Connect all the drivers to all the controllers.
13
14 This function makes sure all the current system drivers manage the correspoinding
15 controllers if have. And at the same time, makes sure all the system controllers
16 have driver to manage it if have.
17 **/
18 VOID
19 BmConnectAllDriversToAllControllers (
20 VOID
21 )
22 {
23 EFI_STATUS Status;
24 UINTN HandleCount;
25 EFI_HANDLE *HandleBuffer;
26 UINTN Index;
27
28 do {
29 //
30 // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
31 //
32 gBS->LocateHandleBuffer (
33 AllHandles,
34 NULL,
35 NULL,
36 &HandleCount,
37 &HandleBuffer
38 );
39
40 for (Index = 0; Index < HandleCount; Index++) {
41 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
42 }
43
44 if (HandleBuffer != NULL) {
45 FreePool (HandleBuffer);
46 }
47
48 //
49 // Check to see if it's possible to dispatch an more DXE drivers.
50 // The above code may have made new DXE drivers show up.
51 // If any new driver is dispatched (Status == EFI_SUCCESS) and we will try
52 // the connect again.
53 //
54 Status = gDS->Dispatch ();
55 } while (!EFI_ERROR (Status));
56 }
57
58 /**
59 This function will connect all the system driver to controller
60 first, and then special connect the default console, this make
61 sure all the system controller available and the platform default
62 console connected.
63
64 **/
65 VOID
66 EFIAPI
67 EfiBootManagerConnectAll (
68 VOID
69 )
70 {
71 //
72 // Connect the platform console first
73 //
74 EfiBootManagerConnectAllDefaultConsoles ();
75
76 //
77 // Generic way to connect all the drivers
78 //
79 BmConnectAllDriversToAllControllers ();
80
81 //
82 // Here we have the assumption that we have already had
83 // platform default console
84 //
85 EfiBootManagerConnectAllDefaultConsoles ();
86 }
87
88 /**
89 This function will create all handles associate with every device
90 path node. If the handle associate with one device path node can not
91 be created successfully, then still give chance to do the dispatch,
92 which load the missing drivers if possible.
93
94 @param DevicePathToConnect The device path which will be connected, it can be
95 a multi-instance device path
96 @param MatchingHandle Return the controller handle closest to the DevicePathToConnect
97
98 @retval EFI_SUCCESS All handles associate with every device path node
99 have been created.
100 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles.
101 @retval EFI_NOT_FOUND Create the handle associate with one device path
102 node failed.
103 @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device
104 drivers on the DevicePath.
105 **/
106 EFI_STATUS
107 EFIAPI
108 EfiBootManagerConnectDevicePath (
109 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
110 OUT EFI_HANDLE *MatchingHandle OPTIONAL
111 )
112 {
113 EFI_STATUS Status;
114 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
115 EFI_HANDLE Handle;
116 EFI_HANDLE PreviousHandle;
117 EFI_TPL CurrentTpl;
118
119 if (DevicePathToConnect == NULL) {
120 return EFI_INVALID_PARAMETER;
121 }
122
123 CurrentTpl = EfiGetCurrentTpl ();
124 //
125 // Start the real work of connect with RemainingDevicePath
126 //
127 PreviousHandle = NULL;
128 do {
129 //
130 // Find the handle that best matches the Device Path. If it is only a
131 // partial match the remaining part of the device path is returned in
132 // RemainingDevicePath.
133 //
134 RemainingDevicePath = DevicePathToConnect;
135 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
136 if (!EFI_ERROR (Status)) {
137 if (Handle == PreviousHandle) {
138 //
139 // If no forward progress is made try invoking the Dispatcher.
140 // A new FV may have been added to the system an new drivers
141 // may now be found.
142 // Status == EFI_SUCCESS means a driver was dispatched
143 // Status == EFI_NOT_FOUND means no new drivers were dispatched
144 //
145 if (CurrentTpl == TPL_APPLICATION) {
146 Status = gDS->Dispatch ();
147 } else {
148 //
149 // Always return EFI_NOT_FOUND here
150 // to prevent dead loop when control handle is found but connection failded case
151 //
152 Status = EFI_NOT_FOUND;
153 }
154 }
155
156 if (!EFI_ERROR (Status)) {
157 PreviousHandle = Handle;
158 //
159 // Connect all drivers that apply to Handle and RemainingDevicePath,
160 // the Recursive flag is FALSE so only one level will be expanded.
161 //
162 // If ConnectController fails to find a driver, then still give the chance to
163 // do dispatch, because partial RemainingDevicePath may be in the new FV
164 //
165 // 1. If the connect fail, RemainingDevicepath and handle will not
166 // change, so next time will do the dispatch, then dispatch's status
167 // will take effect
168 // 2. If the connect success, the RemainingDevicepath and handle will
169 // change, then avoid the dispatch, we have chance to continue the
170 // next connection
171 //
172 Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
173 if (Status == EFI_NOT_FOUND) {
174 Status = EFI_SUCCESS;
175 }
176
177 if (MatchingHandle != NULL) {
178 *MatchingHandle = Handle;
179 }
180 }
181 }
182
183 //
184 // Loop until RemainingDevicePath is an empty device path
185 //
186 } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
187
188 ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));
189
190 return Status;
191 }
192
193 /**
194 This function will disconnect all current system handles.
195
196 gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
197 If handle is a bus type handle, all childrens also are disconnected recursively by
198 gBS->DisconnectController().
199 **/
200 VOID
201 EFIAPI
202 EfiBootManagerDisconnectAll (
203 VOID
204 )
205 {
206 UINTN HandleCount;
207 EFI_HANDLE *HandleBuffer;
208 UINTN Index;
209
210 //
211 // Disconnect all
212 //
213 gBS->LocateHandleBuffer (
214 AllHandles,
215 NULL,
216 NULL,
217 &HandleCount,
218 &HandleBuffer
219 );
220 for (Index = 0; Index < HandleCount; Index++) {
221 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
222 }
223
224 if (HandleBuffer != NULL) {
225 FreePool (HandleBuffer);
226 }
227 }
228
229 /**
230 Connect the specific Usb device which match the short form device path,
231 and whose bus is determined by Host Controller (Uhci or Ehci).
232
233 @param DevicePath A short-form device path that starts with the first
234 element being a USB WWID or a USB Class device
235 path
236
237 @return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
238 DevicePath is not a USB device path.
239
240 @return EFI_SUCCESS Success to connect USB device
241 @return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
242
243 **/
244 EFI_STATUS
245 BmConnectUsbShortFormDevicePath (
246 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
247 )
248 {
249 EFI_STATUS Status;
250 EFI_HANDLE *Handles;
251 UINTN HandleCount;
252 UINTN Index;
253 EFI_PCI_IO_PROTOCOL *PciIo;
254 UINT8 Class[3];
255 BOOLEAN AtLeastOneConnected;
256
257 //
258 // Check the passed in parameters
259 //
260 if (DevicePath == NULL) {
261 return EFI_INVALID_PARAMETER;
262 }
263
264 if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
265 ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
266 )
267 {
268 return EFI_INVALID_PARAMETER;
269 }
270
271 //
272 // Find the usb host controller firstly, then connect with the remaining device path
273 //
274 AtLeastOneConnected = FALSE;
275 Status = gBS->LocateHandleBuffer (
276 ByProtocol,
277 &gEfiPciIoProtocolGuid,
278 NULL,
279 &HandleCount,
280 &Handles
281 );
282 if (!EFI_ERROR (Status)) {
283 for (Index = 0; Index < HandleCount; Index++) {
284 Status = gBS->HandleProtocol (
285 Handles[Index],
286 &gEfiPciIoProtocolGuid,
287 (VOID **)&PciIo
288 );
289 if (!EFI_ERROR (Status)) {
290 //
291 // Check whether the Pci device is the wanted usb host controller
292 //
293 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
294 if (!EFI_ERROR (Status) &&
295 ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
296 )
297 {
298 Status = gBS->ConnectController (
299 Handles[Index],
300 NULL,
301 DevicePath,
302 FALSE
303 );
304 if (!EFI_ERROR (Status)) {
305 AtLeastOneConnected = TRUE;
306 }
307 }
308 }
309 }
310
311 if (Handles != NULL) {
312 FreePool (Handles);
313 }
314 }
315
316 return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
317 }