12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067 |
- /** @file
- Implementation for PlatformBootManagerLib library class interfaces.
- Copyright (C) 2015-2016, Red Hat, Inc.
- Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
- Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <IndustryStandard/Pci22.h>
- #include <IndustryStandard/Virtio095.h>
- #include <Library/BootLogoLib.h>
- #include <Library/DevicePathLib.h>
- #include <Library/PcdLib.h>
- #include <Library/PlatformBmPrintScLib.h>
- #include <Library/QemuBootOrderLib.h>
- #include <Library/TpmPlatformHierarchyLib.h>
- #include <Library/UefiBootManagerLib.h>
- #include <Protocol/DevicePath.h>
- #include <Protocol/FirmwareVolume2.h>
- #include <Protocol/GraphicsOutput.h>
- #include <Protocol/LoadedImage.h>
- #include <Protocol/PciIo.h>
- #include <Protocol/PciRootBridgeIo.h>
- #include <Protocol/VirtioDevice.h>
- #include <Guid/EventGroup.h>
- #include <Guid/GlobalVariable.h>
- #include <Guid/RootBridgesConnectedEventGroup.h>
- #include <Guid/SerialPortLibVendor.h>
- #include "PlatformBm.h"
- #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
- #pragma pack (1)
- typedef struct {
- VENDOR_DEVICE_PATH SerialDxe;
- UART_DEVICE_PATH Uart;
- VENDOR_DEFINED_DEVICE_PATH TermType;
- EFI_DEVICE_PATH_PROTOCOL End;
- } PLATFORM_SERIAL_CONSOLE;
- #pragma pack ()
- STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
- //
- // VENDOR_DEVICE_PATH SerialDxe
- //
- {
- { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
- EDKII_SERIAL_PORT_LIB_VENDOR_GUID
- },
- //
- // UART_DEVICE_PATH Uart
- //
- {
- { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
- 0, // Reserved
- FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
- FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
- FixedPcdGet8 (PcdUartDefaultParity), // Parity
- FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
- },
- //
- // VENDOR_DEFINED_DEVICE_PATH TermType
- //
- {
- {
- MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
- DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
- }
- //
- // Guid to be filled in dynamically
- //
- },
- //
- // EFI_DEVICE_PATH_PROTOCOL End
- //
- {
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
- DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
- }
- };
- #pragma pack (1)
- typedef struct {
- USB_CLASS_DEVICE_PATH Keyboard;
- EFI_DEVICE_PATH_PROTOCOL End;
- } PLATFORM_USB_KEYBOARD;
- #pragma pack ()
- STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
- //
- // USB_CLASS_DEVICE_PATH Keyboard
- //
- {
- {
- MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
- DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
- },
- 0xFFFF, // VendorId: any
- 0xFFFF, // ProductId: any
- 3, // DeviceClass: HID
- 1, // DeviceSubClass: boot
- 1 // DeviceProtocol: keyboard
- },
- //
- // EFI_DEVICE_PATH_PROTOCOL End
- //
- {
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
- DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
- }
- };
- /**
- Check if the handle satisfies a particular condition.
- @param[in] Handle The handle to check.
- @param[in] ReportText A caller-allocated string passed in for reporting
- purposes. It must never be NULL.
- @retval TRUE The condition is satisfied.
- @retval FALSE Otherwise. This includes the case when the condition could not
- be fully evaluated due to an error.
- **/
- typedef
- BOOLEAN
- (EFIAPI *FILTER_FUNCTION)(
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- );
- /**
- Process a handle.
- @param[in] Handle The handle to process.
- @param[in] ReportText A caller-allocated string passed in for reporting
- purposes. It must never be NULL.
- **/
- typedef
- VOID
- (EFIAPI *CALLBACK_FUNCTION)(
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- );
- /**
- Locate all handles that carry the specified protocol, filter them with a
- callback function, and pass each handle that passes the filter to another
- callback.
- @param[in] ProtocolGuid The protocol to look for.
- @param[in] Filter The filter function to pass each handle to. If this
- parameter is NULL, then all handles are processed.
- @param[in] Process The callback function to pass each handle to that
- clears the filter.
- **/
- STATIC
- VOID
- FilterAndProcess (
- IN EFI_GUID *ProtocolGuid,
- IN FILTER_FUNCTION Filter OPTIONAL,
- IN CALLBACK_FUNCTION Process
- )
- {
- EFI_STATUS Status;
- EFI_HANDLE *Handles;
- UINTN NoHandles;
- UINTN Idx;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- ProtocolGuid,
- NULL /* SearchKey */,
- &NoHandles,
- &Handles
- );
- if (EFI_ERROR (Status)) {
- //
- // This is not an error, just an informative condition.
- //
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: %g: %r\n",
- __FUNCTION__,
- ProtocolGuid,
- Status
- ));
- return;
- }
- ASSERT (NoHandles > 0);
- for (Idx = 0; Idx < NoHandles; ++Idx) {
- CHAR16 *DevicePathText;
- STATIC CHAR16 Fallback[] = L"<device path unavailable>";
- //
- // The ConvertDevicePathToText() function handles NULL input transparently.
- //
- DevicePathText = ConvertDevicePathToText (
- DevicePathFromHandle (Handles[Idx]),
- FALSE, // DisplayOnly
- FALSE // AllowShortcuts
- );
- if (DevicePathText == NULL) {
- DevicePathText = Fallback;
- }
- if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {
- Process (Handles[Idx], DevicePathText);
- }
- if (DevicePathText != Fallback) {
- FreePool (DevicePathText);
- }
- }
- gBS->FreePool (Handles);
- }
- /**
- This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
- **/
- STATIC
- BOOLEAN
- EFIAPI
- IsPciDisplay (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
- {
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- if (EFI_ERROR (Status)) {
- //
- // This is not an error worth reporting.
- //
- return FALSE;
- }
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- 0 /* Offset */,
- sizeof Pci / sizeof (UINT32),
- &Pci
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
- return FALSE;
- }
- return IS_PCI_DISPLAY (&Pci);
- }
- /**
- This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
- the VIRTIO_DEVICE_PROTOCOL level.
- **/
- STATIC
- BOOLEAN
- EFIAPI
- IsVirtioRng (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
- {
- EFI_STATUS Status;
- VIRTIO_DEVICE_PROTOCOL *VirtIo;
- Status = gBS->HandleProtocol (
- Handle,
- &gVirtioDeviceProtocolGuid,
- (VOID **)&VirtIo
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- return (BOOLEAN)(VirtIo->SubSystemDeviceId ==
- VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);
- }
- /**
- This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
- the EFI_PCI_IO_PROTOCOL level.
- **/
- STATIC
- BOOLEAN
- EFIAPI
- IsVirtioPciRng (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
- {
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT16 VendorId;
- UINT16 DeviceId;
- UINT8 RevisionId;
- BOOLEAN Virtio10;
- UINT16 SubsystemId;
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- //
- // Read and check VendorId.
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_VENDOR_ID_OFFSET,
- 1,
- &VendorId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
- if (VendorId != VIRTIO_VENDOR_ID) {
- return FALSE;
- }
- //
- // Read DeviceId and RevisionId.
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_DEVICE_ID_OFFSET,
- 1,
- &DeviceId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint8,
- PCI_REVISION_ID_OFFSET,
- 1,
- &RevisionId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
- //
- // From DeviceId and RevisionId, determine whether the device is a
- // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
- // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
- // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
- // only be sanity-checked, and SubsystemId will decide.
- //
- if ((DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) &&
- (RevisionId >= 0x01))
- {
- Virtio10 = TRUE;
- } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {
- Virtio10 = FALSE;
- } else {
- return FALSE;
- }
- //
- // Read and check SubsystemId as dictated by Virtio10.
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_SUBSYSTEM_ID_OFFSET,
- 1,
- &SubsystemId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
- if (Virtio10 && (SubsystemId >= 0x40)) {
- return TRUE;
- }
- if (!Virtio10 && (SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {
- return TRUE;
- }
- return FALSE;
- PciError:
- DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
- return FALSE;
- }
- /**
- This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
- the matching driver to produce all first-level child handles.
- **/
- STATIC
- VOID
- EFIAPI
- Connect (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
- {
- EFI_STATUS Status;
- Status = gBS->ConnectController (
- Handle, // ControllerHandle
- NULL, // DriverImageHandle
- NULL, // RemainingDevicePath -- produce all children
- FALSE // Recursive
- );
- DEBUG ((
- EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
- "%a: %s: %r\n",
- __FUNCTION__,
- ReportText,
- Status
- ));
- }
- /**
- 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 ((
- DEBUG_ERROR,
- "%a: %s: handle %p: device path not found\n",
- __FUNCTION__,
- ReportText,
- Handle
- ));
- return;
- }
- Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: adding to ConOut: %r\n",
- __FUNCTION__,
- ReportText,
- Status
- ));
- return;
- }
- Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: adding to ErrOut: %r\n",
- __FUNCTION__,
- ReportText,
- Status
- ));
- return;
- }
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: %s: added to ConOut and ErrOut\n",
- __FUNCTION__,
- ReportText
- ));
- }
- STATIC
- 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:
- - FvMain's base address or size changed (historical),
- - FvMain'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.
- **/
- STATIC
- 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_BEGIN ();
- CHAR16 *DevicePathString;
- DevicePathString = ConvertDevicePathToText (
- BootOptions[Index].FilePath,
- FALSE,
- FALSE
- );
- DEBUG ((
- EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
- "%a: removing stale Boot#%04x %s: %r\n",
- __FUNCTION__,
- (UINT32)BootOptions[Index].OptionNumber,
- DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
- Status
- ));
- if (DevicePathString != NULL) {
- FreePool (DevicePathString);
- }
- DEBUG_CODE_END ();
- }
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
- }
- STATIC
- 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 and ESC 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);
- }
- //
- // 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
- )
- {
- UINT16 FrontPageTimeout;
- RETURN_STATUS PcdStatus;
- EFI_STATUS Status;
- //
- // Signal EndOfDxe PI Event
- //
- EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
- //
- // Disable the TPM 2 platform hierarchy
- //
- ConfigureTpmPlatformHierarchy ();
- //
- // Dispatch deferred images after EndOfDxe event.
- //
- EfiBootManagerDispatchDeferredImages ();
- //
- // 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.
- //
- FrontPageTimeout = GetFrontPageTimeoutFromQemu ();
- PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);
- ASSERT_RETURN_ERROR (PcdStatus);
- //
- // Reflect the PCD in the standard Timeout variable.
- //
- Status = gRT->SetVariable (
- EFI_TIME_OUT_VARIABLE_NAME,
- &gEfiGlobalVariableGuid,
- (EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS),
- sizeof FrontPageTimeout,
- &FrontPageTimeout
- );
- DEBUG ((
- EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
- "%a: SetVariable(%s, %u): %r\n",
- __FUNCTION__,
- EFI_TIME_OUT_VARIABLE_NAME,
- FrontPageTimeout,
- Status
- ));
- //
- // Register platform-specific boot options and keyboard shortcuts.
- //
- PlatformRegisterOptionsAndKeys ();
- //
- // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
- // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
- //
- FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioRng, Connect);
- //
- // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
- // instances on Virtio PCI RNG devices.
- //
- FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciRng, Connect);
- }
- /**
- 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 scenario
- > Signal console ready platform customized event
- > Run diagnostics like memory testing
- > Connect certain devices
- > Dispatch additional option roms
- > Special boot: e.g.: USB boot, enter UI
- **/
- VOID
- EFIAPI
- PlatformBootManagerAfterConsole (
- VOID
- )
- {
- RETURN_STATUS Status;
- //
- // Show the splash screen.
- //
- BootLogoEnableLogo ();
- //
- // Process QEMU's -kernel command line option. The kernel booted this way
- // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
- // connected any and all PCI root bridges, and then signaled the ACPI
- // platform driver.
- //
- TryRunningQemuKernel ();
- //
- // Connect the purported boot devices.
- //
- Status = ConnectDevicesFromQemu ();
- if (RETURN_ERROR (Status)) {
- //
- // Connect the rest of the devices.
- //
- EfiBootManagerConnectAll ();
- }
- //
- // Enumerate all possible boot options, then filter and reorder them based on
- // the QEMU configuration.
- //
- EfiBootManagerRefreshAllBootOption ();
- //
- // Register UEFI Shell
- //
- PlatformRegisterFvBootOption (
- &gUefiShellFileGuid,
- L"EFI Internal Shell",
- LOAD_OPTION_ACTIVE
- );
- RemoveStaleFvFileOptions ();
- SetBootOrderFromQemu ();
- PlatformBmPrintScRegisterHandler ();
- }
- /**
- This function is called each second during the boot manager waits the
- timeout.
- @param TimeoutRemain The remaining timeout.
- **/
- VOID
- EFIAPI
- PlatformBootManagerWaitCallback (
- UINT16 TimeoutRemain
- )
- {
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
- UINT16 TimeoutInitial;
- TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);
- //
- // If PcdPlatformBootTimeOut is set to zero, then we consider
- // that no progress update should be enacted.
- //
- if (TimeoutInitial == 0) {
- return;
- }
- Black.Raw = 0x00000000;
- White.Raw = 0x00FFFFFF;
- BootLogoUpdateProgress (
- White.Pixel,
- Black.Pixel,
- L"Start boot option",
- White.Pixel,
- (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,
- 0
- );
- }
- /**
- The function is called when no boot option could be launched,
- including platform recovery options and options pointing to applications
- built into firmware volumes.
- If this function returns, BDS attempts to enter an infinite loop.
- **/
- VOID
- EFIAPI
- PlatformBootManagerUnableToBoot (
- VOID
- )
- {
- EFI_STATUS Status;
- EFI_INPUT_KEY Key;
- EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
- UINTN Index;
- //
- // BootManagerMenu doesn't contain the correct information when return status
- // is EFI_NOT_FOUND.
- //
- Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
- if (EFI_ERROR (Status)) {
- return;
- }
- //
- // Normally BdsDxe does not print anything to the system console, but this is
- // a last resort -- the end-user will likely not see any DEBUG messages
- // logged in this situation.
- //
- // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
- // here to see if it makes sense to request and wait for a keypress.
- //
- if (gST->ConIn != NULL) {
- AsciiPrint (
- "%a: No bootable option or device was found.\n"
- "%a: Press any key to enter the Boot Manager Menu.\n",
- gEfiCallerBaseName,
- gEfiCallerBaseName
- );
- Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
- ASSERT_EFI_ERROR (Status);
- ASSERT (Index == 0);
- //
- // Drain any queued keys.
- //
- while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
- //
- // just throw away Key
- //
- }
- }
- for ( ; ;) {
- EfiBootManagerBoot (&BootManagerMenu);
- }
- }
|