]>
Commit | Line | Data |
---|---|---|
067ed98a RN |
1 | /** @file\r |
2 | Library functions which contain all the code to connect console device.\r | |
3 | \r | |
d1102dba | 4 | Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r |
fad21b7c | 5 | (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r |
9d510e61 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
067ed98a RN |
7 | \r |
8 | **/\r | |
9 | \r | |
10 | #include "InternalBm.h"\r | |
11 | \r | |
1436aea4 | 12 | CHAR16 *mConVarName[] = {\r |
067ed98a RN |
13 | L"ConIn",\r |
14 | L"ConOut",\r | |
15 | L"ErrOut",\r | |
16 | L"ConInDev",\r | |
17 | L"ConOutDev",\r | |
18 | L"ErrOutDev"\r | |
19 | };\r | |
20 | \r | |
21 | /**\r | |
22 | Search out the video controller.\r | |
23 | \r | |
24 | @return PCI device path of the video controller.\r | |
25 | **/\r | |
26 | EFI_HANDLE\r | |
27 | BmGetVideoController (\r | |
28 | VOID\r | |
29 | )\r | |
30 | {\r | |
1436aea4 MK |
31 | EFI_STATUS Status;\r |
32 | UINTN RootBridgeHandleCount;\r | |
33 | EFI_HANDLE *RootBridgeHandleBuffer;\r | |
34 | UINTN HandleCount;\r | |
35 | EFI_HANDLE *HandleBuffer;\r | |
36 | UINTN RootBridgeIndex;\r | |
37 | UINTN Index;\r | |
38 | EFI_HANDLE VideoController;\r | |
39 | EFI_PCI_IO_PROTOCOL *PciIo;\r | |
40 | PCI_TYPE00 Pci;\r | |
067ed98a RN |
41 | \r |
42 | //\r | |
43 | // Make all the PCI_IO protocols show up\r | |
44 | //\r | |
45 | Status = gBS->LocateHandleBuffer (\r | |
46 | ByProtocol,\r | |
47 | &gEfiPciRootBridgeIoProtocolGuid,\r | |
48 | NULL,\r | |
49 | &RootBridgeHandleCount,\r | |
50 | &RootBridgeHandleBuffer\r | |
51 | );\r | |
52 | if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {\r | |
53 | return NULL;\r | |
54 | }\r | |
55 | \r | |
56 | VideoController = NULL;\r | |
57 | for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {\r | |
58 | gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);\r | |
59 | \r | |
60 | //\r | |
61 | // Start to check all the pci io to find the first video controller\r | |
62 | //\r | |
63 | Status = gBS->LocateHandleBuffer (\r | |
64 | ByProtocol,\r | |
65 | &gEfiPciIoProtocolGuid,\r | |
66 | NULL,\r | |
67 | &HandleCount,\r | |
68 | &HandleBuffer\r | |
69 | );\r | |
70 | if (EFI_ERROR (Status)) {\r | |
71 | continue;\r | |
72 | }\r | |
73 | \r | |
74 | for (Index = 0; Index < HandleCount; Index++) {\r | |
1436aea4 | 75 | Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&PciIo);\r |
067ed98a RN |
76 | if (!EFI_ERROR (Status)) {\r |
77 | //\r | |
78 | // Check for all video controller\r | |
79 | //\r | |
80 | Status = PciIo->Pci.Read (\r | |
1436aea4 MK |
81 | PciIo,\r |
82 | EfiPciIoWidthUint32,\r | |
83 | 0,\r | |
84 | sizeof (Pci) / sizeof (UINT32),\r | |
85 | &Pci\r | |
86 | );\r | |
067ed98a RN |
87 | if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {\r |
88 | // TODO: use IS_PCI_DISPLAY??\r | |
89 | VideoController = HandleBuffer[Index];\r | |
90 | break;\r | |
91 | }\r | |
92 | }\r | |
93 | }\r | |
1436aea4 | 94 | \r |
067ed98a RN |
95 | FreePool (HandleBuffer);\r |
96 | \r | |
97 | if (VideoController != NULL) {\r | |
98 | break;\r | |
99 | }\r | |
100 | }\r | |
1436aea4 | 101 | \r |
067ed98a | 102 | FreePool (RootBridgeHandleBuffer);\r |
d1102dba | 103 | \r |
067ed98a RN |
104 | return VideoController;\r |
105 | }\r | |
106 | \r | |
107 | /**\r | |
d1102dba | 108 | Query all the children of VideoController and return the device paths of all the\r |
067ed98a RN |
109 | children that support GraphicsOutput protocol.\r |
110 | \r | |
111 | @param VideoController PCI handle of video controller.\r | |
112 | \r | |
113 | @return Device paths of all the children that support GraphicsOutput protocol.\r | |
114 | **/\r | |
115 | EFI_DEVICE_PATH_PROTOCOL *\r | |
116 | EFIAPI\r | |
117 | EfiBootManagerGetGopDevicePath (\r | |
1436aea4 | 118 | IN EFI_HANDLE VideoController\r |
067ed98a RN |
119 | )\r |
120 | {\r | |
121 | UINTN Index;\r | |
122 | EFI_STATUS Status;\r | |
123 | EFI_GUID **ProtocolBuffer;\r | |
124 | UINTN ProtocolBufferCount;\r | |
125 | UINTN ProtocolIndex;\r | |
126 | EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r | |
127 | UINTN EntryCount;\r | |
128 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r | |
129 | EFI_DEVICE_PATH_PROTOCOL *Next;\r | |
130 | EFI_DEVICE_PATH_PROTOCOL *Previous;\r | |
131 | EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r | |
132 | EFI_DEVICE_PATH_PROTOCOL *GopPool;\r | |
133 | EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;\r | |
134 | \r | |
067ed98a RN |
135 | Status = gBS->ProtocolsPerHandle (\r |
136 | VideoController,\r | |
137 | &ProtocolBuffer,\r | |
138 | &ProtocolBufferCount\r | |
139 | );\r | |
140 | if (EFI_ERROR (Status)) {\r | |
141 | return NULL;\r | |
142 | }\r | |
143 | \r | |
144 | GopPool = NULL;\r | |
145 | \r | |
146 | for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) {\r | |
147 | Status = gBS->OpenProtocolInformation (\r | |
148 | VideoController,\r | |
149 | ProtocolBuffer[ProtocolIndex],\r | |
150 | &OpenInfoBuffer,\r | |
151 | &EntryCount\r | |
152 | );\r | |
153 | if (EFI_ERROR (Status)) {\r | |
154 | continue;\r | |
155 | }\r | |
156 | \r | |
157 | for (Index = 0; Index < EntryCount; Index++) {\r | |
158 | //\r | |
159 | // Query all the children\r | |
160 | //\r | |
161 | if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r | |
162 | Status = gBS->OpenProtocol (\r | |
163 | OpenInfoBuffer[Index].ControllerHandle,\r | |
164 | &gEfiDevicePathProtocolGuid,\r | |
1436aea4 | 165 | (VOID **)&DevicePath,\r |
067ed98a RN |
166 | NULL,\r |
167 | NULL,\r | |
168 | EFI_OPEN_PROTOCOL_GET_PROTOCOL\r | |
169 | );\r | |
170 | if (EFI_ERROR (Status)) {\r | |
171 | continue;\r | |
172 | }\r | |
173 | \r | |
174 | Previous = NULL;\r | |
175 | for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {\r | |
176 | Previous = Next;\r | |
177 | }\r | |
1436aea4 | 178 | \r |
067ed98a RN |
179 | ASSERT (Previous != NULL);\r |
180 | \r | |
1436aea4 | 181 | if ((DevicePathType (Previous) == ACPI_DEVICE_PATH) && (DevicePathSubType (Previous) == ACPI_ADR_DP)) {\r |
067ed98a RN |
182 | Status = gBS->OpenProtocol (\r |
183 | OpenInfoBuffer[Index].ControllerHandle,\r | |
184 | &gEfiGraphicsOutputProtocolGuid,\r | |
185 | NULL,\r | |
186 | NULL,\r | |
187 | NULL,\r | |
188 | EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r | |
189 | );\r | |
190 | if (!EFI_ERROR (Status)) {\r | |
191 | //\r | |
192 | // Append the device path to GOP pool when there is GOP protocol installed.\r | |
193 | //\r | |
194 | TempDevicePath = GopPool;\r | |
1436aea4 | 195 | GopPool = AppendDevicePathInstance (GopPool, DevicePath);\r |
067ed98a RN |
196 | gBS->FreePool (TempDevicePath);\r |
197 | }\r | |
198 | }\r | |
199 | \r | |
1436aea4 | 200 | if ((DevicePathType (Previous) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (Previous) == HW_CONTROLLER_DP)) {\r |
067ed98a RN |
201 | //\r |
202 | // Recursively look for GOP child in this frame buffer handle\r | |
203 | //\r | |
87000d77 | 204 | DEBUG ((DEBUG_INFO, "[Bds] Looking for GOP child deeper ... \n"));\r |
1436aea4 | 205 | TempDevicePath = GopPool;\r |
067ed98a | 206 | ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle);\r |
1436aea4 | 207 | GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath);\r |
067ed98a RN |
208 | gBS->FreePool (ReturnDevicePath);\r |
209 | gBS->FreePool (TempDevicePath);\r | |
210 | }\r | |
211 | }\r | |
212 | }\r | |
213 | \r | |
214 | FreePool (OpenInfoBuffer);\r | |
215 | }\r | |
216 | \r | |
217 | FreePool (ProtocolBuffer);\r | |
218 | \r | |
219 | return GopPool;\r | |
220 | }\r | |
221 | \r | |
222 | /**\r | |
223 | Connect the platform active active video controller.\r | |
224 | \r | |
225 | @param VideoController PCI handle of video controller.\r | |
226 | \r | |
227 | @retval EFI_NOT_FOUND There is no active video controller.\r | |
228 | @retval EFI_SUCCESS The video controller is connected.\r | |
229 | **/\r | |
230 | EFI_STATUS\r | |
231 | EFIAPI\r | |
232 | EfiBootManagerConnectVideoController (\r | |
1436aea4 | 233 | EFI_HANDLE VideoController OPTIONAL\r |
067ed98a RN |
234 | )\r |
235 | {\r | |
1436aea4 | 236 | EFI_DEVICE_PATH_PROTOCOL *Gop;\r |
d1102dba | 237 | \r |
067ed98a RN |
238 | if (VideoController == NULL) {\r |
239 | //\r | |
240 | // Get the platform vga device\r | |
241 | //\r | |
242 | VideoController = BmGetVideoController ();\r | |
243 | }\r | |
d1102dba | 244 | \r |
067ed98a RN |
245 | if (VideoController == NULL) {\r |
246 | return EFI_NOT_FOUND;\r | |
247 | }\r | |
248 | \r | |
249 | //\r | |
3b28e744 | 250 | // Try to connect the PCI device path, so that GOP driver could start on this\r |
067ed98a | 251 | // device and create child handles with GraphicsOutput Protocol installed\r |
d1102dba | 252 | // on them, then we get device paths of these child handles and select\r |
067ed98a RN |
253 | // them as possible console device.\r |
254 | //\r | |
255 | gBS->ConnectController (VideoController, NULL, NULL, FALSE);\r | |
256 | \r | |
257 | Gop = EfiBootManagerGetGopDevicePath (VideoController);\r | |
258 | if (Gop == NULL) {\r | |
259 | return EFI_NOT_FOUND;\r | |
260 | }\r | |
261 | \r | |
262 | EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);\r | |
263 | FreePool (Gop);\r | |
264 | \r | |
265 | //\r | |
266 | // Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.\r | |
267 | //\r | |
268 | return gBS->ConnectController (VideoController, NULL, NULL, TRUE);\r | |
269 | }\r | |
270 | \r | |
271 | /**\r | |
272 | Fill console handle in System Table if there are no valid console handle in.\r | |
273 | \r | |
274 | Firstly, check the validation of console handle in System Table. If it is invalid,\r | |
d1102dba | 275 | update it by the first console device handle from EFI console variable.\r |
067ed98a RN |
276 | \r |
277 | @param VarName The name of the EFI console variable.\r | |
278 | @param ConsoleGuid Specified Console protocol GUID.\r | |
d1102dba | 279 | @param ConsoleHandle On IN, console handle in System Table to be checked.\r |
067ed98a | 280 | On OUT, new console handle in system table.\r |
d1102dba | 281 | @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.\r |
067ed98a RN |
282 | On OUT, new console protocol on new console handle in system table.\r |
283 | \r | |
284 | @retval TRUE System Table has been updated.\r | |
285 | @retval FALSE System Table hasn't been updated.\r | |
286 | \r | |
287 | **/\r | |
d1102dba | 288 | BOOLEAN\r |
067ed98a | 289 | BmUpdateSystemTableConsole (\r |
1436aea4 MK |
290 | IN CHAR16 *VarName,\r |
291 | IN EFI_GUID *ConsoleGuid,\r | |
292 | IN OUT EFI_HANDLE *ConsoleHandle,\r | |
293 | IN OUT VOID **ProtocolInterface\r | |
067ed98a RN |
294 | )\r |
295 | {\r | |
1436aea4 MK |
296 | EFI_STATUS Status;\r |
297 | UINTN DevicePathSize;\r | |
298 | EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r | |
299 | EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r | |
300 | EFI_DEVICE_PATH_PROTOCOL *Instance;\r | |
301 | EFI_DEVICE_PATH_PROTOCOL *FullInstance;\r | |
302 | VOID *Interface;\r | |
303 | EFI_HANDLE NewHandle;\r | |
304 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r | |
067ed98a RN |
305 | \r |
306 | ASSERT (VarName != NULL);\r | |
307 | ASSERT (ConsoleHandle != NULL);\r | |
308 | ASSERT (ConsoleGuid != NULL);\r | |
309 | ASSERT (ProtocolInterface != NULL);\r | |
310 | \r | |
311 | if (*ConsoleHandle != NULL) {\r | |
312 | Status = gBS->HandleProtocol (\r | |
1436aea4 MK |
313 | *ConsoleHandle,\r |
314 | ConsoleGuid,\r | |
315 | &Interface\r | |
316 | );\r | |
317 | if ((Status == EFI_SUCCESS) && (Interface == *ProtocolInterface)) {\r | |
067ed98a RN |
318 | //\r |
319 | // If ConsoleHandle is valid and console protocol on this handle also\r | |
320 | // also matched, just return.\r | |
321 | //\r | |
322 | return FALSE;\r | |
323 | }\r | |
324 | }\r | |
d1102dba | 325 | \r |
067ed98a RN |
326 | //\r |
327 | // Get all possible consoles device path from EFI variable\r | |
328 | //\r | |
1436aea4 | 329 | GetEfiGlobalVariable2 (VarName, (VOID **)&VarConsole, NULL);\r |
067ed98a RN |
330 | if (VarConsole == NULL) {\r |
331 | //\r | |
332 | // If there is no any console device, just return.\r | |
333 | //\r | |
334 | return FALSE;\r | |
335 | }\r | |
336 | \r | |
337 | FullDevicePath = VarConsole;\r | |
338 | \r | |
339 | do {\r | |
340 | //\r | |
341 | // Check every instance of the console variable\r | |
342 | //\r | |
1436aea4 | 343 | Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r |
067ed98a | 344 | if (Instance == NULL) {\r |
87000d77 | 345 | DEBUG ((DEBUG_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));\r |
067ed98a RN |
346 | // We should not ASSERT when all the console devices are removed.\r |
347 | // ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r | |
348 | FreePool (FullDevicePath);\r | |
349 | return FALSE;\r | |
350 | }\r | |
d1102dba | 351 | \r |
067ed98a RN |
352 | //\r |
353 | // Find console device handle by device path instance\r | |
354 | //\r | |
fad21b7c | 355 | FullInstance = Instance;\r |
1436aea4 MK |
356 | Status = gBS->LocateDevicePath (\r |
357 | ConsoleGuid,\r | |
358 | &Instance,\r | |
359 | &NewHandle\r | |
360 | );\r | |
fad21b7c | 361 | FreePool (FullInstance);\r |
067ed98a RN |
362 | if (!EFI_ERROR (Status)) {\r |
363 | //\r | |
364 | // Get the console protocol on this console device handle\r | |
365 | //\r | |
366 | Status = gBS->HandleProtocol (\r | |
367 | NewHandle,\r | |
368 | ConsoleGuid,\r | |
369 | &Interface\r | |
370 | );\r | |
371 | if (!EFI_ERROR (Status)) {\r | |
372 | //\r | |
373 | // Update new console handle in System Table.\r | |
374 | //\r | |
375 | *ConsoleHandle = NewHandle;\r | |
376 | *ProtocolInterface = Interface;\r | |
377 | if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {\r | |
378 | //\r | |
379 | // If it is console out device, set console mode 80x25 if current mode is invalid.\r | |
380 | //\r | |
1436aea4 | 381 | TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Interface;\r |
067ed98a RN |
382 | if (TextOut->Mode->Mode == -1) {\r |
383 | TextOut->SetMode (TextOut, 0);\r | |
384 | }\r | |
385 | }\r | |
1436aea4 | 386 | \r |
fad21b7c | 387 | FreePool (FullDevicePath);\r |
067ed98a RN |
388 | return TRUE;\r |
389 | }\r | |
390 | }\r | |
067ed98a RN |
391 | } while (Instance != NULL);\r |
392 | \r | |
393 | //\r | |
394 | // No any available console devcie found.\r | |
395 | //\r | |
fad21b7c | 396 | FreePool (FullDevicePath);\r |
067ed98a RN |
397 | return FALSE;\r |
398 | }\r | |
399 | \r | |
400 | /**\r | |
401 | This function updates the console variable based on ConVarName. It can\r | |
402 | add or remove one specific console device path from the variable\r | |
403 | \r | |
404 | @param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.\r | |
405 | @param CustomizedConDevicePath The console device path to be added to\r | |
406 | the console variable. Cannot be multi-instance.\r | |
407 | @param ExclusiveDevicePath The console device path to be removed\r | |
408 | from the console variable. Cannot be multi-instance.\r | |
409 | \r | |
410 | @retval EFI_UNSUPPORTED The added device path is the same as a removed one.\r | |
411 | @retval EFI_SUCCESS Successfully added or removed the device path from the\r | |
412 | console variable.\r | |
413 | @retval others Return status of RT->SetVariable().\r | |
414 | \r | |
415 | **/\r | |
416 | EFI_STATUS\r | |
417 | EFIAPI\r | |
418 | EfiBootManagerUpdateConsoleVariable (\r | |
419 | IN CONSOLE_TYPE ConsoleType,\r | |
420 | IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r | |
421 | IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r | |
422 | )\r | |
423 | {\r | |
424 | EFI_STATUS Status;\r | |
425 | EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r | |
426 | EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r | |
427 | EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r | |
428 | \r | |
f0209935 | 429 | if (ConsoleType >= ARRAY_SIZE (mConVarName)) {\r |
067ed98a RN |
430 | return EFI_INVALID_PARAMETER;\r |
431 | }\r | |
432 | \r | |
433 | //\r | |
434 | // Notes: check the device path point, here should check\r | |
435 | // with compare memory\r | |
436 | //\r | |
437 | if (CustomizedConDevicePath == ExclusiveDevicePath) {\r | |
438 | return EFI_UNSUPPORTED;\r | |
439 | }\r | |
1436aea4 | 440 | \r |
067ed98a RN |
441 | //\r |
442 | // Delete the ExclusiveDevicePath from current default console\r | |
443 | //\r | |
1436aea4 | 444 | GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **)&VarConsole, NULL);\r |
067ed98a RN |
445 | //\r |
446 | // Initialize NewDevicePath\r | |
447 | //\r | |
448 | NewDevicePath = VarConsole;\r | |
449 | \r | |
450 | //\r | |
451 | // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r | |
452 | // In the end, NewDevicePath is the final device path.\r | |
453 | //\r | |
1436aea4 MK |
454 | if ((ExclusiveDevicePath != NULL) && (VarConsole != NULL)) {\r |
455 | NewDevicePath = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r | |
067ed98a | 456 | }\r |
1436aea4 | 457 | \r |
067ed98a RN |
458 | //\r |
459 | // Try to append customized device path to NewDevicePath.\r | |
460 | //\r | |
461 | if (CustomizedConDevicePath != NULL) {\r | |
462 | if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r | |
463 | //\r | |
464 | // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r | |
465 | //\r | |
466 | NewDevicePath = BmDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r | |
467 | //\r | |
468 | // In the first check, the default console variable will be _ModuleEntryPoint,\r | |
469 | // just append current customized device path\r | |
470 | //\r | |
471 | TempNewDevicePath = NewDevicePath;\r | |
1436aea4 | 472 | NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r |
067ed98a | 473 | if (TempNewDevicePath != NULL) {\r |
1436aea4 | 474 | FreePool (TempNewDevicePath);\r |
067ed98a RN |
475 | }\r |
476 | }\r | |
477 | }\r | |
478 | \r | |
479 | //\r | |
480 | // Finally, Update the variable of the default console by NewDevicePath\r | |
481 | //\r | |
482 | Status = gRT->SetVariable (\r | |
483 | mConVarName[ConsoleType],\r | |
484 | &gEfiGlobalVariableGuid,\r | |
485 | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r | |
1436aea4 | 486 | | ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),\r |
067ed98a RN |
487 | GetDevicePathSize (NewDevicePath),\r |
488 | NewDevicePath\r | |
489 | );\r | |
490 | \r | |
491 | if (VarConsole == NewDevicePath) {\r | |
492 | if (VarConsole != NULL) {\r | |
1436aea4 | 493 | FreePool (VarConsole);\r |
067ed98a RN |
494 | }\r |
495 | } else {\r | |
496 | if (VarConsole != NULL) {\r | |
1436aea4 | 497 | FreePool (VarConsole);\r |
067ed98a | 498 | }\r |
1436aea4 | 499 | \r |
067ed98a | 500 | if (NewDevicePath != NULL) {\r |
1436aea4 | 501 | FreePool (NewDevicePath);\r |
067ed98a RN |
502 | }\r |
503 | }\r | |
504 | \r | |
505 | return Status;\r | |
506 | }\r | |
507 | \r | |
067ed98a RN |
508 | /**\r |
509 | Connect the console device base on the variable ConsoleType.\r | |
510 | \r | |
511 | @param ConsoleType ConIn, ConOut or ErrOut.\r | |
512 | \r | |
513 | @retval EFI_NOT_FOUND There is not any console devices connected\r | |
514 | success\r | |
515 | @retval EFI_SUCCESS Success connect any one instance of the console\r | |
516 | device path base on the variable ConVarName.\r | |
517 | \r | |
518 | **/\r | |
519 | EFI_STATUS\r | |
520 | EFIAPI\r | |
521 | EfiBootManagerConnectConsoleVariable (\r | |
1436aea4 | 522 | IN CONSOLE_TYPE ConsoleType\r |
067ed98a RN |
523 | )\r |
524 | {\r | |
525 | EFI_STATUS Status;\r | |
526 | EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r | |
527 | EFI_DEVICE_PATH_PROTOCOL *Instance;\r | |
528 | EFI_DEVICE_PATH_PROTOCOL *Next;\r | |
529 | EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r | |
530 | UINTN Size;\r | |
531 | BOOLEAN DeviceExist;\r | |
532 | EFI_HANDLE Handle;\r | |
533 | \r | |
534 | if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {\r | |
535 | return EFI_INVALID_PARAMETER;\r | |
536 | }\r | |
537 | \r | |
538 | Status = EFI_SUCCESS;\r | |
539 | DeviceExist = FALSE;\r | |
540 | Handle = NULL;\r | |
541 | \r | |
542 | //\r | |
543 | // Check if the console variable exist\r | |
544 | //\r | |
1436aea4 | 545 | GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **)&StartDevicePath, NULL);\r |
067ed98a RN |
546 | if (StartDevicePath == NULL) {\r |
547 | return EFI_UNSUPPORTED;\r | |
548 | }\r | |
549 | \r | |
550 | CopyOfDevicePath = StartDevicePath;\r | |
551 | do {\r | |
552 | //\r | |
553 | // Check every instance of the console variable\r | |
554 | //\r | |
1436aea4 | 555 | Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r |
067ed98a RN |
556 | if (Instance == NULL) {\r |
557 | FreePool (StartDevicePath);\r | |
558 | return EFI_UNSUPPORTED;\r | |
559 | }\r | |
d1102dba | 560 | \r |
1436aea4 | 561 | Next = Instance;\r |
067ed98a RN |
562 | while (!IsDevicePathEndType (Next)) {\r |
563 | Next = NextDevicePathNode (Next);\r | |
564 | }\r | |
565 | \r | |
566 | SetDevicePathEndNode (Next);\r | |
567 | //\r | |
568 | // Connect the USB console\r | |
d1102dba | 569 | // USB console device path is a short-form device path that\r |
067ed98a RN |
570 | // starts with the first element being a USB WWID\r |
571 | // or a USB Class device path\r | |
572 | //\r | |
573 | if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r | |
574 | ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))\r | |
1436aea4 MK |
575 | )\r |
576 | {\r | |
067ed98a RN |
577 | Status = BmConnectUsbShortFormDevicePath (Instance);\r |
578 | if (!EFI_ERROR (Status)) {\r | |
579 | DeviceExist = TRUE;\r | |
580 | }\r | |
581 | } else {\r | |
582 | for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {\r | |
1436aea4 | 583 | if ((DevicePathType (Next) == ACPI_DEVICE_PATH) && (DevicePathSubType (Next) == ACPI_ADR_DP)) {\r |
067ed98a | 584 | break;\r |
1436aea4 MK |
585 | } else if ((DevicePathType (Next) == HARDWARE_DEVICE_PATH) &&\r |
586 | (DevicePathSubType (Next) == HW_CONTROLLER_DP) &&\r | |
587 | (DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH) &&\r | |
588 | (DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP)\r | |
589 | )\r | |
590 | {\r | |
067ed98a RN |
591 | break;\r |
592 | }\r | |
593 | }\r | |
1436aea4 | 594 | \r |
067ed98a RN |
595 | if (!IsDevicePathEnd (Next)) {\r |
596 | //\r | |
597 | // For GOP device path, start the video driver with NULL remaining device path\r | |
598 | //\r | |
599 | SetDevicePathEndNode (Next);\r | |
600 | Status = EfiBootManagerConnectDevicePath (Instance, &Handle);\r | |
601 | if (!EFI_ERROR (Status)) {\r | |
602 | gBS->ConnectController (Handle, NULL, NULL, TRUE);\r | |
603 | }\r | |
604 | } else {\r | |
605 | Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r | |
606 | }\r | |
1436aea4 | 607 | \r |
067ed98a RN |
608 | if (EFI_ERROR (Status)) {\r |
609 | //\r | |
610 | // Delete the instance from the console varialbe\r | |
611 | //\r | |
612 | EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);\r | |
613 | } else {\r | |
614 | DeviceExist = TRUE;\r | |
615 | }\r | |
616 | }\r | |
1436aea4 MK |
617 | \r |
618 | FreePool (Instance);\r | |
067ed98a RN |
619 | } while (CopyOfDevicePath != NULL);\r |
620 | \r | |
621 | FreePool (StartDevicePath);\r | |
622 | \r | |
623 | if (!DeviceExist) {\r | |
624 | return EFI_NOT_FOUND;\r | |
625 | }\r | |
626 | \r | |
627 | return EFI_SUCCESS;\r | |
628 | }\r | |
629 | \r | |
067ed98a RN |
630 | /**\r |
631 | This function will search every input/output device in current system,\r | |
632 | and make every input/output device as potential console device.\r | |
633 | **/\r | |
634 | VOID\r | |
635 | EFIAPI\r | |
636 | EfiBootManagerConnectAllConsoles (\r | |
637 | VOID\r | |
638 | )\r | |
639 | {\r | |
640 | UINTN Index;\r | |
641 | EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r | |
642 | UINTN HandleCount;\r | |
643 | EFI_HANDLE *HandleBuffer;\r | |
644 | \r | |
645 | Index = 0;\r | |
646 | HandleCount = 0;\r | |
647 | HandleBuffer = NULL;\r | |
648 | ConDevicePath = NULL;\r | |
649 | \r | |
650 | //\r | |
651 | // Update all the console variables\r | |
652 | //\r | |
653 | gBS->LocateHandleBuffer (\r | |
1436aea4 MK |
654 | ByProtocol,\r |
655 | &gEfiSimpleTextInProtocolGuid,\r | |
656 | NULL,\r | |
657 | &HandleCount,\r | |
658 | &HandleBuffer\r | |
659 | );\r | |
067ed98a RN |
660 | \r |
661 | for (Index = 0; Index < HandleCount; Index++) {\r | |
662 | gBS->HandleProtocol (\r | |
1436aea4 MK |
663 | HandleBuffer[Index],\r |
664 | &gEfiDevicePathProtocolGuid,\r | |
665 | (VOID **)&ConDevicePath\r | |
666 | );\r | |
067ed98a RN |
667 | EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);\r |
668 | }\r | |
669 | \r | |
670 | if (HandleBuffer != NULL) {\r | |
1436aea4 | 671 | FreePool (HandleBuffer);\r |
067ed98a RN |
672 | HandleBuffer = NULL;\r |
673 | }\r | |
674 | \r | |
675 | gBS->LocateHandleBuffer (\r | |
1436aea4 MK |
676 | ByProtocol,\r |
677 | &gEfiSimpleTextOutProtocolGuid,\r | |
678 | NULL,\r | |
679 | &HandleCount,\r | |
680 | &HandleBuffer\r | |
681 | );\r | |
067ed98a RN |
682 | for (Index = 0; Index < HandleCount; Index++) {\r |
683 | gBS->HandleProtocol (\r | |
1436aea4 MK |
684 | HandleBuffer[Index],\r |
685 | &gEfiDevicePathProtocolGuid,\r | |
686 | (VOID **)&ConDevicePath\r | |
687 | );\r | |
067ed98a RN |
688 | EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);\r |
689 | EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);\r | |
690 | }\r | |
691 | \r | |
692 | if (HandleBuffer != NULL) {\r | |
1436aea4 | 693 | FreePool (HandleBuffer);\r |
067ed98a RN |
694 | }\r |
695 | \r | |
696 | //\r | |
697 | // Connect all console variables\r | |
698 | //\r | |
699 | EfiBootManagerConnectAllDefaultConsoles ();\r | |
700 | }\r | |
701 | \r | |
067ed98a RN |
702 | /**\r |
703 | This function will connect all the console devices base on the console\r | |
704 | device variable ConIn, ConOut and ErrOut.\r | |
705 | \r | |
706 | @retval EFI_DEVICE_ERROR All the consoles were not connected due to an error.\r | |
707 | @retval EFI_SUCCESS Success connect any one instance of the console\r | |
708 | device path base on the variable ConVarName.\r | |
709 | **/\r | |
710 | EFI_STATUS\r | |
711 | EFIAPI\r | |
712 | EfiBootManagerConnectAllDefaultConsoles (\r | |
713 | VOID\r | |
714 | )\r | |
715 | {\r | |
1436aea4 MK |
716 | EFI_STATUS Status;\r |
717 | BOOLEAN OneConnected;\r | |
718 | BOOLEAN SystemTableUpdated;\r | |
067ed98a RN |
719 | \r |
720 | OneConnected = FALSE;\r | |
721 | \r | |
722 | Status = EfiBootManagerConnectConsoleVariable (ConOut);\r | |
723 | if (!EFI_ERROR (Status)) {\r | |
724 | OneConnected = TRUE;\r | |
725 | }\r | |
067ed98a | 726 | \r |
1436aea4 | 727 | PERF_EVENT ("ConOutReady");\r |
d1102dba | 728 | \r |
067ed98a RN |
729 | Status = EfiBootManagerConnectConsoleVariable (ConIn);\r |
730 | if (!EFI_ERROR (Status)) {\r | |
731 | OneConnected = TRUE;\r | |
732 | }\r | |
1436aea4 | 733 | \r |
67e9ab84 | 734 | PERF_EVENT ("ConInReady");\r |
067ed98a RN |
735 | \r |
736 | Status = EfiBootManagerConnectConsoleVariable (ErrOut);\r | |
737 | if (!EFI_ERROR (Status)) {\r | |
738 | OneConnected = TRUE;\r | |
739 | }\r | |
1436aea4 | 740 | \r |
67e9ab84 | 741 | PERF_EVENT ("ErrOutReady");\r |
067ed98a RN |
742 | \r |
743 | SystemTableUpdated = FALSE;\r | |
744 | //\r | |
745 | // Fill console handles in System Table if no console device assignd.\r | |
746 | //\r | |
1436aea4 | 747 | if (BmUpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **)&gST->ConIn)) {\r |
067ed98a RN |
748 | SystemTableUpdated = TRUE;\r |
749 | }\r | |
1436aea4 MK |
750 | \r |
751 | if (BmUpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **)&gST->ConOut)) {\r | |
067ed98a RN |
752 | SystemTableUpdated = TRUE;\r |
753 | }\r | |
1436aea4 MK |
754 | \r |
755 | if (BmUpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **)&gST->StdErr)) {\r | |
067ed98a RN |
756 | SystemTableUpdated = TRUE;\r |
757 | }\r | |
758 | \r | |
759 | if (SystemTableUpdated) {\r | |
760 | //\r | |
761 | // Update the CRC32 in the EFI System Table header\r | |
762 | //\r | |
763 | gST->Hdr.CRC32 = 0;\r | |
764 | gBS->CalculateCrc32 (\r | |
1436aea4 MK |
765 | (UINT8 *)&gST->Hdr,\r |
766 | gST->Hdr.HeaderSize,\r | |
767 | &gST->Hdr.CRC32\r | |
768 | );\r | |
067ed98a RN |
769 | }\r |
770 | \r | |
771 | return OneConnected ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r | |
772 | }\r |