/** Initialize the platform default console variables when the console variable is empty. @param PlatformConsole Predfined platform default console device array. **/ VOID InitializeConsoleVariables ( IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole ) { UINTN Index; EFI_DEVICE_PATH_PROTOCOL *VarConOut; EFI_DEVICE_PATH_PROTOCOL *VarConIn; EFI_BOOT_MODE BootMode; BootMode = GetBootModeHob (); VarConOut = GetEfiGlobalVariable (L"ConOut"); if (VarConOut != NULL) { FreePool (VarConOut); } VarConIn = GetEfiGlobalVariable (L"ConIn"); if (VarConIn != NULL) { FreePool (VarConIn); } if (VarConOut == NULL || VarConIn == NULL) { // // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot // for (Index = 0; PlatformConsole[Index].DevicePath != NULL; Index++) { // // Update the console variable with the connect type // if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL); } if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL); } if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL); } } } }
/** This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the handle, and adds it to ConOut and ErrOut. **/ STATIC VOID EFIAPI AddOutput ( IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; DevicePath = DevicePathFromHandle (Handle); if (DevicePath == NULL) { DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n", __FUNCTION__, ReportText, Handle)); return; } Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, ReportText, Status)); return; } Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, ReportText, Status)); return; } DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, ReportText)); }
/** Do the platform init, can be customized by OEM/IBV Possible things that can be done in PlatformBootManagerBeforeConsole: > Update console variable: 1. include hot-plug devices; > 2. Clear ConIn and add SOL for AMT > Register new Driver#### or Boot#### > Register new Key####: e.g.: F12 > Signal ReadyToLock event > Authentication action: 1. connect Auth devices; > 2. Identify auto logon user. **/ VOID EFIAPI PlatformBootManagerBeforeConsole ( VOID ) { // // Signal EndOfDxe PI Event // EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); // // Locate the PCI root bridges and make the PCI bus driver connect each, // non-recursively. This will produce a number of child handles with PciIo on // them. // FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); // // Find all display class PCI devices (using the handles from the previous // step), and connect them non-recursively. This should produce a number of // child handles with GOPs on them. // FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); // // Now add the device path of all handles with GOP on them to ConOut and // ErrOut. // FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); // // Add the hardcoded short-form USB keyboard device path to ConIn. // EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); // // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. // ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4); CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); EfiBootManagerUpdateConsoleVariable (ConOut, (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); EfiBootManagerUpdateConsoleVariable (ErrOut, (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); // // Register platform-specific boot options and keyboard shortcuts. // PlatformRegisterOptionsAndKeys (); }
/** Do the platform specific action before the console is connected. Such as: Update console variable; Register new Driver#### or Boot####; Signal ReadyToLock event. **/ VOID EFIAPI PlatformBootManagerBeforeConsole ( VOID ) { UINTN Index; EFI_STATUS Status; WIN_NT_SYSTEM_CONFIGURATION *Configuration; GetVariable2 (L"Setup", &gEfiWinNtSystemConfigGuid, (VOID **) &Configuration, NULL); if (Configuration != NULL) { // // SetupVariable is corrupt // Configuration->ConOutRow = PcdGet32 (PcdConOutColumn); Configuration->ConOutColumn = PcdGet32 (PcdConOutRow); Status = gRT->SetVariable ( L"Setup", &gEfiWinNtSystemConfigGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (WIN_NT_SYSTEM_CONFIGURATION), Configuration ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Failed to save Setup Variable to non-volatile storage, Status = %r\n", Status)); } FreePool (Configuration); } // // Update the ocnsole variables. // for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) { if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL); } if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL); } if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL); } } // // From PI spec vol2: // Prior to invoking any UEFI drivers, applications, or connecting consoles, // the platform should signal the event EFI_END_OF_DXE_EVENT_GUID // EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); }
/** Do the platform specific action before the console is connected. Such as: Update console variable; Register new Driver#### or Boot####; Signal ReadyToLock event. **/ VOID EFIAPI PlatformBootManagerBeforeConsole ( VOID ) { UINTN Index; EFI_STATUS Status; WIN_NT_SYSTEM_CONFIGURATION *Configuration; EFI_INPUT_KEY Enter; EFI_INPUT_KEY F2; EFI_BOOT_MANAGER_LOAD_OPTION BootOption; // // Update the ocnsole variables. // for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) { if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL); } if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL); } if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL); } } // // Register ENTER as CONTINUE key // Enter.ScanCode = SCAN_NULL; Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); // // Map F2 to Boot Manager Menu // F2.ScanCode = SCAN_F2; F2.UnicodeChar = CHAR_NULL; EfiBootManagerGetBootManagerMenu (&BootOption); EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL); // // Register UEFI Shell // PlatformRegisterFvBootOption (&mUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE); }
/** Find the platform active active video controller and connect it. @retval EFI_NOT_FOUND There is no active video controller. @retval EFI_SUCCESS The video controller is connected. **/ EFI_STATUS ConnectVideoController ( VOID ) { EFI_HANDLE VideoController; EFI_DEVICE_PATH_PROTOCOL *Gop; // // Get the platform vga device // VideoController = GetVideoController (); 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) { // // Last chance - just try VGA controller // Don't assume all VGA controller support GOP operation // DEBUG ((EFI_D_ERROR, "[Bds] GOP not found, try VGA device path!\n")); Gop = DuplicateDevicePath (DevicePathFromHandle (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); }
/** 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); }
// // BDS Platform Functions // VOID EFIAPI PlatformBootManagerBeforeConsole ( VOID ) { EFI_HANDLE Handle; EFI_STATUS Status; EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save; BOOLEAN SecureBootSupportEnabled; BOOLEAN SecureBootEnabled; SecureBootSupportEnabled = FALSE; SecureBootEnabled = FALSE; if (FeaturePcdGet (PcdSupportSecureBoot)) { // // Auto provision UEFI Secure boot. // SecureBootSupportEnabled = TRUE; SecureBootEnabled = PlatformAutoProvisionSecureBoot (); // // UEFI Secure boot not supported / validated for this firmware release. // ASSERT (FALSE); } if (FeaturePcdGet (PcdEnableSecureLock)) { if (!SecureBootEnabled) { PcdSetBool (PcdConInConnectOnDemand, TRUE); } DEBUG ( (EFI_D_INFO, "Secure Lock ENABLED Secure Boot Support %s Secure Boot %s\n", SecureBootSupportEnabled ? L"ENABLED" : L"DISABLED", SecureBootEnabled ? L"ENABLED" : L"DISABLED" )); } else { DEBUG ( (EFI_D_INFO, "Secure Lock DISABLED Secure Boot Support %s Secure Boot %s\n", SecureBootSupportEnabled ? L"ENABLED" : L"DISABLED", SecureBootEnabled ? L"ENABLED" : L"DISABLED" )); } // // Add platform string package // InitializeStringSupport (); InitializeConsoleVariables (gPlatformConsole); UpdateConOut (); RegisterLoadOptions (); Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **)&AcpiS3Save); if (!EFI_ERROR (Status)) { AcpiS3Save->S3Save (AcpiS3Save, NULL); } // // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter // Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &gExitPmAuthProtocolGuid, EFI_NATIVE_INTERFACE, NULL ); ASSERT_EFI_ERROR (Status); // // Append Usb Keyboard short form DevicePath into "ConInDev" // EfiBootManagerUpdateConsoleVariable ( ConInDev, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL ); // // Before user authentication, the user identification devices need be connected // from the platform customized device paths // ConnectAuthDevice (); // // As console is not ready, the auto logon user will be identified. // UserIdentify (&mCurrentUser); }
VOID UpdateConOut ( VOID ) { EFI_HANDLE VideoController; EFI_DEVICE_PATH_PROTOCOL *Gop; EFI_HANDLE OnboardVideoController = NULL; EFI_HANDLE AddinVideoController = NULL; UINTN VideoSelect; // // Get the platform vga device // VideoController = PlatformGetVideoController (&OnboardVideoController, &AddinVideoController); if (VideoController == NULL) { return ; } // Force to Auto VideoSelect = 0; // If device selected by SystemConfig is not present, force to Auto if (VideoSelect == 1 && OnboardVideoController == NULL) { VideoSelect = 0; } if (VideoSelect == 2 && AddinVideoController == NULL) { VideoSelect = 0; } switch(VideoSelect) { case 1: // Onboard selected VideoController = OnboardVideoController; DEBUG((EFI_D_INFO, "Video select: Onboard\n")); break; case 2: // Add-in selected VideoController = AddinVideoController; DEBUG((EFI_D_INFO, "Video select: Add-in\n")); break; case 0: default: // Use first VideoController found, which is what GetVideoController returns as VideoController DEBUG((EFI_D_INFO, "Video select: Auto\n")); break; } // // 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 ; } // // Update ConOut variable to remove device path of on-board/add-in video controller // and add the device path of the specified video controller // EfiBootManagerUpdateConsoleVariable (ConOut, NULL, DevicePathFromHandle (OnboardVideoController)); EfiBootManagerUpdateConsoleVariable (ConOut, Gop, DevicePathFromHandle (AddinVideoController)); FreePool (Gop); }
/** 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 (); }
/** 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; }
/** Do the platform init, can be customized by OEM/IBV Possible things that can be done in PlatformBootManagerBeforeConsole: > Update console variable: 1. include hot-plug devices; > 2. Clear ConIn and add SOL for AMT > Register new Driver#### or Boot#### > Register new Key####: e.g.: F12 > Signal ReadyToLock event > Authentication action: 1. connect Auth devices; > 2. Identify auto logon user. **/ VOID EFIAPI PlatformBootManagerBeforeConsole ( VOID ) { // // Signal EndOfDxe PI Event // EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); // // Locate the PCI root bridges and make the PCI bus driver connect each, // non-recursively. This will produce a number of child handles with PciIo on // them. // FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); // // Signal the ACPI platform driver that it can download QEMU ACPI tables. // EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid); // // Find all display class PCI devices (using the handles from the previous // step), and connect them non-recursively. This should produce a number of // child handles with GOPs on them. // FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); // // Now add the device path of all handles with GOP on them to ConOut and // ErrOut. // FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); // // Add the hardcoded short-form USB keyboard device path to ConIn. // EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); // // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. // CopyGuid (&mSerialConsole.TermType.Guid, PcdGetPtr (PcdTerminalTypeGuidBuffer)); EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); EfiBootManagerUpdateConsoleVariable (ConOut, (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); EfiBootManagerUpdateConsoleVariable (ErrOut, (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); // // Set the front page timeout from the QEMU configuration. // PcdSet16 (PcdPlatformBootTimeOut, GetFrontPageTimeoutFromQemu ()); // // Register platform-specific boot options and keyboard shortcuts. // PlatformRegisterOptionsAndKeys (); }
/** Connect the console device base on the variable ConsoleType. @param ConsoleType ConIn, ConOut or ErrOut. @param NeedDispatch Whether need to dispatch. @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, IN BOOLEAN NeedDispatch ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *StartDevicePath; UINTN VariableSize; 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; // // Check if the console variable exist // StartDevicePath = EfiBootManagerGetVariableAndSize ( mConVarName[ConsoleType], &gEfiGlobalVariableGuid, &VariableSize ); 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 (FeaturePcdGet (PcdShortformBootSupport) && (DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)) ) { Status = EfiBootManagerConnectUsbShortFormDevicePath (Instance); if (!EFI_ERROR (Status)) { DeviceExist = TRUE; } } else { // // Connect the instance device path // Status = ConnectDevicePath (Instance, NeedDispatch, NULL); if (EFI_ERROR (Status)) { // // Do not delete the instance from the console variable if the device path is of GOP type // and the parent controller exists in the system // This is to support the monitor hotplug in a headless boot // for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) { if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) { break; } } if (!IsDevicePathEnd (Next)) { Next = Instance; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Next, &Handle); if (!EFI_ERROR (Status) && (DevicePathType (Next) != ACPI_DEVICE_PATH || DevicePathSubType (Next) != ACPI_ADR_DP)) { // // We found the parent controller but it's not the direct parent of the ADR device path instance // which indicates the video controller doesn't exist. // If this happens, we need to delete the invalid device path from ConOut // Status = EFI_NOT_FOUND; } } } else { DeviceExist = TRUE; } if (EFI_ERROR (Status)) { // // Delete the instance from the console variable // EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance); } } FreePool(Instance); } while (CopyOfDevicePath != NULL); FreePool (StartDevicePath); if ((ConsoleType == ConOut) && FeaturePcdGet (PcdBdsFindDisplay) && !HasLocalDisplay ()) { // // Force to connect local video controller // Backward compatible to old platforms which don't insert the GOP device path to ConOut // DEBUG ((EFI_D_ERROR, "[Bds] Local display isn't found, find & connect it automatically\n")); Status = ConnectVideoController (); if (!EFI_ERROR (Status)) { DeviceExist = TRUE; } } if (!DeviceExist) { return EFI_NOT_FOUND; } return EFI_SUCCESS; }