-/** @file
- Library functions which contain all the code to connect console device.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalBm.h"
-
-CHAR16 *mConVarName[] = {
- L"ConIn",
- L"ConOut",
- L"ErrOut",
- L"ConInDev",
- L"ConOutDev",
- L"ErrOutDev"
-};
-
-/**
- Search out the video controller.
-
- @return PCI device path of the video controller.
-**/
-EFI_HANDLE
-BmGetVideoController (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN RootBridgeHandleCount;
- EFI_HANDLE *RootBridgeHandleBuffer;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINTN RootBridgeIndex;
- UINTN Index;
- EFI_HANDLE VideoController;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
-
- //
- // Make all the PCI_IO protocols show up
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiPciRootBridgeIoProtocolGuid,
- NULL,
- &RootBridgeHandleCount,
- &RootBridgeHandleBuffer
- );
- if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {
- return NULL;
- }
-
- VideoController = NULL;
- for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
- gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
-
- //
- // Start to check all the pci io to find the first video controller
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiPciIoProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
- if (!EFI_ERROR (Status)) {
- //
- // Check for all video controller
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- 0,
- sizeof (Pci) / sizeof (UINT32),
- &Pci
- );
- if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {
- // TODO: use IS_PCI_DISPLAY??
- VideoController = HandleBuffer[Index];
- break;
- }
- }
- }
- FreePool (HandleBuffer);
-
- if (VideoController != NULL) {
- break;
- }
- }
- FreePool (RootBridgeHandleBuffer);
-
- return VideoController;
-}
-
-/**
- Query all the children of VideoController and return the device paths of all the
- children that support GraphicsOutput protocol.
-
- @param VideoController PCI handle of video controller.
-
- @return Device paths of all the children that support GraphicsOutput protocol.
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-EfiBootManagerGetGopDevicePath (
- IN EFI_HANDLE VideoController
- )
-{
- UINTN Index;
- EFI_STATUS Status;
- EFI_GUID **ProtocolBuffer;
- UINTN ProtocolBufferCount;
- UINTN ProtocolIndex;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
- UINTN EntryCount;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *Next;
- EFI_DEVICE_PATH_PROTOCOL *Previous;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *GopPool;
- EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
-
-
- Status = gBS->ProtocolsPerHandle (
- VideoController,
- &ProtocolBuffer,
- &ProtocolBufferCount
- );
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- GopPool = NULL;
-
- for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) {
- Status = gBS->OpenProtocolInformation (
- VideoController,
- ProtocolBuffer[ProtocolIndex],
- &OpenInfoBuffer,
- &EntryCount
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- for (Index = 0; Index < EntryCount; Index++) {
- //
- // Query all the children
- //
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &DevicePath,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- Previous = NULL;
- for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
- Previous = Next;
- }
- ASSERT (Previous != NULL);
-
- if (DevicePathType (Previous) == ACPI_DEVICE_PATH && DevicePathSubType (Previous) == ACPI_ADR_DP) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiGraphicsOutputProtocolGuid,
- NULL,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- //
- // Append the device path to GOP pool when there is GOP protocol installed.
- //
- TempDevicePath = GopPool;
- GopPool = AppendDevicePathInstance (GopPool, DevicePath);
- gBS->FreePool (TempDevicePath);
- }
- }
-
- if (DevicePathType (Previous) == HARDWARE_DEVICE_PATH && DevicePathSubType (Previous) == HW_CONTROLLER_DP) {
- //
- // Recursively look for GOP child in this frame buffer handle
- //
- DEBUG ((EFI_D_INFO, "[Bds] Looking for GOP child deeper ... \n"));
- TempDevicePath = GopPool;
- ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle);
- GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath);
- gBS->FreePool (ReturnDevicePath);
- gBS->FreePool (TempDevicePath);
- }
- }
- }
-
- FreePool (OpenInfoBuffer);
- }
-
- FreePool (ProtocolBuffer);
-
- return GopPool;
-}
-
-/**
- Connect the platform active active video controller.
-
- @param VideoController PCI handle of video controller.
-
- @retval EFI_NOT_FOUND There is no active video controller.
- @retval EFI_SUCCESS The video controller is connected.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerConnectVideoController (
- EFI_HANDLE VideoController OPTIONAL
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *Gop;
-
- if (VideoController == NULL) {
- //
- // Get the platform vga device
- //
- VideoController = BmGetVideoController ();
- }
-
- if (VideoController == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Try to connect the PCI device path, so that GOP dirver could start on this
- // device and create child handles with GraphicsOutput Protocol installed
- // on them, then we get device paths of these child handles and select
- // them as possible console device.
- //
- gBS->ConnectController (VideoController, NULL, NULL, FALSE);
-
- Gop = EfiBootManagerGetGopDevicePath (VideoController);
- if (Gop == NULL) {
- return EFI_NOT_FOUND;
- }
-
- EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);
- FreePool (Gop);
-
- //
- // Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.
- //
- return gBS->ConnectController (VideoController, NULL, NULL, TRUE);
-}
-
-/**
- Fill console handle in System Table if there are no valid console handle in.
-
- Firstly, check the validation of console handle in System Table. If it is invalid,
- update it by the first console device handle from EFI console variable.
-
- @param VarName The name of the EFI console variable.
- @param ConsoleGuid Specified Console protocol GUID.
- @param ConsoleHandle On IN, console handle in System Table to be checked.
- On OUT, new console handle in system table.
- @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
- On OUT, new console protocol on new console handle in system table.
-
- @retval TRUE System Table has been updated.
- @retval FALSE System Table hasn't been updated.
-
-**/
-BOOLEAN
-BmUpdateSystemTableConsole (
- IN CHAR16 *VarName,
- IN EFI_GUID *ConsoleGuid,
- IN OUT EFI_HANDLE *ConsoleHandle,
- IN OUT VOID **ProtocolInterface
- )
-{
- EFI_STATUS Status;
- UINTN DevicePathSize;
- EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *VarConsole;
- EFI_DEVICE_PATH_PROTOCOL *Instance;
- VOID *Interface;
- EFI_HANDLE NewHandle;
- EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
-
- ASSERT (VarName != NULL);
- ASSERT (ConsoleHandle != NULL);
- ASSERT (ConsoleGuid != NULL);
- ASSERT (ProtocolInterface != NULL);
-
- if (*ConsoleHandle != NULL) {
- Status = gBS->HandleProtocol (
- *ConsoleHandle,
- ConsoleGuid,
- &Interface
- );
- if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {
- //
- // If ConsoleHandle is valid and console protocol on this handle also
- // also matched, just return.
- //
- return FALSE;
- }
- }
-
- //
- // Get all possible consoles device path from EFI variable
- //
- GetEfiGlobalVariable2 (VarName, (VOID **) &VarConsole, NULL);
- if (VarConsole == NULL) {
- //
- // If there is no any console device, just return.
- //
- return FALSE;
- }
-
- FullDevicePath = VarConsole;
-
- do {
- //
- // Check every instance of the console variable
- //
- Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
- if (Instance == NULL) {
- DEBUG ((EFI_D_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));
- // We should not ASSERT when all the console devices are removed.
- // ASSERT_EFI_ERROR (EFI_NOT_FOUND);
- FreePool (FullDevicePath);
- return FALSE;
- }
-
- //
- // Find console device handle by device path instance
- //
- Status = gBS->LocateDevicePath (
- ConsoleGuid,
- &Instance,
- &NewHandle
- );
- if (!EFI_ERROR (Status)) {
- //
- // Get the console protocol on this console device handle
- //
- Status = gBS->HandleProtocol (
- NewHandle,
- ConsoleGuid,
- &Interface
- );
- if (!EFI_ERROR (Status)) {
- //
- // Update new console handle in System Table.
- //
- *ConsoleHandle = NewHandle;
- *ProtocolInterface = Interface;
- if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {
- //
- // If it is console out device, set console mode 80x25 if current mode is invalid.
- //
- TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;
- if (TextOut->Mode->Mode == -1) {
- TextOut->SetMode (TextOut, 0);
- }
- }
- return TRUE;
- }
- }
-
- } while (Instance != NULL);
-
- //
- // No any available console devcie found.
- //
- return FALSE;
-}
-
-/**
- This function updates the console variable based on ConVarName. It can
- add or remove one specific console device path from the variable
-
- @param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.
- @param CustomizedConDevicePath The console device path to be added to
- the console variable. Cannot be multi-instance.
- @param ExclusiveDevicePath The console device path to be removed
- from the console variable. Cannot be multi-instance.
-
- @retval EFI_UNSUPPORTED The added device path is the same as a removed one.
- @retval EFI_SUCCESS Successfully added or removed the device path from the
- console variable.
- @retval others Return status of RT->SetVariable().
-
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerUpdateConsoleVariable (
- IN CONSOLE_TYPE ConsoleType,
- IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
- IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *VarConsole;
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
-
- if (ConsoleType >= sizeof (mConVarName) / sizeof (mConVarName[0])) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Notes: check the device path point, here should check
- // with compare memory
- //
- if (CustomizedConDevicePath == ExclusiveDevicePath) {
- return EFI_UNSUPPORTED;
- }
- //
- // Delete the ExclusiveDevicePath from current default console
- //
- GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &VarConsole, NULL);
- //
- // Initialize NewDevicePath
- //
- NewDevicePath = VarConsole;
-
- //
- // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
- // In the end, NewDevicePath is the final device path.
- //
- if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
- NewDevicePath = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
- }
- //
- // Try to append customized device path to NewDevicePath.
- //
- if (CustomizedConDevicePath != NULL) {
- if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
- //
- // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
- //
- NewDevicePath = BmDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
- //
- // In the first check, the default console variable will be _ModuleEntryPoint,
- // just append current customized device path
- //
- TempNewDevicePath = NewDevicePath;
- NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
- if (TempNewDevicePath != NULL) {
- FreePool(TempNewDevicePath);
- }
- }
- }
-
- //
- // Finally, Update the variable of the default console by NewDevicePath
- //
- Status = gRT->SetVariable (
- mConVarName[ConsoleType],
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
- | ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),
- GetDevicePathSize (NewDevicePath),
- NewDevicePath
- );
-
- if (VarConsole == NewDevicePath) {
- if (VarConsole != NULL) {
- FreePool(VarConsole);
- }
- } else {
- if (VarConsole != NULL) {
- FreePool(VarConsole);
- }
- if (NewDevicePath != NULL) {
- FreePool(NewDevicePath);
- }
- }
-
- return Status;
-}
-
-
-/**
- Connect the console device base on the variable ConsoleType.
-
- @param ConsoleType ConIn, ConOut or ErrOut.
-
- @retval EFI_NOT_FOUND There is not any console devices connected
- success
- @retval EFI_SUCCESS Success connect any one instance of the console
- device path base on the variable ConVarName.
-
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerConnectConsoleVariable (
- IN CONSOLE_TYPE ConsoleType
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *Instance;
- EFI_DEVICE_PATH_PROTOCOL *Next;
- EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
- UINTN Size;
- BOOLEAN DeviceExist;
- EFI_HANDLE Handle;
-
- if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_SUCCESS;
- DeviceExist = FALSE;
- Handle = NULL;
-
- //
- // Check if the console variable exist
- //
- GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &StartDevicePath, NULL);
- if (StartDevicePath == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- CopyOfDevicePath = StartDevicePath;
- do {
- //
- // Check every instance of the console variable
- //
- Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
- if (Instance == NULL) {
- FreePool (StartDevicePath);
- return EFI_UNSUPPORTED;
- }
-
- Next = Instance;
- while (!IsDevicePathEndType (Next)) {
- Next = NextDevicePathNode (Next);
- }
-
- SetDevicePathEndNode (Next);
- //
- // Connect the USB console
- // USB console device path is a short-form device path that
- // starts with the first element being a USB WWID
- // or a USB Class device path
- //
- if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
- ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))
- ) {
- Status = BmConnectUsbShortFormDevicePath (Instance);
- if (!EFI_ERROR (Status)) {
- DeviceExist = TRUE;
- }
- } else {
- for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
- if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
- break;
- } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
- DevicePathSubType (Next) == HW_CONTROLLER_DP &&
- DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
- DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
- ) {
- break;
- }
- }
- if (!IsDevicePathEnd (Next)) {
- //
- // For GOP device path, start the video driver with NULL remaining device path
- //
- SetDevicePathEndNode (Next);
- Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
- if (!EFI_ERROR (Status)) {
- gBS->ConnectController (Handle, NULL, NULL, TRUE);
- }
- } else {
- Status = EfiBootManagerConnectDevicePath (Instance, NULL);
- }
- if (EFI_ERROR (Status)) {
- //
- // Delete the instance from the console varialbe
- //
- EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);
- } else {
- DeviceExist = TRUE;
- }
- }
- FreePool(Instance);
- } while (CopyOfDevicePath != NULL);
-
- FreePool (StartDevicePath);
-
- if (!DeviceExist) {
- return EFI_NOT_FOUND;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- This function will search every input/output device in current system,
- and make every input/output device as potential console device.
-**/
-VOID
-EFIAPI
-EfiBootManagerConnectAllConsoles (
- VOID
- )
-{
- UINTN Index;
- EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
-
- Index = 0;
- HandleCount = 0;
- HandleBuffer = NULL;
- ConDevicePath = NULL;
-
- //
- // Update all the console variables
- //
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleTextInProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
-
- for (Index = 0; Index < HandleCount; Index++) {
- gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ConDevicePath
- );
- EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);
- }
-
- if (HandleBuffer != NULL) {
- FreePool(HandleBuffer);
- HandleBuffer = NULL;
- }
-
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleTextOutProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- for (Index = 0; Index < HandleCount; Index++) {
- gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ConDevicePath
- );
- EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);
- EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);
- }
-
- if (HandleBuffer != NULL) {
- FreePool(HandleBuffer);
- }
-
- //
- // Connect all console variables
- //
- EfiBootManagerConnectAllDefaultConsoles ();
-}
-
-
-/**
- This function will connect all the console devices base on the console
- device variable ConIn, ConOut and ErrOut.
-
- @retval EFI_DEVICE_ERROR All the consoles were not connected due to an error.
- @retval EFI_SUCCESS Success connect any one instance of the console
- device path base on the variable ConVarName.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerConnectAllDefaultConsoles (
- VOID
- )
-{
- EFI_STATUS Status;
- BOOLEAN OneConnected;
- BOOLEAN SystemTableUpdated;
-
- OneConnected = FALSE;
-
- Status = EfiBootManagerConnectConsoleVariable (ConOut);
- if (!EFI_ERROR (Status)) {
- OneConnected = TRUE;
- }
- PERF_START (NULL, "ConOutReady", "BDS", 1);
- PERF_END (NULL, "ConOutReady", "BDS", 0);
-
-
- Status = EfiBootManagerConnectConsoleVariable (ConIn);
- if (!EFI_ERROR (Status)) {
- OneConnected = TRUE;
- }
- PERF_START (NULL, "ConInReady", "BDS", 1);
- PERF_END (NULL, "ConInReady", "BDS", 0);
-
- Status = EfiBootManagerConnectConsoleVariable (ErrOut);
- if (!EFI_ERROR (Status)) {
- OneConnected = TRUE;
- }
- PERF_START (NULL, "ErrOutReady", "BDS", 1);
- PERF_END (NULL, "ErrOutReady", "BDS", 0);
-
- SystemTableUpdated = FALSE;
- //
- // Fill console handles in System Table if no console device assignd.
- //
- if (BmUpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {
- SystemTableUpdated = TRUE;
- }
- if (BmUpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {
- SystemTableUpdated = TRUE;
- }
- if (BmUpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {
- SystemTableUpdated = TRUE;
- }
-
- if (SystemTableUpdated) {
- //
- // Update the CRC32 in the EFI System Table header
- //
- gST->Hdr.CRC32 = 0;
- gBS->CalculateCrc32 (
- (UINT8 *) &gST->Hdr,
- gST->Hdr.HeaderSize,
- &gST->Hdr.CRC32
- );
- }
-
- return OneConnected ? EFI_SUCCESS : EFI_DEVICE_ERROR;
-}
+/** @file\r
+ Library functions which contain all the code to connect console device.\r
+\r
+Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "InternalBm.h"\r
+\r
+CHAR16 *mConVarName[] = {\r
+ L"ConIn",\r
+ L"ConOut",\r
+ L"ErrOut",\r
+ L"ConInDev",\r
+ L"ConOutDev",\r
+ L"ErrOutDev"\r
+};\r
+\r
+/**\r
+ Search out the video controller.\r
+\r
+ @return PCI device path of the video controller.\r
+**/\r
+EFI_HANDLE\r
+BmGetVideoController (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN RootBridgeHandleCount;\r
+ EFI_HANDLE *RootBridgeHandleBuffer;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN RootBridgeIndex;\r
+ UINTN Index;\r
+ EFI_HANDLE VideoController;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+\r
+ //\r
+ // Make all the PCI_IO protocols show up\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ NULL,\r
+ &RootBridgeHandleCount,\r
+ &RootBridgeHandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {\r
+ return NULL;\r
+ }\r
+\r
+ VideoController = NULL;\r
+ for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {\r
+ gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);\r
+\r
+ //\r
+ // Start to check all the pci io to find the first video controller\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Check for all video controller\r
+ //\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+ if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {\r
+ // TODO: use IS_PCI_DISPLAY??\r
+ VideoController = HandleBuffer[Index];\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ FreePool (HandleBuffer);\r
+\r
+ if (VideoController != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ FreePool (RootBridgeHandleBuffer);\r
+\r
+ return VideoController;\r
+}\r
+\r
+/**\r
+ Query all the children of VideoController and return the device paths of all the\r
+ children that support GraphicsOutput protocol.\r
+\r
+ @param VideoController PCI handle of video controller.\r
+\r
+ @return Device paths of all the children that support GraphicsOutput protocol.\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+EfiBootManagerGetGopDevicePath (\r
+ IN EFI_HANDLE VideoController\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_GUID **ProtocolBuffer;\r
+ UINTN ProtocolBufferCount;\r
+ UINTN ProtocolIndex;\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
+ UINTN EntryCount;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Next;\r
+ EFI_DEVICE_PATH_PROTOCOL *Previous;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *GopPool;\r
+ EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;\r
+\r
+\r
+ Status = gBS->ProtocolsPerHandle (\r
+ VideoController,\r
+ &ProtocolBuffer,\r
+ &ProtocolBufferCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ GopPool = NULL;\r
+\r
+ for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) {\r
+ Status = gBS->OpenProtocolInformation (\r
+ VideoController,\r
+ ProtocolBuffer[ProtocolIndex],\r
+ &OpenInfoBuffer,\r
+ &EntryCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index = 0; Index < EntryCount; Index++) {\r
+ //\r
+ // Query all the children\r
+ //\r
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+ Status = gBS->OpenProtocol (\r
+ OpenInfoBuffer[Index].ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ Previous = NULL;\r
+ for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {\r
+ Previous = Next;\r
+ }\r
+ ASSERT (Previous != NULL);\r
+\r
+ if (DevicePathType (Previous) == ACPI_DEVICE_PATH && DevicePathSubType (Previous) == ACPI_ADR_DP) {\r
+ Status = gBS->OpenProtocol (\r
+ OpenInfoBuffer[Index].ControllerHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Append the device path to GOP pool when there is GOP protocol installed.\r
+ //\r
+ TempDevicePath = GopPool;\r
+ GopPool = AppendDevicePathInstance (GopPool, DevicePath);\r
+ gBS->FreePool (TempDevicePath);\r
+ }\r
+ }\r
+\r
+ if (DevicePathType (Previous) == HARDWARE_DEVICE_PATH && DevicePathSubType (Previous) == HW_CONTROLLER_DP) {\r
+ //\r
+ // Recursively look for GOP child in this frame buffer handle\r
+ //\r
+ DEBUG ((EFI_D_INFO, "[Bds] Looking for GOP child deeper ... \n"));\r
+ TempDevicePath = GopPool;\r
+ ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle);\r
+ GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath);\r
+ gBS->FreePool (ReturnDevicePath);\r
+ gBS->FreePool (TempDevicePath);\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (OpenInfoBuffer);\r
+ }\r
+\r
+ FreePool (ProtocolBuffer);\r
+\r
+ return GopPool;\r
+}\r
+\r
+/**\r
+ Connect the platform active active video controller.\r
+\r
+ @param VideoController PCI handle of video controller.\r
+\r
+ @retval EFI_NOT_FOUND There is no active video controller.\r
+ @retval EFI_SUCCESS The video controller is connected.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectVideoController (\r
+ EFI_HANDLE VideoController OPTIONAL\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Gop;\r
+\r
+ if (VideoController == NULL) {\r
+ //\r
+ // Get the platform vga device\r
+ //\r
+ VideoController = BmGetVideoController ();\r
+ }\r
+\r
+ if (VideoController == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Try to connect the PCI device path, so that GOP driver could start on this\r
+ // device and create child handles with GraphicsOutput Protocol installed\r
+ // on them, then we get device paths of these child handles and select\r
+ // them as possible console device.\r
+ //\r
+ gBS->ConnectController (VideoController, NULL, NULL, FALSE);\r
+\r
+ Gop = EfiBootManagerGetGopDevicePath (VideoController);\r
+ if (Gop == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);\r
+ FreePool (Gop);\r
+\r
+ //\r
+ // Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.\r
+ //\r
+ return gBS->ConnectController (VideoController, NULL, NULL, TRUE);\r
+}\r
+\r
+/**\r
+ Fill console handle in System Table if there are no valid console handle in.\r
+\r
+ Firstly, check the validation of console handle in System Table. If it is invalid,\r
+ update it by the first console device handle from EFI console variable.\r
+\r
+ @param VarName The name of the EFI console variable.\r
+ @param ConsoleGuid Specified Console protocol GUID.\r
+ @param ConsoleHandle On IN, console handle in System Table to be checked.\r
+ On OUT, new console handle in system table.\r
+ @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.\r
+ On OUT, new console protocol on new console handle in system table.\r
+\r
+ @retval TRUE System Table has been updated.\r
+ @retval FALSE System Table hasn't been updated.\r
+\r
+**/\r
+BOOLEAN\r
+BmUpdateSystemTableConsole (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *ConsoleGuid,\r
+ IN OUT EFI_HANDLE *ConsoleHandle,\r
+ IN OUT VOID **ProtocolInterface\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN DevicePathSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullInstance;\r
+ VOID *Interface;\r
+ EFI_HANDLE NewHandle;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
+\r
+ ASSERT (VarName != NULL);\r
+ ASSERT (ConsoleHandle != NULL);\r
+ ASSERT (ConsoleGuid != NULL);\r
+ ASSERT (ProtocolInterface != NULL);\r
+\r
+ if (*ConsoleHandle != NULL) {\r
+ Status = gBS->HandleProtocol (\r
+ *ConsoleHandle,\r
+ ConsoleGuid,\r
+ &Interface\r
+ );\r
+ if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {\r
+ //\r
+ // If ConsoleHandle is valid and console protocol on this handle also\r
+ // also matched, just return.\r
+ //\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get all possible consoles device path from EFI variable\r
+ //\r
+ GetEfiGlobalVariable2 (VarName, (VOID **) &VarConsole, NULL);\r
+ if (VarConsole == NULL) {\r
+ //\r
+ // If there is no any console device, just return.\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ FullDevicePath = VarConsole;\r
+\r
+ do {\r
+ //\r
+ // Check every instance of the console variable\r
+ //\r
+ Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r
+ if (Instance == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));\r
+ // We should not ASSERT when all the console devices are removed.\r
+ // ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
+ FreePool (FullDevicePath);\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Find console device handle by device path instance\r
+ //\r
+ FullInstance = Instance;\r
+ Status = gBS->LocateDevicePath (\r
+ ConsoleGuid,\r
+ &Instance,\r
+ &NewHandle\r
+ );\r
+ FreePool (FullInstance);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get the console protocol on this console device handle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ NewHandle,\r
+ ConsoleGuid,\r
+ &Interface\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Update new console handle in System Table.\r
+ //\r
+ *ConsoleHandle = NewHandle;\r
+ *ProtocolInterface = Interface;\r
+ if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {\r
+ //\r
+ // If it is console out device, set console mode 80x25 if current mode is invalid.\r
+ //\r
+ TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;\r
+ if (TextOut->Mode->Mode == -1) {\r
+ TextOut->SetMode (TextOut, 0);\r
+ }\r
+ }\r
+ FreePool (FullDevicePath);\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ } while (Instance != NULL);\r
+\r
+ //\r
+ // No any available console devcie found.\r
+ //\r
+ FreePool (FullDevicePath);\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ This function updates the console variable based on ConVarName. It can\r
+ add or remove one specific console device path from the variable\r
+\r
+ @param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.\r
+ @param CustomizedConDevicePath The console device path to be added to\r
+ the console variable. Cannot be multi-instance.\r
+ @param ExclusiveDevicePath The console device path to be removed\r
+ from the console variable. Cannot be multi-instance.\r
+\r
+ @retval EFI_UNSUPPORTED The added device path is the same as a removed one.\r
+ @retval EFI_SUCCESS Successfully added or removed the device path from the\r
+ console variable.\r
+ @retval others Return status of RT->SetVariable().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerUpdateConsoleVariable (\r
+ IN CONSOLE_TYPE ConsoleType,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+\r
+ if (ConsoleType >= ARRAY_SIZE (mConVarName)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Notes: check the device path point, here should check\r
+ // with compare memory\r
+ //\r
+ if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Delete the ExclusiveDevicePath from current default console\r
+ //\r
+ GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &VarConsole, NULL);\r
+ //\r
+ // Initialize NewDevicePath\r
+ //\r
+ NewDevicePath = VarConsole;\r
+\r
+ //\r
+ // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
+ // In the end, NewDevicePath is the final device path.\r
+ //\r
+ if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
+ NewDevicePath = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
+ }\r
+ //\r
+ // Try to append customized device path to NewDevicePath.\r
+ //\r
+ if (CustomizedConDevicePath != NULL) {\r
+ if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
+ //\r
+ // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
+ //\r
+ NewDevicePath = BmDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
+ //\r
+ // In the first check, the default console variable will be _ModuleEntryPoint,\r
+ // just append current customized device path\r
+ //\r
+ TempNewDevicePath = NewDevicePath;\r
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
+ if (TempNewDevicePath != NULL) {\r
+ FreePool(TempNewDevicePath);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Finally, Update the variable of the default console by NewDevicePath\r
+ //\r
+ Status = gRT->SetVariable (\r
+ mConVarName[ConsoleType],\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+ | ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),\r
+ GetDevicePathSize (NewDevicePath),\r
+ NewDevicePath\r
+ );\r
+\r
+ if (VarConsole == NewDevicePath) {\r
+ if (VarConsole != NULL) {\r
+ FreePool(VarConsole);\r
+ }\r
+ } else {\r
+ if (VarConsole != NULL) {\r
+ FreePool(VarConsole);\r
+ }\r
+ if (NewDevicePath != NULL) {\r
+ FreePool(NewDevicePath);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Connect the console device base on the variable ConsoleType.\r
+\r
+ @param ConsoleType ConIn, ConOut or ErrOut.\r
+\r
+ @retval EFI_NOT_FOUND There is not any console devices connected\r
+ success\r
+ @retval EFI_SUCCESS Success connect any one instance of the console\r
+ device path base on the variable ConVarName.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectConsoleVariable (\r
+ IN CONSOLE_TYPE ConsoleType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *Next;\r
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
+ UINTN Size;\r
+ BOOLEAN DeviceExist;\r
+ EFI_HANDLE Handle;\r
+\r
+ if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ DeviceExist = FALSE;\r
+ Handle = NULL;\r
+\r
+ //\r
+ // Check if the console variable exist\r
+ //\r
+ GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &StartDevicePath, NULL);\r
+ if (StartDevicePath == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CopyOfDevicePath = StartDevicePath;\r
+ do {\r
+ //\r
+ // Check every instance of the console variable\r
+ //\r
+ Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
+ if (Instance == NULL) {\r
+ FreePool (StartDevicePath);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Next = Instance;\r
+ while (!IsDevicePathEndType (Next)) {\r
+ Next = NextDevicePathNode (Next);\r
+ }\r
+\r
+ SetDevicePathEndNode (Next);\r
+ //\r
+ // Connect the USB console\r
+ // USB console device path is a short-form device path that\r
+ // starts with the first element being a USB WWID\r
+ // or a USB Class device path\r
+ //\r
+ if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
+ ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))\r
+ ) {\r
+ Status = BmConnectUsbShortFormDevicePath (Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ }\r
+ } else {\r
+ for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {\r
+ if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {\r
+ break;\r
+ } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&\r
+ DevicePathSubType (Next) == HW_CONTROLLER_DP &&\r
+ DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&\r
+ DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP\r
+ ) {\r
+ break;\r
+ }\r
+ }\r
+ if (!IsDevicePathEnd (Next)) {\r
+ //\r
+ // For GOP device path, start the video driver with NULL remaining device path\r
+ //\r
+ SetDevicePathEndNode (Next);\r
+ Status = EfiBootManagerConnectDevicePath (Instance, &Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+ }\r
+ } else {\r
+ Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Delete the instance from the console varialbe\r
+ //\r
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);\r
+ } else {\r
+ DeviceExist = TRUE;\r
+ }\r
+ }\r
+ FreePool(Instance);\r
+ } while (CopyOfDevicePath != NULL);\r
+\r
+ FreePool (StartDevicePath);\r
+\r
+ if (!DeviceExist) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will search every input/output device in current system,\r
+ and make every input/output device as potential console device.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerConnectAllConsoles (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+\r
+ Index = 0;\r
+ HandleCount = 0;\r
+ HandleBuffer = NULL;\r
+ ConDevicePath = NULL;\r
+\r
+ //\r
+ // Update all the console variables\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ConDevicePath\r
+ );\r
+ EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool(HandleBuffer);\r
+ HandleBuffer = NULL;\r
+ }\r
+\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ConDevicePath\r
+ );\r
+ EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);\r
+ EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool(HandleBuffer);\r
+ }\r
+\r
+ //\r
+ // Connect all console variables\r
+ //\r
+ EfiBootManagerConnectAllDefaultConsoles ();\r
+}\r
+\r
+\r
+/**\r
+ This function will connect all the console devices base on the console\r
+ device variable ConIn, ConOut and ErrOut.\r
+\r
+ @retval EFI_DEVICE_ERROR All the consoles were not connected due to an error.\r
+ @retval EFI_SUCCESS Success connect any one instance of the console\r
+ device path base on the variable ConVarName.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectAllDefaultConsoles (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN OneConnected;\r
+ BOOLEAN SystemTableUpdated;\r
+\r
+ OneConnected = FALSE;\r
+\r
+ Status = EfiBootManagerConnectConsoleVariable (ConOut);\r
+ if (!EFI_ERROR (Status)) {\r
+ OneConnected = TRUE;\r
+ }\r
+ PERF_EVENT ("ConOutReady");\r
+\r
+\r
+ Status = EfiBootManagerConnectConsoleVariable (ConIn);\r
+ if (!EFI_ERROR (Status)) {\r
+ OneConnected = TRUE;\r
+ }\r
+ PERF_EVENT ("ConInReady");\r
+\r
+ Status = EfiBootManagerConnectConsoleVariable (ErrOut);\r
+ if (!EFI_ERROR (Status)) {\r
+ OneConnected = TRUE;\r
+ }\r
+ PERF_EVENT ("ErrOutReady");\r
+\r
+ SystemTableUpdated = FALSE;\r
+ //\r
+ // Fill console handles in System Table if no console device assignd.\r
+ //\r
+ if (BmUpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {\r
+ SystemTableUpdated = TRUE;\r
+ }\r
+ if (BmUpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
+ SystemTableUpdated = TRUE;\r
+ }\r
+ if (BmUpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
+ SystemTableUpdated = TRUE;\r
+ }\r
+\r
+ if (SystemTableUpdated) {\r
+ //\r
+ // Update the CRC32 in the EFI System Table header\r
+ //\r
+ gST->Hdr.CRC32 = 0;\r
+ gBS->CalculateCrc32 (\r
+ (UINT8 *) &gST->Hdr,\r
+ gST->Hdr.HeaderSize,\r
+ &gST->Hdr.CRC32\r
+ );\r
+ }\r
+\r
+ return OneConnected ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
+}\r