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.web08.5317.1646210712946866896 for ; Wed, 02 Mar 2022 00:45:13 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from localhost.localdomain (unknown [10.2.5.185]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9Dxn89_Lh9i7TkBAA--.6283S15; Wed, 02 Mar 2022 16:44:54 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Subject: [edk2-platforms][PATCH V1 13/15] Platform/Loongson: Add Platform Boot Manager Lib. Date: Wed, 2 Mar 2022 03:44:45 -0500 Message-Id: <20220302084447.2991355-14-lixianglai@loongson.cn> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220302084447.2991355-1-lixianglai@loongson.cn> References: <20220302084447.2991355-1-lixianglai@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf9Dxn89_Lh9i7TkBAA--.6283S15 X-Coremail-Antispam: 1UD129KBjvAXoWDGw13CFy8CF4kJrWDGr4xtFb_yoWrWw1Dto W0kry0yw1kKr4rXa4kCrn7GayxWF4q939xXrnYvF47Xa1DWw15Ka4DX3W5JasxtF1kAF1D G34fJa93AFZ3trZ5n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Content-Transfer-Encoding: quoted-printable The Library provides Boot Manager interfaces. Signed-off-by: xianglai li --- .../PlatformBootManagerLib/PlatformBm.c | 761 ++++++++++++++++++ .../PlatformBootManagerLib/PlatformBm.h | 126 +++ .../PlatformBootManagerLib.inf | 78 ++ .../PlatformBootManagerLib/QemuKernel.c | 449 +++++++++++ 4 files changed, 1414 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..1805a6a9b3 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.c @@ -0,0 +1,761 @@ +/** @file=0D + Implementation for PlatformBootManagerLib library class interfaces.=0D +=0D + Copyright (c) 2021 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 +/**=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 +/**=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 +/**=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 +/**=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 +//=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 + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D + BootLogoEnableLogo ();=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D +=0D + //=0D + // Connect the rest of the devices.=0D + //=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D + EfiBootManagerConnectAll ();=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D +=0D + SetBootParams ();=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 + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D + TryRunningQemuKernel ();=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D +=0D + //=0D + // Enumerate all possible boot options, then filter and reorder them bas= ed on=0D + // the QEMU configuration.=0D + //=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D + EfiBootManagerRefreshAllBootOption ();=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D +=0D + //=0D + // Register UEFI Shell=0D + //=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D + PlatformRegisterFvBootOption (=0D + &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE=0D + );=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D +=0D + RemoveStaleFvFileOptions ();=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=0D + SetBootOrderFromQemu ();=0D + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__));=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 +=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..5b7dd20794 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.h @@ -0,0 +1,126 @@ +/** @file=0D + Head file for BDS Platform specific code=0D +=0D + Copyright (c) 2021 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 +/*=0D + Setup the boot parameter.=0D +=0D + @param VOID=0D +=0D + @retval EFI_SUCCESS The boot parameter was established su= ccessfully.=0D + @retval EFI_INVALID_PARAMETER Input GUID is NULL.=0D + @retval EFI_NOT_FOUND Attempted to delete non-existant entr= y=0D + @retval EFI_OUT_OF_RESOURCES Not enough memory available=0D + */=0D +EFI_STATUS=0D +EFIAPI=0D +SetBootParams (VOID);=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..0242381fc5 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBootManagerLib.inf @@ -0,0 +1,78 @@ +## @file=0D +# Implementation for PlatformBootManagerLib library class interfaces.=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=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 +# The following information is for reference only and not required by the = build tools.=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 + QemuFwCfgLib=0D + UefiBootManagerLib=0D + UefiBootServicesTableLib=0D + UefiLib=0D + UefiRuntimeServicesTableLib=0D + BpiLib=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..bb25edcada --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Qem= uKernel.c @@ -0,0 +1,449 @@ +/** @file=0D + Try to run Linux kernel.=0D +=0D + Copyright (c) 2021 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 +=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 +/*=0D + Calculates the checksum.=0D +=0D + @param buffer A pointer to the data to calculate the checksum.=0D + @param length The number of data involved in calculating the checksum= .=0D +=0D + @retval the value of checksum.=0D + */=0D +UINT8=0D +CalculateCheckSum8 (=0D + IN CONST UINT8 *buffer, IN UINTN length=0D + )=0D +{=0D + UINT8 checksum;=0D + UINTN count;=0D +=0D + for (checksum =3D 0, count =3D 0; count < length; count++) {=0D + checksum =3D (UINT8) (checksum + * (buffer + count));=0D + }=0D + return (UINT8) (0x100 - checksum);=0D +}=0D +/*=0D + Iterates through all memory maps merging adjacent memory regions.=0D +=0D + @param array A pointer to a memory-mapped table.=0D + @param length The length of the memory-mapped table.=0D + @param bpmem Adjusted memory information table.=0D + @param index The Index of Adjusted memory information table.=0D + @param memtype Specifies the memory type.=0D +=0D + @retval the value of checksum.=0D + */=0D +UINT32=0D +memmap_sort (=0D + IN MEMMAP array[],=0D + IN UINT32 length,=0D + OUT MEM_MAP * bpmem,=0D + IN UINT32 index,=0D + IN UINT32 memtype=0D + )=0D +{=0D + UINT64 tempmemsize =3D 0;=0D + UINT32 j =3D 0;=0D + UINT32 t =3D 0;=0D +=0D + for (j =3D 0; j < length; ) {=0D + tempmemsize =3D array[j].MemSize;=0D + for (t =3D j + 1; t < length; t++) {=0D + if (array[j].MemStart + tempmemsize =3D=3D array[t].MemStart) {=0D + tempmemsize +=3D array[t].MemSize;=0D + } else {=0D + break;=0D + }=0D + }=0D +=0D + bpmem->Map[index].MemType =3D memtype;=0D + bpmem->Map[index].MemStart =3D array[j].MemStart;=0D + bpmem->Map[index].MemSize =3D tempmemsize;=0D + DEBUG ((DEBUG_INFO, "map[%d]:type %x, start 0x%llx, end 0x%llx\n",=0D + index,=0D + bpmem->Map[index].MemType,=0D + bpmem->Map[index].MemStart,=0D + bpmem->Map[index].MemStart+ bpmem->Map[index].MemSize=0D + ));=0D + j =3D t;=0D + index++;=0D + }=0D + return index;=0D +}=0D +/*=0D + Look for memory-mapped information.=0D +=0D + @param Bpi A pointer to the boot parameter interface.=0D +=0D + @retval The address of the memory-mapped table.=0D + */=0D +MEM_MAP *=0D +FindNewInterfaceMem (=0D + IN BootParamsInterface *Bpi=0D + )=0D +{=0D + CHAR8 *p =3DNULL;=0D + MEM_MAP *new_interface_mem =3D NULL;=0D + EXT_LIST *listpointer =3D NULL;=0D +=0D + if (Bpi =3D=3D NULL) {=0D + return new_interface_mem;=0D + }=0D +=0D + p =3D (CHAR8 *)& (Bpi->Signature);=0D + if (AsciiStrnCmp (p, "BPI", 3) =3D=3D 0) {=0D + listpointer =3D Bpi->ExtList;=0D + for (; listpointer !=3D NULL; listpointer =3D listpointer->next) {=0D + CHAR8 *pl =3D (CHAR8 *) & (listpointer->Signature);=0D + if (AsciiStrnCmp (pl, "MEM", 3) =3D=3D 0) {=0D + new_interface_mem =3D (MEM_MAP *)listpointer;=0D + }=0D + }=0D + }=0D +=0D + return new_interface_mem;=0D +}=0D +/**=0D + Gets the system memory mapping information.=0D +=0D + @param MapKey memory-mapped key.=0D + @param MemoryMapSize The size of the memory-mapped information.=0D + @param DescriptorSize The size of the memory-mapped information descrip= tor.=0D +=0D + @retval VOID=0D +**/=0D +EFI_MEMORY_DESCRIPTOR *=0D +GetSystemMemap (=0D + OUT UINTN *MapKey,=0D + OUT UINTN *MemoryMapSize,=0D + OUT UINTN *DescriptorSize=0D + )=0D +{=0D + EFI_STATUS Status =3D EFI_SUCCESS;=0D + EFI_MEMORY_DESCRIPTOR *MemoryMap =3D NULL;=0D + UINTN MemoryMapSizeTemp =3D 0;=0D + UINTN DescriptorSizeTemp =3D 0;=0D + UINT8 TmpMemoryMap[1];=0D + UINT32 DescriptorVersion =3D 0;=0D +=0D + // Get System MemoryMapSize=0D + MemoryMapSizeTemp =3D sizeof (TmpMemoryMap);=0D + Status =3D gBS->GetMemoryMap (=0D + &MemoryMapSizeTemp,=0D + (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,=0D + MapKey,=0D + &DescriptorSizeTemp,=0D + &DescriptorVersion=0D + );=0D + ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D +=0D + DEBUG ((DEBUG_INFO, "%a %a:%d Status 0x%x\n", __FILE__, __func__, __LINE= __, Status));=0D + // Enlarge space here, because we will allocate pool now.=0D + MemoryMapSizeTemp +=3D EFI_PAGE_SIZE;=0D + Status =3D gBS->AllocatePool (=0D + EfiLoaderData,=0D + MemoryMapSizeTemp,=0D + (VOID **) &MemoryMap=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + DEBUG ((DEBUG_INFO, "%a %a:%d Status 0x%x\n", __FILE__, __func__, __LINE= __, Status));=0D +=0D + *MemoryMapSize =3D MemoryMapSizeTemp;=0D + *DescriptorSize =3D DescriptorSizeTemp;=0D + if (NULL =3D=3D MemoryMap) {=0D + return NULL;=0D + }=0D +=0D + // Get System MemoryMap=0D + Status =3D gBS->GetMemoryMap (=0D + &MemoryMapSizeTemp,=0D + MemoryMap,=0D + MapKey,=0D + &DescriptorSizeTemp,=0D + &DescriptorVersion=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + DEBUG ((DEBUG_INFO, "%a %a:%d Status 0x%x\n", __FILE__, __func__, __LINE= __, Status));=0D + *MemoryMapSize =3D MemoryMapSizeTemp;=0D + *DescriptorSize =3D DescriptorSizeTemp;=0D +=0D + return MemoryMap;=0D +}=0D +/**=0D + Memory-mapped information is processed according to the different types= =0D + of memory in the memory-mapped table.=0D +=0D + @param new_interface_mem A pointer to a memory-mapped table.=0D + @param MemoryMapPtr A pointer to the memory descriptor struct.=0D + @param MemoryMapSize The size of the memory-mapped table.=0D + @param DescriptorSize The size of the descriptor.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +MemMapSort (=0D + IN OUT MEM_MAP *new_interface_mem,=0D + IN EFI_MEMORY_DESCRIPTOR *MemoryMapPtr,=0D + IN UINTN MemoryMapSize,=0D + IN UINTN DescriptorSize=0D + )=0D +{=0D + MEMMAP reserve_mem[MAX_MEM_MAP];=0D + MEMMAP free_mem[MAX_MEM_MAP];=0D + MEMMAP acpi_table_mem[MAX_MEM_MAP];=0D + MEMMAP acpi_nvs_mem[MAX_MEM_MAP];=0D + UINT32 free_index =3D 0;=0D + UINT32 reserve_index =3D 0;=0D + UINT32 acpi_table_index =3D 0;=0D + UINT32 acpi_nvs_index =3D 0;=0D + UINT64 tempMemsize =3D 0;=0D + UINT32 tmp_index =3D 0;=0D + UINT32 Index, j, t;=0D + UINT8 checksum =3D 0;=0D +=0D + if ((NULL =3D=3D new_interface_mem)=0D + || (NULL =3D=3D MemoryMapPtr))=0D + {=0D + return ;=0D + }=0D +=0D + ZeroMem(reserve_mem, sizeof(MEMMAP) * MAX_MEM_MAP);=0D + ZeroMem(free_mem, sizeof(MEMMAP) * MAX_MEM_MAP);=0D + ZeroMem(acpi_table_mem, sizeof(MEMMAP) * MAX_MEM_MAP);=0D + ZeroMem(acpi_nvs_mem, sizeof(MEMMAP) * MAX_MEM_MAP);=0D +=0D + tmp_index =3D new_interface_mem->MapCount;=0D +=0D + for (Index =3D 0; Index < (MemoryMapSize / DescriptorSize); Index++) {=0D + if (MemoryMapPtr->NumberOfPages =3D=3D 0) {=0D + continue;=0D + }=0D +=0D + switch (MemoryMapPtr->Type) {=0D + case EfiACPIReclaimMemory:=0D + acpi_table_mem[acpi_table_index].MemType =3D ACPI_TABLE;=0D + acpi_table_mem[acpi_table_index].MemStart =3D (MemoryMapPtr->Physi= calStart) & 0xffffffffffff;=0D + acpi_table_mem[acpi_table_index].MemSize =3D MemoryMapPtr->NumberO= fPages * 4096;=0D + acpi_table_index++;=0D + break;=0D +=0D + case EfiACPIMemoryNVS:=0D + acpi_nvs_mem[acpi_nvs_index].MemType =3D ACPI_NVS;=0D + acpi_nvs_mem[acpi_nvs_index].MemStart =3D (MemoryMapPtr->PhysicalS= tart) & 0xffffffffffff;=0D + acpi_nvs_mem[acpi_nvs_index].MemSize =3D MemoryMapPtr->NumberOfPag= es * 4096;=0D + acpi_nvs_index++;=0D + break;=0D +=0D + case EfiRuntimeServicesData:=0D + case EfiRuntimeServicesCode:=0D + case EfiReservedMemoryType:=0D + case EfiPalCode:=0D + reserve_mem[reserve_index].MemType =3D SYSTEM_RAM_RESERVED;=0D + reserve_mem[reserve_index].MemStart =3D (MemoryMapPtr->PhysicalSta= rt) & 0xffffffffffff;=0D + reserve_mem[reserve_index].MemSize =3D MemoryMapPtr->NumberOfPages= * 4096;=0D + reserve_index++;=0D + break;=0D +=0D + default :=0D + free_mem[free_index].MemType =3D SYSTEM_RAM;=0D + free_mem[free_index].MemStart =3D (MemoryMapPtr->PhysicalStart) & = 0xffffffffffff;=0D + free_mem[free_index].MemSize =3D MemoryMapPtr->NumberOfPages * 409= 6;=0D + free_index++;=0D + break;=0D + };=0D + // Get next item=0D + MemoryMapPtr =3D (EFI_MEMORY_DESCRIPTOR *) ((UINTN)MemoryMapPtr + Desc= riptorSize);=0D + }=0D +=0D + /* Recovery sort */=0D + for (j =3D 0; j < free_index; ) {=0D + tempMemsize =3D free_mem[j].MemSize;=0D + for (t =3D j + 1; t < free_index; t++) {=0D + if ((free_mem[j].MemStart + tempMemsize =3D=3D free_mem[t].MemStart)= =0D + && (free_mem[j].MemType =3D=3D free_mem[t].MemType))=0D + {=0D + tempMemsize +=3D free_mem[t].MemSize;=0D + } else {=0D + break;=0D + }=0D + }=0D +=0D + new_interface_mem->Map[tmp_index].MemType =3D SYSTEM_RAM;=0D + new_interface_mem->Map[tmp_index].MemStart =3D free_mem[j].MemStart;=0D + new_interface_mem->Map[tmp_index].MemSize =3D tempMemsize;=0D +=0D + j =3D t;=0D + tmp_index++;=0D + }=0D +=0D + tmp_index =3D memmap_sort (reserve_mem, reserve_index, new_interface_mem= , tmp_index, SYSTEM_RAM_RESERVED);=0D +=0D + new_interface_mem->MapCount =3D tmp_index;=0D + new_interface_mem->Header.CheckSum =3D 0;=0D +=0D + checksum =3D CalculateCheckSum8 ((CONST UINT8 *)new_interface_mem, new_i= nterface_mem->Header.Length);=0D + new_interface_mem->Header.CheckSum =3D checksum;=0D +=0D + return ;=0D +}=0D +/**=0D + Establish linux kernel boot parameters.=0D +=0D + @param Bpi A pointer to the boot parameter interface.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +SetupLinuxBootParams (=0D + IN OUT BootParamsInterface *Bpi=0D + )=0D +{=0D + EFI_MEMORY_DESCRIPTOR *MemoryMapPtr =3D NULL;=0D + MEM_MAP *new_interface_mem =3D NULL;=0D + UINTN MapKey =3D 0;=0D + UINTN MemoryMapSize =3D 0;=0D + UINTN DescriptorSize =3D 0;=0D +=0D + new_interface_mem =3D FindNewInterfaceMem (Bpi);=0D + MemoryMapPtr =3D GetSystemMemap (&MapKey, &MemoryMapSize, &DescriptorSiz= e);=0D +=0D + DEBUG ((DEBUG_INFO, "new_interface_mem %p MemoryMapPtr %p MapKey %x.\n",= =0D + new_interface_mem, MemoryMapPtr, MapKey));=0D + MemMapSort (new_interface_mem, MemoryMapPtr, MemoryMapSize, DescriptorSi= ze);=0D +=0D + gBS->ExitBootServices (gImageHandle, MapKey);=0D +=0D + return ;=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 +TryRunningQemuKernel (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT32 Size;=0D + UINT32 Argc;=0D + VOID **Argv;=0D + UINTN CommandLineSize;=0D + CHAR8 *CommandLine;=0D + VOID *KernelEntryPoint;=0D + VOID *Bpi;=0D + EFI_PHYSICAL_ADDRESS Address;=0D +=0D + CommandLine =3D NULL;=0D + CHAR8 *Args[] =3D {"a0", CommandLine};=0D + Argc =3D ARRAY_SIZE (Args);=0D + Size =3D Argc * sizeof (VOID **);=0D + Size +=3D sizeof (VOID **);=0D +=0D + Size +=3D ALIGN_UP (AsciiStrLen (Args[0]) + 1, 4);=0D +=0D + if (!QemuFwCfgIsAvailable ()) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + /* get command line size */=0D + QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);=0D + CommandLineSize =3D (UINTN) QemuFwCfgRead32 ();=0D + DEBUG ((DEBUG_INFO, "command line size: %d.\n", CommandLineSize));=0D +=0D + Size +=3D ALIGN_UP (CommandLineSize + 1, 4);=0D + DEBUG ((DEBUG_INFO, "kernel args size: %d.\n", Size));=0D + //Argv =3D LoadLinuxAllocateCommandLinePages (EFI_SIZE_TO_PAGES (Size));= =0D + Status =3D gBS->AllocatePages (=0D + AllocateAnyPages,=0D + EfiRuntimeServicesData,=0D + EFI_SIZE_TO_PAGES (Size),=0D + &Address=0D + );=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D + Argv =3D (VOID *) (UINTN) Address;=0D + DEBUG ((DEBUG_INFO, "kernel argv address: 0x%0x.\n", Argv));=0D +=0D + VOID **P =3D Argv;=0D + CHAR8 *Pos =3D (CHAR8 *) (Argv + (Argc + 1));=0D + AsciiStrCpyS (Pos, 256, Args[0]);=0D + *P++ =3D Pos;=0D +=0D + Pos +=3D ALIGN_UP (AsciiStrLen (Args[0]) + 1, 4);=0D + /* get command line content */=0D + QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);=0D + QemuFwCfgReadBytes (CommandLineSize, Pos);=0D + *P++ =3D Pos;=0D +=0D + *P =3D NULL;=0D +=0D + /* get kernel entry point */=0D + QemuFwCfgSelectItem (QemuFwCfgItemKernelEntry);=0D + KernelEntryPoint =3D (VOID *) ((UINTN) ((UINT32)QemuFwCfgRead64 ()));=0D +=0D + DEBUG ((DEBUG_INFO, "kernel entry point: %p.\n", KernelEntryPoint));=0D + if (KernelEntryPoint =3D=3D NULL) {=0D + DEBUG ((DEBUG_INFO, "kernel entry point invalid.\n"));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + Status =3D EfiGetSystemConfigurationTable (=0D + &gEfiLoongsonBootparamsTableGuid,=0D + (VOID **) &Bpi=0D + );=0D + if ((EFI_ERROR (Status))=0D + || (Bpi =3D=3D NULL))=0D + {=0D + DEBUG ((DEBUG_ERROR, "Get Boot Params Table Failed!\n"));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + SetupLinuxBootParams ((BootParamsInterface *)Bpi);=0D +=0D + DEBUG ((DEBUG_INFO, "kernel argc: %d, argv: 0x%0x, bpi: 0x%0x.\n", Argc,= Argv, Bpi));=0D + DEBUG ((DEBUG_INFO, "entry kernel ...\n"));=0D + ((EFI_KERNEL_ENTRY_POINT)KernelEntryPoint) (Argc, Argv, Bpi, NULL);=0D +=0D + return EFI_SUCCESS;=0D +}=0D --=20 2.27.0