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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#112337): https://edk2.groups.io/g/devel/message/112337
Mute This Topic: https://groups.io/mt/103119570/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to