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