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