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