| /** @file | |
| Library functions which contain all the code to connect console device. | |
| Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> | |
| (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #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 ((DEBUG_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 driver 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; | |
| EFI_DEVICE_PATH_PROTOCOL *FullInstance; | |
| 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 ((DEBUG_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 | |
| // | |
| FullInstance = Instance; | |
| Status = gBS->LocateDevicePath ( | |
| ConsoleGuid, | |
| &Instance, | |
| &NewHandle | |
| ); | |
| FreePool (FullInstance); | |
| 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); | |
| } | |
| } | |
| FreePool (FullDevicePath); | |
| return TRUE; | |
| } | |
| } | |
| } while (Instance != NULL); | |
| // | |
| // No any available console devcie found. | |
| // | |
| FreePool (FullDevicePath); | |
| 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 >= ARRAY_SIZE (mConVarName)) { | |
| 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_EVENT ("ConOutReady"); | |
| Status = EfiBootManagerConnectConsoleVariable (ConIn); | |
| if (!EFI_ERROR (Status)) { | |
| OneConnected = TRUE; | |
| } | |
| PERF_EVENT ("ConInReady"); | |
| Status = EfiBootManagerConnectConsoleVariable (ErrOut); | |
| if (!EFI_ERROR (Status)) { | |
| OneConnected = TRUE; | |
| } | |
| PERF_EVENT ("ErrOutReady"); | |
| 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; | |
| } |