X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FLibrary%2FPlatformBootManagerLib%2FBdsPlatform.c;h=862fa6ebb4e5f67f3693e1b4bc281546b77cd8df;hp=1988b3e04c3034f7f78971f9565fddac563728b0;hb=a34a886962561f6d8550b2a1bb193798ca456431;hpb=a7566234e92c91ba43e0f016b7d14fb08b871161 diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index 1988b3e04c..862fa6ebb4 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -2,19 +2,20 @@ Platform BDS customizations. Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.
- 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 + 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. + 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 "BdsPlatform.h" +#include #include -#include +#include // @@ -36,11 +37,6 @@ CONST UINT8 PciHostIrqs[] = { 0x0a, 0x0a, 0x0b, 0x0b }; -// -// Array Size macro -// -#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) - // // Type definitions // @@ -88,6 +84,233 @@ InstallDevicePathCallback ( VOID ); +VOID +PlatformRegisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + ASSERT (DevicePath != NULL); + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + } + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + +/** + Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options + whose device paths do not resolve exactly to an FvFile in the system. + + This removes any boot options that point to binaries built into the firmware + and have become stale due to any of the following: + - DXEFV's base address or size changed (historical), + - DXEFV's FvNameGuid changed, + - the FILE_GUID of the pointed-to binary changed, + - the referenced binary is no longer built into the firmware. + + EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only + avoids exact duplicates. +**/ +VOID +RemoveStaleFvFileOptions ( + VOID + ) +{ + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + UINTN Index; + + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, + LoadOptionTypeBoot); + + for (Index = 0; Index < BootOptionCount; ++Index) { + EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode; + EFI_STATUS Status; + EFI_HANDLE FvHandle; + + // + // If the device path starts with neither MemoryMapped(...) nor Fv(...), + // then keep the boot option. + // + Node1 = BootOptions[Index].FilePath; + if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH && + DevicePathSubType (Node1) == HW_MEMMAP_DP) && + !(DevicePathType (Node1) == MEDIA_DEVICE_PATH && + DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) { + continue; + } + + // + // If the second device path node is not FvFile(...), then keep the boot + // option. + // + Node2 = NextDevicePathNode (Node1); + if (DevicePathType (Node2) != MEDIA_DEVICE_PATH || + DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) { + continue; + } + + // + // Locate the Firmware Volume2 protocol instance that is denoted by the + // boot option. If this lookup fails (i.e., the boot option references a + // firmware volume that doesn't exist), then we'll proceed to delete the + // boot option. + // + SearchNode = Node1; + Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, + &SearchNode, &FvHandle); + + if (!EFI_ERROR (Status)) { + // + // The firmware volume was found; now let's see if it contains the FvFile + // identified by GUID. + // + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode; + UINTN BufferSize; + EFI_FV_FILETYPE FoundType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINT32 AuthenticationStatus; + + Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, + (VOID **)&FvProtocol); + ASSERT_EFI_ERROR (Status); + + FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2; + // + // Buffer==NULL means we request metadata only: BufferSize, FoundType, + // FileAttributes. + // + Status = FvProtocol->ReadFile ( + FvProtocol, + &FvFileNode->FvFileName, // NameGuid + NULL, // Buffer + &BufferSize, + &FoundType, + &FileAttributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + // + // The FvFile was found. Keep the boot option. + // + continue; + } + } + + // + // Delete the boot option. + // + Status = EfiBootManagerDeleteLoadOptionVariable ( + BootOptions[Index].OptionNumber, LoadOptionTypeBoot); + DEBUG_CODE ( + CHAR16 *DevicePathString; + + DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath, + FALSE, FALSE); + DEBUG (( + EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE, + "%a: removing stale Boot#%04x %s: %r\n", + __FUNCTION__, + (UINT32)BootOptions[Index].OptionNumber, + DevicePathString == NULL ? L"" : DevicePathString, + Status + )); + if (DevicePathString != NULL) { + FreePool (DevicePathString); + } + ); + } + + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + +VOID +PlatformRegisterOptionsAndKeys ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Enter; + EFI_INPUT_KEY F2; + EFI_INPUT_KEY Esc; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode = SCAN_NULL; + Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; + Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Map F2 to Boot Manager Menu + // + F2.ScanCode = SCAN_F2; + F2.UnicodeChar = CHAR_NULL; + Esc.ScanCode = SCAN_ESC; + Esc.UnicodeChar = CHAR_NULL; + Status = EfiBootManagerGetBootManagerMenu (&BootOption); + ASSERT_EFI_ERROR (Status); + Status = EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL + ); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); + Status = EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL + ); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); +} + EFI_STATUS EFIAPI ConnectRootBridge ( @@ -105,28 +328,28 @@ SaveS3BootScript ( // // BDS Platform Functions // +/** + 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 ) -/*++ - -Routine Description: - - Platform Bds init. Incude the platform firmware vendor, revision - and so crc check. - -Arguments: - -Returns: - - None. - ---*/ { - EFI_HANDLE Handle; - EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_STATUS Status; + RETURN_STATUS PcdStatus; DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n")); InstallDevicePathCallback (); @@ -164,6 +387,19 @@ Returns: &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE, NULL); ASSERT_EFI_ERROR (Status); + + // + // Dispatch deferred images after EndOfDxe event and ReadyToLock + // installation. + // + EfiBootManagerDispatchDeferredImages (); + + PlatformInitializeConsole (gPlatformConsole); + PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, + GetFrontPageTimeoutFromQemu ()); + ASSERT_RETURN_ERROR (PcdStatus); + + PlatformRegisterOptionsAndKeys (); } @@ -192,28 +428,21 @@ ConnectRootBridge ( } +/** + Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut. + + @param[in] DeviceHandle Handle of the LPC Bridge device. + + @retval EFI_SUCCESS Console devices on the LPC bridge have been added to + ConOut, ConIn, and ErrOut. + + @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing + from DeviceHandle. +**/ EFI_STATUS PrepareLpcBridgeDevicePath ( IN EFI_HANDLE DeviceHandle ) -/*++ - -Routine Description: - - Add IsaKeyboard to ConIn, - add IsaSerial to ConOut, ConIn, ErrOut. - LPC Bridge: 06 01 00 - -Arguments: - - DeviceHandle - Handle of PCIIO protocol. - -Returns: - - EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut. - EFI_STATUS - No LPC bridge is added. - ---*/ { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; @@ -234,9 +463,10 @@ Returns: // // Register Keyboard // - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); - BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); // // Register COM1 @@ -244,14 +474,17 @@ Returns: DevicePath = TempDevicePath; gPnp16550ComPortDeviceNode.UID = 0; - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); // // Print Device Path // - DevPathStr = DevicePathToStr(DevicePath); + DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE); if (DevPathStr != NULL) { DEBUG(( EFI_D_INFO, @@ -263,9 +496,9 @@ Returns: FreePool(DevPathStr); } - BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); - BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); - BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); // // Register COM2 @@ -273,14 +506,17 @@ Returns: DevicePath = TempDevicePath; gPnp16550ComPortDeviceNode.UID = 1; - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); // // Print Device Path // - DevPathStr = DevicePathToStr(DevicePath); + DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE); if (DevPathStr != NULL) { DEBUG(( EFI_D_INFO, @@ -292,9 +528,9 @@ Returns: FreePool(DevPathStr); } - BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); - BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); - BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); return EFI_SUCCESS; } @@ -333,7 +569,7 @@ GetGopDevicePath ( } // - // Try to connect this handle, so that GOP dirver could start on this + // Try to connect this handle, 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. @@ -352,7 +588,8 @@ GetGopDevicePath ( // Add all the child handles as possible Console Device // for (Index = 0; Index < GopHandleCount; Index++) { - Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); + Status = gBS->HandleProtocol (GopHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); if (EFI_ERROR (Status)) { continue; } @@ -365,17 +602,17 @@ GetGopDevicePath ( // In current implementation, we only enable one of the child handles // as console device, i.e. sotre one of the child handle's device // path to variable "ConOut" - // In futhure, we could select all child handles to be console device + // In future, we could select all child handles to be console device // *GopDevicePath = TempDevicePath; // - // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() - // Add the integrity GOP device path. + // Delete the PCI device's path that added by + // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path. // - BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath); - BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath); + EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL); } } gBS->FreePool (GopHandleBuffer); @@ -384,27 +621,20 @@ GetGopDevicePath ( return EFI_SUCCESS; } -EFI_STATUS -PreparePciVgaDevicePath ( - IN EFI_HANDLE DeviceHandle - ) -/*++ - -Routine Description: - - Add PCI VGA to ConOut. - PCI VGA: 03 00 00 - -Arguments: - - DeviceHandle - Handle of PCIIO protocol. +/** + Add PCI display to ConOut. -Returns: + @param[in] DeviceHandle Handle of the PCI display device. - EFI_SUCCESS - PCI VGA is added to ConOut. - EFI_STATUS - No PCI VGA device is added. + @retval EFI_SUCCESS The PCI display device has been added to ConOut. ---*/ + @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing + from DeviceHandle. +**/ +EFI_STATUS +PreparePciDisplayDevicePath ( + IN EFI_HANDLE DeviceHandle + ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; @@ -424,32 +654,26 @@ Returns: GetGopDevicePath (DevicePath, &GopDevicePath); DevicePath = GopDevicePath; - BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); return EFI_SUCCESS; } -EFI_STATUS -PreparePciSerialDevicePath ( - IN EFI_HANDLE DeviceHandle - ) -/*++ - -Routine Description: - +/** Add PCI Serial to ConOut, ConIn, ErrOut. - PCI Serial: 07 00 02 - -Arguments: - - DeviceHandle - Handle of PCIIO protocol. -Returns: + @param[in] DeviceHandle Handle of the PCI serial device. - EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut. - EFI_STATUS - No PCI Serial device is added. + @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn, + ErrOut. ---*/ + @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing + from DeviceHandle. +**/ +EFI_STATUS +PreparePciSerialDevicePath ( + IN EFI_HANDLE DeviceHandle + ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; @@ -464,12 +688,14 @@ Returns: return Status; } - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); - DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); - BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); - BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); - BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); return EFI_SUCCESS; } @@ -581,7 +807,8 @@ VisitAllPciInstances ( @param[in] PciIo - PCI IO protocol instance @param[in] Pci - PCI Header register block - @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_SUCCESS - PCI Device check and Console variable update + successfully. @retval EFI_STATUS - PCI Device check or Console variable update fail. **/ @@ -635,14 +862,14 @@ DetectAndPreparePlatformPciDevicePath ( } // - // Here we decide which VGA device to enable in PCI bus + // Here we decide which display device to enable in PCI bus // - if (IS_PCI_VGA (Pci)) { + if (IS_PCI_DISPLAY (Pci)) { // // Add them to ConOut. // - DEBUG ((EFI_D_INFO, "Found PCI VGA device\n")); - PreparePciVgaDevicePath (Handle); + DEBUG ((EFI_D_INFO, "Found PCI display device\n")); + PreparePciDisplayDevicePath (Handle); return EFI_SUCCESS; } @@ -655,7 +882,8 @@ DetectAndPreparePlatformPciDevicePath ( @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE. - @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_SUCCESS - PCI Device check and Console variable update + successfully. @retval EFI_STATUS - PCI Device check or Console variable update fail. **/ @@ -669,61 +897,39 @@ DetectAndPreparePlatformPciDevicePaths ( } -EFI_STATUS -PlatformBdsConnectConsole ( - IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole - ) -/*++ - -Routine Description: - - Connect the predefined platform default console device. Always try to find - and enable the vga device if have. - -Arguments: - - PlatformConsole - Predfined platform default console device array. - -Returns: - - EFI_SUCCESS - Success connect at least one ConIn and ConOut - device, there must have one ConOut device is - active vga device. +/** + Connect the predefined platform default console device. - EFI_STATUS - Return the status of - BdsLibConnectAllDefaultConsoles () + Always try to find and enable PCI display devices. ---*/ + @param[in] PlatformConsole Predefined platform default console device array. +**/ +VOID +PlatformInitializeConsole ( + IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) { - EFI_STATUS Status; UINTN Index; EFI_DEVICE_PATH_PROTOCOL *VarConout; EFI_DEVICE_PATH_PROTOCOL *VarConin; - UINTN DevicePathSize; // // Connect RootBridge // - VarConout = BdsLibGetVariableAndSize ( - VarConsoleOut, - &gEfiGlobalVariableGuid, - &DevicePathSize - ); - VarConin = BdsLibGetVariableAndSize ( - VarConsoleInp, - &gEfiGlobalVariableGuid, - &DevicePathSize - ); + GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, + NULL); + GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL); if (VarConout == NULL || VarConin == NULL) { // - // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + // Do platform specific PCI Device check and add them to ConOut, ConIn, + // ErrOut // DetectAndPreparePlatformPciDevicePaths (FALSE); // // Have chance to connect the platform default console, - // the platform default console is the minimue device group + // the platform default console is the minimum device group // the platform should support // for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) { @@ -731,13 +937,16 @@ Returns: // Update the console variable with the connect type // if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { - BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, + PlatformConsole[Index].DevicePath, NULL); } if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { - BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, + PlatformConsole[Index].DevicePath, NULL); } if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { - BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, + PlatformConsole[Index].DevicePath, NULL); } } } else { @@ -746,16 +955,6 @@ Returns: // DetectAndPreparePlatformPciDevicePaths (TRUE); } - - // - // Connect the all the default console with current cosole variable - // - Status = BdsLibConnectAllDefaultConsoles (); - if (EFI_ERROR (Status)) { - return Status; - } - - return EFI_SUCCESS; } @@ -964,6 +1163,37 @@ PciAcpiInitialization ( IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0); } +/** + This function detects if OVMF is running on Xen. + +**/ +STATIC +BOOLEAN +XenDetected ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + STATIC INTN FoundHob = -1; + + if (FoundHob == 0) { + return FALSE; + } else if (FoundHob == 1) { + return TRUE; + } + + // + // See if a XenInfo HOB is available + // + GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid); + if (GuidHob == NULL) { + FoundHob = 0; + return FALSE; + } + + FoundHob = 1; + return TRUE; +} EFI_STATUS EFIAPI @@ -977,7 +1207,11 @@ ConnectRecursivelyIfPciMassStorage ( EFI_DEVICE_PATH_PROTOCOL *DevicePath; CHAR16 *DevPathStr; - if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) { + // + // Recognize PCI Mass Storage, and Xen PCI devices + // + if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) || + (XenDetected() && IS_CLASS2 (PciHeader, 0xFF, 0x80))) { DevicePath = NULL; Status = gBS->HandleProtocol ( Handle, @@ -991,11 +1225,15 @@ ConnectRecursivelyIfPciMassStorage ( // // Print Device Path // - DevPathStr = DevicePathToStr (DevicePath); + DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE); if (DevPathStr != NULL) { DEBUG(( EFI_D_INFO, - "Found Mass Storage device: %s\n", + "Found %s device: %s\n", + (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ? + L"Mass Storage" : + L"Xen" + ), DevPathStr )); FreePool(DevPathStr); @@ -1016,8 +1254,8 @@ ConnectRecursivelyIfPciMassStorage ( This notification function is invoked when the EMU Variable FVB has been changed. - @param Event The event that occured - @param Context For EFI compatiblity. Not used. + @param Event The event that occurred + @param Context For EFI compatibility. Not used. **/ VOID @@ -1042,6 +1280,7 @@ VisitingFileSystemInstance ( { EFI_STATUS Status; STATIC BOOLEAN ConnectedToFileSystem = FALSE; + RETURN_STATUS PcdStatus; if (ConnectedToFileSystem) { return EFI_ALREADY_STARTED; @@ -1061,7 +1300,9 @@ VisitingFileSystemInstance ( NULL, &mEmuVariableEventReg ); - PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent); + PcdStatus = PcdSet64S (PcdEmuVariableEvent, + (UINT64)(UINTN) mEmuVariableEvent); + ASSERT_RETURN_ERROR (PcdStatus); return EFI_SUCCESS; } @@ -1080,29 +1321,18 @@ PlatformBdsRestoreNvVarsFromHardDisk ( } +/** + Connect with predefined platform connect sequence. + The OEM/IBV can customize with their own connect sequence. +**/ VOID PlatformBdsConnectSequence ( VOID ) -/*++ - -Routine Description: - - Connect with predeined platform connect sequence, - the OEM/IBV can customize with their own connect sequence. - -Arguments: - - None. - -Returns: - - None. - ---*/ { - UINTN Index; + UINTN Index; + RETURN_STATUS Status; DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n")); @@ -1117,104 +1347,20 @@ Returns: // // Build the platform boot option // - BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); + EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL); Index++; } - // - // Just use the simple policy to connect all devices - // - BdsLibConnectAll (); - - PciAcpiInitialization (); - - // - // Clear the logo after all devices are connected. - // - gST->ConOut->ClearScreen (gST->ConOut); -} - -VOID -PlatformBdsGetDriverOption ( - IN OUT LIST_ENTRY *BdsDriverLists - ) -/*++ - -Routine Description: - - Load the predefined driver option, OEM/IBV can customize this - to load their own drivers - -Arguments: - - BdsDriverLists - The header of the driver option link list. - -Returns: - - None. - ---*/ -{ - DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n")); - return; -} - -VOID -PlatformBdsDiagnostics ( - IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, - IN BOOLEAN QuietBoot, - IN BASEM_MEMORY_TEST BaseMemoryTest - ) -/*++ - -Routine Description: - - Perform the platform diagnostic, such like test memory. OEM/IBV also - can customize this fuction to support specific platform diagnostic. - -Arguments: - - MemoryTestLevel - The memory test intensive level - - QuietBoot - Indicate if need to enable the quiet boot - - BaseMemoryTest - A pointer to BaseMemoryTest() - -Returns: - - None. - ---*/ -{ - EFI_STATUS Status; - - DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n")); - - // - // Here we can decide if we need to show - // the diagnostics screen - // Notes: this quiet boot code should be remove - // from the graphic lib - // - if (QuietBoot) { - EnableQuietBoot (PcdGetPtr(PcdLogoFile)); + Status = ConnectDevicesFromQemu (); + if (RETURN_ERROR (Status)) { // - // Perform system diagnostic + // Just use the simple policy to connect all devices // - Status = BaseMemoryTest (MemoryTestLevel); - if (EFI_ERROR (Status)) { - DisableQuietBoot (); - } - - return ; + DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n")); + EfiBootManagerConnectAll (); } - // - // Perform system diagnostic - // - Status = BaseMemoryTest (MemoryTestLevel); } - /** Save the S3 boot script. @@ -1247,22 +1393,25 @@ SaveS3BootScript ( } +/** + Do the platform specific action after the console is ready + + Possible things that can be done in PlatformBootManagerAfterConsole: + + > Console post action: + > Dynamically switch output mode from 100x31 to 80x25 for certain senarino + > Signal console ready platform customized event + > Run diagnostics like memory testing + > Connect certain devices + > Dispatch aditional option roms + > Special boot: e.g.: USB boot, enter UI +**/ VOID EFIAPI PlatformBootManagerAfterConsole ( VOID ) -/*++ - -Routine Description: - - The function will excute with as the platform policy, current policy - is driven by boot mode. IBV/OEM can customize this code for their specific - policy action. - ---*/ { - EFI_STATUS Status; EFI_BOOT_MODE BootMode; DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n")); @@ -1278,187 +1427,57 @@ Routine Description: PlatformBdsRestoreNvVarsFromHardDisk (); } - // - // Load the driver option as the driver option list - // - PlatformBdsGetDriverOption (DriverOptionList); - // // Get current Boot Mode // - Status = BdsLibGetBootMode (&BootMode); - DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); + BootMode = GetBootModeHob (); + DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode)); // // Go the different platform policy with different boot mode // Notes: this part code can be change with the table policy // ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); - // - // Connect platform console - // - Status = PlatformBdsConnectConsole (gPlatformConsole); - if (EFI_ERROR (Status)) { - // - // Here OEM/IBV can customize with defined action - // - PlatformBdsNoConsoleAction (); - } // - // Memory test and Logo show + // Logo show // - PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); + BootLogoEnableLogo (); // - // Perform some platform specific connect sequence + // Set PCI Interrupt Line registers and ACPI SCI_EN // - PlatformBdsConnectSequence (); + PciAcpiInitialization (); // // Process QEMU's -kernel command line option // TryRunningQemuKernel (); - DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n")); - BdsLibConnectAll (); - BdsLibEnumerateAllBootOption (BootOptionList); - - SetBootOrderFromQemu (BootOptionList); - // - // The BootOrder variable may have changed, reload the in-memory list with - // it. // - BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); - - PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE); -} - -VOID -EFIAPI -PlatformBdsBootSuccess ( - IN BDS_COMMON_OPTION *Option - ) -/*++ - -Routine Description: - - Hook point after a boot attempt succeeds. We don't expect a boot option to - return, so the EFI 1.0 specification defines that you will default to an - interactive mode and stop processing the BootOrder list in this case. This - is alos a platform implementation and can be customized by IBV/OEM. - -Arguments: - - Option - Pointer to Boot Option that succeeded to boot. - -Returns: - - None. - ---*/ -{ - CHAR16 *TmpStr; - - DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n")); - // - // If Boot returned with EFI_SUCCESS and there is not in the boot device - // select loop then we need to pop up a UI and wait for user input. + // Perform some platform specific connect sequence // - TmpStr = Option->StatusString; - if (TmpStr != NULL) { - BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); - FreePool (TmpStr); - } -} - -VOID -EFIAPI -PlatformBdsBootFail ( - IN BDS_COMMON_OPTION *Option, - IN EFI_STATUS Status, - IN CHAR16 *ExitData, - IN UINTN ExitDataSize - ) -/*++ - -Routine Description: - - Hook point after a boot attempt fails. - -Arguments: - - Option - Pointer to Boot Option that failed to boot. - - Status - Status returned from failed boot. - - ExitData - Exit data returned from failed boot. - - ExitDataSize - Exit data size returned from failed boot. - -Returns: - - None. - ---*/ -{ - CHAR16 *TmpStr; + PlatformBdsConnectSequence (); - DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n")); + EfiBootManagerRefreshAllBootOption (); // - // If Boot returned with failed status then we need to pop up a UI and wait - // for user input. + // Register UEFI Shell // - TmpStr = Option->StatusString; - if (TmpStr != NULL) { - BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); - FreePool (TmpStr); - } -} - -EFI_STATUS -PlatformBdsNoConsoleAction ( - VOID - ) -/*++ - -Routine Description: - - This function is remained for IBV/OEM to do some platform action, - if there no console device can be connected. - -Arguments: - - None. - -Returns: - - EFI_SUCCESS - Direct return success now. + PlatformRegisterFvBootOption ( + PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE + ); ---*/ -{ - DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n")); - return EFI_SUCCESS; + RemoveStaleFvFileOptions (); + SetBootOrderFromQemu (); } -VOID -EFIAPI -PlatformBdsLockNonUpdatableFlash ( - VOID - ) -{ - DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n")); - return; -} - - /** This notification function is invoked when an instance of the EFI_DEVICE_PATH_PROTOCOL is produced. - @param Event The event that occured - @param Context For EFI compatiblity. Not used. + @param Event The event that occurred + @param Context For EFI compatibility. Not used. **/ VOID @@ -1504,7 +1523,8 @@ NotifyDevPath ( // // Get the DevicePath protocol on that handle // - Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode); + Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, + (VOID **)&DevPathNode); ASSERT_EFI_ERROR (Status); while (!IsDevicePathEnd (DevPathNode)) { @@ -1554,7 +1574,8 @@ InstallDevicePathCallback ( } /** - This function is called each second during the boot manager waits the timeout. + This function is called each second during the boot manager waits the + timeout. @param TimeoutRemain The remaining timeout. **/ @@ -1564,25 +1585,22 @@ PlatformBootManagerWaitCallback ( UINT16 TimeoutRemain ) { -} - -/** - Lock the ConsoleIn device in system table. All key - presses will be ignored until the Password is typed in. The only way to - disable the password is to type it in to a ConIn device. - - @param Password Password used to lock ConIn device. - - @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully. - @retval EFI_UNSUPPORTED Password not found - -**/ -EFI_STATUS -EFIAPI -LockKeyboards ( - IN CHAR16 *Password - ) -{ - return EFI_UNSUPPORTED; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; + UINT16 Timeout; + + Timeout = PcdGet16 (PcdPlatformBootTimeOut); + + Black.Raw = 0x00000000; + White.Raw = 0x00FFFFFF; + + BootLogoUpdateProgress ( + White.Pixel, + Black.Pixel, + L"Start boot option", + White.Pixel, + (Timeout - TimeoutRemain) * 100 / Timeout, + 0 + ); }