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