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