From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web12.3351.1668155156006854147 for ; Fri, 11 Nov 2022 00:25:57 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8AxHLYSB25jpA8GAA--.7060S3; Fri, 11 Nov 2022 16:25:54 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8AxiFcGB25jisUQAA--.27843S14; Fri, 11 Nov 2022 16:25:53 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: Bibo Mao , Chao Li , Leif Lindholm , Liming Gao , Michael D Kinney Subject: [edk2-platforms][PATCH V5 12/15] Platform/Loongson: Add Platform Boot Manager Lib. Date: Fri, 11 Nov 2022 16:25:18 +0800 Message-Id: <192edc8781a4166404787c2c3c5390879c7e5741.1668154207.git.lixianglai@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8AxiFcGB25jisUQAA--.27843S14 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWfuryrurWDXr4xXFW8CF18uFg_yoW5Ww4kXo WIkFy8Aw1kKr4xWa4kGr1kGa1xXFnFgwsxXr1vvF1UWanF9w1Ygas8X3Z8t3sxAF1kZ3W7 Ja4fJas3AFWSqF95n29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUqq1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64 kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY 1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6x kF7I0E14v26F4UJVW0owAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2 zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VCjz48v1sIEY20_WwAm72CE4IkC6x 0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82IYc2Ij64vIr41l42xK82IY6x8ErcxF aVAv8VWrMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxV Cjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42IY 6xIIjxv20xvE14v26F1j6w1UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6x AIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY 1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7xRE6wZ7UUUUU== Content-Transfer-Encoding: quoted-printable The Library provides Boot Manager interfaces. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Cc: Bibo Mao Cc: Chao Li Cc: Leif Lindholm Cc: Liming Gao Cc: Michael D Kinney Signed-off-by: xianglai li --- .../PlatformBootManagerLib/PlatformBm.c | 742 ++++++++++++++++++ .../PlatformBootManagerLib/PlatformBm.h | 112 +++ .../PlatformBootManagerLib.inf | 75 ++ .../PlatformBootManagerLib/QemuKernel.c | 81 ++ 4 files changed, 1010 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/PlatformBm.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/PlatformBm.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/PlatformBootManagerLib.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/QemuKernel.c diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/PlatformBm.c b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/PlatformBm.c new file mode 100644 index 0000000000..eb7f4241f0 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.c @@ -0,0 +1,742 @@ +/** @file=0D + Implementation for PlatformBootManagerLib library class interfaces.=0D +=0D + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "PlatformBm.h"=0D +=0D +STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole =3D {=0D + //=0D + // VENDOR_DEVICE_PATH SerialDxe=0D + //=0D + {=0D + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_P= ATH) },=0D + SERIAL_DXE_FILE_GUID=0D + },=0D +=0D + //=0D + // UART_DEVICE_PATH Uart=0D + //=0D + {=0D + { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PAT= H) },=0D + 0, // Reserved=0D + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate=0D + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits=0D + FixedPcdGet8 (PcdUartDefaultParity), // Parity=0D + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits=0D + },=0D +=0D + //=0D + // VENDOR_DEFINED_DEVICE_PATH TermType=0D + //=0D + {=0D + {=0D + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,=0D + DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)=0D + }=0D + //=0D + // Guid to be filled in dynamically=0D + //=0D + },=0D +=0D + //=0D + // EFI_DEVICE_PATH_PROTOCOL End=0D + //=0D + {=0D + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,=0D + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)=0D + }=0D +};=0D +=0D +STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard =3D {=0D + //=0D + // USB_CLASS_DEVICE_PATH Keyboard=0D + //=0D + {=0D + {=0D + MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,=0D + DP_NODE_LEN (USB_CLASS_DEVICE_PATH)=0D + },=0D + 0xFFFF, // VendorId: any=0D + 0xFFFF, // ProductId: any=0D + 3, // DeviceClass: HID=0D + 1, // DeviceSubClass: boot=0D + 1 // DeviceProtocol: keyboard=0D + },=0D +=0D + //=0D + // EFI_DEVICE_PATH_PROTOCOL End=0D + //=0D + {=0D + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,=0D + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)=0D + }=0D +};=0D +=0D +/**=0D + Locate all handles that carry the specified protocol, filter them with a= =0D + callback function, and pass each handle that passes the filter to anothe= r=0D + callback.=0D +=0D + @param[in] ProtocolGuid The protocol to look for.=0D +=0D + @param[in] Filter The filter function to pass each handle to. If = this=0D + parameter is NULL, then all handles are process= ed.=0D +=0D + @param[in] Process The callback function to pass each handle to th= at=0D + clears the filter.=0D +**/=0D +VOID=0D +FilterAndProcess (=0D + IN EFI_GUID *ProtocolGuid,=0D + IN FILTER_FUNCTION Filter OPTIONAL,=0D + IN CALLBACK_FUNCTION Process=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_HANDLE *Handles;=0D + UINTN NoHandles;=0D + UINTN Idx;=0D +=0D + Status =3D gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,=0D + NULL /* SearchKey */, &NoHandles, &Handles);=0D + if (EFI_ERROR (Status)) {=0D + //=0D + // This is not an error, just an informative condition.=0D + //=0D + DEBUG ((DEBUG_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,=0D + Status));=0D + return;=0D + }=0D +=0D + ASSERT (NoHandles > 0);=0D + for (Idx =3D 0; Idx < NoHandles; ++Idx) {=0D + CHAR16 *DevicePathText;=0D + STATIC CHAR16 Fallback[] =3D L"";=0D +=0D + //=0D + // The ConvertDevicePathToText () function handles NULL input transpar= ently.=0D + //=0D + DevicePathText =3D ConvertDevicePathToText (=0D + DevicePathFromHandle (Handles[Idx]),=0D + FALSE, // DisplayOnly=0D + FALSE // AllowShortcuts=0D + );=0D + if (DevicePathText =3D=3D NULL) {=0D + DevicePathText =3D Fallback;=0D + }=0D +=0D + if ((Filter =3D=3D NULL)=0D + || (Filter (Handles[Idx], DevicePathText)))=0D + {=0D + Process (Handles[Idx], DevicePathText);=0D + }=0D +=0D + if (DevicePathText !=3D Fallback) {=0D + FreePool (DevicePathText);=0D + }=0D + }=0D + gBS->FreePool (Handles);=0D +}=0D +=0D +/**=0D + This FILTER_FUNCTION checks if a handle corresponds to a PCI display dev= ice.=0D +=0D + @param Handle The handle to check=0D + @param ReportText A pointer to a string at the time of the error.=0D +=0D + @retval TURE THe handle corresponds to a PCI display device.=0D + @retval FALSE THe handle does not corresponds to a PCI display de= vice.=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +IsPciDisplay (=0D + IN EFI_HANDLE Handle,=0D + IN CONST CHAR16 *ReportText=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_PCI_IO_PROTOCOL *PciIo;=0D + PCI_TYPE00 Pci;=0D +=0D + Status =3D gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,=0D + (VOID**)&PciIo);=0D + if (EFI_ERROR (Status)) {=0D + //=0D + // This is not an error worth reporting.=0D + //=0D + return FALSE;=0D + }=0D +=0D + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,= =0D + sizeof Pci / sizeof (UINT32), &Pci);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status)= );=0D + return FALSE;=0D + }=0D +=0D + return IS_PCI_DISPLAY (&Pci);=0D +}=0D +=0D +/**=0D + This CALLBACK_FUNCTION attempts to connect a handle non-recursively, ask= ing=0D + the matching driver to produce all first-level child handles.=0D +=0D + @param Handle The handle to connect.=0D + @param ReportText A pointer to a string at the time of the error.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +EFIAPI=0D +Connect (=0D + IN EFI_HANDLE Handle,=0D + IN CONST CHAR16 *ReportText=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + Status =3D gBS->ConnectController (=0D + Handle, // ControllerHandle=0D + NULL, // DriverImageHandle=0D + NULL, // RemainingDevicePath -- produce all children=0D + FALSE // Recursive=0D + );=0D + DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE, "%a: %s: %r\n"= ,=0D + __FUNCTION__, ReportText, Status));=0D +}=0D +=0D +/**=0D + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the=0D + handle, and adds it to ConOut and ErrOut.=0D +=0D + @param Handle The handle to retrieves.=0D + @param ReportText A pointer to a string at the time of the error.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +EFIAPI=0D +AddOutput (=0D + IN EFI_HANDLE Handle,=0D + IN CONST CHAR16 *ReportText=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_DEVICE_PATH_PROTOCOL *DevicePath;=0D +=0D + DevicePath =3D DevicePathFromHandle (Handle);=0D + if (DevicePath =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "%a: %s: handle %p: device path not found\n",=0D + __FUNCTION__, ReportText, Handle));=0D + return;=0D + }=0D +=0D + Status =3D EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL= );=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,=0D + ReportText, Status));=0D + return;=0D + }=0D +=0D + Status =3D EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL= );=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,=0D + ReportText, Status));=0D + return;=0D + }=0D +=0D + DEBUG ((DEBUG_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTIO= N__,=0D + ReportText));=0D +}=0D +/**=0D + Register the boot option.=0D +=0D + @param FileGuid File Guid.=0D + @param Description Option descriptor.=0D + @param Attributes Option Attributes.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +PlatformRegisterFvBootOption (=0D + IN EFI_GUID *FileGuid,=0D + IN CHAR16 *Description,=0D + IN UINT32 Attributes=0D + )=0D +{=0D + EFI_STATUS Status;=0D + INTN OptionIndex;=0D + EFI_BOOT_MANAGER_LOAD_OPTION NewOption;=0D + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;=0D + UINTN BootOptionCount;=0D + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;=0D + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;=0D + EFI_DEVICE_PATH_PROTOCOL *DevicePath;=0D +=0D + Status =3D gBS->HandleProtocol (=0D + gImageHandle,=0D + &gEfiLoadedImageProtocolGuid,=0D + (VOID **) &LoadedImage=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);=0D + DevicePath =3D DevicePathFromHandle (LoadedImage->DeviceHandle);=0D + ASSERT (DevicePath !=3D NULL);=0D + DevicePath =3D AppendDevicePathNode (=0D + DevicePath,=0D + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode=0D + );=0D + ASSERT (DevicePath !=3D NULL);=0D +=0D + Status =3D EfiBootManagerInitializeLoadOption (=0D + &NewOption,=0D + LoadOptionNumberUnassigned,=0D + LoadOptionTypeBoot,=0D + Attributes,=0D + Description,=0D + DevicePath,=0D + NULL,=0D + 0=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D + FreePool (DevicePath);=0D +=0D + BootOptions =3D EfiBootManagerGetLoadOptions (=0D + &BootOptionCount, LoadOptionTypeBoot=0D + );=0D +=0D + OptionIndex =3D EfiBootManagerFindLoadOption (=0D + &NewOption, BootOptions, BootOptionCount=0D + );=0D +=0D + if (OptionIndex =3D=3D -1) {=0D + Status =3D EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN)= ;=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D + EfiBootManagerFreeLoadOption (&NewOption);=0D + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);=0D +}=0D +=0D +/**=0D + Remove all MemoryMapped (...)/FvFile (...) and Fv (...)/FvFile (...) boo= t options=0D + whose device paths do not resolve exactly to an FvFile in the system.=0D +=0D + This removes any boot options that point to binaries built into the firm= ware=0D + and have become stale due to any of the following:=0D + - FvMain's base address or size changed (historical),=0D + - FvMain's FvNameGuid changed,=0D + - the FILE_GUID of the pointed-to binary changed,=0D + - the referenced binary is no longer built into the firmware.=0D +=0D + EfiBootManagerFindLoadOption () used in PlatformRegisterFvBootOption () = only=0D + avoids exact duplicates.=0D +**/=0D +VOID=0D +RemoveStaleFvFileOptions (=0D + VOID=0D + )=0D +{=0D + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;=0D + UINTN BootOptionCount;=0D + UINTN Index;=0D +=0D + BootOptions =3D EfiBootManagerGetLoadOptions (&BootOptionCount,=0D + LoadOptionTypeBoot);=0D +=0D + for (Index =3D 0; Index < BootOptionCount; ++Index) {=0D + EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;=0D + EFI_STATUS Status;=0D + EFI_HANDLE FvHandle;=0D +=0D + //=0D + // If the device path starts with neither MemoryMapped (...) nor Fv (.= ..),=0D + // then keep the boot option.=0D + //=0D + Node1 =3D BootOptions[Index].FilePath;=0D + if (!(DevicePathType (Node1) =3D=3D HARDWARE_DEVICE_PATH=0D + && DevicePathSubType (Node1) =3D=3D HW_MEMMAP_DP)=0D + && !(DevicePathType (Node1) =3D=3D MEDIA_DEVICE_PATH=0D + && DevicePathSubType (Node1) =3D=3D MEDIA_PIWG_FW_VOL_DP))=0D + {=0D + continue;=0D + }=0D +=0D + //=0D + // If the second device path node is not FvFile (...), then keep the b= oot=0D + // option.=0D + //=0D + Node2 =3D NextDevicePathNode (Node1);=0D + if ((DevicePathType (Node2) !=3D MEDIA_DEVICE_PATH)=0D + || (DevicePathSubType (Node2) !=3D MEDIA_PIWG_FW_FILE_DP))=0D + {=0D + continue;=0D + }=0D +=0D + //=0D + // Locate the Firmware Volume2 protocol instance that is denoted by th= e=0D + // boot option. If this lookup fails (i.e., the boot option references= a=0D + // firmware volume that doesn't exist), then we'll proceed to delete t= he=0D + // boot option.=0D + //=0D + SearchNode =3D Node1;=0D + Status =3D gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,=0D + &SearchNode, &FvHandle);=0D +=0D + if (!EFI_ERROR (Status)) {=0D + //=0D + // The firmware volume was found; now let's see if it contains the F= vFile=0D + // identified by GUID.=0D + //=0D + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;=0D + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;=0D + UINTN BufferSize;=0D + EFI_FV_FILETYPE FoundType;=0D + EFI_FV_FILE_ATTRIBUTES FileAttributes;=0D + UINT32 AuthenticationStatus;=0D +=0D + Status =3D gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2Protoc= olGuid,=0D + (VOID **)&FvProtocol);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + FvFileNode =3D (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;=0D + //=0D + // Buffer=3D=3DNULL means we request metadata only: BufferSize, Foun= dType,=0D + // FileAttributes.=0D + //=0D + Status =3D FvProtocol->ReadFile (=0D + FvProtocol,=0D + &FvFileNode->FvFileName, // NameGuid=0D + NULL, // Buffer=0D + &BufferSize,=0D + &FoundType,=0D + &FileAttributes,=0D + &AuthenticationStatus=0D + );=0D + if (!EFI_ERROR (Status)) {=0D + //=0D + // The FvFile was found. Keep the boot option.=0D + //=0D + continue;=0D + }=0D + }=0D +=0D + //=0D + // Delete the boot option.=0D + //=0D + Status =3D EfiBootManagerDeleteLoadOptionVariable (=0D + BootOptions[Index].OptionNumber, LoadOptionTypeBoot);=0D + DEBUG_CODE (=0D + CHAR16 *DevicePathString;=0D +=0D + DevicePathString =3D ConvertDevicePathToText (BootOptions[Index].Fil= ePath,=0D + FALSE, FALSE);=0D + DEBUG ((=0D + EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,=0D + "%a: removing stale Boot#%04x %s: %r\n",=0D + __FUNCTION__,=0D + (UINT32)BootOptions[Index].OptionNumber,=0D + DevicePathString =3D=3D NULL ? L"" : DevicePathString= ,=0D + Status=0D + ));=0D + if (DevicePathString !=3D NULL) {=0D + FreePool (DevicePathString);=0D + }=0D + );=0D + }=0D +=0D + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);=0D +}=0D +=0D +/**=0D + Register the boot option And Keys.=0D +=0D + @param VOID=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +PlatformRegisterOptionsAndKeys (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_INPUT_KEY Enter;=0D + EFI_INPUT_KEY F2;=0D + EFI_INPUT_KEY Esc;=0D + EFI_BOOT_MANAGER_LOAD_OPTION BootOption;=0D +=0D + //=0D + // Register ENTER as CONTINUE key=0D + //=0D + Enter.ScanCode =3D SCAN_NULL;=0D + Enter.UnicodeChar =3D CHAR_CARRIAGE_RETURN;=0D + Status =3D EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Map F2 and ESC to Boot Manager Menu=0D + //=0D + F2.ScanCode =3D SCAN_F2;=0D + F2.UnicodeChar =3D CHAR_NULL;=0D + Esc.ScanCode =3D SCAN_ESC;=0D + Esc.UnicodeChar =3D CHAR_NULL;=0D + Status =3D EfiBootManagerGetBootManagerMenu (&BootOption);=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D EfiBootManagerAddKeyOptionVariable (=0D + NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL=0D + );=0D + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_ALREADY_STARTED);= =0D + Status =3D EfiBootManagerAddKeyOptionVariable (=0D + NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL=0D + );=0D + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_ALREADY_STARTED);= =0D +}=0D +=0D +//=0D +// BDS Platform Functions=0D +//=0D +/**=0D + Do the platform init, can be customized by OEM/IBV=0D + Possible things that can be done in PlatformBootManagerBeforeConsole:=0D + > Update console variable: 1. include hot-plug devices;=0D + > 2. Clear ConIn and add SOL for AMT=0D + > Register new Driver#### or Boot####=0D + > Register new Key####: e.g.: F12=0D + > Signal ReadyToLock event=0D + > Authentication action: 1. connect Auth devices;=0D + > 2. Identify auto logon user.=0D +**/=0D +VOID=0D +EFIAPI=0D +PlatformBootManagerBeforeConsole (=0D + VOID=0D + )=0D +{=0D + RETURN_STATUS PcdStatus;=0D +=0D + //=0D + // Signal EndOfDxe PI Event=0D + //=0D + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);=0D +=0D + //=0D + // Dispatch deferred images after EndOfDxe event.=0D + //=0D + EfiBootManagerDispatchDeferredImages ();=0D +=0D + //=0D + // Locate the PCI root bridges and make the PCI bus driver connect each,= =0D + // non-recursively. This will produce a number of child handles with Pci= Io on=0D + // them.=0D + //=0D + FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);=0D +=0D + //=0D + // Signal the ACPI platform driver that it can download QEMU ACPI tables= .=0D + //=0D + EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);=0D +=0D + //=0D + // Find all display class PCI devices (using the handles from the previo= us=0D + // step), and connect them non-recursively. This should produce a number= of=0D + // child handles with GOPs on them.=0D + //=0D + FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);=0D +=0D + //=0D + // Now add the device path of all handles with GOP on them to ConOut and= =0D + // ErrOut.=0D + //=0D + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);=0D +=0D + //=0D + // Add the hardcoded short-form USB keyboard device path to ConIn.=0D + //=0D + EfiBootManagerUpdateConsoleVariable (ConIn,=0D + (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);=0D +=0D + //=0D + // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut= .=0D + //=0D + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);=0D + EfiBootManagerUpdateConsoleVariable (ConIn,=0D + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);=0D + EfiBootManagerUpdateConsoleVariable (ConOut,=0D + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);=0D + EfiBootManagerUpdateConsoleVariable (ErrOut,=0D + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);=0D +=0D + //=0D + // Set the front page timeout from the QEMU configuration.=0D + //=0D + PcdStatus =3D PcdSet16S (PcdPlatformBootTimeOut,=0D + GetFrontPageTimeoutFromQemu ());=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + //=0D + // Register platform-specific boot options and keyboard shortcuts.=0D + //=0D + PlatformRegisterOptionsAndKeys ();=0D +}=0D +=0D +/**=0D + Do the platform specific action after the console is ready=0D + Possible things that can be done in PlatformBootManagerAfterConsole:=0D + > Console post action:=0D + > Dynamically switch output mode from 100x31 to 80x25 for certain sena= rino=0D + > Signal console ready platform customized event=0D + > Run diagnostics like memory testing=0D + > Connect certain devices=0D + > Dispatch aditional option roms=0D + > Special boot: e.g.: USB boot, enter UI=0D +**/=0D +VOID=0D +EFIAPI=0D +PlatformBootManagerAfterConsole (=0D + VOID=0D + )=0D +{=0D + //=0D + // Show the splash screen.=0D + //=0D + BootLogoEnableLogo ();=0D +=0D + //=0D + // Connect the rest of the devices.=0D + //=0D + EfiBootManagerConnectAll ();=0D +=0D + //=0D + // Process QEMU's -kernel command line option. Note that the kernel boot= ed=0D + // this way should receive ACPI tables, which is why we connect all devi= ces=0D + // first (see above) -- PCI enumeration blocks ACPI table installation, = if=0D + // there is a PCI host.=0D + //=0D + TryRunningQemuKernel ();=0D +=0D + //=0D + // Enumerate all possible boot options, then filter and reorder them bas= ed on=0D + // the QEMU configuration.=0D + //=0D + EfiBootManagerRefreshAllBootOption ();=0D +=0D + //=0D + // Register UEFI Shell=0D + //=0D + PlatformRegisterFvBootOption (=0D + &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE=0D + );=0D +=0D + RemoveStaleFvFileOptions ();=0D + SetBootOrderFromQemu ();=0D +}=0D +=0D +/**=0D + This function is called each second during the boot manager waits the=0D + timeout.=0D +=0D + @param TimeoutRemain The remaining timeout.=0D +**/=0D +VOID=0D +EFIAPI=0D +PlatformBootManagerWaitCallback (=0D + IN UINT16 TimeoutRemain=0D + )=0D +{=0D + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;=0D + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;=0D + UINT16 Timeout;=0D +=0D + Timeout =3D PcdGet16 (PcdPlatformBootTimeOut);=0D +=0D + Black.Raw =3D 0x00000000;=0D + White.Raw =3D 0x00FFFFFF;=0D +=0D + BootLogoUpdateProgress (=0D + White.Pixel,=0D + Black.Pixel,=0D + L"Start boot option",=0D + White.Pixel,=0D + (Timeout - TimeoutRemain) * 100 / Timeout,=0D + 0=0D + );=0D +}=0D +=0D +/**=0D + The function is called when no boot option could be launched,=0D + including platform recovery options and options pointing to applications= =0D + built into firmware volumes.=0D +=0D + If this function returns, BDS attempts to enter an infinite loop.=0D +**/=0D +VOID=0D +EFIAPI=0D +PlatformBootManagerUnableToBoot (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_INPUT_KEY Key;=0D + EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;=0D + UINTN Index;=0D +=0D + //=0D + // BootManagerMenu doesn't contain the correct information when return s= tatus=0D + // is EFI_NOT_FOUND.=0D + //=0D + Status =3D EfiBootManagerGetBootManagerMenu (&BootManagerMenu);=0D + if (EFI_ERROR (Status)) {=0D + return;=0D + }=0D + //=0D + // Normally BdsDxe does not print anything to the system console, but th= is is=0D + // a last resort -- the end-user will likely not see any DEBUG messages= =0D + // logged in this situation.=0D + //=0D + // AsciiPrint () will NULL-check gST->ConOut internally. We check gST->C= onIn=0D + // here to see if it makes sense to request and wait for a keypress.=0D + //=0D + if (gST->ConIn !=3D NULL) {=0D + AsciiPrint (=0D + "%a: No bootable option or device was found.\n"=0D + "%a: Press any key to enter the Boot Manager Menu.\n",=0D + gEfiCallerBaseName,=0D + gEfiCallerBaseName=0D + );=0D + Status =3D gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);=0D + ASSERT_EFI_ERROR (Status);=0D + ASSERT (Index =3D=3D 0);=0D +=0D + //=0D + // Drain any queued keys.=0D + //=0D + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {=0D + //=0D + // just throw away Key=0D + //=0D + }=0D + }=0D +=0D + for (;;) {=0D + EfiBootManagerBoot (&BootManagerMenu);=0D + }=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/PlatformBm.h b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/PlatformBm.h new file mode 100644 index 0000000000..f20c78252f --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.h @@ -0,0 +1,112 @@ +/** @file=0D + Head file for BDS Platform specific code=0D +=0D + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef PLATFORM_BM_H_=0D +#define PLATFORM_BM_H_=0D +=0D +#include =0D +=0D +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >>= 8) }=0D +=0D +#define SERIAL_DXE_FILE_GUID { \=0D + 0xD3987D4B, 0x971A, 0x435F, \=0D + { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \=0D + }=0D +=0D +#define ALIGN_UP(addr, align) \=0D + ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))=0D +=0D +#pragma pack (1)=0D +typedef struct {=0D + VENDOR_DEVICE_PATH SerialDxe;=0D + UART_DEVICE_PATH Uart;=0D + VENDOR_DEFINED_DEVICE_PATH TermType;=0D + EFI_DEVICE_PATH_PROTOCOL End;=0D +} PLATFORM_SERIAL_CONSOLE;=0D +#pragma pack ()=0D +=0D +#pragma pack (1)=0D +typedef struct {=0D + USB_CLASS_DEVICE_PATH Keyboard;=0D + EFI_DEVICE_PATH_PROTOCOL End;=0D +} PLATFORM_USB_KEYBOARD;=0D +#pragma pack ()=0D +=0D +/**=0D + Check if the handle satisfies a particular condition.=0D +=0D + @param[in] Handle The handle to check.=0D + @param[in] ReportText A caller-allocated string passed in for reporting= =0D + purposes. It must never be NULL.=0D +=0D + @retval TRUE The condition is satisfied.=0D + @retval FALSE Otherwise. This includes the case when the condition coul= d not=0D + be fully evaluated due to an error.=0D +**/=0D +typedef=0D +BOOLEAN=0D +(EFIAPI *FILTER_FUNCTION) (=0D + IN EFI_HANDLE Handle,=0D + IN CONST CHAR16 *ReportText=0D + );=0D +=0D +/**=0D + Process a handle.=0D +=0D + @param[in] Handle The handle to process.=0D + @param[in] ReportText A caller-allocated string passed in for reporting= =0D + purposes. It must never be NULL.=0D +**/=0D +typedef=0D +VOID=0D +(EFIAPI *CALLBACK_FUNCTION) (=0D + IN EFI_HANDLE Handle,=0D + IN CONST CHAR16 *ReportText=0D + );=0D +=0D +/**=0D + * execute from kernel entry point.=0D + *=0D + * @param[in] Argc The count of args.=0D + * @param[in] Argv The pointer to args array.=0D + * @param[in] Bpi The pointer to bootparaminterface struct.=0D + * @param[in] Vec The fourth args for kernel.=0D + ***/=0D +typedef=0D +VOID=0D +(EFIAPI *EFI_KERNEL_ENTRY_POINT) (=0D + IN UINTN Argc,=0D + IN VOID *Argv,=0D + IN VOID *Bpi,=0D + IN VOID *Vec=0D + );=0D +=0D +/**=0D + Download the kernel, the initial ramdisk, and the kernel command line fr= om=0D + QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the tw= o=0D + image files, and load and start the kernel from it.=0D +=0D + The kernel will be instructed via its command line to load the initrd fr= om=0D + the same Simple FileSystem.=0D +=0D + @retval EFI_NOT_FOUND Kernel image was not found.=0D + @retval EFI_OUT_OF_RESOURCES Memory allocation failed.=0D + @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.=0D +=0D + @return Error codes from any of the underlying=0D + functions. On success, the function doesn'= t=0D + return.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TryRunningQemuKernel (=0D + VOID=0D + );=0D +=0D +#endif // PLATFORM_BM_H_=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/PlatformBootManagerLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library= /PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 0000000000..0ea6fea5c5 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBootManagerLib.inf @@ -0,0 +1,75 @@ +## @file=0D +# Implementation for PlatformBootManagerLib library class interfaces.=0D +#=0D +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D PlatformBootManagerLib=0D + FILE_GUID =3D 469184E8-FADA-41E4-8823-012CA19B40D4= =0D + MODULE_TYPE =3D DXE_DRIVER=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D PlatformBootManagerLib|DXE_DRIVER=0D +=0D +#=0D +# VALID_ARCHITECTURES =3D LOONGARCH64=0D +#=0D +=0D +[Sources]=0D + PlatformBm.c=0D + QemuKernel.c=0D +=0D +[Packages]=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + MdePkg/MdePkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D + ShellPkg/ShellPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + BaseMemoryLib=0D + BootLogoLib=0D + DebugLib=0D + DevicePathLib=0D + MemoryAllocationLib=0D + PcdLib=0D + PrintLib=0D + QemuBootOrderLib=0D + QemuLoadImageLib=0D + QemuFwCfgLib=0D + UefiBootManagerLib=0D + UefiBootServicesTableLib=0D + UefiLib=0D + UefiRuntimeServicesTableLib=0D +=0D +[FixedPcd]=0D + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate=0D + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits=0D + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity=0D + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits=0D +=0D +[Pcd]=0D + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut=0D +=0D +[Guids]=0D + gEfiFileInfoGuid=0D + gEfiFileSystemInfoGuid=0D + gEfiFileSystemVolumeLabelInfoIdGuid=0D + gEfiEndOfDxeEventGroupGuid=0D + gRootBridgesConnectedEventGroupGuid=0D + gUefiShellFileGuid=0D + gEfiLoongsonBootparamsTableGuid ## SOMETIM= ES_PRODUCES ## SystemTable=0D + gEfiTtyTermGuid=0D +=0D +[Protocols]=0D + gEfiDevicePathProtocolGuid=0D + gEfiFirmwareVolume2ProtocolGuid=0D + gEfiGraphicsOutputProtocolGuid=0D + gEfiLoadedImageProtocolGuid=0D + gEfiPciRootBridgeIoProtocolGuid=0D + gEfiSimpleFileSystemProtocolGuid=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/QemuKernel.c b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/QemuKernel.c new file mode 100644 index 0000000000..386003a8d7 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Qem= uKernel.c @@ -0,0 +1,81 @@ +/** @file=0D + Try to run Linux kernel.=0D +=0D + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - mem - Memory=0D + - Bpi - Boot Parameter Interface=0D + - FwCfg - FirmWare Configure=0D +**/=0D +=0D +#include =0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +/**=0D + Download the kernel, the initial ramdisk, and the kernel command line fr= om=0D + QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the tw= o=0D + image files, and load and start the kernel from it.=0D +=0D + The kernel will be instructed via its command line to load the initrd fr= om=0D + the same Simple FileSystem.=0D +=0D + @retval EFI_NOT_FOUND Kernel image was not found.=0D + @retval EFI_OUT_OF_RESOURCES Memory allocation failed.=0D + @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.=0D +=0D + @return Error codes from any of the underlying=0D + functions. On success, the function doesn'= t=0D + return.=0D +**/=0D +EFI_STATUS=0D +TryRunningQemuKernel (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_HANDLE KernelImageHandle;=0D +=0D + Status =3D QemuLoadKernelImage (&KernelImageHandle);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + //=0D + // Signal the EFI_EVENT_GROUP_READY_TO_BOOT event.=0D + //=0D + EfiSignalEventReadyToBoot ();=0D +=0D + REPORT_STATUS_CODE (=0D + EFI_PROGRESS_CODE,=0D + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)=0D + );=0D +=0D + //=0D + // Start the image.=0D + //=0D + Status =3D QemuStartKernelImage (&KernelImageHandle);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "%a: QemuStartKernelImage(): %r\n",=0D + __FUNCTION__,=0D + Status=0D + ));=0D + }=0D +=0D + QemuUnloadKernelImage (KernelImageHandle);=0D +=0D + return Status;=0D +}=0D --=20 2.31.1