From: Benjamin Doron <benjamin.do...@9elements.com> Parse coreboot FMAP structures to find the memory region in SPI flash by the FMAP area name.
Cc: Guo Dong <guo.d...@intel.com> Cc: Ray Ni <ray...@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james...@intel.com> Cc: Gua Guo <gua....@intel.com> Signed-off-by: Benjamin Doron <benjamin.do...@9elements.com> --- UefiPayloadPkg/Include/Coreboot.h | 21 ++++ UefiPayloadPkg/Include/Library/FmapParserLib.h | 35 +++++++ UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.c | 104 ++++++++++++++++++++ UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.inf | 28 ++++++ UefiPayloadPkg/UefiPayloadPkg.dsc | 1 + 5 files changed, 189 insertions(+) diff --git a/UefiPayloadPkg/Include/Coreboot.h b/UefiPayloadPkg/Include/Coreboot.h index 2d454f7c893c..6c33dda9ef85 100644 --- a/UefiPayloadPkg/Include/Coreboot.h +++ b/UefiPayloadPkg/Include/Coreboot.h @@ -249,6 +249,27 @@ struct cb_cbmem_tab { UINT64 cbmem_tab; }; +#define CB_TAG_FMAP 0x0037 +#define FMAP_STRLEN 32 /* includes null-terminator */ +struct fmap_area { + UINT32 offset; /* offset relative to base */ + UINT32 size; /* size in bytes */ + UINT8 name[FMAP_STRLEN]; /* descriptive name */ + UINT16 flags; /* flags for this area */ +} __attribute__ ((packed)); + +struct fmap { + UINT8 signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */ + UINT8 ver_major; /* major version */ + UINT8 ver_minor; /* minor version */ + UINT64 base; /* address of the firmware binary */ + UINT32 size; /* size of firmware binary in bytes */ + UINT8 name[FMAP_STRLEN]; /* name of this firmware binary */ + UINT16 nareas; /* number of areas described by + fmap_areas[] below */ + struct fmap_area areas[]; +} __attribute__ ((packed)); + /* Helpful macros */ #define MEM_RANGE_COUNT(_rec) \ diff --git a/UefiPayloadPkg/Include/Library/FmapParserLib.h b/UefiPayloadPkg/Include/Library/FmapParserLib.h new file mode 100644 index 000000000000..f03b9b22a85b --- /dev/null +++ b/UefiPayloadPkg/Include/Library/FmapParserLib.h @@ -0,0 +1,35 @@ +/** @file + Contains helper functions for parsing FMAP. + + Copyright (c) 2023, 9elements GmbH.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi/UefiBaseType.h> +#include <Uefi/UefiMultiPhase.h> +#include <Pi/PiMultiPhase.h> + +#define FMAP_SIGNATURE "__FMAP__" +#define FMAP_VER_MAJOR 1 +#define FMAP_VER_MINOR 1 + +/** + Find a requested FMAP area's address and size. + + @param[in] FmapAreaName Name string of FMAP area to find + @param[out] FmapAreaAddress Pointer to return of FMAP area memory address + @param[out] FmapAreaSize Pointer to return of FMAP area size + + @retval EFI_SUCCESS Successfully found the FMAP area information. + @retval EFI_INVALID_PARAMETER Input arguments are invalid. + @retval EFI_NOT_FOUND Failed to find the FMAP area information. + +**/ +EFI_STATUS +EFIAPI +FmapLocateArea ( + IN CHAR8 *FmapAreaName, + IN OUT EFI_PHYSICAL_ADDRESS *FmapAreaAddress, + IN OUT UINT32 *FmapAreaSize + ); diff --git a/UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.c b/UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.c new file mode 100644 index 000000000000..1a181b7266f0 --- /dev/null +++ b/UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.c @@ -0,0 +1,104 @@ +/** @file + Contains helper functions for parsing FMAP. + + Copyright (c) 2023, 9elements GmbH.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> +#include <Library/BaseLib.h> +#include <Library/BlParseLib.h> +#include <Library/DebugLib.h> +#include <Library/FmapParserLib.h> +#include <Coreboot.h> + +/** + Find coreboot record with given Tag. + NOTE: This coreboot-specific function definition is absent + from the common BlParseLib header. + + @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 + ); + +/** + Find a requested FMAP area's address and size. + + @param[in] FmapAreaName Name string of FMAP area to find + @param[out] FmapAreaAddress Pointer to return of FMAP area memory address + @param[out] FmapAreaSize Pointer to return of FMAP area size + + @retval EFI_SUCCESS Successfully found the FMAP area information. + @retval EFI_INVALID_PARAMETER Input arguments are invalid. + @retval EFI_NOT_FOUND Failed to find the FMAP area information. + +**/ +EFI_STATUS +EFIAPI +FmapLocateArea ( + IN CHAR8 *FmapAreaName, + IN OUT EFI_PHYSICAL_ADDRESS *FmapAreaAddress, + IN OUT UINT32 *FmapAreaSize + ) +{ + struct cb_cbmem_ref *CbMemRef; + struct fmap *Fmap; + UINTN Index; + + // + // Perform basic validation + // + if ((FmapAreaName == NULL) || (FmapAreaAddress == NULL) || (FmapAreaSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // FMAP_STRLEN includes sizeof NULL-terminator, so this also too long + if (AsciiStrLen (FmapAreaName) >= FMAP_STRLEN) { + return EFI_INVALID_PARAMETER; + } + + // The coreboot table contains large structures as references + CbMemRef = FindCbTag (CB_TAG_FMAP); + if (CbMemRef == NULL) { + return EFI_NOT_FOUND; + } + + Fmap = (VOID *)(UINTN)CbMemRef->cbmem_addr; // Support PEI and DXE + if (Fmap == NULL) { + return EFI_NOT_FOUND; + } + + // + // Perform FMAP validation + // + if ((AsciiStrnCmp ((CHAR8 *)Fmap->signature, FMAP_SIGNATURE, 8) != 0) + || (Fmap->ver_major != FMAP_VER_MAJOR) || (Fmap->ver_minor != FMAP_VER_MINOR)) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < Fmap->nareas; Index++) { + if (AsciiStrCmp ((CHAR8 *)Fmap->areas[Index].name, FmapAreaName) == 0) { + DEBUG (( + DEBUG_INFO, + "FMAP: Found area \"%a\" at offset 0x%x (size 0x%0x)\n", + FmapAreaName, + Fmap->areas[Index].offset, + Fmap->areas[Index].size + )); + + *FmapAreaAddress = Fmap->base + Fmap->areas[Index].offset; + *FmapAreaSize = Fmap->areas[Index].size; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.inf b/UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.inf new file mode 100644 index 000000000000..8e64a67614d9 --- /dev/null +++ b/UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.inf @@ -0,0 +1,28 @@ +## @file +# Contains helper functions for parsing FMAP. +# +# Copyright (c) 2023, 9elements GmbH.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbFmapParserLib + FILE_GUID = 6B4EE7FA-413A-445A-91B2-E63F3106FDE3 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FmapParserLib + +[Sources] + CbFmapParserLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + BlParseLib + DebugLib diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 2dbd875f377a..35e2f85a2ba8 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -280,6 +280,7 @@ !if $(UNIVERSAL_PAYLOAD) == FALSE !if $(BOOTLOADER) == "COREBOOT" BlParseLib|UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf + FmapParserLib|UefiPayloadPkg/Library/CbFmapParserLib/CbFmapParserLib.inf !else BlParseLib|UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf !endif -- 2.43.0