diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Devices/EFI/Firmware/UefiPayloadPkg | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiPayloadPkg')
56 files changed, 10413 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c new file mode 100644 index 00000000..64377d9f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c @@ -0,0 +1,171 @@ +/** @file + This driver will report some MMIO/IO resources to dxe core, extract smbios and acpi + tables from bootloader. + + Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "BlSupportDxe.h" + +/** + Reserve MMIO/IO resource in GCD + + @param IsMMIO Flag of whether it is mmio resource or io resource. + @param GcdType Type of the space. + @param BaseAddress Base address of the space. + @param Length Length of the space. + @param Alignment Align with 2^Alignment + @param ImageHandle Handle for the image of this driver. + + @retval EFI_SUCCESS Reserve successful +**/ +EFI_STATUS +ReserveResourceInGcd ( + IN BOOLEAN IsMMIO, + IN UINTN GcdType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINTN Alignment, + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + if (IsMMIO) { + Status = gDS->AddMemorySpace ( + GcdType, + BaseAddress, + Length, + EFI_MEMORY_UC + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to add memory space :0x%lx 0x%lx\n", + BaseAddress, + Length + )); + } + ASSERT_EFI_ERROR (Status); + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdType, + Alignment, + Length, + &BaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = gDS->AddIoSpace ( + GcdType, + BaseAddress, + Length + ); + ASSERT_EFI_ERROR (Status); + Status = gDS->AllocateIoSpace ( + EfiGcdAllocateAddress, + GcdType, + Alignment, + Length, + &BaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + + +/** + Main entry for the bootloader support DXE module. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +BlDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *GuidHob; + SYSTEM_TABLE_INFO *SystemTableInfo; + EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo; + ACPI_BOARD_INFO *AcpiBoardInfo; + + Status = EFI_SUCCESS; + // + // Report MMIO/IO Resources + // + Status = ReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFEC00000, SIZE_4KB, 0, ImageHandle); // IOAPIC + ASSERT_EFI_ERROR (Status); + + Status = ReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFED00000, SIZE_1KB, 0, ImageHandle); // HPET + ASSERT_EFI_ERROR (Status); + + // + // Find the system table information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiSystemTableInfoGuid); + ASSERT (GuidHob != NULL); + SystemTableInfo = (SYSTEM_TABLE_INFO *)GET_GUID_HOB_DATA (GuidHob); + + // + // Install Acpi Table + // + if (SystemTableInfo->AcpiTableBase != 0 && SystemTableInfo->AcpiTableSize != 0) { + DEBUG ((DEBUG_ERROR, "Install Acpi Table at 0x%lx, length 0x%x\n", SystemTableInfo->AcpiTableBase, SystemTableInfo->AcpiTableSize)); + Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, (VOID *)(UINTN)SystemTableInfo->AcpiTableBase); + ASSERT_EFI_ERROR (Status); + } + + // + // Install Smbios Table + // + if (SystemTableInfo->SmbiosTableBase != 0 && SystemTableInfo->SmbiosTableSize != 0) { + DEBUG ((DEBUG_ERROR, "Install Smbios Table at 0x%lx, length 0x%x\n", SystemTableInfo->SmbiosTableBase, SystemTableInfo->SmbiosTableSize)); + Status = gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, (VOID *)(UINTN)SystemTableInfo->SmbiosTableBase); + ASSERT_EFI_ERROR (Status); + } + + // + // Find the frame buffer information and update PCDs + // + GuidHob = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + if (GuidHob != NULL) { + GfxInfo = (EFI_PEI_GRAPHICS_INFO_HOB *)GET_GUID_HOB_DATA (GuidHob); + Status = PcdSet32S (PcdVideoHorizontalResolution, GfxInfo->GraphicsMode.HorizontalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdVideoVerticalResolution, GfxInfo->GraphicsMode.VerticalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdSetupVideoHorizontalResolution, GfxInfo->GraphicsMode.HorizontalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdSetupVideoVerticalResolution, GfxInfo->GraphicsMode.VerticalResolution); + ASSERT_EFI_ERROR (Status); + } + + // + // Set PcdPciExpressBaseAddress and PcdPciExpressBaseSize by HOB info + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + if (GuidHob != NULL) { + AcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + Status = PcdSet64S (PcdPciExpressBaseAddress, AcpiBoardInfo->PcieBaseAddress); + ASSERT_EFI_ERROR (Status); + Status = PcdSet64S (PcdPciExpressBaseSize, AcpiBoardInfo->PcieBaseSize); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.h new file mode 100644 index 00000000..594b5488 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.h @@ -0,0 +1,30 @@ +/** @file + The header file of bootloader support DXE. + +Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef __DXE_BOOTLOADER_SUPPORT_H__ +#define __DXE_BOOTLOADER_SUPPORT_H__ + +#include <PiDxe.h> + +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DxeServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiLib.h> +#include <Library/IoLib.h> +#include <Library/HobLib.h> + +#include <Guid/Acpi.h> +#include <Guid/SmBios.h> +#include <Guid/SystemTableInfoGuid.h> +#include <Guid/AcpiBoardInfoGuid.h> +#include <Guid/GraphicsInfoHob.h> + +#include <IndustryStandard/Acpi.h> + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf new file mode 100644 index 00000000..95e0ba42 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf @@ -0,0 +1,60 @@ +## @file +# Bootloader Support DXE Module +# +# Report some MMIO/IO resources to dxe core, extract smbios and acpi tables +# +# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BlSupportDxe + FILE_GUID = C68DAA4E-7AB5-41e8-A91D-5954421053F3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = BlDxeEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BlSupportDxe.c + BlSupportDxe.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + BaseMemoryLib + UefiLib + HobLib + +[Guids] + gEfiAcpiTableGuid + gEfiSmbiosTableGuid + gUefiSystemTableInfoGuid + gUefiAcpiBoardInfoGuid + gEfiGraphicsInfoHobGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize + +[Depex] + TRUE diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt new file mode 100644 index 00000000..5ed6f61e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt @@ -0,0 +1,80 @@ +================================================================================ +Build And Integration Instructions +2020 Aug 1st +================================================================================ + +================================================================================ +DISCLAIMER +================================================================================ +This release note as well as the software described in it is furnished under license +and may only be used or copied in accordance with the terms of the license. The +information in this manual is furnished for informational use only, is subject to +change without notice, and should not be construed as a commitment by Intel Corporation. +Intel Corporation assumes no responsibility or liability for any errors or inaccuracies +that may appear in this document or any software that may be provided in association +with this document. +Except as permitted by such license, no part of this document may be reproduced, +stored in a retrieval system, or transmitted in any form or by any means without +the express written consent of Intel Corporation. + +================================================================================ + INDEX +================================================================================ +A. INTRODUCTION +B. HOW TO BUILD +C. HOW TO INTEGRATE INTO COREBOOT +D. HOW TO INTEGRATE INTO SLIM BOOTLOADER + +================================================================================ +A. INTRODUCTION +================================================================================ +This document provides instructions on how to build UEFI Payload and how to +integrate it into coreboot or Slim Bootloader firmware. + +================================================================================ +B. HOW TO BUILD +================================================================================ +1. Run the below two commands in windows command prompt window: + > edksetup.bat + + For pure X64 build: + > build -a x64 -p UefiPayloadPkg\UefiPayloadPkg.dsc -b <BuildType> -t <ToolChain> + -D BOOTLOADER=<Bootloader> + + For X64 build with IA32 entry point: + > build -a IA32 -a X64 -p UefiPayloadPkg\UefiPayloadPkg.dsc -b <BuildType> -t <ToolChain> + -D BOOTLOADER=<Bootloader> + + <BuildType> support 'DEBUG', 'RELEASE' and 'NOOPT'. + <ToolChain> is the EDK II build environment on your host. Tested with VS2015x86 toolchain. + <Bootloader> could be "SBL" for Slim Bootloader and "COREBOOT" for coreboot. + + Refer to https://github.com/tianocore/tianocore.github.io/wiki/UDK2018-How-to-Build for + details about EDK II build steps. + + NOTE: Pure 32bit UEFI payload support could be added if required later. + +2. If build is successfully, the payload image (UEFIPAYLOAD.fd) will be generated inside the + folder of Build\UefiPayloadPkg. + +================================================================================ +C. HOW TO INTEGRATE INTO COREBOOT +================================================================================ +1. Copy the payload image (UEFIPAYLOAD.fd) into the top-level directory of Coreboot source tree. +2. Run "make menuconfig" in linux console to start Coreboot configuration surface. +3. In the Payload section, + 1) Choose "Tianocore Payload" for the option of "Add a payload". + 2) Update the path of payload image for the option of "Tianocore binary". + 3) Choose "UEFIPayload" for the option of "Tianocore Payload". +4. If the graphics console is required in UEFI payload, enable framebuffer initialization in coreboot. + This could be done by enabling native graphics or using VGA BIOS option rom. +5. Build the coreboot firmware image. + +================================================================================ +D. HOW TO INTEGRATE INTO SLIM BOOTLOADER +================================================================================ +Please refer https://slimbootloader.github.io/how-tos/integrate-multiple-payloads.html for below steps. +1. Copy the payload image (UEFIPAYLOAD.fd) into Slim Bootloader source at PayloadPkg\PayloadBins\UefiPld.fd +2. Update config data to make UEFI payload as default payload if required. +3. Build Slim Bootloader with UEFI payload: + BuildLoader.py build <Platform> -p "OsLoader.efi:LLDR:Lz4;UefiPld.fd:UEFI:Lzma" diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/ComponentName.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/ComponentName.c new file mode 100644 index 00000000..d5a91967 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/ComponentName.c @@ -0,0 +1,184 @@ +/** @file + UEFI Component Name(2) protocol implementation for the generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include <PiDxe.h> +#include <Library/UefiLib.h> + +extern EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2; + +// +// Driver name table for GraphicsOutput module. +// It is shared by the implementation of ComponentName & ComponentName2 Protocol. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mGraphicsOutputDriverNameTable[] = { + { + "eng;en", + L"Generic Graphics Output Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mGraphicsOutputDriverNameTable, + DriverName, + (BOOLEAN) (This == &mGraphicsOutputComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName = { + GraphicsOutputComponentNameGetDriverName, + GraphicsOutputComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GraphicsOutputComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GraphicsOutputComponentNameGetControllerName, + "en" +}; diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c new file mode 100644 index 00000000..8529ebaf --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c @@ -0,0 +1,739 @@ +/** @file + Implementation for a generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "GraphicsOutput.h" +CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = { + { + ACPI_DEVICE_PATH, + ACPI_ADR_DP, + { sizeof (ACPI_ADR_DEVICE_PATH), 0 }, + }, + ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0) +}; + +EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = { + MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8 +}; + +// +// The driver should only start on one graphics controller. +// So a global flag is used to remember that the driver is already started. +// +BOOLEAN mDriverStarted = FALSE; + +/** + Returns information for an available graphics mode that the graphics device + and the set of active video output devices supports. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Valid mode information was returned. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_INVALID_PARAMETER ModeNumber is not valid. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + *SizeOfInfo = This->Mode->SizeOfInfo; + *Info = AllocateCopyPool (*SizeOfInfo, This->Mode->Info); + return EFI_SUCCESS; +} + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber +) +{ + RETURN_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); + + Black.Blue = 0; + Black.Green = 0; + Black.Red = 0; + Black.Reserved = 0; + + Status = FrameBufferBlt ( + Private->FrameBufferBltLibConfigure, + &Black, + EfiBltVideoFill, + 0, 0, + 0, 0, + This->Mode->Info->HorizontalResolution, + This->Mode->Info->VerticalResolution, + 0 + ); + return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS; +} + +/** + Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer. + + @param This Protocol instance pointer. + @param BltBuffer The data to transfer to the graphics screen. + Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). + @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen. + @param SourceX The X coordinate of source for the BltOperation. + @param SourceY The Y coordinate of source for the BltOperation. + @param DestinationX The X coordinate of destination for the BltOperation. + @param DestinationY The Y coordinate of destination for the BltOperation. + @param Width The width of a rectangle in the blt rectangle in pixels. + @param Height The height of a rectangle in the blt rectangle in pixels. + @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation. + If a Delta of zero is used, the entire BltBuffer is being operated on. + If a subrectangle of the BltBuffer is being used then Delta + represents the number of bytes in a row of the BltBuffer. + + @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + RETURN_STATUS Status; + EFI_TPL Tpl; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); + // + // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = FrameBufferBlt ( + Private->FrameBufferBltLibConfigure, + BltBuffer, + BltOperation, + SourceX, SourceY, + DestinationX, DestinationY, Width, Height, + Delta + ); + gBS->RestoreTPL (Tpl); + + return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; +} + +CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = { + GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE, // Signature + NULL, // GraphicsOutputHandle + { + GraphicsOutputQueryMode, + GraphicsOutputSetMode, + GraphicsOutputBlt, + NULL // Mode + }, + { + 1, // MaxMode + 0, // Mode + NULL, // Info + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo + 0, // FrameBufferBase + 0 // FrameBufferSize + }, + NULL, // DevicePath + NULL, // PciIo + 0, // PciAttributes + NULL, // FrameBufferBltLibConfigure + 0 // FrameBufferBltLibConfigureSize +}; + +/** + Test whether the Controller can be managed by the driver. + + @param This Driver Binding protocol instance pointer. + @param Controller The PCI controller. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS The driver can manage the video device. + @retval other The driver cannot manage the video device. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Since there is only one GraphicsInfo HOB, the driver only manages one video device. + // + if (mDriverStarted) { + return EFI_ALREADY_STARTED; + } + + // + // Test the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Test the DevicePath protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if ((RemainingDevicePath == NULL) || + IsDevicePathEnd (RemainingDevicePath) || + CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0) { + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Start the video controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle The PCI controller. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS The driver starts to manage the video device. + @retval other The driver cannot manage the video device. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + RETURN_STATUS ReturnStatus; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH *PciDevicePath; + PCI_TYPE00 Pci; + UINT8 Index; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources; + VOID *HobStart; + EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *DeviceInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + + FrameBufferBase = 0; + + HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB))); + GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); + + HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid); + if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) { + // + // Use default device infomation when the device info HOB doesn't exist + // + DeviceInfo = &mDefaultGraphicsDeviceInfo; + DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName)); + } else { + DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); + DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB:\n" + " VendorId = %04x, DeviceId = %04x,\n" + " RevisionId = %02x, BarIndex = %x,\n" + " SubsystemVendorId = %04x, SubsystemId = %04x\n", + gEfiCallerBaseName, + DeviceInfo->VendorId, DeviceInfo->DeviceId, + DeviceInfo->RevisionId, DeviceInfo->BarIndex, + DeviceInfo->SubsystemVendorId, DeviceInfo->SubsystemId)); + } + + // + // Open the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &PciDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + // + // Read the PCI Class Code from the PCI Device + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); + if (!EFI_ERROR (Status)) { + if (!IS_PCI_DISPLAY (&Pci) || ( + ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) || + ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) || + ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) || + ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) || + ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID)) + ) + ) { + // + // It's not a video device, or device infomation doesn't match. + // + Status = EFI_UNSUPPORTED; + } else { + // + // If it's a video device and device information matches, use the BarIndex + // from device information, or any BAR if BarIndex is not specified + // whose size >= the frame buffer size from GraphicsInfo HOB. + // Store the new frame buffer base. + // + for (Index = 0; Index < MAX_PCI_BAR; Index++) { + if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) { + continue; + } + Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[%a]: BAR[%d]: Base = %lx, Length = %lx\n", + gEfiCallerBaseName, Index, Resources->AddrRangeMin, Resources->AddrLen)); + if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && + (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) && + (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && + (Resources->AddrLen >= GraphicsInfo->FrameBufferSize) + ) { + if (FrameBufferBase == 0) { + FrameBufferBase = Resources->AddrRangeMin; + } + if (DeviceInfo->BarIndex == MAX_UINT8) { + if (Resources->AddrRangeMin == GraphicsInfo->FrameBufferBase) { + FrameBufferBase = Resources->AddrRangeMin; + break; + } + } else { + break; + } + } + } + } + if (Index == MAX_PCI_BAR) { + Status = EFI_UNSUPPORTED; + } else { + DEBUG ((DEBUG_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName)); + } + } + } + + if (EFI_ERROR (Status)) { + goto CloseProtocols; + } + + if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + + Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CloseProtocols; + } + + Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase; + Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize; + Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode; + + // + // Fix up Mode pointer in GraphicsOutput + // + Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode; + + // + // Set attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &Private->PciAttributes + ); + if (!EFI_ERROR (Status)) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + + if (EFI_ERROR (Status)) { + goto FreeMemory; + } + + // + // Create the FrameBufferBltLib configuration. + // + ReturnStatus = FrameBufferBltConfigure ( + (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, + Private->GraphicsOutput.Mode->Info, + Private->FrameBufferBltLibConfigure, + &Private->FrameBufferBltLibConfigureSize + ); + if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) { + Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize); + if (Private->FrameBufferBltLibConfigure != NULL) { + ReturnStatus = FrameBufferBltConfigure ( + (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, + Private->GraphicsOutput.Mode->Info, + Private->FrameBufferBltLibConfigure, + &Private->FrameBufferBltLibConfigureSize + ); + } + } + if (RETURN_ERROR (ReturnStatus)) { + Status = EFI_OUT_OF_RESOURCES; + goto RestorePciAttributes; + } + + Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode); + if (Private->DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RestorePciAttributes; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->GraphicsOutputHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (!EFI_ERROR (Status)) { + mDriverStarted = TRUE; + } else { + gBS->UninstallMultipleProtocolInterfaces ( + Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + } + } + +RestorePciAttributes: + if (EFI_ERROR (Status)) { + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + Private->PciAttributes, + NULL + ); + } + +FreeMemory: + if (EFI_ERROR (Status)) { + if (Private != NULL) { + if (Private->DevicePath != NULL) { + FreePool (Private->DevicePath); + } + if (Private->FrameBufferBltLibConfigure != NULL) { + FreePool (Private->FrameBufferBltLibConfigure); + } + FreePool (Private); + } + } + +CloseProtocols: + if (EFI_ERROR (Status)) { + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + +/** + Stop the video controller. + + @param This Driver Binding protocol instance pointer. + @param Controller The PCI controller. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + if (NumberOfChildren == 0) { + + // + // Close the PCI I/O Protocol + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; + } + + ASSERT (NumberOfChildren == 1); + Status = gBS->OpenProtocol ( + ChildHandleBuffer[0], + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Gop, + This->DriverBindingHandle, + ChildHandleBuffer[0], + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Private->GraphicsOutputHandle + ); + ASSERT_EFI_ERROR (Status); + // + // Remove the GOP protocol interface from the system + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Restore original PCI attributes + // + Status = Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationSet, + Private->PciAttributes, + NULL + ); + ASSERT_EFI_ERROR (Status); + + FreePool (Private->DevicePath); + FreePool (Private->FrameBufferBltLibConfigure); + mDriverStarted = FALSE; + } else { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->GraphicsOutputHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + +EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = { + GraphicsOutputDriverBindingSupported, + GraphicsOutputDriverBindingStart, + GraphicsOutputDriverBindingStop, + 0x10, + NULL, + NULL +}; + +/** + The Entry Point for GraphicsOutput driver. + + It installs DriverBinding, ComponentName and ComponentName2 protocol if there is + GraphicsInfo HOB passed from Graphics PEIM. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeGraphicsOutput ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *HobStart; + + HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + + if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) { + return EFI_NOT_FOUND; + } + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &mGraphicsOutputDriverBinding, + ImageHandle, + &mGraphicsOutputComponentName, + &mGraphicsOutputComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.h new file mode 100644 index 00000000..00b4c017 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.h @@ -0,0 +1,53 @@ +/** @file + Header file for a generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +#ifndef _GRAPHICS_OUTPUT_DXE_H_ +#define _GRAPHICS_OUTPUT_DXE_H_ +#include <PiDxe.h> + +#include <IndustryStandard/Pci.h> +#include <IndustryStandard/Acpi.h> +#include <Guid/GraphicsInfoHob.h> +#include <Protocol/DriverBinding.h> +#include <Protocol/PciIo.h> +#include <Protocol/DevicePath.h> +#include <Protocol/GraphicsOutput.h> +#include <Protocol/ComponentName.h> +#include <Protocol/ComponentName2.h> + +#include <Library/BaseLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/HobLib.h> +#include <Library/DevicePathLib.h> +#include <Library/FrameBufferBltLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiLib.h> + +#define MAX_PCI_BAR 6 + +typedef struct { + UINT32 Signature; + EFI_HANDLE GraphicsOutputHandle; + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutputMode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 PciAttributes; + FRAME_BUFFER_CONFIGURE *FrameBufferBltLibConfigure; + UINTN FrameBufferBltLibConfigureSize; +} GRAPHICS_OUTPUT_PRIVATE_DATA; + +#define GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('g', 'g', 'o', 'p') +#define GRAPHICS_OUTPUT_PRIVATE_FROM_THIS(a) \ + CR(a, GRAPHICS_OUTPUT_PRIVATE_DATA, GraphicsOutput, GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE) + +extern EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2; +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf new file mode 100644 index 00000000..ecbea5e3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf @@ -0,0 +1,53 @@ +## @file +# This driver produces GraphicsOutput protocol based on the GraphicsInfo HOB information. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GraphicsOutputDxe + FILE_GUID = 0B04B2ED-861C-42cd-A22F-C3AAFACCB896 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeGraphicsOutput + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + GraphicsOutput.h + GraphicsOutput.c + ComponentName.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + FrameBufferBltLib + UefiLib + HobLib + +[Guids] + gEfiGraphicsInfoHobGuid ## CONSUMES ## HOB + gEfiGraphicsDeviceInfoHobGuid ## CONSUMES ## HOB + +[Protocols] + gEfiGraphicsOutputProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiPciIoProtocolGuid ## TO_START diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Coreboot.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Coreboot.h new file mode 100644 index 00000000..12fd10da --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Coreboot.h @@ -0,0 +1,249 @@ +/** @file + Coreboot PEI module include file. + + Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _COREBOOT_PEI_H_INCLUDED_ +#define _COREBOOT_PEI_H_INCLUDED_ + +#if defined(_MSC_VER) +#pragma warning( disable : 4200 ) +#endif + +#define DYN_CBMEM_ALIGN_SIZE (4096) + +#define IMD_ENTRY_MAGIC (~0xC0389481) +#define CBMEM_ENTRY_MAGIC (~0xC0389479) + +struct cbmem_entry { + UINT32 magic; + UINT32 start; + UINT32 size; + UINT32 id; +}; + +struct cbmem_root { + UINT32 max_entries; + UINT32 num_entries; + UINT32 locked; + UINT32 size; + struct cbmem_entry entries[0]; +}; + +struct imd_entry { + UINT32 magic; + UINT32 start_offset; + UINT32 size; + UINT32 id; +}; + +struct imd_root { + UINT32 max_entries; + UINT32 num_entries; + UINT32 flags; + UINT32 entry_align; + UINT32 max_offset; + struct imd_entry entries[0]; +}; + +struct cbuint64 { + UINT32 lo; + UINT32 hi; +}; + +#define CB_HEADER_SIGNATURE 0x4F49424C + +struct cb_header { + UINT32 signature; + UINT32 header_bytes; + UINT32 header_checksum; + UINT32 table_bytes; + UINT32 table_checksum; + UINT32 table_entries; +}; + +struct cb_record { + UINT32 tag; + UINT32 size; +}; + +#define CB_TAG_UNUSED 0x0000 +#define CB_TAG_MEMORY 0x0001 + +struct cb_memory_range { + struct cbuint64 start; + struct cbuint64 size; + UINT32 type; +}; + +#define CB_MEM_RAM 1 +#define CB_MEM_RESERVED 2 +#define CB_MEM_ACPI 3 +#define CB_MEM_NVS 4 +#define CB_MEM_UNUSABLE 5 +#define CB_MEM_VENDOR_RSVD 6 +#define CB_MEM_TABLE 16 + +struct cb_memory { + UINT32 tag; + UINT32 size; + struct cb_memory_range map[0]; +}; + +#define CB_TAG_MAINBOARD 0x0003 + +struct cb_mainboard { + UINT32 tag; + UINT32 size; + UINT8 vendor_idx; + UINT8 part_number_idx; + UINT8 strings[0]; +}; +#define CB_TAG_VERSION 0x0004 +#define CB_TAG_EXTRA_VERSION 0x0005 +#define CB_TAG_BUILD 0x0006 +#define CB_TAG_COMPILE_TIME 0x0007 +#define CB_TAG_COMPILE_BY 0x0008 +#define CB_TAG_COMPILE_HOST 0x0009 +#define CB_TAG_COMPILE_DOMAIN 0x000a +#define CB_TAG_COMPILER 0x000b +#define CB_TAG_LINKER 0x000c +#define CB_TAG_ASSEMBLER 0x000d + +struct cb_string { + UINT32 tag; + UINT32 size; + UINT8 string[0]; +}; + +#define CB_TAG_SERIAL 0x000f + +struct cb_serial { + UINT32 tag; + UINT32 size; +#define CB_SERIAL_TYPE_IO_MAPPED 1 +#define CB_SERIAL_TYPE_MEMORY_MAPPED 2 + UINT32 type; + UINT32 baseaddr; + UINT32 baud; + UINT32 regwidth; + + // Crystal or input frequency to the chip containing the UART. + // Provide the board specific details to allow the payload to + // initialize the chip containing the UART and make independent + // decisions as to which dividers to select and their values + // to eventually arrive at the desired console baud-rate. + UINT32 input_hertz; + + // UART PCI address: bus, device, function + // 1 << 31 - Valid bit, PCI UART in use + // Bus << 20 + // Device << 15 + // Function << 12 + UINT32 uart_pci_addr; +}; + +#define CB_TAG_CONSOLE 0x00010 + +struct cb_console { + UINT32 tag; + UINT32 size; + UINT16 type; +}; + +#define CB_TAG_CONSOLE_SERIAL8250 0 +#define CB_TAG_CONSOLE_VGA 1 // OBSOLETE +#define CB_TAG_CONSOLE_BTEXT 2 // OBSOLETE +#define CB_TAG_CONSOLE_LOGBUF 3 +#define CB_TAG_CONSOLE_SROM 4 // OBSOLETE +#define CB_TAG_CONSOLE_EHCI 5 + +#define CB_TAG_FORWARD 0x00011 + +struct cb_forward { + UINT32 tag; + UINT32 size; + UINT64 forward; +}; + +#define CB_TAG_FRAMEBUFFER 0x0012 +struct cb_framebuffer { + UINT32 tag; + UINT32 size; + + UINT64 physical_address; + UINT32 x_resolution; + UINT32 y_resolution; + UINT32 bytes_per_line; + UINT8 bits_per_pixel; + UINT8 red_mask_pos; + UINT8 red_mask_size; + UINT8 green_mask_pos; + UINT8 green_mask_size; + UINT8 blue_mask_pos; + UINT8 blue_mask_size; + UINT8 reserved_mask_pos; + UINT8 reserved_mask_size; +}; + +#define CB_TAG_VDAT 0x0015 +struct cb_vdat { + UINT32 tag; + UINT32 size; /* size of the entire entry */ + UINT64 vdat_addr; + UINT32 vdat_size; +}; + +#define CB_TAG_TIMESTAMPS 0x0016 +#define CB_TAG_CBMEM_CONSOLE 0x0017 +#define CB_TAG_MRC_CACHE 0x0018 +struct cb_cbmem_tab { + UINT32 tag; + UINT32 size; + UINT64 cbmem_tab; +}; + +/* Helpful macros */ + +#define MEM_RANGE_COUNT(_rec) \ + (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0])) + +#define MEM_RANGE_PTR(_rec, _idx) \ + (void *)(((UINT8 *) (_rec)) + sizeof(*(_rec)) \ + + (sizeof((_rec)->map[0]) * (_idx))) + + +#endif // _COREBOOT_PEI_H_INCLUDED_ diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h new file mode 100644 index 00000000..a43e8f20 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h @@ -0,0 +1,30 @@ +/** @file + This file defines the hob structure for board related information from acpi table + + Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __ACPI_BOARD_INFO_GUID_H__ +#define __ACPI_BOARD_INFO_GUID_H__ + +/// +/// Board information GUID +/// +extern EFI_GUID gUefiAcpiBoardInfoGuid; + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[2]; + UINT8 ResetValue; + UINT64 PmEvtBase; + UINT64 PmGpeEnBase; + UINT64 PmCtrlRegBase; + UINT64 PmTimerRegBase; + UINT64 ResetRegAddress; + UINT64 PcieBaseAddress; + UINT64 PcieBaseSize; +} ACPI_BOARD_INFO; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/MemoryMapInfoGuid.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/MemoryMapInfoGuid.h new file mode 100644 index 00000000..8bb5c741 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/MemoryMapInfoGuid.h @@ -0,0 +1,36 @@ +/** @file + This file defines the hob structure for memory map information. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEMORY_MAP_INFO_GUID_H__ +#define __MEMORY_MAP_INFO_GUID_H__ + +#include <Library/PcdLib.h> + +/// +/// Memory Map Information GUID +/// +extern EFI_GUID gLoaderMemoryMapInfoGuid; + +#pragma pack(1) +typedef struct { + UINT64 Base; + UINT64 Size; + UINT8 Type; + UINT8 Flag; + UINT8 Reserved[6]; +} MEMROY_MAP_ENTRY; + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[3]; + UINT32 Count; + MEMROY_MAP_ENTRY Entry[0]; +} MEMROY_MAP_INFO; +#pragma pack() + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/SerialPortInfoGuid.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/SerialPortInfoGuid.h new file mode 100644 index 00000000..57df5e20 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/SerialPortInfoGuid.h @@ -0,0 +1,31 @@ +/** @file + This file defines the hob structure for serial port. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SERIAL_PORT_INFO_GUID_H__ +#define __SERIAL_PORT_INFO_GUID_H__ + +/// +/// Serial Port Information GUID +/// +extern EFI_GUID gUefiSerialPortInfoGuid; + +#define PLD_SERIAL_TYPE_IO_MAPPED 1 +#define PLD_SERIAL_TYPE_MEMORY_MAPPED 2 + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[3]; + UINT32 Type; + UINT32 BaseAddr; + UINT32 Baud; + UINT32 RegWidth; + UINT32 InputHertz; + UINT32 UartPciAddr; +} SERIAL_PORT_INFO; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/SystemTableInfoGuid.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/SystemTableInfoGuid.h new file mode 100644 index 00000000..5fe7dd12 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/SystemTableInfoGuid.h @@ -0,0 +1,26 @@ +/** @file + This file defines the hob structure for system tables like ACPI, SMBIOS tables. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SYSTEM_TABLE_INFO_GUID_H__ +#define __SYSTEM_TABLE_INFO_GUID_H__ + +/// +/// System Table Information GUID +/// +extern EFI_GUID gUefiSystemTableInfoGuid; + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[3]; + UINT64 AcpiTableBase; + UINT32 AcpiTableSize; + UINT64 SmbiosTableBase; + UINT32 SmbiosTableSize; +} SYSTEM_TABLE_INFO; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h new file mode 100644 index 00000000..79eb3fc0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h @@ -0,0 +1,120 @@ +/** @file + This library will parse the coreboot table in memory and extract those required + information. + + Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include <PiPei.h> +#include <Guid/GraphicsInfoHob.h> +#include <Guid/MemoryMapInfoGuid.h> +#include <Guid/SerialPortInfoGuid.h> +#include <Guid/SystemTableInfoGuid.h> +#include <Guid/AcpiBoardInfoGuid.h> + +#ifndef __BOOTLOADER_PARSE_LIB__ +#define __BOOTLOADER_PARSE_LIB__ + +#define GET_BOOTLOADER_PARAMETER() (*(UINTN *)(UINTN)(PcdGet32(PcdPayloadStackTop) - sizeof(UINT64))) +#define SET_BOOTLOADER_PARAMETER(Value) GET_BOOTLOADER_PARAMETER()=Value + +typedef RETURN_STATUS \ + (*BL_MEM_INFO_CALLBACK) (MEMROY_MAP_ENTRY *MemoryMapEntry, VOID *Param); + +/** + This function retrieves the parameter base address from boot loader. + + This function will get bootloader specific parameter address for UEFI payload. + e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +EFIAPI +GetParameterBase ( + VOID + ); + +/** + Acquire the memory map information. + + @param MemInfoCallback The callback routine + @param Params Pointer to the callback routine parameter + + @retval RETURN_SUCCESS Successfully find out the memory information. + @retval RETURN_NOT_FOUND Failed to find the memory information. + +**/ +RETURN_STATUS +EFIAPI +ParseMemoryInfo ( + IN BL_MEM_INFO_CALLBACK MemInfoCallback, + IN VOID *Params + ); + +/** + Acquire acpi table and smbios table from slim bootloader + + @param SystemTableInfo Pointer to the system table info + + @retval RETURN_SUCCESS Successfully find out the tables. + @retval RETURN_NOT_FOUND Failed to find the tables. + +**/ +RETURN_STATUS +EFIAPI +ParseSystemTable ( + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ); + + +/** + Find the serial port information + + @param SERIAL_PORT_INFO Pointer to serial port info structure + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +EFIAPI +ParseSerialInfo ( + OUT SERIAL_PORT_INFO *SerialPortInfo + ); + + +/** + Find the video frame buffer information + + @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxInfo ( + OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo + ); + +/** + Find the video frame buffer device information + + @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxDeviceInfo ( + OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/PlatformSupportLib.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/PlatformSupportLib.h new file mode 100644 index 00000000..762d1ae5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/PlatformSupportLib.h @@ -0,0 +1,28 @@ +/** @file + Bootloader Platform Support library. Platform can provide an implementation of this + library class to provide hooks that may be required for some type of + platform features. + +Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BOOTLOADER_PLATFORM_SUPPORT_LIB__ +#define __BOOTLOADER_PLATFORM_SUPPORT_LIB__ + +/** + Parse platform specific information from bootloader + + @retval RETURN_SUCCESS The platform specific coreboot support succeeded. + @retval RETURN_DEVICE_ERROR The platform specific coreboot support could not be completed. + +**/ +EFI_STATUS +EFIAPI +ParsePlatformInfo ( + VOID + ); + +#endif // __BOOTLOADER_PLATFORM_SUPPORT_LIB__ + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c new file mode 100644 index 00000000..5a428eae --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c @@ -0,0 +1,270 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> +#include <Library/IoLib.h> +#include <Library/HobLib.h> +#include <Library/DebugLib.h> + +#include <Guid/AcpiBoardInfoGuid.h> +#include <IndustryStandard/Acpi.h> + +#define ACPI_TIMER_COUNT_SIZE BIT24 + +UINTN mPmTimerReg = 0; + +/** + The constructor function enables ACPI IO space. + + If ACPI I/O space not enabled, this function will enable it. + It will always return RETURN_SUCCESS. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +AcpiTimerLibConstructor ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + ACPI_BOARD_INFO *pAcpiBoardInfo; + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + + pAcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + + mPmTimerReg = (UINTN)pAcpiBoardInfo->PmTimerRegBase; + + return EFI_SUCCESS; +} + +/** + Internal function to read the current tick counter of ACPI. + + Internal function to read the current tick counter of ACPI. + + @return The tick counter read. + +**/ +UINT32 +InternalAcpiGetTimerTick ( + VOID + ) +{ + if (mPmTimerReg == 0) { + AcpiTimerLibConstructor (); + } + return IoRead32 (mPmTimerReg); +} + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param Delay A period of time to delay in ticks. + +**/ +VOID +InternalAcpiDelay ( + IN UINT32 Delay + ) +{ + UINT32 Ticks; + UINT32 Times; + + Times = Delay >> 22; + Delay &= BIT22 - 1; + do { + // + // The target timer count is calculated here + // + Ticks = InternalAcpiGetTimerTick () + Delay; + Delay = BIT22; + // + // Wait until time out + // Delay >= 2^23 could not be handled by this function + // Timer wrap-arounds are handled correctly by this function + // + while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) { + CpuPause (); + } + } while (Times-- > 0); +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + MicroSeconds, + ACPI_TIMER_FREQUENCY + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + NanoSeconds, + ACPI_TIMER_FREQUENCY + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return (UINT64)InternalAcpiGetTimerTick (); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + *StartValue = 0; + } + + if (EndValue != NULL) { + *EndValue = ACPI_TIMER_COUNT_SIZE - 1; + } + + return ACPI_TIMER_FREQUENCY; +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency = GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, + // i.e. highest bit set in Remainder should <= 33. + // + Shift = MAX (0, HighBitSet64 (Remainder) - 33); + Remainder = RShiftU64 (Remainder, (UINTN) Shift); + Frequency = RShiftU64 (Frequency, (UINTN) Shift); + NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); + + return NanoSeconds; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf new file mode 100644 index 00000000..252cdb35 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf @@ -0,0 +1,40 @@ +## @file +# ACPI Timer Library Instance. +# +# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiTimerLib + FILE_GUID = A41BF616-EF77-4658-9992-D813071C34CF + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + CONSTRUCTOR = AcpiTimerLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + AcpiTimerLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + IoLib + HobLib + DebugLib + +[Guids] + gUefiAcpiBoardInfoGuid diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c new file mode 100644 index 00000000..463274d4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c @@ -0,0 +1,560 @@ +/** @file + This library will parse the coreboot table in memory and extract those required + information. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi/UefiBaseType.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/BlParseLib.h> +#include <IndustryStandard/Acpi.h> +#include <Coreboot.h> + + +/** + Convert a packed value from cbuint64 to a UINT64 value. + + @param val The pointer to packed data. + + @return the UNIT64 value after conversion. + +**/ +UINT64 +cb_unpack64 ( + IN struct cbuint64 val + ) +{ + return LShiftU64 (val.hi, 32) | val.lo; +} + + +/** + Returns the sum of all elements in a buffer of 16-bit values. During + calculation, the carry bits are also been added. + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits included during additions. + +**/ +UINT16 +CbCheckSum16 ( + IN UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT32 Sum; + UINT32 TmpValue; + UINTN Idx; + UINT8 *TmpPtr; + + Sum = 0; + TmpPtr = (UINT8 *)Buffer; + for(Idx = 0; Idx < Length; Idx++) { + TmpValue = TmpPtr[Idx]; + if (Idx % 2 == 1) { + TmpValue <<= 8; + } + + Sum += TmpValue; + + // Wrap + if (Sum >= 0x10000) { + Sum = (Sum + (Sum >> 16)) & 0xFFFF; + } + } + + return (UINT16)((~Sum) & 0xFFFF); +} + + +/** + Check the coreboot table if it is valid. + + @param Header Pointer to coreboot table + + @retval TRUE The coreboot table is valid. + @retval Others The coreboot table is not valid. + +**/ +BOOLEAN +IsValidCbTable ( + IN struct cb_header *Header + ) +{ + UINT16 CheckSum; + + if ((Header == NULL) || (Header->table_bytes == 0)) { + return FALSE; + } + + if (Header->signature != CB_HEADER_SIGNATURE) { + return FALSE; + } + + // + // Check the checksum of the coreboot table header + // + CheckSum = CbCheckSum16 ((UINT16 *)Header, sizeof (*Header)); + if (CheckSum != 0) { + DEBUG ((DEBUG_ERROR, "Invalid coreboot table header checksum\n")); + return FALSE; + } + + CheckSum = CbCheckSum16 ((UINT16 *)((UINT8 *)Header + sizeof (*Header)), Header->table_bytes); + if (CheckSum != Header->table_checksum) { + DEBUG ((DEBUG_ERROR, "Incorrect checksum of all the coreboot table entries\n")); + return FALSE; + } + + return TRUE; +} + + +/** + This function retrieves the parameter base address from boot loader. + + This function will get bootloader specific parameter address for UEFI payload. + e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +EFIAPI +GetParameterBase ( + VOID + ) +{ + struct cb_header *Header; + struct cb_record *Record; + UINT8 *TmpPtr; + UINT8 *CbTablePtr; + UINTN Idx; + + // + // coreboot could pass coreboot table to UEFI payload + // + Header = (struct cb_header *)(UINTN)GET_BOOTLOADER_PARAMETER (); + if (IsValidCbTable (Header)) { + return Header; + } + + // + // Find simplified coreboot table in memory range 0 ~ 4KB. + // Some GCC version does not allow directly access to NULL pointer, + // so start the search from 0x10 instead. + // + for (Idx = 16; Idx < 4096; Idx += 16) { + Header = (struct cb_header *)Idx; + if (Header->signature == CB_HEADER_SIGNATURE) { + break; + } + } + + if (Idx >= 4096) { + return NULL; + } + + // + // Check the coreboot header + // + if (!IsValidCbTable (Header)) { + return NULL; + } + + // + // Find full coreboot table in high memory + // + CbTablePtr = NULL; + TmpPtr = (UINT8 *)Header + Header->header_bytes; + for (Idx = 0; Idx < Header->table_entries; Idx++) { + Record = (struct cb_record *)TmpPtr; + if (Record->tag == CB_TAG_FORWARD) { + CbTablePtr = (VOID *)(UINTN)((struct cb_forward *)(UINTN)Record)->forward; + break; + } + TmpPtr += Record->size; + } + + // + // Check the coreboot header in high memory + // + if (!IsValidCbTable ((struct cb_header *)CbTablePtr)) { + return NULL; + } + + SET_BOOTLOADER_PARAMETER ((UINT32)(UINTN)CbTablePtr); + + return CbTablePtr; +} + + +/** + Find coreboot record with given Tag. + + @param Tag The tag id to be found + + @retval NULL The Tag is not found. + @retval Others The pointer to the record found. + +**/ +VOID * +FindCbTag ( + IN UINT32 Tag + ) +{ + struct cb_header *Header; + struct cb_record *Record; + UINT8 *TmpPtr; + UINT8 *TagPtr; + UINTN Idx; + + Header = (struct cb_header *) GetParameterBase (); + + TagPtr = NULL; + TmpPtr = (UINT8 *)Header + Header->header_bytes; + for (Idx = 0; Idx < Header->table_entries; Idx++) { + Record = (struct cb_record *)TmpPtr; + if (Record->tag == Tag) { + TagPtr = TmpPtr; + break; + } + TmpPtr += Record->size; + } + + return TagPtr; +} + + +/** + Find the given table with TableId from the given coreboot memory Root. + + @param Root The coreboot memory table to be searched in + @param TableId Table id to be found + @param MemTable To save the base address of the memory table found + @param MemTableSize To save the size of memory table found + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +FindCbMemTable ( + IN struct cbmem_root *Root, + IN UINT32 TableId, + OUT VOID **MemTable, + OUT UINT32 *MemTableSize + ) +{ + UINTN Idx; + BOOLEAN IsImdEntry; + struct cbmem_entry *Entries; + + if ((Root == NULL) || (MemTable == NULL)) { + return RETURN_INVALID_PARAMETER; + } + // + // Check if the entry is CBMEM or IMD + // and handle them separately + // + Entries = Root->entries; + if (Entries[0].magic == CBMEM_ENTRY_MAGIC) { + IsImdEntry = FALSE; + } else { + Entries = (struct cbmem_entry *)((struct imd_root *)Root)->entries; + if (Entries[0].magic == IMD_ENTRY_MAGIC) { + IsImdEntry = TRUE; + } else { + return RETURN_NOT_FOUND; + } + } + + for (Idx = 0; Idx < Root->num_entries; Idx++) { + if (Entries[Idx].id == TableId) { + if (IsImdEntry) { + *MemTable = (VOID *) ((UINTN)Entries[Idx].start + (UINTN)Root); + } else { + *MemTable = (VOID *) (UINTN)Entries[Idx].start; + } + if (MemTableSize != NULL) { + *MemTableSize = Entries[Idx].size; + } + + DEBUG ((DEBUG_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n", + TableId, *MemTable, Entries[Idx].size)); + return RETURN_SUCCESS; + } + } + + return RETURN_NOT_FOUND; +} + +/** + Acquire the coreboot memory table with the given table id + + @param TableId Table id to be searched + @param MemTable Pointer to the base address of the memory table + @param MemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +ParseCbMemTable ( + IN UINT32 TableId, + OUT VOID **MemTable, + OUT UINT32 *MemTableSize + ) +{ + EFI_STATUS Status; + struct cb_memory *rec; + struct cb_memory_range *Range; + UINT64 Start; + UINT64 Size; + UINTN Index; + struct cbmem_root *CbMemRoot; + + if (MemTable == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *MemTable = NULL; + Status = RETURN_NOT_FOUND; + + // + // Get the coreboot memory table + // + rec = (struct cb_memory *)FindCbTag (CB_TAG_MEMORY); + if (rec == NULL) { + return Status; + } + + for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { + Range = MEM_RANGE_PTR(rec, Index); + Start = cb_unpack64(Range->start); + Size = cb_unpack64(Range->size); + + if ((Range->type == CB_MEM_TABLE) && (Start > 0x1000)) { + CbMemRoot = (struct cbmem_root *)(UINTN)(Start + Size - DYN_CBMEM_ALIGN_SIZE); + Status = FindCbMemTable (CbMemRoot, TableId, MemTable, MemTableSize); + if (!EFI_ERROR (Status)) { + break; + } + } + } + + return Status; +} + + + +/** + Acquire the memory information from the coreboot table in memory. + + @param MemInfoCallback The callback routine + @param Params Pointer to the callback routine parameter + + @retval RETURN_SUCCESS Successfully find out the memory information. + @retval RETURN_NOT_FOUND Failed to find the memory information. + +**/ +RETURN_STATUS +EFIAPI +ParseMemoryInfo ( + IN BL_MEM_INFO_CALLBACK MemInfoCallback, + IN VOID *Params + ) +{ + struct cb_memory *rec; + struct cb_memory_range *Range; + UINTN Index; + MEMROY_MAP_ENTRY MemoryMap; + + // + // Get the coreboot memory table + // + rec = (struct cb_memory *)FindCbTag (CB_TAG_MEMORY); + if (rec == NULL) { + return RETURN_NOT_FOUND; + } + + for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { + Range = MEM_RANGE_PTR(rec, Index); + MemoryMap.Base = cb_unpack64(Range->start); + MemoryMap.Size = cb_unpack64(Range->size); + MemoryMap.Type = (UINT8)Range->type; + MemoryMap.Flag = 0; + DEBUG ((DEBUG_INFO, "%d. %016lx - %016lx [%02x]\n", + Index, MemoryMap.Base, MemoryMap.Base + MemoryMap.Size - 1, MemoryMap.Type)); + + MemInfoCallback (&MemoryMap, Params); + } + + return RETURN_SUCCESS; +} + + +/** + Acquire acpi table and smbios table from coreboot + + @param SystemTableInfo Pointer to the system table info + + @retval RETURN_SUCCESS Successfully find out the tables. + @retval RETURN_NOT_FOUND Failed to find the tables. + +**/ +RETURN_STATUS +EFIAPI +ParseSystemTable ( + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ) +{ + EFI_STATUS Status; + VOID *MemTable; + UINT32 MemTableSize; + + Status = ParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), &MemTable, &MemTableSize); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + SystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)MemTable; + SystemTableInfo->SmbiosTableSize = MemTableSize; + + Status = ParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), &MemTable, &MemTableSize); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + SystemTableInfo->AcpiTableBase = (UINT64) (UINTN)MemTable; + SystemTableInfo->AcpiTableSize = MemTableSize; + + return Status; +} + + +/** + Find the serial port information + + @param SERIAL_PORT_INFO Pointer to serial port info structure + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +EFIAPI +ParseSerialInfo ( + OUT SERIAL_PORT_INFO *SerialPortInfo + ) +{ + struct cb_serial *CbSerial; + + CbSerial = FindCbTag (CB_TAG_SERIAL); + if (CbSerial == NULL) { + return RETURN_NOT_FOUND; + } + + SerialPortInfo->BaseAddr = CbSerial->baseaddr; + SerialPortInfo->RegWidth = CbSerial->regwidth; + SerialPortInfo->Type = CbSerial->type; + SerialPortInfo->Baud = CbSerial->baud; + SerialPortInfo->InputHertz = CbSerial->input_hertz; + SerialPortInfo->UartPciAddr = CbSerial->uart_pci_addr; + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer information + + @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxInfo ( + OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo + ) +{ + struct cb_framebuffer *CbFbRec; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GfxMode; + + if (GfxInfo == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbFbRec = FindCbTag (CB_TAG_FRAMEBUFFER); + if (CbFbRec == NULL) { + return RETURN_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "Found coreboot video frame buffer information\n")); + DEBUG ((DEBUG_INFO, "physical_address: 0x%lx\n", CbFbRec->physical_address)); + DEBUG ((DEBUG_INFO, "x_resolution: 0x%x\n", CbFbRec->x_resolution)); + DEBUG ((DEBUG_INFO, "y_resolution: 0x%x\n", CbFbRec->y_resolution)); + DEBUG ((DEBUG_INFO, "bits_per_pixel: 0x%x\n", CbFbRec->bits_per_pixel)); + DEBUG ((DEBUG_INFO, "bytes_per_line: 0x%x\n", CbFbRec->bytes_per_line)); + + DEBUG ((DEBUG_INFO, "red_mask_size: 0x%x\n", CbFbRec->red_mask_size)); + DEBUG ((DEBUG_INFO, "red_mask_pos: 0x%x\n", CbFbRec->red_mask_pos)); + DEBUG ((DEBUG_INFO, "green_mask_size: 0x%x\n", CbFbRec->green_mask_size)); + DEBUG ((DEBUG_INFO, "green_mask_pos: 0x%x\n", CbFbRec->green_mask_pos)); + DEBUG ((DEBUG_INFO, "blue_mask_size: 0x%x\n", CbFbRec->blue_mask_size)); + DEBUG ((DEBUG_INFO, "blue_mask_pos: 0x%x\n", CbFbRec->blue_mask_pos)); + DEBUG ((DEBUG_INFO, "reserved_mask_size: 0x%x\n", CbFbRec->reserved_mask_size)); + DEBUG ((DEBUG_INFO, "reserved_mask_pos: 0x%x\n", CbFbRec->reserved_mask_pos)); + + GfxMode = &GfxInfo->GraphicsMode; + GfxMode->Version = 0; + GfxMode->HorizontalResolution = CbFbRec->x_resolution; + GfxMode->VerticalResolution = CbFbRec->y_resolution; + GfxMode->PixelsPerScanLine = (CbFbRec->bytes_per_line << 3) / CbFbRec->bits_per_pixel; + if ((CbFbRec->red_mask_pos == 0) && (CbFbRec->green_mask_pos == 8) && (CbFbRec->blue_mask_pos == 16)) { + GfxMode->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; + } else if ((CbFbRec->blue_mask_pos == 0) && (CbFbRec->green_mask_pos == 8) && (CbFbRec->red_mask_pos == 16)) { + GfxMode->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + } + GfxMode->PixelInformation.RedMask = ((1 << CbFbRec->red_mask_size) - 1) << CbFbRec->red_mask_pos; + GfxMode->PixelInformation.GreenMask = ((1 << CbFbRec->green_mask_size) - 1) << CbFbRec->green_mask_pos; + GfxMode->PixelInformation.BlueMask = ((1 << CbFbRec->blue_mask_size) - 1) << CbFbRec->blue_mask_pos; + GfxMode->PixelInformation.ReservedMask = ((1 << CbFbRec->reserved_mask_size) - 1) << CbFbRec->reserved_mask_pos; + + GfxInfo->FrameBufferBase = CbFbRec->physical_address; + GfxInfo->FrameBufferSize = CbFbRec->bytes_per_line * CbFbRec->y_resolution; + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer device information + + @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information. + +**/ +RETURN_STATUS +EFIAPI +ParseGfxDeviceInfo ( + OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo + ) +{ + return RETURN_NOT_FOUND; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf new file mode 100644 index 00000000..4b09fc78 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf @@ -0,0 +1,39 @@ +## @file +# Coreboot Table Parse Library. +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbParseLib + FILE_GUID = 49EDFC9E-5945-4386-9C0B-C9B60CD45BB1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BlParseLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CbParseLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + IoLib + DebugLib + PcdLib + +[Pcd] + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/Hob.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/Hob.c new file mode 100644 index 00000000..1a1705b0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/Hob.c @@ -0,0 +1,706 @@ +/** @file + + Copyright (c) 2010, Apple Inc. All rights reserved.<BR> + Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/HobLib.h> +#include <Library/PcdLib.h> + +VOID *mHobList; + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + ASSERT (mHobList != NULL); + return mHobList; +} + + +/** + Build a Handoff Information Table HOB + + This function initialize a HOB region from EfiMemoryBegin with length + EfiMemoryLength. And EfiFreeMemoryBottom and EfiFreeMemoryTop should + be inside the HOB region. + + @param[in] EfiMemoryBegin Total memory start address + @param[in] EfiMemoryLength Total memory length reported in handoff HOB. + @param[in] EfiFreeMemoryBottom Free memory start address + @param[in] EfiFreeMemoryTop Free memory end address. + + @return The pointer to the handoff HOB table. + +**/ +EFI_HOB_HANDOFF_INFO_TABLE* +EFIAPI +HobConstructor ( + IN VOID *EfiMemoryBegin, + IN UINTN EfiMemoryLength, + IN VOID *EfiFreeMemoryBottom, + IN VOID *EfiFreeMemoryTop + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = EfiFreeMemoryBottom; + HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1); + + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BOOT_WITH_FULL_CONFIGURATION; + + Hob->EfiMemoryTop = (UINTN)EfiMemoryBegin + EfiMemoryLength; + Hob->EfiMemoryBottom = (UINTN)EfiMemoryBegin; + Hob->EfiFreeMemoryTop = (UINTN)EfiFreeMemoryTop; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + mHobList = Hob; + return Hob; +} + +/** + Add a new HOB to the HOB List. + + @param HobType Type of the new HOB. + @param HobLength Length of the new HOB to allocate. + + @return NULL if there is no space to create a hob. + @return The address point to the new created hob. + +**/ +VOID * +EFIAPI +CreateHob ( + IN UINT16 HobType, + IN UINT16 HobLength + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + VOID *Hob; + + HandOffHob = GetHobList (); + + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < HobLength) { + return NULL; + } + + Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength; + ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return Hob; +} + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + ASSERT(Hob != NULL); + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; +} + +VOID +EFIAPI +BuildFvHobs ( + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute + ) +{ + + EFI_RESOURCE_ATTRIBUTE_TYPE Resource; + + BuildFvHob (PhysicalStart, NumberOfBytes); + + if (ResourceAttribute == NULL) { + Resource = (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE); + } else { + Resource = *ResourceAttribute; + } + + BuildResourceDescriptorHob (EFI_RESOURCE_FIRMWARE_DEVICE, Resource, PhysicalStart, NumberOfBytes); +} + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + + + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ){ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + + + + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && + ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); + + CopyGuid (&Hob->ModuleName, ModuleName); + Hob->EntryPoint = EntryPoint; +} + +/** + Builds a GUID HOB with a certain data length. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + // + // Make sure that data length is not too long. + // + ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); + + Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); + CopyGuid (&Hob->Name, Guid); + return Hob + 1; +} + + +/** + Copies a data buffer to a newly-built HOB. + + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field and returns the start address of the GUID HOB data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + VOID *HobData; + + ASSERT (Data != NULL || DataLength == 0); + + HobData = BuildGuidHob (Guid, DataLength); + + return CopyMem (HobData, Data, DataLength); +} + + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); +} + +/** + Builds a EFI_HOB_TYPE_FV3 HOB. + + This function builds a EFI_HOB_TYPE_FV3 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param AuthenticationStatus The authentication status. + @param ExtractedFv TRUE if the FV was extracted as a file within + another firmware volume. FALSE otherwise. + @param FvName The name of the Firmware Volume. + Valid only if IsExtractedFv is TRUE. + @param FileName The name of the file. + Valid only if IsExtractedFv is TRUE. + +**/ +VOID +EFIAPI +BuildFv3Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT32 AuthenticationStatus, + IN BOOLEAN ExtractedFv, + IN CONST EFI_GUID *FvName, OPTIONAL + IN CONST EFI_GUID *FileName OPTIONAL + ) +{ + EFI_HOB_FIRMWARE_VOLUME3 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV3, sizeof (EFI_HOB_FIRMWARE_VOLUME3)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + Hob->AuthenticationStatus = AuthenticationStatus; + Hob->ExtractedFv = ExtractedFv; + if (ExtractedFv) { + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); + } +} + + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_HOB_CPU *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); +} + + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK)); + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiBootServicesData; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + + +/** + Update the Stack Hob if the stack has been moved + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +UpdateStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { + if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) { + // + // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type + // to be reclaimed by DXE core. + // + BuildMemoryAllocationHob ( + Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength, + EfiConventionalMemory + ); + // + // Update the BSP Stack Hob to reflect the new stack info. + // + Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length; + break; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } +} + + + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf new file mode 100644 index 00000000..48a262dd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf @@ -0,0 +1,39 @@ +#/** @file +# +# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = HobLib + FILE_GUID = AD6B4D55-8DBE-48C8-88E3-CFDBB6E9D193 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = HobLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + Hob.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + +[Guids] + gEfiHobMemoryAllocModuleGuid + gEfiHobMemoryAllocStackGuid + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridge.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridge.h new file mode 100644 index 00000000..8bb31eab --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridge.h @@ -0,0 +1,80 @@ +/** @file + Header file of PciHostBridgeLib. + + Copyright (C) 2016, Red Hat, Inc. + Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCI_HOST_BRIDGE_H +#define _PCI_HOST_BRIDGE_H + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} CB_PCI_ROOT_BRIDGE_DEVICE_PATH; + +PCI_ROOT_BRIDGE * +ScanForRootBridges ( + UINTN *NumberOfRootBridges +); + +/** + Initialize a PCI_ROOT_BRIDGE structure. + + @param[in] Supports Supported attributes. + + @param[in] Attributes Initial attributes. + + @param[in] AllocAttributes Allocation attributes. + + @param[in] RootBusNumber The bus number to store in RootBus. + + @param[in] MaxSubBusNumber The inclusive maximum bus number that can be + assigned to any subordinate bus found behind any + PCI bridge hanging off this root bus. + + The caller is responsible for ensuring that + RootBusNumber <= MaxSubBusNumber. If + RootBusNumber equals MaxSubBusNumber, then the + root bus has no room for subordinate buses. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. + + @param[in] PMem Prefetchable MMIO aperture. + + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. + + @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the + caller) that should be filled in by this + function. + + @retval EFI_SUCCESS Initialization successful. A device path + consisting of an ACPI device path node, with + UID = RootBusNumber, has been allocated and + linked into RootBus. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. +**/ +EFI_STATUS +InitRootBridge ( + IN UINT64 Supports, + IN UINT64 Attributes, + IN UINT64 AllocAttributes, + IN UINT8 RootBusNumber, + IN UINT8 MaxSubBusNumber, + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, + IN PCI_ROOT_BRIDGE_APERTURE *PMem, + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, + OUT PCI_ROOT_BRIDGE *RootBus +); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c new file mode 100644 index 00000000..de4901e5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c @@ -0,0 +1,222 @@ +/** @file + Library instance of PciHostBridgeLib library class for coreboot. + + Copyright (C) 2016, Red Hat, Inc. + Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include <PiDxe.h> + +#include <IndustryStandard/Pci.h> +#include <Protocol/PciHostBridgeResourceAllocation.h> +#include <Protocol/PciRootBridgeIo.h> + +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PciHostBridgeLib.h> +#include <Library/PciLib.h> + +#include "PciHostBridge.h" + +STATIC +CONST +CB_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A03), // HID + 0 // UID + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + + +/** + Initialize a PCI_ROOT_BRIDGE structure. + + @param[in] Supports Supported attributes. + + @param[in] Attributes Initial attributes. + + @param[in] AllocAttributes Allocation attributes. + + @param[in] RootBusNumber The bus number to store in RootBus. + + @param[in] MaxSubBusNumber The inclusive maximum bus number that can be + assigned to any subordinate bus found behind any + PCI bridge hanging off this root bus. + + The caller is responsible for ensuring that + RootBusNumber <= MaxSubBusNumber. If + RootBusNumber equals MaxSubBusNumber, then the + root bus has no room for subordinate buses. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. + + @param[in] PMem Prefetchable MMIO aperture. + + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. + + @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the + caller) that should be filled in by this + function. + + @retval EFI_SUCCESS Initialization successful. A device path + consisting of an ACPI device path node, with + UID = RootBusNumber, has been allocated and + linked into RootBus. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. +**/ +EFI_STATUS +InitRootBridge ( + IN UINT64 Supports, + IN UINT64 Attributes, + IN UINT64 AllocAttributes, + IN UINT8 RootBusNumber, + IN UINT8 MaxSubBusNumber, + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, + IN PCI_ROOT_BRIDGE_APERTURE *PMem, + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, + OUT PCI_ROOT_BRIDGE *RootBus +) +{ + CB_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath; + + // + // Be safe if other fields are added to PCI_ROOT_BRIDGE later. + // + ZeroMem (RootBus, sizeof *RootBus); + + RootBus->Segment = 0; + + RootBus->Supports = Supports; + RootBus->Attributes = Attributes; + + RootBus->DmaAbove4G = FALSE; + + RootBus->AllocationAttributes = AllocAttributes; + RootBus->Bus.Base = RootBusNumber; + RootBus->Bus.Limit = MaxSubBusNumber; + CopyMem (&RootBus->Io, Io, sizeof (*Io)); + CopyMem (&RootBus->Mem, Mem, sizeof (*Mem)); + CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G)); + CopyMem (&RootBus->PMem, PMem, sizeof (*PMem)); + CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G)); + + RootBus->NoExtendedConfigSpace = FALSE; + + DevicePath = AllocateCopyPool (sizeof (mRootBridgeDevicePathTemplate), + &mRootBridgeDevicePathTemplate); + if (DevicePath == NULL) { + DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES)); + return EFI_OUT_OF_RESOURCES; + } + DevicePath->AcpiDevicePath.UID = RootBusNumber; + RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; + + DEBUG ((DEBUG_INFO, + "%a: populated root bus %d, with room for %d subordinate bus(es)\n", + __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber)); + return EFI_SUCCESS; +} + + +/** + Return all the root bridge instances in an array. + + @param Count Return the count of root bridge instances. + + @return All the root bridge instances in an array. + The array should be passed into PciHostBridgeFreeRootBridges() + when it's not used. +**/ +PCI_ROOT_BRIDGE * +EFIAPI +PciHostBridgeGetRootBridges ( + UINTN *Count +) +{ + return ScanForRootBridges (Count); +} + + +/** + Free the root bridge instances array returned from + PciHostBridgeGetRootBridges(). + + @param The root bridge instances array. + @param The count of the array. +**/ +VOID +EFIAPI +PciHostBridgeFreeRootBridges ( + PCI_ROOT_BRIDGE *Bridges, + UINTN Count +) +{ + if (Bridges == NULL && Count == 0) { + return; + } + ASSERT (Bridges != NULL && Count > 0); + + do { + --Count; + FreePool (Bridges[Count].DevicePath); + } while (Count > 0); + + FreePool (Bridges); +} + + +/** + Inform the platform that the resource conflict happens. + + @param HostBridgeHandle Handle of the Host Bridge. + @param Configuration Pointer to PCI I/O and PCI memory resource + descriptors. The Configuration contains the resources + for all the root bridges. The resource for each root + bridge is terminated with END descriptor and an + additional END is appended indicating the end of the + entire resources. The resource descriptor field + values follow the description in + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + .SubmitResources(). +**/ +VOID +EFIAPI +PciHostBridgeResourceConflict ( + EFI_HANDLE HostBridgeHandle, + VOID *Configuration +) +{ + // + // coreboot UEFI Payload does not do PCI enumeration and should not call this + // library interface. + // + ASSERT (FALSE); +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf new file mode 100644 index 00000000..1de17c8f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf @@ -0,0 +1,41 @@ +## @file +# Library instance of PciHostBridgeLib library class for coreboot. +# +# Copyright (C) 2016, Red Hat, Inc. +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciHostBridgeLib + FILE_GUID = 62EE5269-CFFD-43a3-BE3F-622FC79F467E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciHostBridgeLib + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciHostBridge.h + PciHostBridgeLib.c + PciHostBridgeSupport.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + PciLib diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c new file mode 100644 index 00000000..79678995 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c @@ -0,0 +1,584 @@ +/** @file + Scan the entire PCI bus for root bridges to support coreboot UEFI payload. + + Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <IndustryStandard/Pci.h> +#include <Protocol/PciHostBridgeResourceAllocation.h> +#include <Protocol/PciRootBridgeIo.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PciHostBridgeLib.h> +#include <Library/PciLib.h> +#include "PciHostBridge.h" + +/** + Adjust the collected PCI resource. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. + + @param[in] PMem Prefetchable MMIO aperture. + + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. +**/ +VOID +AdjustRootBridgeResource ( + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, + IN PCI_ROOT_BRIDGE_APERTURE *PMem, + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G +) +{ + UINT64 Mask; + + // + // For now try to downgrade everything into MEM32 since + // - coreboot does not assign resource above 4GB + // - coreboot might allocate interleaved MEM32 and PMEM32 resource + // in some cases + // + if (PMem->Base < Mem->Base) { + Mem->Base = PMem->Base; + } + + if (PMem->Limit > Mem->Limit) { + Mem->Limit = PMem->Limit; + } + + PMem->Base = MAX_UINT64; + PMem->Limit = 0; + + if (MemAbove4G->Base < 0x100000000ULL) { + if (MemAbove4G->Base < Mem->Base) { + Mem->Base = MemAbove4G->Base; + } + if (MemAbove4G->Limit > Mem->Limit) { + Mem->Limit = MemAbove4G->Limit; + } + MemAbove4G->Base = MAX_UINT64; + MemAbove4G->Limit = 0; + } + + if (PMemAbove4G->Base < 0x100000000ULL) { + if (PMemAbove4G->Base < Mem->Base) { + Mem->Base = PMemAbove4G->Base; + } + if (PMemAbove4G->Limit > Mem->Limit) { + Mem->Limit = PMemAbove4G->Limit; + } + PMemAbove4G->Base = MAX_UINT64; + PMemAbove4G->Limit = 0; + } + + // + // Align IO resource at 4K boundary + // + Mask = 0xFFFULL; + Io->Limit = ((Io->Limit + Mask) & ~Mask) - 1; + if (Io->Base != MAX_UINT64) { + Io->Base &= ~Mask; + } + + // + // Align MEM resource at 1MB boundary + // + Mask = 0xFFFFFULL; + Mem->Limit = ((Mem->Limit + Mask) & ~Mask) - 1; + if (Mem->Base != MAX_UINT64) { + Mem->Base &= ~Mask; + } +} + +/** + Probe a bar is existed or not. + + @param[in] Address PCI address for the BAR. + @param[out] OriginalValue The original bar value returned. + @param[out] Value The probed bar value returned. +**/ +STATIC +VOID +PcatPciRootBridgeBarExisted ( + IN UINT64 Address, + OUT UINT32 *OriginalValue, + OUT UINT32 *Value +) +{ + UINTN PciAddress; + + PciAddress = (UINTN)Address; + + // + // Preserve the original value + // + *OriginalValue = PciRead32 (PciAddress); + + // + // Disable timer interrupt while the BAR is probed + // + DisableInterrupts (); + + PciWrite32 (PciAddress, 0xFFFFFFFF); + *Value = PciRead32 (PciAddress); + PciWrite32 (PciAddress, *OriginalValue); + + // + // Enable interrupt + // + EnableInterrupts (); +} + +/** + Parse PCI bar and collect the assigned PCI resource information. + + @param[in] Command Supported attributes. + + @param[in] Bus PCI bus number. + + @param[in] Device PCI device number. + + @param[in] Function PCI function number. + + @param[in] BarOffsetBase PCI bar start offset. + + @param[in] BarOffsetEnd PCI bar end offset. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. + + @param[in] PMem Prefetchable MMIO aperture. + + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. +**/ +STATIC +VOID +PcatPciRootBridgeParseBars ( + IN UINT16 Command, + IN UINTN Bus, + IN UINTN Device, + IN UINTN Function, + IN UINTN BarOffsetBase, + IN UINTN BarOffsetEnd, + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, + IN PCI_ROOT_BRIDGE_APERTURE *PMem, + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G + +) +{ + UINT32 OriginalValue; + UINT32 Value; + UINT32 OriginalUpperValue; + UINT32 UpperValue; + UINT64 Mask; + UINTN Offset; + UINTN LowBit; + UINT64 Base; + UINT64 Length; + UINT64 Limit; + PCI_ROOT_BRIDGE_APERTURE *MemAperture; + + for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) { + PcatPciRootBridgeBarExisted ( + PCI_LIB_ADDRESS (Bus, Device, Function, Offset), + &OriginalValue, &Value + ); + if (Value == 0) { + continue; + } + if ((Value & BIT0) == BIT0) { + // + // IO Bar + // + if (Command & EFI_PCI_COMMAND_IO_SPACE) { + Mask = 0xfffffffc; + Base = OriginalValue & Mask; + Length = ((~(Value & Mask)) & Mask) + 0x04; + if (!(Value & 0xFFFF0000)) { + Length &= 0x0000FFFF; + } + Limit = Base + Length - 1; + + if ((Base > 0) && (Base < Limit)) { + if (Io->Base > Base) { + Io->Base = Base; + } + if (Io->Limit < Limit) { + Io->Limit = Limit; + } + } + } + } else { + // + // Mem Bar + // + if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) { + + Mask = 0xfffffff0; + Base = OriginalValue & Mask; + Length = Value & Mask; + + if ((Value & (BIT1 | BIT2)) == 0) { + // + // 32bit + // + Length = ((~Length) + 1) & 0xffffffff; + + if ((Value & BIT3) == BIT3) { + MemAperture = PMem; + } else { + MemAperture = Mem; + } + } else { + // + // 64bit + // + Offset += 4; + PcatPciRootBridgeBarExisted ( + PCI_LIB_ADDRESS (Bus, Device, Function, Offset), + &OriginalUpperValue, + &UpperValue + ); + + Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32); + Length = Length | LShiftU64 ((UINT64) UpperValue, 32); + if (Length != 0) { + LowBit = LowBitSet64 (Length); + Length = LShiftU64 (1ULL, LowBit); + } + + if ((Value & BIT3) == BIT3) { + MemAperture = PMemAbove4G; + } else { + MemAperture = MemAbove4G; + } + } + + Limit = Base + Length - 1; + if ((Base > 0) && (Base < Limit)) { + if (MemAperture->Base > Base) { + MemAperture->Base = Base; + } + if (MemAperture->Limit < Limit) { + MemAperture->Limit = Limit; + } + } + } + } + } +} + +/** + Scan for all root bridges in platform. + + @param[out] NumberOfRootBridges Number of root bridges detected + + @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array. +**/ +PCI_ROOT_BRIDGE * +ScanForRootBridges ( + OUT UINTN *NumberOfRootBridges +) +{ + UINTN PrimaryBus; + UINTN SubBus; + UINT8 Device; + UINT8 Function; + UINTN NumberOfDevices; + UINTN Address; + PCI_TYPE01 Pci; + UINT64 Attributes; + UINT64 Base; + UINT64 Limit; + UINT64 Value; + PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, PMem, PMemAbove4G, *MemAperture; + PCI_ROOT_BRIDGE *RootBridges; + UINTN BarOffsetEnd; + + + *NumberOfRootBridges = 0; + RootBridges = NULL; + + // + // After scanning all the PCI devices on the PCI root bridge's primary bus, + // update the Primary Bus Number for the next PCI root bridge to be this PCI + // root bridge's subordinate bus number + 1. + // + for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) { + SubBus = PrimaryBus; + Attributes = 0; + + ZeroMem (&Io, sizeof (Io)); + ZeroMem (&Mem, sizeof (Mem)); + ZeroMem (&MemAbove4G, sizeof (MemAbove4G)); + ZeroMem (&PMem, sizeof (PMem)); + ZeroMem (&PMemAbove4G, sizeof (PMemAbove4G)); + Io.Base = Mem.Base = MemAbove4G.Base = PMem.Base = PMemAbove4G.Base = MAX_UINT64; + // + // Scan all the PCI devices on the primary bus of the PCI root bridge + // + for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) { + + for (Function = 0; Function <= PCI_MAX_FUNC; Function++) { + + // + // Compute the PCI configuration address of the PCI device to probe + // + Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0); + + // + // Read the Vendor ID from the PCI Configuration Header + // + if (PciRead16 (Address) == MAX_UINT16) { + if (Function == 0) { + // + // If the PCI Configuration Read fails, or a PCI device does not + // exist, then skip this entire PCI device + // + break; + } else { + // + // If PCI function != 0, VendorId == 0xFFFF, we continue to search + // PCI function. + // + continue; + } + } + + // + // Read the entire PCI Configuration Header + // + PciReadBuffer (Address, sizeof (Pci), &Pci); + + // + // Increment the number of PCI device found on the primary bus of the + // PCI root bridge + // + NumberOfDevices++; + + // + // Look for devices with the VGA Palette Snoop enabled in the COMMAND + // register of the PCI Config Header + // + if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16; + } + + BarOffsetEnd = 0; + + // + // PCI-PCI Bridge + // + if (IS_PCI_BRIDGE (&Pci)) { + // + // Get the Bus range that the PPB is decoding + // + if (Pci.Bridge.SubordinateBus > SubBus) { + // + // If the subordinate bus number of the PCI-PCI bridge is greater + // than the PCI root bridge's current subordinate bus number, + // then update the PCI root bridge's subordinate bus number + // + SubBus = Pci.Bridge.SubordinateBus; + } + + // + // Get the I/O range that the PPB is decoding + // + Value = Pci.Bridge.IoBase & 0x0f; + Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8; + Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff; + if (Value == BIT0) { + Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16); + Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16); + } + if ((Base > 0) && (Base < Limit)) { + if (Io.Base > Base) { + Io.Base = Base; + } + if (Io.Limit < Limit) { + Io.Limit = Limit; + } + } + + // + // Get the Memory range that the PPB is decoding + // + Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16; + Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff; + if ((Base > 0) && (Base < Limit)) { + if (Mem.Base > Base) { + Mem.Base = Base; + } + if (Mem.Limit < Limit) { + Mem.Limit = Limit; + } + } + + // + // Get the Prefetchable Memory range that the PPB is decoding + // + Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f; + Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16; + Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0) + << 16) | 0xfffff; + MemAperture = &PMem; + if (Value == BIT0) { + Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32); + Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32); + MemAperture = &PMemAbove4G; + } + if ((Base > 0) && (Base < Limit)) { + if (MemAperture->Base > Base) { + MemAperture->Base = Base; + } + if (MemAperture->Limit < Limit) { + MemAperture->Limit = Limit; + } + } + + // + // Look at the PPB Configuration for legacy decoding attributes + // + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) + == EFI_PCI_BRIDGE_CONTROL_ISA) { + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; + } + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) + == EFI_PCI_BRIDGE_CONTROL_VGA) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) + != 0) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16; + } + } + + BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]); + } else { + // + // Parse the BARs of the PCI device to get what I/O Ranges, Memory + // Ranges, and Prefetchable Memory Ranges the device is decoding + // + if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) { + BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]); + } + } + + PcatPciRootBridgeParseBars ( + Pci.Hdr.Command, + PrimaryBus, + Device, + Function, + OFFSET_OF (PCI_TYPE00, Device.Bar), + BarOffsetEnd, + &Io, + &Mem, &MemAbove4G, + &PMem, &PMemAbove4G + ); + + // + // See if the PCI device is an IDE controller + // + if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE, + PCI_CLASS_MASS_STORAGE_IDE)) { + if (Pci.Hdr.ClassCode[0] & 0x80) { + Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; + Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; + } + if (Pci.Hdr.ClassCode[0] & 0x01) { + Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; + } + if (Pci.Hdr.ClassCode[0] & 0x04) { + Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; + } + } + + // + // See if the PCI device is a legacy VGA controller or + // a standard VGA controller + // + if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) || + IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA) + ) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16; + } + + // + // See if the PCI Device is a PCI - ISA or PCI - EISA + // or ISA_POSITIVE_DECODE Bridge device + // + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) { + if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA || + Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA || + Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) { + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; + } + } + + // + // If this device is not a multi function device, then skip the rest + // of this PCI device + // + if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + break; + } + } + } + + // + // If at least one PCI device was found on the primary bus of this PCI + // root bridge, then the PCI root bridge exists. + // + if (NumberOfDevices > 0) { + RootBridges = ReallocatePool ( + (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE), + (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE), + RootBridges + ); + ASSERT (RootBridges != NULL); + + AdjustRootBridgeResource (&Io, &Mem, &MemAbove4G, &PMem, &PMemAbove4G); + + InitRootBridge ( + Attributes, Attributes, 0, + (UINT8) PrimaryBus, (UINT8) SubBus, + &Io, &Mem, &MemAbove4G, &PMem, &PMemAbove4G, + &RootBridges[*NumberOfRootBridges] + ); + RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE; + // + // Increment the index for the next PCI Root Bridge + // + (*NumberOfRootBridges)++; + } + } + + return RootBridges; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c new file mode 100644 index 00000000..30c11185 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c @@ -0,0 +1,59 @@ +/** @file + PCI Segment Information Library that returns one segment whose + segment base address is retrieved from AcpiBoardInfo HOB. + + Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <Guid/AcpiBoardInfoGuid.h> + +#include <Library/HobLib.h> +#include <Library/PciSegmentInfoLib.h> +#include <Library/DebugLib.h> + +STATIC PCI_SEGMENT_INFO mPciSegment0 = { + 0, // Segment number + 0, // To be fixed later + 0, // Start bus number + 255 // End bus number +}; + +/** + Return an array of PCI_SEGMENT_INFO holding the segment information. + + Note: The returned array/buffer is owned by callee. + + @param Count Return the count of segments. + + @retval A callee owned array holding the segment information. +**/ +PCI_SEGMENT_INFO * +EFIAPI +GetPciSegmentInfo ( + UINTN *Count + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + ACPI_BOARD_INFO *AcpiBoardInfo; + + ASSERT (Count != NULL); + if (Count == NULL) { + return NULL; + } + + if (mPciSegment0.BaseAddress == 0) { + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + + AcpiBoardInfo = (ACPI_BOARD_INFO *) GET_GUID_HOB_DATA (GuidHob); + mPciSegment0.BaseAddress = AcpiBoardInfo->PcieBaseAddress; + } + *Count = 1; + return &mPciSegment0; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf new file mode 100644 index 00000000..9f9adb7d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf @@ -0,0 +1,36 @@ +## @file +# PCI Segment Information Library that returns one segment whose +# segment base address is retrieved from AcpiBoardInfo HOB. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciSegmentInfoLibAcpiBoardInfo + FILE_GUID = 0EA82AA2-6C36-4FD5-BC90-FFA3ECB5E0CE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentInfoLib | DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciSegmentInfoLibAcpiBoardInfo.c + +[Packages] + MdePkg/MdePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + PcdLib + HobLib + DebugLib diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c new file mode 100644 index 00000000..0e95c4c8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c @@ -0,0 +1,265 @@ +/** @file + This file include all platform action which can be customized + by IBV/OEM. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PlatformBootManager.h" +#include "PlatformConsole.h" + +VOID +InstallReadyToLock ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + + DEBUG((DEBUG_INFO,"InstallReadyToLock entering......\n")); + // + // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter + // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n")); + + // + // Install DxeSmmReadyToLock protocol in order to lock SMM + // + Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **) &SmmAccess); + if (!EFI_ERROR (Status)) { + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiDxeSmmReadyToLockProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + DEBUG((DEBUG_INFO,"InstallReadyToLock end\n")); + return; +} + +/** + Return the index of the load option in the load option array. + + The function consider two load options are equal when the + OptionType, Attributes, Description, FilePath and OptionalData are equal. + + @param Key Pointer to the load option to be found. + @param Array Pointer to the array of load options to be found. + @param Count Number of entries in the Array. + + @retval -1 Key wasn't found in the Array. + @retval 0 ~ Count-1 The index of the Key in the Array. +**/ +INTN +PlatformFindLoadOption ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, + IN UINTN Count +) +{ + UINTN Index; + + for (Index = 0; Index < Count; Index++) { + if ((Key->OptionType == Array[Index].OptionType) && + (Key->Attributes == Array[Index].Attributes) && + (StrCmp (Key->Description, Array[Index].Description) == 0) && + (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) && + (Key->OptionalDataSize == Array[Index].OptionalDataSize) && + (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) { + return (INTN) Index; + } + } + + return -1; +} + +/** + Register a boot option using a file GUID in the FV. + + @param FileGuid The file GUID name in FV. + @param Description The boot option description. + @param Attributes The attributes used for the boot option loading. +**/ +VOID +PlatformRegisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes +) +{ + EFI_STATUS Status; + UINTN 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 = AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + if (!EFI_ERROR (Status)) { + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + + OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount); + + if (OptionIndex == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1); + ASSERT_EFI_ERROR (Status); + } + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + } +} + +/** + Do the platform specific action before the console is connected. + + Such as: + Update console variable; + Register new Driver#### or Boot####; + Signal ReadyToLock event. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID +) +{ + EFI_INPUT_KEY Enter; + EFI_INPUT_KEY F2; + EFI_INPUT_KEY Down; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode = SCAN_NULL; + Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; + EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + + // + // Map F2 to Boot Manager Menu + // + F2.ScanCode = SCAN_F2; + F2.UnicodeChar = CHAR_NULL; + EfiBootManagerGetBootManagerMenu (&BootOption); + EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL); + + // + // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key. + // + Down.ScanCode = SCAN_DOWN; + Down.UnicodeChar = CHAR_NULL; + EfiBootManagerGetBootManagerMenu (&BootOption); + EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &Down, NULL); + + // + // Install ready to lock. + // This needs to be done before option rom dispatched. + // + InstallReadyToLock (); + + // + // Dispatch deferred images after EndOfDxe event and ReadyToLock installation. + // + EfiBootManagerDispatchDeferredImages (); + + PlatformConsoleInit (); +} + +/** + Do the platform specific action after the console is connected. + + Such as: + Dynamically switch output mode; + Signal console ready platform customized event; + Run diagnostics like memory testing; + Connect certain devices; + Dispatch additional option roms. +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID +) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL White; + + Black.Blue = Black.Green = Black.Red = Black.Reserved = 0; + White.Blue = White.Green = White.Red = White.Reserved = 0xFF; + + EfiBootManagerConnectAll (); + EfiBootManagerRefreshAllBootOption (); + + // + // Register UEFI Shell + // + PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE); + + Print ( + L"\n" + L"F2 or Down to enter Boot Manager Menu.\n" + L"ENTER to boot directly.\n" + L"\n" + ); + +} + +/** + This function is called each second during the boot manager waits the timeout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + UINT16 TimeoutRemain +) +{ + return; +} + +/** + 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 + ) +{ + return; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h new file mode 100644 index 00000000..a698c975 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h @@ -0,0 +1,132 @@ +/**@file + Head file for BDS Platform specific code + +Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PLATFORM_BOOT_MANAGER_H +#define _PLATFORM_BOOT_MANAGER_H + +#include <PiDxe.h> +#include <Protocol/LoadedImage.h> + +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootManagerLib.h> +#include <Library/PcdLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HiiLib.h> +#include <Library/PrintLib.h> +#include <Library/DxeServicesLib.h> +#include <Library/BootLogoLib.h> +#include <Protocol/SmmAccess2.h> + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN ConnectType; +} PLATFORM_CONSOLE_CONNECT_ENTRY; + +extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE,\ + END_ENTIRE_DEVICE_PATH_SUBTYPE,\ + { END_DEVICE_PATH_LENGTH, 0 },\ + } + +#define CONSOLE_OUT BIT0 +#define CONSOLE_IN BIT1 +#define STD_ERROR BIT2 + +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_KEYBOARD 1 + +typedef struct { + USB_CLASS_DEVICE_PATH UsbClass; + EFI_DEVICE_PATH_PROTOCOL End; +} USB_CLASS_FORMAT_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Instance; +} WIN_NT_VENDOR_DEVICE_PATH_NODE; + +// +// Below is the platform console device path +// +typedef struct { + VENDOR_DEVICE_PATH NtBus; + WIN_NT_VENDOR_DEVICE_PATH_NODE SerialDevice; + UART_DEVICE_PATH Uart; + VENDOR_DEVICE_PATH TerminalType; + EFI_DEVICE_PATH_PROTOCOL End; +} NT_ISA_SERIAL_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH NtBus; + WIN_NT_VENDOR_DEVICE_PATH_NODE NtGopDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} NT_PLATFORM_GOP_DEVICE_PATH; + +extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath; + +/** + Use SystemTable Conout to stop video based Simple Text Out consoles from going + to the video device. Put up LogoFile on every video device that is a console. + + @param[in] LogoFile File name of logo to display on the center of the screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. + @retval EFI_UNSUPPORTED Logo not found + +**/ +EFI_STATUS +PlatformBootManagerEnableQuietBoot ( + IN EFI_GUID *LogoFile +); + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. + +**/ +EFI_STATUS +PlatformBootManagerDisableQuietBoot ( + VOID +); + +/** + Show progress bar with title above it. It only works in Graphics mode. + + @param TitleForeground Foreground color for Title. + @param TitleBackground Background color for Title. + @param Title Title above progress bar. + @param ProgressColor Progress bar color. + @param Progress Progress (0-100) + @param PreviousValue The previous value of the progress. + + @retval EFI_STATUS Success update the progress bar + +**/ +EFI_STATUS +PlatformBootManagerShowProgress ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + IN CHAR16 *Title, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + IN UINTN Progress, + IN UINTN PreviousValue +); + +#endif // _PLATFORM_BOOT_MANAGER_H diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 00000000..691acb6b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -0,0 +1,71 @@ +## @file +# Include all platform action which can be customized by IBV/OEM. +# +# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformBootManagerLib + FILE_GUID = F0D9063A-DADB-4185-85E2-D7ACDA93F7A6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PlatformData.c + PlatformConsole.c + PlatformConsole.h + PlatformBootManager.c + PlatformBootManager.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiLib + UefiBootManagerLib + PcdLib + DxeServicesLib + MemoryAllocationLib + DevicePathLib + HiiLib + PrintLib + PlatformHookLib + +[Guids] + gEfiEndOfDxeEventGroupGuid + +[Protocols] + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiGraphicsOutputProtocolGuid ## CONSUMES + gEfiUgaDrawProtocolGuid ## CONSUMES + gEfiBootLogoProtocolGuid ## CONSUMES + gEfiDxeSmmReadyToLockProtocolGuid + gEfiSmmAccess2ProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn + gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand + gUefiPayloadPkgTokenSpaceGuid.PcdShellFile + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c new file mode 100644 index 00000000..7d65f62e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c @@ -0,0 +1,615 @@ +/** @file +This file include all platform action which can be customized by IBV/OEM. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PlatformBootManager.h" +#include "PlatformConsole.h" +#include <Guid/SerialPortLibVendor.h> + +#define PCI_DEVICE_PATH_NODE(Func, Dev) \ + { \ + { \ + HARDWARE_DEVICE_PATH, \ + HW_PCI_DP, \ + { \ + (UINT8) (sizeof (PCI_DEVICE_PATH)), \ + (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \ + } \ + }, \ + (Func), \ + (Dev) \ + } + +#define PNPID_DEVICE_PATH_NODE(PnpId) \ + { \ + { \ + ACPI_DEVICE_PATH, \ + ACPI_DP, \ + { \ + (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \ + (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \ + }, \ + }, \ + EISA_PNP_ID((PnpId)), \ + 0 \ + } + +#define gPciRootBridge \ + PNPID_DEVICE_PATH_NODE(0x0A03) + +#define gPnp16550ComPort \ + PNPID_DEVICE_PATH_NODE(0x0501) + +#define gPnpPs2Keyboard \ + PNPID_DEVICE_PATH_NODE(0x0303) + +#define gUartVendor \ + { \ + { \ + HARDWARE_DEVICE_PATH, \ + HW_VENDOR_DP, \ + { \ + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \ + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \ + } \ + }, \ + EDKII_SERIAL_PORT_LIB_VENDOR_GUID \ + } + +#define gUart \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_UART_DP, \ + { \ + (UINT8) (sizeof (UART_DEVICE_PATH)), \ + (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \ + } \ + }, \ + 0, \ + 115200, \ + 8, \ + 1, \ + 1 \ + } + +#define gPcAnsiTerminal \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_VENDOR_DP, \ + { \ + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \ + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \ + } \ + }, \ + DEVICE_PATH_MESSAGING_PC_ANSI \ + } + +ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard; +ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort; +UART_DEVICE_PATH gUartDeviceNode = gUart; +VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal; +VENDOR_DEVICE_PATH gUartDeviceVendorNode = gUartVendor; + +// +// Predefined platform root bridge +// +PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = { + gPciRootBridge, + gEndEntire +}; + +EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = { + (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0, + NULL +}; + +BOOLEAN mDetectVgaOnly; + +/** + Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut. + + @param[in] DeviceHandle Handle of the LPC Bridge device. + + @retval EFI_SUCCESS Console devices on the LPC bridge have been added to + ConOut, ConIn, and ErrOut. + + @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing + from DeviceHandle. +**/ +EFI_STATUS +PrepareLpcBridgeDevicePath ( + IN EFI_HANDLE DeviceHandle +) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + TempDevicePath = DevicePath; + + // + // Register Keyboard + // + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + + // + // Register COM1 + // + DevicePath = TempDevicePath; + DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVendorNode); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + + return EFI_SUCCESS; +} + +/** + Return the GOP device path in the platform. + + @param[in] PciDevicePath - Device path for the PCI graphics device. + @param[out] GopDevicePath - Return the device path with GOP installed. + + @retval EFI_SUCCESS - PCI VGA is added to ConOut. + @retval EFI_INVALID_PARAMETER - The device path parameter is invalid. + @retval EFI_STATUS - No GOP device found. +**/ +EFI_STATUS +GetGopDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath +) +{ + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE PciDeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; + UINTN GopHandleCount; + EFI_HANDLE *GopHandleBuffer; + + if (PciDevicePath == NULL || GopDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the GopDevicePath to be PciDevicePath + // + *GopDevicePath = PciDevicePath; + TempPciDevicePath = PciDevicePath; + + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempPciDevicePath, + &PciDeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiGraphicsOutputProtocolGuid, + NULL, + &GopHandleCount, + &GopHandleBuffer + ); + if (!EFI_ERROR (Status)) { + // + // Add all the child handles as possible Console Device + // + for (Index = 0; Index < GopHandleCount; Index++) { + Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); + if (EFI_ERROR (Status)) { + continue; + } + if (CompareMem ( + PciDevicePath, + TempDevicePath, + GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH + ) == 0) { + // + // In current implementation, we only enable one of the child handles + // as console device, i.e. sotre one of the child handle's device + // path to variable "ConOut" + // In future, we could select all child handles to be console device + // + *GopDevicePath = TempDevicePath; + + // + // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() + // Add the integrity GOP device path. + // + EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath); + EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath, NULL); + } + } + gBS->FreePool (GopHandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + Add PCI VGA to ConOut, ConIn, ErrOut. + + @param[in] DeviceHandle - Handle of PciIo protocol. + + @retval EFI_SUCCESS - PCI VGA is added to ConOut. + @retval EFI_STATUS - No PCI VGA device is added. + +**/ +EFI_STATUS +PreparePciVgaDevicePath ( + IN EFI_HANDLE DeviceHandle +) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GetGopDevicePath (DevicePath, &GopDevicePath); + DevicePath = GopDevicePath; + + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + + return EFI_SUCCESS; +} + +/** + Add PCI Serial to ConOut, ConIn, ErrOut. + + @param[in] DeviceHandle - Handle of PciIo protocol. + + @retval EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut. + @retval EFI_STATUS - No PCI Serial device is added. + +**/ +EFI_STATUS +PreparePciSerialDevicePath ( + IN EFI_HANDLE DeviceHandle +) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + + return EFI_SUCCESS; +} + + +/** + For every PCI instance execute a callback function. + + @param[in] Id - The protocol GUID for callback + @param[in] CallBackFunction - The callback function + @param[in] Context - The context of the callback + + @retval EFI_STATUS - Callback function failed. + +**/ +EFI_STATUS +EFIAPI +VisitAllInstancesOfProtocol ( + IN EFI_GUID *Id, + IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, + IN VOID *Context +) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + VOID *Instance; + + // + // Start to check all the PciIo to find all possible device + // + HandleCount = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + Id, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance); + if (EFI_ERROR (Status)) { + continue; + } + + Status = (*CallBackFunction) ( + HandleBuffer[Index], + Instance, + Context + ); + } + + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + + +/** + For every PCI instance execute a callback function. + + @param[in] Handle - The PCI device handle + @param[in] Instance - The instance of the PciIo protocol + @param[in] Context - The context of the callback + + @retval EFI_STATUS - Callback function failed. + +**/ +EFI_STATUS +EFIAPI +VisitingAPciInstance ( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context +) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + PciIo = (EFI_PCI_IO_PROTOCOL*) Instance; + + // + // Check for all PCI device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) ( + Handle, + PciIo, + &Pci + ); + +} + + +/** + For every PCI instance execute a callback function. + + @param[in] CallBackFunction - Callback function pointer + + @retval EFI_STATUS - Callback function failed. + +**/ +EFI_STATUS +EFIAPI +VisitAllPciInstances ( + IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction +) +{ + return VisitAllInstancesOfProtocol ( + &gEfiPciIoProtocolGuid, + VisitingAPciInstance, + (VOID*)(UINTN) CallBackFunction + ); +} + + +/** + Do platform specific PCI Device check and add them to + ConOut, ConIn, ErrOut. + + @param[in] Handle - Handle of PCI device instance + @param[in] PciIo - PCI IO protocol instance + @param[in] Pci - PCI Header register block + + @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +EFIAPI +DetectAndPreparePlatformPciDevicePath ( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN PCI_TYPE00 *Pci +) +{ + EFI_STATUS Status; + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + if (!mDetectVgaOnly) { + // + // Here we decide whether it is LPC Bridge + // + if ((IS_PCI_LPC (Pci)) || + ((IS_PCI_ISA_PDECODE (Pci)) && + (Pci->Hdr.VendorId == 0x8086) + ) + ) { + // + // Add IsaKeyboard to ConIn, + // add IsaSerial to ConOut, ConIn, ErrOut + // + DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n")); + PrepareLpcBridgeDevicePath (Handle); + return EFI_SUCCESS; + } + // + // Here we decide which Serial device to enable in PCI bus + // + if (IS_PCI_16550SERIAL (Pci)) { + // + // Add them to ConOut, ConIn, ErrOut. + // + DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n")); + PreparePciSerialDevicePath (Handle); + return EFI_SUCCESS; + } + } + + // + // Here we decide which VGA device to enable in PCI bus + // + if (IS_PCI_VGA (Pci)) { + // + // Add them to ConOut. + // + DEBUG ((DEBUG_INFO, "Found PCI VGA device\n")); + PreparePciVgaDevicePath (Handle); + return EFI_SUCCESS; + } + + return Status; +} + + +/** + Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + + @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE. + + @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +DetectAndPreparePlatformPciDevicePaths ( + BOOLEAN DetectVgaOnly +) +{ + mDetectVgaOnly = DetectVgaOnly; + + EfiBootManagerUpdateConsoleVariable ( + ConIn, + (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, + NULL + ); + + return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath); +} + + +/** + The function will connect root bridge + + @return EFI_SUCCESS Connect RootBridge successfully. + +**/ +EFI_STATUS +ConnectRootBridge ( + VOID +) +{ + EFI_STATUS Status; + EFI_HANDLE RootHandle; + + // + // Make all the PCI_IO protocols on PCI Seg 0 show up + // + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &gPlatformRootBridges[0], + &RootHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Platform console init. Include the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformConsoleInit ( + VOID +) +{ + gUartDeviceNode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + gUartDeviceNode.DataBits = PcdGet8 (PcdUartDefaultDataBits); + gUartDeviceNode.Parity = PcdGet8 (PcdUartDefaultParity); + gUartDeviceNode.StopBits = PcdGet8 (PcdUartDefaultStopBits); + + ConnectRootBridge (); + + // + // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + // + DetectAndPreparePlatformPciDevicePaths (FALSE); + +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.h new file mode 100644 index 00000000..3d1b062c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.h @@ -0,0 +1,70 @@ +/** @file +Head file for BDS Platform specific code + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PLATFORM_CONSOLE_H +#define _PLATFORM_CONSOLE_H + +#include <PiDxe.h> +#include <IndustryStandard/Pci.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/DevicePathLib.h> +#include <Protocol/PciIo.h> + +#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0) +#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550) + +// +// Type definitions +// + +// +// Platform Root Bridge +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH; + +typedef +EFI_STATUS +(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context +); + +/** + @param[in] Handle - Handle of PCI device instance + @param[in] PciIo - PCI IO protocol instance + @param[in] Pci - PCI Header register block +**/ +typedef +EFI_STATUS +(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN PCI_TYPE00 *Pci +); + +/** + Platform console init. Include the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformConsoleInit ( + VOID +); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformData.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformData.c new file mode 100644 index 00000000..27bab753 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformData.c @@ -0,0 +1,39 @@ +/**@file + Defined the platform specific device path which will be filled to + ConIn/ConOut variables. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PlatformBootManager.h" + +/// +/// Predefined platform default console device path +/// +GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = { + { + NULL, + 0 + } +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = { + { + { + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + { + (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)), + (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8) + } + }, + 0xffff, // VendorId + 0xffff, // ProductId + CLASS_HID, // DeviceClass + SUBCLASS_BOOT, // DeviceSubClass + PROTOCOL_KEYBOARD // DeviceProtocol + }, + gEndEntire +}; diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.c new file mode 100644 index 00000000..621c6bce --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.c @@ -0,0 +1,98 @@ +/** @file + Platform Hook Library instance for UART device. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> +#include <Uefi/UefiBaseType.h> +#include <Library/PciLib.h> +#include <Library/PlatformHookLib.h> +#include <Library/BlParseLib.h> +#include <Library/PcdLib.h> + +typedef struct { + UINT16 VendorId; ///< Vendor ID to match the PCI device. The value 0xFFFF terminates the list of entries. + UINT16 DeviceId; ///< Device ID to match the PCI device + UINT32 ClockRate; ///< UART clock rate. Set to 0 for default clock rate of 1843200 Hz + UINT64 Offset; ///< The byte offset into to the BAR + UINT8 BarIndex; ///< Which BAR to get the UART base address + UINT8 RegisterStride; ///< UART register stride in bytes. Set to 0 for default register stride of 1 byte. + UINT16 ReceiveFifoDepth; ///< UART receive FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + UINT16 TransmitFifoDepth; ///< UART transmit FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + UINT8 Reserved[2]; +} PCI_SERIAL_PARAMETER; + +/** + Performs platform specific initialization required for the CPU to access + the hardware associated with a SerialPortLib instance. This function does + not initialize the serial port hardware itself. Instead, it initializes + hardware devices that are required for the CPU to access the serial port + hardware. This function may be called more than once. + + @retval RETURN_SUCCESS The platform specific initialization succeeded. + @retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed. + +**/ +RETURN_STATUS +EFIAPI +PlatformHookSerialPortInitialize ( + VOID + ) +{ + RETURN_STATUS Status; + UINT32 DeviceVendor; + PCI_SERIAL_PARAMETER *SerialParam; + SERIAL_PORT_INFO SerialPortInfo; + + Status = ParseSerialInfo (&SerialPortInfo); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (SerialPortInfo.Type == PLD_SERIAL_TYPE_MEMORY_MAPPED) { + Status = PcdSetBoolS (PcdSerialUseMmio, TRUE); + } else { //IO + Status = PcdSetBoolS (PcdSerialUseMmio, FALSE); + } + if (RETURN_ERROR (Status)) { + return Status; + } + Status = PcdSet64S (PcdSerialRegisterBase, SerialPortInfo.BaseAddr); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet32S (PcdSerialRegisterStride, SerialPortInfo.RegWidth); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet32S (PcdSerialBaudRate, SerialPortInfo.Baud); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet64S (PcdUartDefaultBaudRate, SerialPortInfo.Baud); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet32S (PcdSerialClockRate, SerialPortInfo.InputHertz); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (SerialPortInfo.UartPciAddr >= 0x80000000) { + DeviceVendor = PciRead32 (SerialPortInfo.UartPciAddr & 0x0ffff000); + SerialParam = PcdGetPtr(PcdPciSerialParameters); + SerialParam->VendorId = (UINT16)DeviceVendor; + SerialParam->DeviceId = DeviceVendor >> 16; + SerialParam->ClockRate = SerialPortInfo.InputHertz; + SerialParam->RegisterStride = (UINT8)SerialPortInfo.RegWidth; + } + + return RETURN_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf new file mode 100644 index 00000000..055b4d21 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf @@ -0,0 +1,39 @@ +## @file +# Platform Hook Library instance for UART device. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformHookLib + FILE_GUID = 40A2CBC6-CFB8-447b-A90E-198E88FD345E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformHookLib + CONSTRUCTOR = PlatformHookSerialPortInitialize + +[Sources] + PlatformHookLib.c + +[LibraryClasses] + BlParseLib + PcdLib + PciLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate ## PRODUCES + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters ## PRODUCES diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.c new file mode 100644 index 00000000..8fa0d15e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.c @@ -0,0 +1,29 @@ +/** @file + Include all platform specific features which can be customized by IBV/OEM. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/UefiLib.h> +#include <Library/PlatformSupportLib.h> + +/** + Parse platform specific information from coreboot. + + @retval RETURN_SUCCESS The platform specific coreboot support succeeded. + @retval RETURN_DEVICE_ERROR The platform specific coreboot support could not be completed. + +**/ +EFI_STATUS +EFIAPI +ParsePlatformInfo ( + VOID + ) +{ + return EFI_SUCCESS; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf new file mode 100644 index 00000000..99e92cbb --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf @@ -0,0 +1,28 @@ +## @file +# Include all platform specific features which can be customized by IBV/OEM. +# +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformSupportLib + FILE_GUID = B42AA265-00CA-4d4b-AC14-DBD5268E1BC7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformSupportLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PlatformSupportLibNull.c + +[Packages] + MdePkg/MdePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.c new file mode 100644 index 00000000..c208d172 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.c @@ -0,0 +1,153 @@ +/** @file + Reset System Library functions for bootloader + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/HobLib.h> +#include <Library/BaseMemoryLib.h> +#include <Guid/AcpiBoardInfoGuid.h> + +ACPI_BOARD_INFO mAcpiBoardInfo; + +/** + The constructor function to initialize mAcpiBoardInfo. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +ResetSystemLibConstructor ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + ACPI_BOARD_INFO *AcpiBoardInfoPtr; + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + + AcpiBoardInfoPtr = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + CopyMem (&mAcpiBoardInfo, AcpiBoardInfoPtr, sizeof (ACPI_BOARD_INFO)); + + return EFI_SUCCESS; +} + + +VOID +AcpiPmControl ( + UINTN SuspendType + ) +{ + UINTN PmCtrlReg; + + ASSERT (SuspendType <= 7); + + PmCtrlReg = (UINTN)mAcpiBoardInfo.PmCtrlRegBase; + IoAndThenOr16 (PmCtrlReg, (UINT16) ~0x3c00, (UINT16) (SuspendType << 10)); + IoOr16 (PmCtrlReg, BIT13); + CpuDeadLoop (); +} + +/** + Calling this function causes a system-wide reset. This sets + all circuitry within the system to its initial state. This type of reset + is asynchronous to system operation and operates without regard to + cycle boundaries. + + System reset should not return, if it returns, it means the system does + not support cold reset. +**/ +VOID +EFIAPI +ResetCold ( + VOID + ) +{ + IoWrite8 ((UINTN)mAcpiBoardInfo.ResetRegAddress, mAcpiBoardInfo.ResetValue); + CpuDeadLoop (); +} + +/** + Calling this function causes a system-wide initialization. The processors + are set to their initial state, and pending cycles are not corrupted. + + System reset should not return, if it returns, it means the system does + not support warm reset. +**/ +VOID +EFIAPI +ResetWarm ( + VOID + ) +{ + IoWrite8 ((UINTN)mAcpiBoardInfo.ResetRegAddress, mAcpiBoardInfo.ResetValue); + CpuDeadLoop (); +} + +/** + Calling this function causes the system to enter a power state equivalent + to the ACPI G2/S5 or G3 states. + + System shutdown should not return, if it returns, it means the system does + not support shut down reset. +**/ +VOID +EFIAPI +ResetShutdown ( + VOID + ) +{ + UINTN PmCtrlReg; + + // + // GPE0_EN should be disabled to avoid any GPI waking up the system from S5 + // + IoWrite16 ((UINTN)mAcpiBoardInfo.PmGpeEnBase, 0); + + // + // Clear Power Button Status + // + IoWrite16((UINTN) mAcpiBoardInfo.PmEvtBase, BIT8); + + // + // Transform system into S5 sleep state + // + PmCtrlReg = (UINTN)mAcpiBoardInfo.PmCtrlRegBase; + IoAndThenOr16 (PmCtrlReg, (UINT16) ~0x3c00, (UINT16) (7 << 10)); + IoOr16 (PmCtrlReg, BIT13); + CpuDeadLoop (); + + ASSERT (FALSE); +} + +/** + This function causes a systemwide reset. The exact type of the reset is + defined by the EFI_GUID that follows the Null-terminated Unicode string passed + into ResetData. If the platform does not recognize the EFI_GUID in ResetData + the platform must pick a supported reset type to perform.The platform may + optionally log the parameters from any non-normal reset that occurs. + + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData The data buffer starts with a Null-terminated string, + followed by the EFI_GUID. +**/ +VOID +EFIAPI +ResetPlatformSpecific ( + IN UINTN DataSize, + IN VOID *ResetData + ) +{ + ResetCold (); +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf new file mode 100644 index 00000000..26e6006a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf @@ -0,0 +1,40 @@ +## @file +# Library instance for ResetSystem library class for bootloader +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ResetSystemLib + FILE_GUID = C5CD4EEE-527F-47df-9C92-B41414AF7479 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ResetSystemLib + + CONSTRUCTOR = ResetSystemLibConstructor +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + ResetSystemLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + DebugLib + IoLib + HobLib + BaseMemoryLib + +[Guids] + gUefiAcpiBoardInfoGuid + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c new file mode 100644 index 00000000..8246a99f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c @@ -0,0 +1,223 @@ +/** @file + This library will parse the Slim Bootloader to get required information. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/HobLib.h> +#include <Library/BlParseLib.h> +#include <IndustryStandard/Acpi.h> + + +/** + This function retrieves the parameter base address from boot loader. + + This function will get bootloader specific parameter address for UEFI payload. + e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +EFIAPI +GetParameterBase ( + VOID + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandoffTable; + + HandoffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)(UINTN) GET_BOOTLOADER_PARAMETER (); + if ((HandoffTable->Header.HobType == EFI_HOB_TYPE_HANDOFF) && + (HandoffTable->Header.HobLength == sizeof (EFI_HOB_HANDOFF_INFO_TABLE)) && + (HandoffTable->Header.Reserved == 0)) { + return (VOID *)HandoffTable; + } + + return NULL; +} + + +/** + This function retrieves a GUIDed HOB data from Slim Bootloader. + + This function will search SBL HOB list to find the first GUIDed HOB that + its GUID matches Guid. + + @param[in] Guid A pointer to HOB GUID to search. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +GetGuidHobDataFromSbl ( + IN EFI_GUID *Guid + ) +{ + UINT8 *GuidHob; + CONST VOID *HobList; + + HobList = GetParameterBase (); + ASSERT (HobList != NULL); + GuidHob = GetNextGuidHob (Guid, HobList); + if (GuidHob != NULL) { + return GET_GUID_HOB_DATA (GuidHob); + } + + return NULL; +} + +/** + Acquire the memory map information. + + @param MemInfoCallback The callback routine + @param Params Pointer to the callback routine parameter + + @retval RETURN_SUCCESS Successfully find out the memory information. + @retval RETURN_NOT_FOUND Failed to find the memory information. + +**/ +RETURN_STATUS +EFIAPI +ParseMemoryInfo ( + IN BL_MEM_INFO_CALLBACK MemInfoCallback, + IN VOID *Params + ) +{ + MEMROY_MAP_INFO *MemoryMapInfo; + UINTN Idx; + + MemoryMapInfo = (MEMROY_MAP_INFO *) GetGuidHobDataFromSbl (&gLoaderMemoryMapInfoGuid); + if (MemoryMapInfo == NULL) { + ASSERT (FALSE); + return RETURN_NOT_FOUND; + } + + for (Idx = 0; Idx < MemoryMapInfo->Count; Idx++) { + MemInfoCallback (&MemoryMapInfo->Entry[Idx], Params); + } + + return RETURN_SUCCESS; +} + +/** + Acquire acpi table and smbios table from slim bootloader + + @param SystemTableInfo Pointer to the system table info + + @retval RETURN_SUCCESS Successfully find out the tables. + @retval RETURN_NOT_FOUND Failed to find the tables. + +**/ +RETURN_STATUS +EFIAPI +ParseSystemTable ( + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ) +{ + SYSTEM_TABLE_INFO *TableInfo; + + TableInfo = (SYSTEM_TABLE_INFO *)GetGuidHobDataFromSbl (&gUefiSystemTableInfoGuid); + if (TableInfo == NULL) { + ASSERT (FALSE); + return RETURN_NOT_FOUND; + } + + CopyMem (SystemTableInfo, TableInfo, sizeof (SYSTEM_TABLE_INFO)); + + return RETURN_SUCCESS; +} + + +/** + Find the serial port information + + @param SERIAL_PORT_INFO Pointer to serial port info structure + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +EFIAPI +ParseSerialInfo ( + OUT SERIAL_PORT_INFO *SerialPortInfo + ) +{ + SERIAL_PORT_INFO *BlSerialInfo; + + BlSerialInfo = (SERIAL_PORT_INFO *) GetGuidHobDataFromSbl (&gUefiSerialPortInfoGuid); + if (BlSerialInfo == NULL) { + ASSERT (FALSE); + return RETURN_NOT_FOUND; + } + + CopyMem (SerialPortInfo, BlSerialInfo, sizeof (SERIAL_PORT_INFO)); + + return RETURN_SUCCESS; +} + + +/** + Find the video frame buffer information + + @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxInfo ( + OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo + ) +{ + EFI_PEI_GRAPHICS_INFO_HOB *BlGfxInfo; + + BlGfxInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) GetGuidHobDataFromSbl (&gEfiGraphicsInfoHobGuid); + if (BlGfxInfo == NULL) { + return RETURN_NOT_FOUND; + } + + CopyMem (GfxInfo, BlGfxInfo, sizeof (EFI_PEI_GRAPHICS_INFO_HOB)); + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer device information + + @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information. + +**/ +RETURN_STATUS +EFIAPI +ParseGfxDeviceInfo ( + OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo + ) +{ + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *BlGfxDeviceInfo; + + BlGfxDeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) GetGuidHobDataFromSbl (&gEfiGraphicsDeviceInfoHobGuid); + if (BlGfxDeviceInfo == NULL) { + return RETURN_NOT_FOUND; + } + + CopyMem (GfxDeviceInfo, BlGfxDeviceInfo, sizeof (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB)); + + return RETURN_SUCCESS; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf new file mode 100644 index 00000000..ed0704cc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf @@ -0,0 +1,46 @@ +## @file +# Slim Bootloader parse library. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SblParseLib + FILE_GUID = DE6FB32C-52CF-4A17-A84C-B323653CB5E0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BlParseLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SblParseLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + PcdLib + HobLib + +[Guids] + gUefiSystemTableInfoGuid + gUefiSerialPortInfoGuid + gLoaderMemoryMapInfoGuid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + +[Pcd] + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c new file mode 100644 index 00000000..822b34c9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c @@ -0,0 +1,365 @@ +/** @file + Ia32-specific functionality for DxeLoad. + +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/HobLib.h> +#include "VirtualMemory.h" +#include "UefiPayloadEntry.h" + +#define STACK_SIZE 0x20000 +#define IDT_ENTRY_COUNT 32 + +typedef struct _X64_IDT_TABLE { + // + // Reserved 4 bytes preceding PeiService and IdtTable, + // since IDT base address should be 8-byte alignment. + // + UINT32 Reserved; + CONST EFI_PEI_SERVICES **PeiService; + X64_IDT_GATE_DESCRIPTOR IdtTable[IDT_ENTRY_COUNT]; +} X64_IDT_TABLE; + +// +// Global Descriptor Table (GDT) +// +GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries[] = { +/* selector { Global Segment Descriptor } */ +/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor +/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor +/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor +/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor +/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor +/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor +/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor +/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor +/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor +}; + +// +// IA32 Gdt register +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = { + sizeof (gGdtEntries) - 1, + (UINTN) gGdtEntries + }; + +GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = { + sizeof (X64_IDT_GATE_DESCRIPTOR) * IDT_ENTRY_COUNT - 1, + 0 +}; + +/** + Allocates and fills in the Page Directory and Page Table Entries to + establish a 4G page table. + + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + + @return The address of page table. + +**/ +UINTN +Create4GPageTablesIa32Pae ( + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize + ) +{ + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINT32 NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN TotalPagesNum; + UINTN PageAddress; + UINT64 AddressEncMask; + + // + // Make sure AddressEncMask is contained to smallest supported address field + // + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64; + + PhysicalAddressBits = 32; + + // + // Calculate the table entries needed. + // + NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, (PhysicalAddressBits - 30)); + + TotalPagesNum = NumberOfPdpEntriesNeeded + 1; + PageAddress = (UINTN) AllocatePageTableMemory (TotalPagesNum); + ASSERT (PageAddress != 0); + + PageMap = (VOID *) PageAddress; + PageAddress += SIZE_4KB; + + PageDirectoryPointerEntry = PageMap; + PhysicalAddress = 0; + + for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. + // + PageDirectoryEntry = (VOID *) PageAddress; + PageAddress += SIZE_4KB; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry | AddressEncMask; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) { + if ((IsNullDetectionEnabled () && PhysicalAddress == 0) + || ((PhysicalAddress < StackBase + StackSize) + && ((PhysicalAddress + SIZE_2MB) > StackBase))) { + // + // Need to split this 2M page that covers stack range. + // + Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, 0, 0); + } else { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress | AddressEncMask; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + } + } + } + + for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + ZeroMem ( + PageDirectoryPointerEntry, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } + + // + // Protect the page table by marking the memory used for page table to be + // read-only. + // + EnablePageTableProtection ((UINTN)PageMap, FALSE); + + return (UINTN) PageMap; +} + +/** + The function will check if IA32 PAE is supported. + + @retval TRUE IA32 PAE is supported. + @retval FALSE IA32 PAE is not supported. + +**/ +BOOLEAN +IsIa32PaeSupport ( + VOID + ) +{ + UINT32 RegEax; + UINT32 RegEdx; + BOOLEAN Ia32PaeSupport; + + Ia32PaeSupport = FALSE; + AsmCpuid (0x0, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x1) { + AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT6) != 0) { + Ia32PaeSupport = TRUE; + } + } + + return Ia32PaeSupport; +} + +/** + The function will check if page table should be setup or not. + + @retval TRUE Page table should be created. + @retval FALSE Page table should not be created. + +**/ +BOOLEAN +ToBuildPageTable ( + VOID + ) +{ + if (!IsIa32PaeSupport ()) { + return FALSE; + } + + if (IsNullDetectionEnabled ()) { + return TRUE; + } + + if (PcdGet8 (PcdHeapGuardPropertyMask) != 0) { + return TRUE; + } + + if (PcdGetBool (PcdCpuStackGuard)) { + return TRUE; + } + + if (IsEnableNonExecNeeded ()) { + return TRUE; + } + + return FALSE; +} + +/** + Transfers control to DxeCore. + + This function performs a CPU architecture specific operations to execute + the entry point of DxeCore with the parameters of HobList. + + @param DxeCoreEntryPoint The entry point of DxeCore. + @param HobList The start of HobList passed to DxeCore. + +**/ +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList + ) +{ + EFI_PHYSICAL_ADDRESS BaseOfStack; + EFI_PHYSICAL_ADDRESS TopOfStack; + UINTN PageTables; + X64_IDT_GATE_DESCRIPTOR *IdtTable; + UINTN SizeOfTemplate; + VOID *TemplateBase; + EFI_PHYSICAL_ADDRESS VectorAddress; + UINT32 Index; + X64_IDT_TABLE *IdtTableForX64; + + // + // Clear page 0 and mark it as allocated if NULL pointer detection is enabled. + // + if (IsNullDetectionEnabled ()) { + ClearFirst4KPage (HobList.Raw); + BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData); + } + + BaseOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); + ASSERT (BaseOfStack != 0); + + if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) { + // + // Compute the top of the stack we were allocated, which is used to load X64 dxe core. + // Pre-allocate a 32 bytes which confroms to x64 calling convention. + // + // The first four parameters to a function are passed in rcx, rdx, r8 and r9. + // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the + // register parameters is reserved on the stack, in case the called function + // wants to spill them; this is important if the function is variadic. + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; + + // + // x64 Calling Conventions requires that the stack must be aligned to 16 bytes + // + TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16); + + // + // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA + // memory, it may be corrupted when copying FV to high-end memory + // + AsmWriteGdtr (&gGdt); + // + // Create page table and save PageMapLevel4 to CR3 + // + PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE, 0, 0); + + // + // Paging might be already enabled. To avoid conflict configuration, + // disable paging first anyway. + // + AsmWriteCr0 (AsmReadCr0 () & (~BIT31)); + AsmWriteCr3 (PageTables); + + // + // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. + // + UpdateStackHob (BaseOfStack, STACK_SIZE); + + SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase); + + VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocatePages (EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT)); + ASSERT (VectorAddress != 0); + + // + // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that + // it may not be gotten correctly after IDT register is re-written. + // + IdtTableForX64 = (X64_IDT_TABLE *) (UINTN) VectorAddress; + IdtTableForX64->PeiService = NULL; + + VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1); + IdtTable = IdtTableForX64->IdtTable; + for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) { + IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e; + IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0; + IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL; + + IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16) VectorAddress; + IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16) (RShiftU64 (VectorAddress, 16)); + IdtTable[Index].Offset32To63 = (UINT32) (RShiftU64 (VectorAddress, 32)); + IdtTable[Index].Reserved = 0; + + CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate); + AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index); + + VectorAddress += SizeOfTemplate; + } + + gLidtDescriptor.Base = (UINTN) IdtTable; + + + AsmWriteIdtr (&gLidtDescriptor); + + DEBUG (( + DEBUG_INFO, + "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n", + __FUNCTION__, + BaseOfStack, + STACK_SIZE + )); + + // + // Go to Long Mode and transfer control to DxeCore. + // Interrupts will not get turned on until the CPU AP is loaded. + // Call x64 drivers passing in single argument, a pointer to the HOBs. + // + AsmEnablePaging64 ( + SYS_CODE64_SEL, + DxeCoreEntryPoint, + (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), + 0, + TopOfStack + ); + } else { + // 32bit UEFI payload could be supported if required later. + DEBUG ((DEBUG_ERROR, "NOT support 32bit UEFI payload\n")); + ASSERT (FALSE); + CpuDeadLoop(); + } + +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm new file mode 100644 index 00000000..91c49ca4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm @@ -0,0 +1,71 @@ +;/** @file +; +; IDT vector entry. +; +; Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;**/ + + SECTION .text + +; +;------------------------------------------------------------------------------ +; Generic IDT Vector Handlers for the Host. +; +;------------------------------------------------------------------------------ + +ALIGN 8 +global ASM_PFX(AsmGetVectorTemplatInfo) +global ASM_PFX(AsmVectorFixup) + +@VectorTemplateBase: + push eax + db 0x6a ; push #VectorNumber +@VectorNum: + db 0 + mov eax, CommonInterruptEntry + jmp eax +@VectorTemplateEnd: + +global ASM_PFX(AsmGetVectorTemplatInfo) +ASM_PFX(AsmGetVectorTemplatInfo): + mov ecx, [esp + 4] + mov dword [ecx], @VectorTemplateBase + mov eax, (@VectorTemplateEnd - @VectorTemplateBase) + ret + +global ASM_PFX(AsmVectorFixup) +ASM_PFX(AsmVectorFixup): + mov eax, dword [esp + 8] + mov ecx, [esp + 4] + mov [ecx + (@VectorNum - @VectorTemplateBase)], al + ret + +;---------------------------------------; +; CommonInterruptEntry ; +;---------------------------------------; +; The follow algorithm is used for the common interrupt routine. + +; +; +---------------------+ <-- 16-byte aligned ensured by processor +; + Old SS + +; +---------------------+ +; + Old RSP + +; +---------------------+ +; + RFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + RIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ + +CommonInterruptEntry: + cli + + jmp $ + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm new file mode 100644 index 00000000..b6618893 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +;* +;* Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR> +;* SPDX-License-Identifier: BSD-2-Clause-Patent + +;------------------------------------------------------------------------------ + +#include <Base.h> + +SECTION .text + +extern ASM_PFX(PayloadEntry) +extern ASM_PFX(PcdGet32 (PcdPayloadStackTop)) + +; +; SecCore Entry Point +; +; Processor is in flat protected mode + +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + + ; + ; Disable all the interrupts + ; + cli + + ; + ; Save the bootloader parameter base address + ; + mov eax, [esp + 4] + + mov esp, FixedPcdGet32 (PcdPayloadStackTop) + + ; + ; Push the bootloader parameter address onto new stack + ; + push 0 + push eax + + ; + ; Call into C code + ; + call ASM_PFX(PayloadEntry) + jmp $ + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c new file mode 100644 index 00000000..4a87ddc7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c @@ -0,0 +1,307 @@ +/** @file + + Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiPayloadEntry.h" + +/** + Allocate pages for code. + + @param[in] Pages Number of pages to be allocated. + + @return Allocated memory. +**/ +VOID* +AllocateCodePages ( + IN UINTN Pages + ) +{ + VOID *Alloc; + EFI_PEI_HOB_POINTERS Hob; + + Alloc = AllocatePages (Pages); + if (Alloc == NULL) { + return NULL; + } + + // find the HOB we just created, and change the type to EfiBootServicesCode + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw != NULL) { + if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == (UINTN)Alloc) { + Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiBootServicesCode; + return Alloc; + } + Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (Hob)); + } + + ASSERT (FALSE); + + FreePages (Alloc, Pages); + return NULL; +} + + +/** + Loads and relocates a PE/COFF image + + @param[in] PeCoffImage Point to a Pe/Coff image. + @param[out] ImageAddress The image memory address after relocation. + @param[out] ImageSize The image size. + @param[out] EntryPoint The image entry point. + + @return EFI_SUCCESS If the image is loaded and relocated successfully. + @return Others If the image failed to load or relocate. +**/ +EFI_STATUS +LoadPeCoffImage ( + IN VOID *PeCoffImage, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +{ + RETURN_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + VOID *Buffer; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + + ImageContext.Handle = PeCoffImage; + ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Allocate Memory for the image + // + Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + + // + // Load the image to our new buffer + // + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +/** + This function searchs a given file type within a valid FV. + + @param FvHeader A pointer to firmware volume header that contains the set of files + to be searched. + @param FileType File type to be searched. + @param FileHeader A pointer to the discovered file, if successful. + + @retval EFI_SUCCESS Successfully found FileType + @retval EFI_NOT_FOUND File type can't be found. +**/ +EFI_STATUS +FvFindFile ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader, + IN EFI_FV_FILETYPE FileType, + OUT EFI_FFS_FILE_HEADER **FileHeader + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader; + EndOfFirmwareVolume = CurrentAddress + FvHeader->FvLength; + + // + // Loop through the FFS files + // + for (EndOfFile = CurrentAddress + FvHeader->HeaderLength; ; ) { + CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; + if (CurrentAddress > EndOfFirmwareVolume) { + break; + } + + File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + if (IS_FFS_FILE2 (File)) { + Size = FFS_FILE2_SIZE (File); + if (Size <= 0x00FFFFFF) { + break; + } + } else { + Size = FFS_FILE_SIZE (File); + if (Size < sizeof (EFI_FFS_FILE_HEADER)) { + break; + } + } + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + break; + } + + // + // Look for file type + // + if (File->Type == FileType) { + *FileHeader = File; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + This function searchs a given section type within a valid FFS file. + + @param FileHeader A pointer to the file header that contains the set of sections to + be searched. + @param SearchType The value of the section type to search. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +FileFindSection ( + IN EFI_FFS_FILE_HEADER *FileHeader, + IN EFI_SECTION_TYPE SectionType, + OUT VOID **SectionData + ) +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINT32 SectionSize; + UINT32 Index; + + if (IS_FFS_FILE2 (FileHeader)) { + FileSize = FFS_FILE2_SIZE (FileHeader); + } else { + FileSize = FFS_FILE_SIZE (FileHeader); + } + FileSize -= sizeof (EFI_FFS_FILE_HEADER); + + Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1); + Index = 0; + while (Index < FileSize) { + if (Section->Type == SectionType) { + if (IS_SECTION2 (Section)) { + *SectionData = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + *SectionData = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + return EFI_SUCCESS; + } + + if (IS_SECTION2 (Section)) { + SectionSize = SECTION2_SIZE (Section); + } else { + SectionSize = SECTION_SIZE (Section); + } + + SectionSize = GET_OCCUPIED_SIZE (SectionSize, 4); + ASSERT (SectionSize != 0); + Index += SectionSize; + + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionSize); + } + + return EFI_NOT_FOUND; +} + + +/** + Find DXE core from FV and build DXE core HOBs. + + @param[out] DxeCoreEntryPoint DXE core entry point + + @retval EFI_SUCCESS If it completed successfully. + @retval EFI_NOT_FOUND If it failed to load DXE FV. +**/ +EFI_STATUS +LoadDxeCore ( + OUT PHYSICAL_ADDRESS *DxeCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *PayloadFv; + EFI_FIRMWARE_VOLUME_HEADER *DxeCoreFv; + EFI_FFS_FILE_HEADER *FileHeader; + VOID *PeCoffImage; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + + PayloadFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdPayloadFdMemBase); + + // + // DXE FV is inside Payload FV. Here find DXE FV from Payload FV + // + Status = FvFindFile (PayloadFv, EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &FileHeader); + if (EFI_ERROR (Status)) { + return Status; + } + Status = FileFindSection (FileHeader, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, (VOID **)&DxeCoreFv); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Report DXE FV to DXE core + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) DxeCoreFv, DxeCoreFv->FvLength); + + // + // Find DXE core file from DXE FV + // + Status = FvFindFile (DxeCoreFv, EFI_FV_FILETYPE_DXE_CORE, &FileHeader); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&PeCoffImage); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get DXE core info + // + Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, DxeCoreEntryPoint); + if (EFI_ERROR (Status)) { + return Status; + } + + BuildModuleHob (&FileHeader->Name, ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, *DxeCoreEntryPoint); + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c new file mode 100644 index 00000000..470f81cd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c @@ -0,0 +1,201 @@ +/** @file + + + Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> + Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiPayloadEntry.h" + +/** + Allocates one or more pages of type EfiBootServicesData. + + Allocates the number of pages of MemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory availble to satisfy the request, then NULL + is returned. + + @param Pages The number of 4 KB pages to allocate. + @return A pointer to the allocated buffer or NULL if allocation fails. +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + EFI_HOB_HANDOFF_INFO_TABLE *HobTable; + + Hob.Raw = GetHobList (); + HobTable = Hob.HandoffInformationTable; + + if (Pages == 0) { + return NULL; + } + + // Make sure allocation address is page alligned. + Offset = HobTable->EfiFreeMemoryTop & EFI_PAGE_MASK; + if (Offset != 0) { + HobTable->EfiFreeMemoryTop -= Offset; + } + + // + // Check available memory for the allocation + // + if (HobTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < HobTable->EfiFreeMemoryBottom) { + return NULL; + } + + HobTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + BuildMemoryAllocationHob (HobTable->EfiFreeMemoryTop, Pages * EFI_PAGE_SIZE, EfiBootServicesData); + + return (VOID *)(UINTN)HobTable->EfiFreeMemoryTop; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ +} + +/** + Allocates one or more pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. + If Pages is 0, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If there is no enough memory at the specified alignment available to satisfy the + request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + + @return A pointer to the allocated buffer or NULL if allocation fails. +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Memory; + UINTN AlignmentMask; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + + // + // Check overflow. + // + ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); + + Memory = (VOID *)(UINTN)AllocatePages (Pages + EFI_SIZE_TO_PAGES (Alignment)); + if (Memory == NULL) { + return NULL; + } + + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + + return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask); +} + + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + EFI_HOB_MEMORY_POOL *Hob; + + if (AllocationSize > 0x4000) { + // Please use AllocatePages for big allocations + return NULL; + } + + Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_TYPE_MEMORY_POOL) + AllocationSize)); + return (VOID *)(Hob + 1); +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = AllocatePool (AllocationSize); + if (Buffer == NULL) { + return NULL; + } + + ZeroMem (Buffer, AllocationSize); + + return Buffer; +} + + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c new file mode 100644 index 00000000..4b5003a3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c @@ -0,0 +1,415 @@ +/** @file + + Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiPayloadEntry.h" + +/** + Callback function to build resource descriptor HOB + + This function build a HOB based on the memory map entry info. + + @param MemoryMapEntry Memory map entry info got from bootloader. + @param Params Not used for now. + + @retval RETURN_SUCCESS Successfully build a HOB. +**/ +EFI_STATUS +MemInfoCallback ( + IN MEMROY_MAP_ENTRY *MemoryMapEntry, + IN VOID *Params + ) +{ + EFI_PHYSICAL_ADDRESS Base; + EFI_RESOURCE_TYPE Type; + UINT64 Size; + EFI_RESOURCE_ATTRIBUTE_TYPE Attribue; + + Type = (MemoryMapEntry->Type == 1) ? EFI_RESOURCE_SYSTEM_MEMORY : EFI_RESOURCE_MEMORY_RESERVED; + Base = MemoryMapEntry->Base; + Size = MemoryMapEntry->Size; + + Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE; + + if (Base >= BASE_4GB ) { + // Remove tested attribute to avoid DXE core to dispatch driver to memory above 4GB + Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED; + } + + BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size); + DEBUG ((DEBUG_INFO , "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type)); + + return RETURN_SUCCESS; +} + + + +/** + Find the board related info from ACPI table + + @param AcpiTableBase ACPI table start address in memory + @param AcpiBoardInfo Pointer to the acpi board info strucutre + + @retval RETURN_SUCCESS Successfully find out all the required information. + @retval RETURN_NOT_FOUND Failed to find the required info. + +**/ +RETURN_STATUS +ParseAcpiInfo ( + IN UINT64 AcpiTableBase, + OUT ACPI_BOARD_INFO *AcpiBoardInfo + ) +{ + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt; + UINT32 *Entry32; + UINTN Entry32Num; + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt; + UINT64 *Entry64; + UINTN Entry64Num; + UINTN Idx; + UINT32 *Signature; + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr; + EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase; + + Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase; + DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp)); + DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress)); + + // + // Search Rsdt First + // + Fadt = NULL; + MmCfgHdr = NULL; + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress); + if (Rsdt != NULL) { + Entry32 = (UINT32 *)(Rsdt + 1); + Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2; + for (Idx = 0; Idx < Entry32Num; Idx++) { + Signature = (UINT32 *)(UINTN)Entry32[Idx]; + if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n")); + } + + if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) { + MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature; + DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n")); + } + + if ((Fadt != NULL) && (MmCfgHdr != NULL)) { + goto Done; + } + } + } + + // + // Search Xsdt Second + // + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress); + if (Xsdt != NULL) { + Entry64 = (UINT64 *)(Xsdt + 1); + Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3; + for (Idx = 0; Idx < Entry64Num; Idx++) { + Signature = (UINT32 *)(UINTN)Entry64[Idx]; + if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n")); + } + + if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) { + MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature; + DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n")); + } + + if ((Fadt != NULL) && (MmCfgHdr != NULL)) { + goto Done; + } + } + } + + if (Fadt == NULL) { + return RETURN_NOT_FOUND; + } + +Done: + + AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk; + AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk; + AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address; + AcpiBoardInfo->ResetValue = Fadt->ResetValue; + AcpiBoardInfo->PmEvtBase = Fadt->Pm1aEvtBlk; + AcpiBoardInfo->PmGpeEnBase = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2; + + if (MmCfgHdr != NULL) { + MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8*) MmCfgHdr + sizeof (*MmCfgHdr)); + AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress; + AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8; + } else { + AcpiBoardInfo->PcieBaseAddress = 0; + AcpiBoardInfo->PcieBaseSize = 0; + } + DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase)); + DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase)); + DEBUG ((DEBUG_INFO, "Reset Reg 0x%lx\n", AcpiBoardInfo->ResetRegAddress)); + DEBUG ((DEBUG_INFO, "Reset Value 0x%x\n", AcpiBoardInfo->ResetValue)); + DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase)); + DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase)); + DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress)); + DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize)); + + // + // Verify values for proper operation + // + ASSERT(Fadt->Pm1aCntBlk != 0); + ASSERT(Fadt->PmTmrBlk != 0); + ASSERT(Fadt->ResetReg.Address != 0); + ASSERT(Fadt->Pm1aEvtBlk != 0); + ASSERT(Fadt->Gpe0Blk != 0); + + DEBUG_CODE_BEGIN (); + BOOLEAN SciEnabled; + + // + // Check the consistency of SCI enabling + // + + // + // Get SCI_EN value + // + if (Fadt->Pm1CntLen == 4) { + SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE; + } else { + // + // if (Pm1CntLen == 2), use 16 bit IO read; + // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback + // + SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE; + } + + if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) && + (Fadt->SmiCmd == 0) && + !SciEnabled) { + // + // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI + // table does not provide a means to enable it through FADT->SmiCmd + // + DEBUG ((DEBUG_ERROR, "ERROR: The ACPI enabling status is inconsistent: SCI is not" + " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd." + " This may cause issues in OS.\n")); + } + DEBUG_CODE_END (); + + return RETURN_SUCCESS; +} + + +/** + It will build HOBs based on information from bootloaders. + + @retval EFI_SUCCESS If it completed successfully. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildHobFromBl ( + VOID + ) +{ + EFI_STATUS Status; + SYSTEM_TABLE_INFO SysTableInfo; + SYSTEM_TABLE_INFO *NewSysTableInfo; + ACPI_BOARD_INFO AcpiBoardInfo; + ACPI_BOARD_INFO *NewAcpiBoardInfo; + EFI_PEI_GRAPHICS_INFO_HOB GfxInfo; + EFI_PEI_GRAPHICS_INFO_HOB *NewGfxInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo; + + // + // Parse memory info and build memory HOBs + // + Status = ParseMemoryInfo (MemInfoCallback, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Create guid hob for frame buffer information + // + Status = ParseGfxInfo (&GfxInfo); + if (!EFI_ERROR (Status)) { + NewGfxInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (GfxInfo)); + ASSERT (NewGfxInfo != NULL); + CopyMem (NewGfxInfo, &GfxInfo, sizeof (GfxInfo)); + DEBUG ((DEBUG_INFO, "Created graphics info hob\n")); + } + + + Status = ParseGfxDeviceInfo (&GfxDeviceInfo); + if (!EFI_ERROR (Status)) { + NewGfxDeviceInfo = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (GfxDeviceInfo)); + ASSERT (NewGfxDeviceInfo != NULL); + CopyMem (NewGfxDeviceInfo, &GfxDeviceInfo, sizeof (GfxDeviceInfo)); + DEBUG ((DEBUG_INFO, "Created graphics device info hob\n")); + } + + + // + // Create guid hob for system tables like acpi table and smbios table + // + Status = ParseSystemTable(&SysTableInfo); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { + NewSysTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO)); + ASSERT (NewSysTableInfo != NULL); + CopyMem (NewSysTableInfo, &SysTableInfo, sizeof (SYSTEM_TABLE_INFO)); + DEBUG ((DEBUG_INFO, "Detected Acpi Table at 0x%lx, length 0x%x\n", SysTableInfo.AcpiTableBase, SysTableInfo.AcpiTableSize)); + DEBUG ((DEBUG_INFO, "Detected Smbios Table at 0x%lx, length 0x%x\n", SysTableInfo.SmbiosTableBase, SysTableInfo.SmbiosTableSize)); + } + + // + // Create guid hob for acpi board information + // + Status = ParseAcpiInfo (SysTableInfo.AcpiTableBase, &AcpiBoardInfo); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { + NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); + ASSERT (NewAcpiBoardInfo != NULL); + CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO)); + DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n")); + } + + // + // Parse platform specific information. + // + Status = ParsePlatformInfo (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status)); + return Status; + } + + return EFI_SUCCESS; +} + + +/** + This function will build some generic HOBs that doesn't depend on information from bootloaders. + +**/ +VOID +BuildGenericHob ( + VOID + ) +{ + UINT32 RegEax; + UINT8 PhysicalAddressBits; + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + + // The UEFI payload FV + BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase), PcdGet32 (PcdPayloadFdMemSize), EfiBootServicesData); + + // + // Build CPU memory space and IO space hob + // + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + + BuildCpuHob (PhysicalAddressBits, 16); + + // + // Report Local APIC range, cause sbl HOB to be NULL, comment now + // + ResourceAttribute = ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED + ); + BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO, ResourceAttribute, 0xFEC80000, SIZE_512KB); + BuildMemoryAllocationHob ( 0xFEC80000, SIZE_512KB, EfiMemoryMappedIO); + +} + + +/** + Entry point to the C language phase of UEFI payload. + + @retval It will not return if SUCCESS, and return error when passing bootloader parameter. +**/ +EFI_STATUS +EFIAPI +PayloadEntry ( + IN UINTN BootloaderParameter + ) +{ + EFI_STATUS Status; + PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_HOB_HANDOFF_INFO_TABLE *HandoffHobTable; + UINTN MemBase; + UINTN MemSize; + UINTN HobMemBase; + UINTN HobMemTop; + EFI_PEI_HOB_POINTERS Hob; + + // Call constructor for all libraries + ProcessLibraryConstructorList (); + + DEBUG ((DEBUG_INFO, "GET_BOOTLOADER_PARAMETER() = 0x%lx\n", GET_BOOTLOADER_PARAMETER())); + DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN))); + + // Initialize floating point operating environment to be compliant with UEFI spec. + InitializeFloatingPointUnits (); + + // HOB region is used for HOB and memory allocation for this module + MemBase = PcdGet32 (PcdPayloadFdMemBase); + HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB); + HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); + + // DXE core assumes the memory below HOB region could be used, so include the FV region memory into HOB range. + MemSize = HobMemTop - MemBase; + HandoffHobTable = HobConstructor ((VOID *)MemBase, MemSize, (VOID *)HobMemBase, (VOID *)HobMemTop); + + // Build HOB based on information from Bootloader + Status = BuildHobFromBl (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "BuildHobFromBl Status = %r\n", Status)); + return Status; + } + + // Build other HOBs required by DXE + BuildGenericHob (); + + // Load the DXE Core + Status = LoadDxeCore (&DxeCoreEntryPoint); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint)); + + // + // Mask off all legacy 8259 interrupt sources + // + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); + + Hob.HandoffInformationTable = HandoffHobTable; + HandOffToDxeCore (DxeCoreEntryPoint, Hob); + + // Should not get here + CpuDeadLoop (); + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h new file mode 100644 index 00000000..b66fd992 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h @@ -0,0 +1,134 @@ +/** @file +* +* Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> +* +* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ + +#ifndef __UEFI_PAYLOAD_ENTRY_H__ +#define __UEFI_PAYLOAD_ENTRY_H__ + +#include <PiPei.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/PeCoffLib.h> +#include <Library/HobLib.h> +#include <Library/PcdLib.h> +#include <Guid/MemoryAllocationHob.h> +#include <Library/IoLib.h> +#include <Library/PeCoffLib.h> +#include <Library/BlParseLib.h> +#include <Library/PlatformSupportLib.h> +#include <Library/UefiCpuLib.h> +#include <IndustryStandard/Acpi.h> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h> +#include <Guid/SerialPortInfoGuid.h> +#include <Guid/SystemTableInfoGuid.h> +#include <Guid/MemoryMapInfoGuid.h> +#include <Guid/AcpiBoardInfoGuid.h> +#include <Guid/GraphicsInfoHob.h> + + +#define LEGACY_8259_MASK_REGISTER_MASTER 0x21 +#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1 +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))) + +/** + Auto-generated function that calls the library constructors for all of the module's + dependent libraries. +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + VOID + ); + +/** + Add a new HOB to the HOB List. + + @param HobType Type of the new HOB. + @param HobLength Length of the new HOB to allocate. + + @return NULL if there is no space to create a hob. + @return The address point to the new created hob. + +**/ +VOID * +EFIAPI +CreateHob ( + IN UINT16 HobType, + IN UINT16 HobLength + ); + +/** + Update the Stack Hob if the stack has been moved + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +UpdateStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Build a Handoff Information Table HOB + + This function initialize a HOB region from EfiMemoryBegin with length + EfiMemoryLength. And EfiFreeMemoryBottom and EfiFreeMemoryTop should + be inside the HOB region. + + @param[in] EfiMemoryBegin Total memory start address + @param[in] EfiMemoryLength Total memory length reported in handoff HOB. + @param[in] EfiFreeMemoryBottom Free memory start address + @param[in] EfiFreeMemoryTop Free memory end address. + + @return The pointer to the handoff HOB table. + +**/ +EFI_HOB_HANDOFF_INFO_TABLE* +EFIAPI +HobConstructor ( + IN VOID *EfiMemoryBegin, + IN UINTN EfiMemoryLength, + IN VOID *EfiFreeMemoryBottom, + IN VOID *EfiFreeMemoryTop + ); + +/** + Find DXE core from FV and build DXE core HOBs. + + @param[out] DxeCoreEntryPoint DXE core entry point + + @retval EFI_SUCCESS If it completed successfully. + @retval EFI_NOT_FOUND If it failed to load DXE FV. +**/ +EFI_STATUS +LoadDxeCore ( + OUT PHYSICAL_ADDRESS *DxeCoreEntryPoint + ); + +/** + Transfers control to DxeCore. + + This function performs a CPU architecture specific operations to execute + the entry point of DxeCore with the parameters of HobList. + + @param DxeCoreEntryPoint The entry point of DxeCore. + @param HobList The start of HobList passed to DxeCore. +**/ +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf new file mode 100644 index 00000000..5be2c263 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf @@ -0,0 +1,93 @@ +## @file +# This is the first module for UEFI payload. +# +# Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PayloadEntry + FILE_GUID = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + UefiPayloadEntry.c + LoadDxeCore.c + MemoryAllocation.c + +[Sources.Ia32] + X64/VirtualMemory.h + X64/VirtualMemory.c + Ia32/DxeLoadFunc.c + Ia32/IdtVectorAsm.nasm + Ia32/SecEntry.nasm + +[Sources.X64] + X64/VirtualMemory.h + X64/VirtualMemory.c + X64/DxeLoadFunc.c + X64/SecEntry.nasm + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + SerialPortLib + IoLib + BlParseLib + HobLib + PeCoffLib + PlatformSupportLib + UefiCpuLib + +[Guids] + gEfiMemoryTypeInformationGuid + gEfiFirmwareFileSystem2Guid + gUefiSystemTableInfoGuid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + gUefiAcpiBoardInfoGuid + +[FeaturePcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES + +[FeaturePcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES + + +[Pcd.IA32,Pcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES + + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop + gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c new file mode 100644 index 00000000..144139bd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c @@ -0,0 +1,107 @@ +/** @file + x64-specifc functionality for DxeLoad. + +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/HobLib.h> +#include "X64/VirtualMemory.h" +#include "UefiPayloadEntry.h" +#define STACK_SIZE 0x20000 + + +/** + Transfers control to DxeCore. + + This function performs a CPU architecture specific operations to execute + the entry point of DxeCore with the parameters of HobList. + It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase. + + @param DxeCoreEntryPoint The entry point of DxeCore. + @param HobList The start of HobList passed to DxeCore. + +**/ +VOID +HandOffToDxeCore ( + IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, + IN EFI_PEI_HOB_POINTERS HobList + ) +{ + VOID *BaseOfStack; + VOID *TopOfStack; + UINTN PageTables; + VOID *GhcbBase; + UINTN GhcbSize; + + // + // Clear page 0 and mark it as allocated if NULL pointer detection is enabled. + // + if (IsNullDetectionEnabled ()) { + ClearFirst4KPage (HobList.Raw); + BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData); + } + + + // + // Allocate 128KB for the Stack + // + BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); + ASSERT (BaseOfStack != NULL); + + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); + TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + // + // Get the address and size of the GHCB pages + // + GhcbBase = (VOID *) PcdGet64 (PcdGhcbBase); + GhcbSize = PcdGet64 (PcdGhcbSize); + + PageTables = 0; + if (FeaturePcdGet (PcdDxeIplBuildPageTables)) { + // + // Create page table and save PageMapLevel4 to CR3 + // + PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE, + (EFI_PHYSICAL_ADDRESS) (UINTN) GhcbBase, GhcbSize); + } else { + // + // Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE + // for the DxeIpl and the DxeCore are both X64. + // + ASSERT (PcdGetBool (PcdSetNxForStack) == FALSE); + ASSERT (PcdGetBool (PcdCpuStackGuard) == FALSE); + } + + + if (FeaturePcdGet (PcdDxeIplBuildPageTables)) { + AsmWriteCr3 (PageTables); + } + + // + // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. + // + UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE); + + // + // Transfer the control to the entry point of DxeCore. + // + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + HobList.Raw, + NULL, + TopOfStack + ); +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm new file mode 100644 index 00000000..654f1166 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +;* +;* Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR> +;* SPDX-License-Identifier: BSD-2-Clause-Patent + +;------------------------------------------------------------------------------ + +#include <Base.h> + +DEFAULT REL +SECTION .text + +extern ASM_PFX(PayloadEntry) +extern ASM_PFX(PcdGet32 (PcdPayloadStackTop)) + +; +; SecCore Entry Point +; +; Processor is in flat protected mode + +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + + ; + ; Disable all the interrupts + ; + cli + + + mov rsp, FixedPcdGet32 (PcdPayloadStackTop) + + ; + ; Push the bootloader parameter address onto new stack + ; + push rcx + mov rax, 0 + push rax ; shadow space + push rax + push rax + push rax + + ; + ; Call into C code + ; + call ASM_PFX(PayloadEntry) + jmp $ + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c new file mode 100644 index 00000000..196e88a2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c @@ -0,0 +1,939 @@ +/** @file + x64 Virtual Memory Management Services in the form of an IA-32 driver. + Used to establish a 1:1 Virtual to Physical Mapping that is required to + enter Long Mode (x64 64-bit mode). + + While we make a 1:1 mapping (identity mapping) for all physical pages + we still need to use the MTRR's to ensure that the cachability attributes + for all memory regions is correct. + + The basic idea is to use 2MB page table entries where ever possible. If + more granularity of cachability is required then 4K page tables are used. + + References: + 1) IA-32 Intel(R) Architecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/HobLib.h> +#include <Register/Intel/Cpuid.h> +#include "VirtualMemory.h" + +// +// Global variable to keep track current available memory used as page table. +// +PAGE_TABLE_POOL *mPageTablePool = NULL; + +/** + Clear legacy memory located at the first 4K-page, if available. + + This function traverses the whole HOB list to check if memory from 0 to 4095 + exists and has not been allocated, and then clear it if so. + + @param HobStart The start of HobList passed to DxeCore. + +**/ +VOID +ClearFirst4KPage ( + IN VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS RscHob; + EFI_PEI_HOB_POINTERS MemHob; + BOOLEAN DoClear; + + RscHob.Raw = HobStart; + MemHob.Raw = HobStart; + DoClear = FALSE; + + // + // Check if page 0 exists and free + // + while ((RscHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + RscHob.Raw)) != NULL) { + if (RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && + RscHob.ResourceDescriptor->PhysicalStart == 0) { + DoClear = TRUE; + // + // Make sure memory at 0-4095 has not been allocated. + // + while ((MemHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, + MemHob.Raw)) != NULL) { + if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + < EFI_PAGE_SIZE) { + DoClear = FALSE; + break; + } + MemHob.Raw = GET_NEXT_HOB (MemHob); + } + break; + } + RscHob.Raw = GET_NEXT_HOB (RscHob); + } + + if (DoClear) { + DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n")); + SetMem (NULL, EFI_PAGE_SIZE, 0); + } + + return; +} + +/** + Return configure status of NULL pointer detection feature. + + @return TRUE NULL pointer detection feature is enabled + @return FALSE NULL pointer detection feature is disabled + +**/ +BOOLEAN +IsNullDetectionEnabled ( + VOID + ) +{ + return ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0); +} + +/** + The function will check if Execute Disable Bit is available. + + @retval TRUE Execute Disable Bit is available. + @retval FALSE Execute Disable Bit is not available. + +**/ +BOOLEAN +IsExecuteDisableBitAvailable ( + VOID + ) +{ + UINT32 RegEax; + UINT32 RegEdx; + BOOLEAN Available; + + Available = FALSE; + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000001) { + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT20) != 0) { + // + // Bit 20: Execute Disable Bit available. + // + Available = TRUE; + } + } + + return Available; +} + +/** + Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not. + + @retval TRUE IA32_EFER.NXE should be enabled. + @retval FALSE IA32_EFER.NXE should not be enabled. + +**/ +BOOLEAN +IsEnableNonExecNeeded ( + VOID + ) +{ + if (!IsExecuteDisableBitAvailable ()) { + return FALSE; + } + + // + // XD flag (BIT63) in page table entry is only valid if IA32_EFER.NXE is set. + // Features controlled by Following PCDs need this feature to be enabled. + // + return (PcdGetBool (PcdSetNxForStack) || + PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0 || + PcdGet32 (PcdImageProtectionPolicy) != 0); +} + +/** + Enable Execute Disable Bit. + +**/ +VOID +EnableExecuteDisableBit ( + VOID + ) +{ + UINT64 MsrRegisters; + + MsrRegisters = AsmReadMsr64 (0xC0000080); + MsrRegisters |= BIT11; + AsmWriteMsr64 (0xC0000080, MsrRegisters); +} + +/** + The function will check if page table entry should be splitted to smaller + granularity. + + @param Address Physical memory address. + @param Size Size of the given physical memory. + @param StackBase Base address of stack. + @param StackSize Size of stack. + @param GhcbBase Base address of GHCB pages. + @param GhcbSize Size of GHCB area. + + @retval TRUE Page table should be split. + @retval FALSE Page table should not be split. +**/ +BOOLEAN +ToSplitPageTable ( + IN EFI_PHYSICAL_ADDRESS Address, + IN UINTN Size, + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN EFI_PHYSICAL_ADDRESS GhcbBase, + IN UINTN GhcbSize + ) +{ + if (IsNullDetectionEnabled () && Address == 0) { + return TRUE; + } + + if (PcdGetBool (PcdCpuStackGuard)) { + if (StackBase >= Address && StackBase < (Address + Size)) { + return TRUE; + } + } + + if (PcdGetBool (PcdSetNxForStack)) { + if ((Address < StackBase + StackSize) && ((Address + Size) > StackBase)) { + return TRUE; + } + } + + if (GhcbBase != 0) { + if ((Address < GhcbBase + GhcbSize) && ((Address + Size) > GhcbBase)) { + return TRUE; + } + } + + return FALSE; +} +/** + Initialize a buffer pool for page table use only. + + To reduce the potential split operation on page table, the pages reserved for + page table should be allocated in the times of PAGE_TABLE_POOL_UNIT_PAGES and + at the boundary of PAGE_TABLE_POOL_ALIGNMENT. So the page pool is always + initialized with number of pages greater than or equal to the given PoolPages. + + Once the pages in the pool are used up, this method should be called again to + reserve at least another PAGE_TABLE_POOL_UNIT_PAGES. But usually this won't + happen in practice. + + @param PoolPages The least page number of the pool to be created. + + @retval TRUE The pool is initialized successfully. + @retval FALSE The memory is out of resource. +**/ +BOOLEAN +InitializePageTablePool ( + IN UINTN PoolPages + ) +{ + VOID *Buffer; + + // + // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for + // header. + // + PoolPages += 1; // Add one page for header. + PoolPages = ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) * + PAGE_TABLE_POOL_UNIT_PAGES; + Buffer = AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT); + if (Buffer == NULL) { + DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n")); + return FALSE; + } + + // + // Link all pools into a list for easier track later. + // + if (mPageTablePool == NULL) { + mPageTablePool = Buffer; + mPageTablePool->NextPool = mPageTablePool; + } else { + ((PAGE_TABLE_POOL *)Buffer)->NextPool = mPageTablePool->NextPool; + mPageTablePool->NextPool = Buffer; + mPageTablePool = Buffer; + } + + // + // Reserve one page for pool header. + // + mPageTablePool->FreePages = PoolPages - 1; + mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1); + + return TRUE; +} + +/** + This API provides a way to allocate memory for page table. + + This API can be called more than once to allocate memory for page tables. + + Allocates the number of 4KB pages and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. + + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +AllocatePageTableMemory ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + if (Pages == 0) { + return NULL; + } + + // + // Renew the pool if necessary. + // + if (mPageTablePool == NULL || + Pages > mPageTablePool->FreePages) { + if (!InitializePageTablePool (Pages)) { + return NULL; + } + } + + Buffer = (UINT8 *)mPageTablePool + mPageTablePool->Offset; + + mPageTablePool->Offset += EFI_PAGES_TO_SIZE (Pages); + mPageTablePool->FreePages -= Pages; + + return Buffer; +} + +/** + Split 2M page to 4K. + + @param[in] PhysicalAddress Start physical address the 2M page covered. + @param[in, out] PageEntry2M Pointer to 2M page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + @param[in] GhcbBase GHCB page area base address. + @param[in] GhcbSize GHCB page area size. + +**/ +VOID +Split2MPageTo4K ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry2M, + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN EFI_PHYSICAL_ADDRESS GhcbBase, + IN UINTN GhcbSize + ) +{ + EFI_PHYSICAL_ADDRESS PhysicalAddress4K; + UINTN IndexOfPageTableEntries; + PAGE_TABLE_4K_ENTRY *PageTableEntry; + UINT64 AddressEncMask; + + // + // Make sure AddressEncMask is contained to smallest supported address field + // + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64; + + PageTableEntry = AllocatePageTableMemory (1); + ASSERT (PageTableEntry != NULL); + + // + // Fill in 2M page entry. + // + *PageEntry2M = (UINT64) (UINTN) PageTableEntry | AddressEncMask | IA32_PG_P | IA32_PG_RW; + + PhysicalAddress4K = PhysicalAddress; + for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) { + // + // Fill in the Page Table entries + // + PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K; + + // + // The GHCB range consists of two pages per CPU, the GHCB and a + // per-CPU variable page. The GHCB page needs to be mapped as an + // unencrypted page while the per-CPU variable page needs to be + // mapped encrypted. These pages alternate in assignment. + // + if ((GhcbBase == 0) + || (PhysicalAddress4K < GhcbBase) + || (PhysicalAddress4K >= GhcbBase + GhcbSize) + || (((PhysicalAddress4K - GhcbBase) & SIZE_4KB) != 0)) { + PageTableEntry->Uint64 |= AddressEncMask; + } + PageTableEntry->Bits.ReadWrite = 1; + + if ((IsNullDetectionEnabled () && PhysicalAddress4K == 0) || + (PcdGetBool (PcdCpuStackGuard) && PhysicalAddress4K == StackBase)) { + PageTableEntry->Bits.Present = 0; + } else { + PageTableEntry->Bits.Present = 1; + } + + if (PcdGetBool (PcdSetNxForStack) + && (PhysicalAddress4K >= StackBase) + && (PhysicalAddress4K < StackBase + StackSize)) { + // + // Set Nx bit for stack. + // + PageTableEntry->Bits.Nx = 1; + } + } +} + +/** + Split 1G page to 2M. + + @param[in] PhysicalAddress Start physical address the 1G page covered. + @param[in, out] PageEntry1G Pointer to 1G page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + @param[in] GhcbBase GHCB page area base address. + @param[in] GhcbSize GHCB page area size. + +**/ +VOID +Split1GPageTo2M ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry1G, + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN EFI_PHYSICAL_ADDRESS GhcbBase, + IN UINTN GhcbSize + ) +{ + EFI_PHYSICAL_ADDRESS PhysicalAddress2M; + UINTN IndexOfPageDirectoryEntries; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINT64 AddressEncMask; + + // + // Make sure AddressEncMask is contained to smallest supported address field + // + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64; + + PageDirectoryEntry = AllocatePageTableMemory (1); + ASSERT (PageDirectoryEntry != NULL); + + // + // Fill in 1G page entry. + // + *PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | AddressEncMask | IA32_PG_P | IA32_PG_RW; + + PhysicalAddress2M = PhysicalAddress; + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) { + if (ToSplitPageTable (PhysicalAddress2M, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) { + // + // Need to split this 2M page that covers NULL or stack range. + // + Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize); + } else { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M | AddressEncMask; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + } + } +} + +/** + Set one page of page table pool memory to be read-only. + + @param[in] PageTableBase Base address of page table (CR3). + @param[in] Address Start address of a page to be set as read-only. + @param[in] Level4Paging Level 4 paging flag. + +**/ +VOID +SetPageTablePoolReadOnly ( + IN UINTN PageTableBase, + IN EFI_PHYSICAL_ADDRESS Address, + IN BOOLEAN Level4Paging + ) +{ + UINTN Index; + UINTN EntryIndex; + UINT64 AddressEncMask; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT64 *PageTable; + UINT64 *NewPageTable; + UINT64 PageAttr; + UINT64 LevelSize[5]; + UINT64 LevelMask[5]; + UINTN LevelShift[5]; + UINTN Level; + UINT64 PoolUnitSize; + + ASSERT (PageTableBase != 0); + + // + // Since the page table is always from page table pool, which is always + // located at the boundary of PcdPageTablePoolAlignment, we just need to + // set the whole pool unit to be read-only. + // + Address = Address & PAGE_TABLE_POOL_ALIGN_MASK; + + LevelShift[1] = PAGING_L1_ADDRESS_SHIFT; + LevelShift[2] = PAGING_L2_ADDRESS_SHIFT; + LevelShift[3] = PAGING_L3_ADDRESS_SHIFT; + LevelShift[4] = PAGING_L4_ADDRESS_SHIFT; + + LevelMask[1] = PAGING_4K_ADDRESS_MASK_64; + LevelMask[2] = PAGING_2M_ADDRESS_MASK_64; + LevelMask[3] = PAGING_1G_ADDRESS_MASK_64; + LevelMask[4] = PAGING_1G_ADDRESS_MASK_64; + + LevelSize[1] = SIZE_4KB; + LevelSize[2] = SIZE_2MB; + LevelSize[3] = SIZE_1GB; + LevelSize[4] = SIZE_512GB; + + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & + PAGING_1G_ADDRESS_MASK_64; + PageTable = (UINT64 *)(UINTN)PageTableBase; + PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE; + + for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) { + Index = ((UINTN)RShiftU64 (Address, LevelShift[Level])); + Index &= PAGING_PAE_INDEX_MASK; + + PageAttr = PageTable[Index]; + if ((PageAttr & IA32_PG_PS) == 0) { + // + // Go to next level of table. + // + PageTable = (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask & + PAGING_4K_ADDRESS_MASK_64); + continue; + } + + if (PoolUnitSize >= LevelSize[Level]) { + // + // Clear R/W bit if current page granularity is not larger than pool unit + // size. + // + if ((PageAttr & IA32_PG_RW) != 0) { + while (PoolUnitSize > 0) { + // + // PAGE_TABLE_POOL_UNIT_SIZE and PAGE_TABLE_POOL_ALIGNMENT are fit in + // one page (2MB). Then we don't need to update attributes for pages + // crossing page directory. ASSERT below is for that purpose. + // + ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64)); + + PageTable[Index] &= ~(UINT64)IA32_PG_RW; + PoolUnitSize -= LevelSize[Level]; + + ++Index; + } + } + + break; + + } else { + // + // The smaller granularity of page must be needed. + // + ASSERT (Level > 1); + + NewPageTable = AllocatePageTableMemory (1); + ASSERT (NewPageTable != NULL); + + PhysicalAddress = PageAttr & LevelMask[Level]; + for (EntryIndex = 0; + EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64); + ++EntryIndex) { + NewPageTable[EntryIndex] = PhysicalAddress | AddressEncMask | + IA32_PG_P | IA32_PG_RW; + if (Level > 2) { + NewPageTable[EntryIndex] |= IA32_PG_PS; + } + PhysicalAddress += LevelSize[Level - 1]; + } + + PageTable[Index] = (UINT64)(UINTN)NewPageTable | AddressEncMask | + IA32_PG_P | IA32_PG_RW; + PageTable = NewPageTable; + } + } +} + +/** + Prevent the memory pages used for page table from been overwritten. + + @param[in] PageTableBase Base address of page table (CR3). + @param[in] Level4Paging Level 4 paging flag. + +**/ +VOID +EnablePageTableProtection ( + IN UINTN PageTableBase, + IN BOOLEAN Level4Paging + ) +{ + PAGE_TABLE_POOL *HeadPool; + PAGE_TABLE_POOL *Pool; + UINT64 PoolSize; + EFI_PHYSICAL_ADDRESS Address; + + if (mPageTablePool == NULL) { + return; + } + + // + // Disable write protection, because we need to mark page table to be write + // protected. + // + AsmWriteCr0 (AsmReadCr0() & ~CR0_WP); + + // + // SetPageTablePoolReadOnly might update mPageTablePool. It's safer to + // remember original one in advance. + // + HeadPool = mPageTablePool; + Pool = HeadPool; + do { + Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Pool; + PoolSize = Pool->Offset + EFI_PAGES_TO_SIZE (Pool->FreePages); + + // + // The size of one pool must be multiple of PAGE_TABLE_POOL_UNIT_SIZE, which + // is one of page size of the processor (2MB by default). Let's apply the + // protection to them one by one. + // + while (PoolSize > 0) { + SetPageTablePoolReadOnly(PageTableBase, Address, Level4Paging); + Address += PAGE_TABLE_POOL_UNIT_SIZE; + PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE; + } + + Pool = Pool->NextPool; + } while (Pool != HeadPool); + + // + // Enable write protection, after page table attribute updated. + // + AsmWriteCr0 (AsmReadCr0() | CR0_WP); +} + +/** + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping. + + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + @param[in] GhcbBase GHCB base address. + @param[in] GhcbSize GHCB size. + + @return The address of 4 level page map. + +**/ +UINTN +CreateIdentityMappingPageTables ( + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN EFI_PHYSICAL_ADDRESS GhcbBase, + IN UINTN GhcbSize + ) +{ + UINT32 RegEax; + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX EcxFlags; + UINT32 RegEdx; + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN IndexOfPml5Entries; + UINTN IndexOfPml4Entries; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINT32 NumberOfPml5EntriesNeeded; + UINT32 NumberOfPml4EntriesNeeded; + UINT32 NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel5Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN TotalPagesNum; + UINTN BigPageAddress; + VOID *Hob; + BOOLEAN Page5LevelSupport; + BOOLEAN Page1GSupport; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + UINT64 AddressEncMask; + IA32_CR4 Cr4; + + // + // Set PageMapLevel5Entry to suppress incorrect compiler/analyzer warnings + // + PageMapLevel5Entry = NULL; + + // + // Make sure AddressEncMask is contained to smallest supported address field + // + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64; + + Page1GSupport = FALSE; + if (PcdGetBool(PcdUse1GPageTable)) { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000001) { + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT26) != 0) { + Page1GSupport = TRUE; + } + } + } + + // + // Get physical address bits supported. + // + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + } + + Page5LevelSupport = FALSE; + if (PcdGetBool (PcdUse5LevelPageTable)) { + AsmCpuidEx ( + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, + &EcxFlags.Uint32, NULL, NULL + ); + if (EcxFlags.Bits.FiveLevelPage != 0) { + Page5LevelSupport = TRUE; + } + } + + DEBUG ((DEBUG_INFO, "AddressBits=%u 5LevelPaging=%u 1GPage=%u\n", PhysicalAddressBits, Page5LevelSupport, Page1GSupport)); + + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses + // when 5-Level Paging is disabled, + // due to either unsupported by HW, or disabled by PCD. + // + ASSERT (PhysicalAddressBits <= 52); + if (!Page5LevelSupport && PhysicalAddressBits > 48) { + PhysicalAddressBits = 48; + } + + // + // Calculate the table entries needed. + // + NumberOfPml5EntriesNeeded = 1; + if (PhysicalAddressBits > 48) { + NumberOfPml5EntriesNeeded = (UINT32) LShiftU64 (1, PhysicalAddressBits - 48); + PhysicalAddressBits = 48; + } + + NumberOfPml4EntriesNeeded = 1; + if (PhysicalAddressBits > 39) { + NumberOfPml4EntriesNeeded = (UINT32) LShiftU64 (1, PhysicalAddressBits - 39); + PhysicalAddressBits = 39; + } + + NumberOfPdpEntriesNeeded = 1; + ASSERT (PhysicalAddressBits > 30); + NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, PhysicalAddressBits - 30); + + // + // Pre-allocate big pages to avoid later allocations. + // + if (!Page1GSupport) { + TotalPagesNum = ((NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1) * NumberOfPml5EntriesNeeded + 1; + } else { + TotalPagesNum = (NumberOfPml4EntriesNeeded + 1) * NumberOfPml5EntriesNeeded + 1; + } + + // + // Substract the one page occupied by PML5 entries if 5-Level Paging is disabled. + // + if (!Page5LevelSupport) { + TotalPagesNum--; + } + + DEBUG ((DEBUG_INFO, "Pml5=%u Pml4=%u Pdp=%u TotalPage=%Lu\n", + NumberOfPml5EntriesNeeded, NumberOfPml4EntriesNeeded, + NumberOfPdpEntriesNeeded, (UINT64)TotalPagesNum)); + + BigPageAddress = (UINTN) AllocatePageTableMemory (TotalPagesNum); + ASSERT (BigPageAddress != 0); + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + PageMap = (VOID *) BigPageAddress; + if (Page5LevelSupport) { + // + // By architecture only one PageMapLevel5 exists - so lets allocate storage for it. + // + PageMapLevel5Entry = PageMap; + BigPageAddress += SIZE_4KB; + } + PageAddress = 0; + + for ( IndexOfPml5Entries = 0 + ; IndexOfPml5Entries < NumberOfPml5EntriesNeeded + ; IndexOfPml5Entries++) { + // + // Each PML5 entry points to a page of PML4 entires. + // So lets allocate space for them and fill them in in the IndexOfPml4Entries loop. + // When 5-Level Paging is disabled, below allocation happens only once. + // + PageMapLevel4Entry = (VOID *) BigPageAddress; + BigPageAddress += SIZE_4KB; + + if (Page5LevelSupport) { + // + // Make a PML5 Entry + // + PageMapLevel5Entry->Uint64 = (UINT64) (UINTN) PageMapLevel4Entry | AddressEncMask; + PageMapLevel5Entry->Bits.ReadWrite = 1; + PageMapLevel5Entry->Bits.Present = 1; + PageMapLevel5Entry++; + } + + for ( IndexOfPml4Entries = 0 + ; IndexOfPml4Entries < (NumberOfPml5EntriesNeeded == 1 ? NumberOfPml4EntriesNeeded : 512) + ; IndexOfPml4Entries++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. + // + PageDirectoryPointerEntry = (VOID *) BigPageAddress; + BigPageAddress += SIZE_4KB; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + if (Page1GSupport) { + PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) { + if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSize, GhcbBase, GhcbSize)) { + Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize, GhcbBase, GhcbSize); + } else { + // + // Fill in the Page Directory entries + // + PageDirectory1GEntry->Uint64 = (UINT64)PageAddress | AddressEncMask; + PageDirectory1GEntry->Bits.ReadWrite = 1; + PageDirectory1GEntry->Bits.Present = 1; + PageDirectory1GEntry->Bits.MustBe1 = 1; + } + } + } else { + for ( IndexOfPdpEntries = 0 + ; IndexOfPdpEntries < (NumberOfPml4EntriesNeeded == 1 ? NumberOfPdpEntriesNeeded : 512) + ; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. + // + PageDirectoryEntry = (VOID *) BigPageAddress; + BigPageAddress += SIZE_4KB; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) { + if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) { + // + // Need to split this 2M page that covers NULL or stack range. + // + Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize); + } else { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PageAddress | AddressEncMask; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + } + } + } + + // + // Fill with null entry for unused PDPTE + // + ZeroMem (PageDirectoryPointerEntry, (512 - IndexOfPdpEntries) * sizeof(PAGE_MAP_AND_DIRECTORY_POINTER)); + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // + ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)); + } + + if (Page5LevelSupport) { + Cr4.UintN = AsmReadCr4 (); + Cr4.Bits.LA57 = 1; + AsmWriteCr4 (Cr4.UintN); + // + // For the PML5 entries we are not using fill in a null entry. + // + ZeroMem (PageMapLevel5Entry, (512 - IndexOfPml5Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)); + } + + // + // Protect the page table by marking the memory used for page table to be + // read-only. + // + EnablePageTableProtection ((UINTN)PageMap, TRUE); + + // + // Set IA32_EFER.NXE if necessary. + // + if (IsEnableNonExecNeeded ()) { + EnableExecuteDisableBit (); + } + + return (UINTN)PageMap; +} + diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h new file mode 100644 index 00000000..0fbbc906 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h @@ -0,0 +1,330 @@ +/** @file + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Architecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + + +#define SYS_CODE64_SEL 0x38 + + +#pragma pack(1) + +typedef union { + struct { + UINT32 LimitLow : 16; + UINT32 BaseLow : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHigh : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHigh : 8; + } Bits; + UINT64 Uint64; +} IA32_GDT; + +typedef struct { + IA32_IDT_GATE_DESCRIPTOR Ia32IdtEntry; + UINT32 Offset32To63; + UINT32 Reserved; +} X64_IDT_GATE_DESCRIPTOR; + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 4KB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +// +// Page Table Entry 1GB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:17; // Must be zero; + UINT64 PageTableBaseAddress:22; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_1G_ENTRY; + +#pragma pack() + +#define CR0_WP BIT16 + +#define IA32_PG_P BIT0 +#define IA32_PG_RW BIT1 +#define IA32_PG_PS BIT7 + +#define PAGING_PAE_INDEX_MASK 0x1FF + +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull +#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull + +#define PAGING_L1_ADDRESS_SHIFT 12 +#define PAGING_L2_ADDRESS_SHIFT 21 +#define PAGING_L3_ADDRESS_SHIFT 30 +#define PAGING_L4_ADDRESS_SHIFT 39 + +#define PAGING_PML4E_NUMBER 4 + +#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB +#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB +#define PAGE_TABLE_POOL_UNIT_PAGES EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE) +#define PAGE_TABLE_POOL_ALIGN_MASK \ + (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1)) + +typedef struct { + VOID *NextPool; + UINTN Offset; + UINTN FreePages; +} PAGE_TABLE_POOL; + +/** + Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not. + + @retval TRUE IA32_EFER.NXE should be enabled. + @retval FALSE IA32_EFER.NXE should not be enabled. + +**/ +BOOLEAN +IsEnableNonExecNeeded ( + VOID + ); + +/** + Enable Execute Disable Bit. + +**/ +VOID +EnableExecuteDisableBit ( + VOID + ); + +/** + Split 2M page to 4K. + + @param[in] PhysicalAddress Start physical address the 2M page covered. + @param[in, out] PageEntry2M Pointer to 2M page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + @param[in] GhcbBase GHCB page area base address. + @param[in] GhcbSize GHCB page area size. + +**/ +VOID +Split2MPageTo4K ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry2M, + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN EFI_PHYSICAL_ADDRESS GhcbBase, + IN UINTN GhcbSize + ); + +/** + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping. + + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + @param[in] GhcbBase GHCB page area base address. + @param[in] GhcbSize GHCB page area size. + + @return The address of 4 level page map. + +**/ +UINTN +CreateIdentityMappingPageTables ( + IN EFI_PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN EFI_PHYSICAL_ADDRESS GhcbBase, + IN UINTN GhcbkSize + ); + + +/** + + Fix up the vector number in the vector code. + + @param VectorBase Base address of the vector handler. + @param VectorNum Index of vector. + +**/ +VOID +EFIAPI +AsmVectorFixup ( + VOID *VectorBase, + UINT8 VectorNum + ); + + +/** + + Get the information of vector template. + + @param TemplateBase Base address of the template code. + + @return Size of the Template code. + +**/ +UINTN +EFIAPI +AsmGetVectorTemplatInfo ( + OUT VOID **TemplateBase + ); + +/** + Clear legacy memory located at the first 4K-page. + + This function traverses the whole HOB list to check if memory from 0 to 4095 + exists and has not been allocated, and then clear it if so. + + @param HobStart The start of HobList passed to DxeCore. + +**/ +VOID +ClearFirst4KPage ( + IN VOID *HobStart + ); + +/** + Return configure status of NULL pointer detection feature. + + @return TRUE NULL pointer detection feature is enabled + @return FALSE NULL pointer detection feature is disabled +**/ +BOOLEAN +IsNullDetectionEnabled ( + VOID + ); + +/** + Prevent the memory pages used for page table from been overwritten. + + @param[in] PageTableBase Base address of page table (CR3). + @param[in] Level4Paging Level 4 paging flag. + +**/ +VOID +EnablePageTableProtection ( + IN UINTN PageTableBase, + IN BOOLEAN Level4Paging + ); + +/** + This API provides a way to allocate memory for page table. + + This API can be called more than once to allocate memory for page tables. + + Allocates the number of 4KB pages and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. + + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +AllocatePageTableMemory ( + IN UINTN Pages + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec new file mode 100644 index 00000000..73e835d9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec @@ -0,0 +1,72 @@ +## @file +# UEFI Payload Package +# +# Provides drivers and definitions to create uefi payload for bootloaders. +# +# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = UefiPayloadPkg + PACKAGE_GUID = E0FC9D50-415E-4946-B686-9A130D5859E7 + PACKAGE_VERSION = 0.1 + +[Includes] + Include + + +[Guids] + # + ## Defines the token space for the UEFI Payload Package PCDs. + # + gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}} + + # + # Gop Temp + # + gBmpImageGuid = { 0x878AC2CC, 0x5343, 0x46F2, { 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } } + + gUefiSystemTableInfoGuid = {0x16c8a6d0, 0xfe8a, 0x4082, {0xa2, 0x8, 0xcf, 0x89, 0xc4, 0x29, 0x4, 0x33}} + gUefiAcpiBoardInfoGuid = {0xad3d31b, 0xb3d8, 0x4506, {0xae, 0x71, 0x2e, 0xf1, 0x10, 0x6, 0xd9, 0xf}} + gUefiSerialPortInfoGuid = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } } + gLoaderMemoryMapInfoGuid = { 0xa1ff7424, 0x7a1a, 0x478e, { 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32 } } + +[Ppis] + gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} } + +[Protocols] + # + # Gop Temp + # + gPlatformGOPPolicyGuid = { 0xec2e931b, 0x3281, 0x48a5, { 0x81, 0x07, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } } + +################################################################################ +# +# PCD Declarations section - list of all PCDs Declared by this Package +# Only this package should be providing the +# declaration, other packages should not. +# +################################################################################ +[PcdsFixedAtBuild, PcdsPatchableInModule] +## Indicates the base address of the payload binary in memory +gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase|0|UINT32|0x10000001 +## Provides the size of the payload binary in memory +gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize|0|UINT32|0x10000002 +## Payload stack top +gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop|0x90000|UINT32|0x10000004 + +## FFS filename to find the shell application. +gUefiPayloadPkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1c, 0x4f, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }|VOID*|0x10000005 + +## Used to help reduce fragmentation in the EFI memory map +gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0x08|UINT32|0x10000012 +gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0x04|UINT32|0x10000013 +gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0x04|UINT32|0x00000014 +gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0xC0|UINT32|0x00000015 +gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0x80|UINT32|0x00000016 + +# Size of the region used by UEFI in permanent memory +gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x02000000|UINT32|0x00000017 diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dsc b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dsc new file mode 100644 index 00000000..8fcf3871 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -0,0 +1,571 @@ +## @file +# Bootloader Payload Package +# +# Provides drivers and definitions to create uefi payload for bootloaders. +# +# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR> +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = UefiPayloadPkg + PLATFORM_GUID = F71608AB-D63D-4491-B744-A99998C8CD96 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + OUTPUT_DIRECTORY = Build/UefiPayloadPkgX64 + FLASH_DEFINITION = UefiPayloadPkg/UefiPayloadPkg.fdf + + DEFINE SOURCE_DEBUG_ENABLE = FALSE + DEFINE PS2_KEYBOARD_ENABLE = FALSE + + # + # SBL: UEFI payload for Slim Bootloader + # COREBOOT: UEFI payload for coreboot + # + DEFINE BOOTLOADER = SBL + + # + # CPU options + # + DEFINE MAX_LOGICAL_PROCESSORS = 64 + + # + # PCI options + # + DEFINE PCIE_BASE_SUPPORT = TRUE + + # + # Serial port set up + # + DEFINE BAUD_RATE = 115200 + DEFINE SERIAL_CLOCK_RATE = 1843200 + DEFINE SERIAL_LINE_CONTROL = 3 # 8-bits, no parity + DEFINE SERIAL_HARDWARE_FLOW_CONTROL = FALSE + DEFINE SERIAL_DETECT_CABLE = FALSE + DEFINE SERIAL_FIFO_CONTROL = 7 # Enable FIFO + DEFINE SERIAL_EXTENDED_TX_FIFO_SIZE = 16 + DEFINE UART_DEFAULT_BAUD_RATE = $(BAUD_RATE) + DEFINE UART_DEFAULT_DATA_BITS = 8 + DEFINE UART_DEFAULT_PARITY = 1 + DEFINE UART_DEFAULT_STOP_BITS = 1 + DEFINE DEFAULT_TERMINAL_TYPE = 0 + + # Enabling the serial terminal will slow down the boot menu redering! + DEFINE DISABLE_SERIAL_TERMINAL = FALSE + + # + # typedef struct { + # UINT16 VendorId; ///< Vendor ID to match the PCI device. The value 0xFFFF terminates the list of entries. + # UINT16 DeviceId; ///< Device ID to match the PCI device + # UINT32 ClockRate; ///< UART clock rate. Set to 0 for default clock rate of 1843200 Hz + # UINT64 Offset; ///< The byte offset into to the BAR + # UINT8 BarIndex; ///< Which BAR to get the UART base address + # UINT8 RegisterStride; ///< UART register stride in bytes. Set to 0 for default register stride of 1 byte. + # UINT16 ReceiveFifoDepth; ///< UART receive FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + # UINT16 TransmitFifoDepth; ///< UART transmit FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + # UINT8 Reserved[2]; + # } PCI_SERIAL_PARAMETER; + # + # Vendor FFFF Device 0000 Prog Interface 1, BAR #0, Offset 0, Stride = 1, Clock 1843200 (0x1c2000) + # + # [Vendor] [Device] [----ClockRate---] [------------Offset-----------] [Bar] [Stride] [RxFifo] [TxFifo] [Rsvd] [Vendor] + DEFINE PCI_SERIAL_PARAMETERS = {0xff,0xff, 0x00,0x00, 0x0,0x20,0x1c,0x00, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x00, 0x01, 0x0,0x0, 0x0,0x0, 0x0,0x0, 0xff,0xff} + + # + # Shell options: [BUILD_SHELL, MIN_BIN, NONE, UEFI_BIN] + # + DEFINE SHELL_TYPE = BUILD_SHELL + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES + GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG + GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG + INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + +[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] + GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000 + XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000 + XCODE:*_*_*_MTOC_FLAGS = -align 0x1000 + CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096 + MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096 + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ + +!include MdePkg/MdeLibs.dsc.inc + +[LibraryClasses] + # + # Entry point + # + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf +!if $(PCIE_BASE_SUPPORT) == FALSE + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf +!else + PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf + PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf +!endif + PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf + PciSegmentInfoLib|UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + + # + # Generic Modules + # + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf + FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf + + # + # Platform + # + TimerLib|UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf + ResetSystemLib|UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + PlatformHookLib|UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf + PlatformBootManagerLib|UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf + IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf + + # + # Misc + # + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf +!if $(SOURCE_DEBUG_ENABLE) == TRUE + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf + DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf +!else + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf +!endif + PlatformSupportLib|UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf +!if $(BOOTLOADER) == "COREBOOT" + BlParseLib|UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf +!else + BlParseLib|UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf +!endif + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf + +[LibraryClasses.common.SEC] + HobLib|UefiPayloadPkg/Library/HobLib/HobLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +[LibraryClasses.common.DXE_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf +!if $(SOURCE_DEBUG_ENABLE) + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + +[LibraryClasses.common.DXE_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf +!if $(SOURCE_DEBUG_ENABLE) + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf + VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf + +[LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. +# +################################################################################ +[PcdsFeatureFlag] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE + +[PcdsFixedAtBuild] + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000 + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000 + # + # Make VariableRuntimeDxe work at emulated non-volatile variable mode. + # + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE + + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0 +!if $(TARGET) == DEBUG + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 } + + +!if $(SOURCE_DEBUG_ENABLE) + gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2 +!endif + +[PcdsPatchableInModule.common] + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7 + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F +!if $(SOURCE_DEBUG_ENABLE) + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F +!endif + + # + # The following parameters are set by Library/PlatformHookLib + # + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|$(BAUD_RATE) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1 + + # + # Enable these parameters to be set on the command line + # + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|$(SERIAL_CLOCK_RATE) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl|$(SERIAL_LINE_CONTROL) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|$(SERIAL_HARDWARE_FLOW_CONTROL) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialDetectCable|$(SERIAL_DETECT_CABLE) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|$(SERIAL_FIFO_CONTROL) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|$(SERIAL_EXTENDED_TX_FIFO_SIZE) + + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|$(UART_DEFAULT_BAUD_RATE) + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|$(UART_DEFAULT_DATA_BITS) + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|$(UART_DEFAULT_PARITY) + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|$(UART_DEFAULT_STOP_BITS) + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|$(DEFAULT_TERMINAL_TYPE) + gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters|$(PCI_SERIAL_PARAMETERS) + + gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|$(MAX_LOGICAL_PROCESSORS) + + +################################################################################ +# +# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsDynamicDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 + + ## This PCD defines the video horizontal resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0 + ## This PCD defines the video vertical resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0 + + ## The PCD is used to specify the video horizontal resolution of text setup. + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|0 + ## The PCD is used to specify the video vertical resolution of text setup. + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|0 + + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize|0 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform. +# +################################################################################ + +!if "IA32" in $(ARCH) + [Components.IA32] + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf +!else + [Components.X64] + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf +!endif + +[Components.X64] + # + # DXE Core + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + <LibraryClasses> + NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + + # + # Components that produce the architectural protocols + # + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + UefiCpuPkg/CpuDxe/CpuDxe.inf + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + MdeModulePkg/Application/UiApp/UiApp.inf { + <LibraryClasses> + NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf + NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf + NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf + } + + PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf + MdeModulePkg/Universal/Metronome/Metronome.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf + PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + + # + # Following are the DXE drivers + # + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + <LibraryClasses> + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + + UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf + + # + # SMBIOS Support + # + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + + # + # ACPI Support + # + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + + # + # PCI Support + # + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf { + <LibraryClasses> + PciHostBridgeLib|UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf + } + + # + # SCSI/ATA/IDE/DISK Support + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf + + # + # SD/eMMC Support + # + MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf + MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf + MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + + # + # Usb Support + # + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # ISA Support + # + MdeModulePkg/Universal/SerialDxe/SerialDxe.inf +!if $(PS2_KEYBOARD_ENABLE) == TRUE + OvmfPkg/SioBusDxe/SioBusDxe.inf + MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf +!endif + + # + # Console Support + # + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +!if $(DISABLE_SERIAL_TERMINAL) == FALSE + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +!endif + UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf + + #------------------------------ + # Build the shell + #------------------------------ + +!if $(SHELL_TYPE) == BUILD_SHELL + + # + # Shell Lib + # +[LibraryClasses] + BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + !include NetworkPkg/NetworkLibs.dsc.inc + +[Components.X64] + ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf { + <PcdsFixedAtBuild> + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the dynamic command. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } + ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf { + <PcdsFixedAtBuild> + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the dynamic command. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } + ShellPkg/Application/Shell/Shell.inf { + <PcdsFixedAtBuild> + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the shell application itself only. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + + #------------------------------ + # Basic commands + #------------------------------ + + <LibraryClasses> + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + + #------------------------------ + # Networking commands + #------------------------------ + + <LibraryClasses> + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + + #------------------------------ + # Support libraries + #------------------------------ + + <LibraryClasses> + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + } + +!endif diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf new file mode 100644 index 00000000..715a6515 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -0,0 +1,301 @@ +## @file +# Bootloader Payload Package +# +# Provides drivers and definitions to create uefi payload for bootloaders. +# +# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +DEFINE FD_BASE = 0x00800000 +DEFINE FD_BLOCK_SIZE = 0x00001000 + +!if $(TARGET) == "NOOPT" +DEFINE FD_SIZE = 0x00850000 +DEFINE NUM_BLOCKS = 0x850 +!else + +DEFINE FD_SIZE = 0x00410000 +DEFINE NUM_BLOCKS = 0x410 +!endif + +################################################################################ +[FD.UefiPayload] +BaseAddress = $(FD_BASE) | gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase +Size = $(FD_SIZE) | gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize +ErasePolarity = 1 +BlockSize = $(FD_BLOCK_SIZE) +NumBlocks = $(NUM_BLOCKS) + +0x00000000|$(FD_SIZE) +FV = PLDFV + +################################################################################ +[FV.PLDFV] +BlockSize = $(FD_BLOCK_SIZE) +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +INF UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + +FILE FV_IMAGE = 4E35FD93-9C72-4c15-8C4B-E77F1DB2D793 { + SECTION FV_IMAGE = DXEFV +} + +################################################################################ + +[FV.DXEFV] +BlockSize = $(FD_BLOCK_SIZE) +FvForceRebase = FALSE +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +APRIORI DXE { + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf +} + +# +# DXE Phase modules +# +INF MdeModulePkg/Core/Dxe/DxeMain.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf +INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf + +INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +INF UefiCpuPkg/CpuDxe/CpuDxe.inf +INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Application/UiApp/UiApp.inf +INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf +INF MdeModulePkg/Universal/Metronome/Metronome.inf +INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf +INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf +INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + +INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf + +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf +# +# PCI Support +# +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf + +# +# ISA Support +# +INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf +!if $(PS2_KEYBOARD_ENABLE) == TRUE +INF OvmfPkg/SioBusDxe/SioBusDxe.inf +INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf +!endif + +# +# Console Support +# +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +!if $(DISABLE_SERIAL_TERMINAL) == FALSE +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +!endif +INF UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf + +# +# SCSI/ATA/IDE/DISK Support +# +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +INF MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf +INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf + +INF FatPkg/EnhancedFatDxe/Fat.inf + +# +# SD/eMMC Support +# +INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf +INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf +INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + +# +# Usb Support +# +INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf +INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf +INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf +INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf +INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + +# +# Shell +# +!if $(SHELL_TYPE) == BUILD_SHELL +INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf +INF ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf +INF ShellPkg/Application/Shell/Shell.inf +!endif + +!if $(SHELL_TYPE) == MIN_BIN +!if $(ARCH) == IA32 +INF RuleOverride = BINARY USE = IA32 ShellBinPkg/MinUefiShell/MinUefiShell.inf +!else +INF RuleOverride = BINARY USE = X64 ShellBinPkg/MinUefiShell/MinUefiShell.inf +!endif +!endif + +!if $(SHELL_TYPE) == UEFI_BIN +!if $(ARCH) == IA32 +INF RuleOverride = BINARY USE = IA32 ShellBinPkg/UefiShell/UefiShell.inf +!else +INF RuleOverride = BINARY USE = X64 ShellBinPkg/UefiShell/UefiShell.inf +!endif +!endif + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) { + PE32 PE32 Align=32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + } + +[Rule.Common.USER_DEFINED.CSM] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.bin + } + +[Rule.Common.SEC.RESET_VECTOR] + FILE RAW = $(NAMED_GUID) { + RAW RAW |.raw + } |