Home | History | Annotate | Download | only in UefiBootManagerLib
      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
     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
    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
    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
    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
    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
    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
    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
    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