diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
index 0637a828b33f..33e5fb8304e9 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
@@ -127,6 +127,7 @@ InitEmuNonVolatileVariableStore (
@retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted.
**/
+
EFI_STATUS
InitRealNonVolatileVariableStore (
OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index ceea5d1ff9ac..52b1f5e80c4b 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -52,6 +52,7 @@
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
[LibraryClasses]
MemoryAllocationLib
diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
index 8d52bb1fdacf..55c181b7e757 100644
--- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
+++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
@@ -112,6 +112,7 @@ PcRtcInit (
BOOLEAN Enabled;
BOOLEAN Pending;
+ DEBUG((DEBUG_INFO, "%a\n", __FUNCTION__));
//
// Acquire RTC Lock to make access to RTC atomic
//
@@ -148,6 +149,7 @@ PcRtcInit (
//
Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a: RTC not functional\n", __FUNCTION__));
//
// Set the variable with default value if the RTC is functioning incorrectly.
//
@@ -233,6 +235,7 @@ PcRtcInit (
//
Status = PcRtcSetTime (&Time, Global);
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a: failed to set RTC time\n", __FUNCTION__));
return EFI_DEVICE_ERROR;
}
@@ -272,8 +275,9 @@ PcRtcInit (
Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
if (EFI_ERROR (Status)) {
if (!EfiAtRuntime ()) {
- EfiReleaseLock (&Global->RtcLock);
+ EfiReleaseLock (&Global->RtcLock);
}
+ DEBUG((DEBUG_INFO, "%a: faield to update RTC\n", __FUNCTION__));
return EFI_DEVICE_ERROR;
}
@@ -293,6 +297,7 @@ PcRtcInit (
if (!EfiAtRuntime ()) {
EfiReleaseLock (&Global->RtcLock);
}
+ DEBUG((DEBUG_INFO, "%a: failed to set variable RTCALARM\n", __FUNCTION__));
return EFI_DEVICE_ERROR;
}
@@ -366,6 +371,7 @@ PcRtcGetTime (
//
Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a RTC did not update\n", __FUNCTION__));
if (!EfiAtRuntime ()) {
EfiReleaseLock (&Global->RtcLock);
}
@@ -407,6 +413,7 @@ PcRtcGetTime (
Status = RtcTimeFieldsValid (Time);
}
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a time fields invalid after convert to EFI\n", __FUNCTION__));
return EFI_DEVICE_ERROR;
}
@@ -458,6 +465,7 @@ PcRtcSetTime (
//
Status = RtcTimeFieldsValid (Time);
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a time fields invalid\n", __FUNCTION__));
return Status;
}
@@ -474,6 +482,7 @@ PcRtcSetTime (
//
Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a RTC did not update\n", __FUNCTION__));
if (!EfiAtRuntime ()) {
EfiReleaseLock (&Global->RtcLock);
}
@@ -507,6 +516,7 @@ PcRtcSetTime (
}
if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_INFO, "%a failed to set variables\n", __FUNCTION__));
if (!EfiAtRuntime ()) {
EfiReleaseLock (&Global->RtcLock);
}
@@ -988,6 +998,14 @@ RtcTimeFieldsValid (
Time->Nanosecond > 999999999 ||
(!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
((Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) != 0)) {
+ DEBUG ((DEBUG_INFO, "Year: %04x\n", Time->Year));
+ DEBUG ((DEBUG_INFO, "Month: %02x\n", Time->Month));
+ DEBUG ((DEBUG_INFO, "Hour: %02x\n", Time->Hour));
+ DEBUG ((DEBUG_INFO, "Minute: %02x\n", Time->Minute));
+ DEBUG ((DEBUG_INFO, "Second: %02x\n", Time->Second));
+ DEBUG ((DEBUG_INFO, "Nanosecond: %08x\n", Time->Nanosecond));
+ DEBUG ((DEBUG_INFO, "TimeZone: %d\n", Time->TimeZone));
+ DEBUG ((DEBUG_INFO, "Daylight: %02x\n", Time->Daylight));
return EFI_INVALID_PARAMETER;
}
diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
index ccda6331373b..aaee51b635c5 100644
--- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
+++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
@@ -128,12 +128,15 @@ InitializePcRtc (
EFI_STATUS Status;
EFI_EVENT Event;
+ DEBUG((DEBUG_INFO, "%a\n", __FUNCTION__));
+
EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK);
mModuleGlobal.CenturyRtcAddress = GetCenturyRtcAddress ();
Status = PcRtcInit (&mModuleGlobal);
ASSERT_EFI_ERROR (Status);
+ DEBUG((DEBUG_INFO, "%a: CreateEventEx1\n", __FUNCTION__));
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
@@ -144,6 +147,7 @@ InitializePcRtc (
);
ASSERT_EFI_ERROR (Status);
+ DEBUG((DEBUG_INFO, "%a: CreateEventEx2\n", __FUNCTION__));
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
@@ -158,7 +162,8 @@ InitializePcRtc (
gRT->SetTime = PcRtcEfiSetTime;
gRT->GetWakeupTime = PcRtcEfiGetWakeupTime;
gRT->SetWakeupTime = PcRtcEfiSetWakeupTime;
-
+
+ DEBUG((DEBUG_INFO, "%a: Install protocol interfaces\n", __FUNCTION__));
Status = gBS->InstallMultipleProtocolInterfaces (
&mHandle,
&gEfiRealTimeClockArchProtocolGuid,
diff --git a/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.c b/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.c
new file mode 100644
index 000000000000..67612dc1b8c2
--- /dev/null
+++ b/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.c
@@ -0,0 +1,231 @@
+/** @file AmdSpiStoreDxe.c
+
+ Copyright (c) 2020, 3mdeb Embedded Systems Consulting
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "AmdSpiDxe.h"
+
+STATIC EFI_EVENT mAmdSpiVirtualAddrChangeEvent;
+
+//
+// Global variable declarations
+//
+AMD_SPI_INSTANCE *mAMDSpiInstance;
+
+AMD_SPI_INSTANCE mAMDSpiInstanceTemplate = {
+ AMD_SPI_SIGNATURE, // Signature
+ NULL, // Handle ... NEED TO BE FILLED
+ {
+ 0, // MediaId ... NEED TO BE FILLED
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching;
+ 0, // BlockSize ... NEED TO BE FILLED
+ 4, // IoAlign
+ 0, // LastBlock ... NEED TO BE FILLED
+ 0, // LowestAlignedLba
+ 1, // LogicalBlocksPerPhysicalBlock
+ }, //Media;
+
+ {
+ FvbGetAttributes, // GetAttributes
+ FvbSetAttributes, // SetAttributes
+ FvbGetPhysicalAddress, // GetPhysicalAddress
+ FvbGetBlockSize, // GetBlockSize
+ FvbRead, // Read
+ FvbWrite, // Write
+ FvbEraseBlocks, // EraseBlocks
+ NULL, //ParentHandle
+ }, // FvbProtoccol;
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
+ }
+ },
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GUID ... NEED TO BE FILLED
+ },
+ 0, // Index
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+ } // DevicePath
+};
+
+STATIC
+EFI_STATUS
+AmdSpiCreateInstance (
+ IN UINTN NumberofBlocks,
+ IN UINTN BlockSize,
+ OUT AMD_SPI_INSTANCE** AMDSpiInstance
+ )
+{
+ EFI_STATUS Status;
+ AMD_SPI_INSTANCE* Instance;
+
+ ASSERT(AMDSpiInstance != NULL);
+
+ Instance = AllocateRuntimeCopyPool (sizeof(AMD_SPI_INSTANCE),&mAMDSpiInstanceTemplate);
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->Media.MediaId = 0;
+ Instance->Media.BlockSize = BlockSize;
+ Instance->Media.LastBlock = NumberofBlocks - 1;
+
+ CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
+ Instance->DevicePath.Index = (UINT8)0;
+
+ Status = AmdSpiFvbInitialize (Instance);
+ if (EFI_ERROR(Status)) {
+ FreePool (Instance);
+ return Status;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool (Instance);
+ return Status;
+ }
+
+ DEBUG((DEBUG_INFO, "%a: Created a new instance\n", __FUNCTION__));
+
+ *AMDSpiInstance = Instance;
+ return Status;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+BlAMDSpiVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ // Convert Fvb
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.EraseBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.GetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.GetBlockSize);
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.GetPhysicalAddress);
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.Read);
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.SetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mAMDSpiInstance->FvbProtocol.Write);
+
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+BlAmdSpiInitialise (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+
+ if (PcdGetBool (PcdEmuVariableNvModeEnable)) {
+ DEBUG ((DEBUG_WARN, "Variable emulation is active! Skipping driver init.\n"));
+ return EFI_SUCCESS;
+ }
+
+ Status = AmdSpiInitialize();
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"%a: Failed to initialize AmdSpi\n", __FUNCTION__));
+ PcdSetBoolS (PcdEmuVariableNvModeEnable, TRUE);
+ return Status;
+ }
+
+ mAMDSpiInstance = AllocateRuntimePool (sizeof(AMD_SPI_INSTANCE*));
+ if (!mAMDSpiInstance) {
+ DEBUG((EFI_D_ERROR, "%a: Out of resources\n", __FUNCTION__));
+ PcdSetBoolS (PcdEmuVariableNvModeEnable, TRUE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmdSpiCreateInstance (3, 0x10000, &mAMDSpiInstance);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "%a: Fail to create instance for AmdSpi\n",
+ __FUNCTION__));
+ PcdSetBoolS (PcdEmuVariableNvModeEnable, TRUE);
+ return Status;
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ BlAMDSpiVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mAmdSpiVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Mark the memory mapped store as MMIO memory
+ //
+ Status = gDS->GetMemorySpaceDescriptor (PcdGet32(PcdFlashNvStorageVariableBase), &GcdDescriptor);
+ if (EFI_ERROR (Status) || GcdDescriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {
+ DEBUG((EFI_D_INFO, "%a: No memory space descriptor for com buffer found\n",
+ __FUNCTION__));
+
+ //
+ // Add a new entry if not covered by existing mapping
+ //
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ PcdGet32(PcdFlashNvStorageVariableBase),
+ 4 * 0x10000,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Mark as runtime service
+ //
+ Status = gDS->SetMemorySpaceAttributes (
+ PcdGet32(PcdFlashNvStorageVariableBase),
+ 4 * 0x10000,
+ EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.h b/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.h
new file mode 100644
index 000000000000..09ca3ea359d2
--- /dev/null
+++ b/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.h
@@ -0,0 +1,118 @@
+/** @file AmdSpiDxe.h
+
+ Copyright (c) 2020, 9elements Agency GmbH
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __AMD_SPI_DXE_H__
+#define __AMD_SPI_DXE_H__
+
+
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define AMD_SPI_SIGNATURE SIGNATURE_32('A', 'S', 'P', 'I')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, AMD_SPI_INSTANCE, FvbProtocol, AMD_SPI_SIGNATURE)
+
+typedef struct _AMD_SPI_INSTANCE AMD_SPI_INSTANCE;
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ UINT8 Index;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NOR_FLASH_DEVICE_PATH;
+#pragma pack ()
+
+struct _AMD_SPI_INSTANCE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_MEDIA Media;
+
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+
+ NOR_FLASH_DEVICE_PATH DevicePath;
+};
+
+//
+// BlAmdSpiFvbDxe.c
+//
+
+EFI_STATUS
+EFIAPI
+AmdSpiFvbInitialize (
+ IN AMD_SPI_INSTANCE* Instance
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbRead(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbWrite(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ );
+
+
+#endif /* __AMD_SPI_DXE_H__ */
diff --git a/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.inf b/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.inf
new file mode 100644
index 000000000000..5a20877a0a30
--- /dev/null
+++ b/UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.inf
@@ -0,0 +1,65 @@
+#/** @file
+#
+# Component description file for SMMSTORE module
+#
+# Copyright (c) 2020, 9elements Agency GmbH
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiPayloadAmdSpiDxe
+ FILE_GUID = D419A03E-3543-4DE8-8AFD-D6AD124D1D61
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = BlAmdSpiInitialise
+
+[Sources.common]
+ AmdSpiDxe.h
+ AmdSpiDxe.c
+ AmdSpiFvbDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ IoLib
+ BaseLib
+ DebugLib
+ HobLib
+ AmdSpiLib
+ UefiLib
+ TimerLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+ DxeServicesTableLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+ gEfiAuthenticatedVariableGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid ## PRODUCES
+ gEfiDiskIoProtocolGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable
+
+[Depex]
+ gEfiCpuArchProtocolGuid
diff --git a/UefiPayloadPkg/AmdSpiDxe/AmdSpiFvbDxe.c b/UefiPayloadPkg/AmdSpiDxe/AmdSpiFvbDxe.c
new file mode 100644
index 000000000000..be9ffacce6d9
--- /dev/null
+++ b/UefiPayloadPkg/AmdSpiDxe/AmdSpiFvbDxe.c
@@ -0,0 +1,823 @@
+/*++ @file AmdSpiFvbDxe.c
+
+ Copyright (c) 2020, 9elements Agency GmbH
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ --*/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "AmdSpiDxe.h"
+
+STATIC EFI_EVENT mFvbVirtualAddrChangeEvent;
+STATIC UINTN mFlashNvStorageVariableBase;
+
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader - A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS - The firmware volume is consistent
+ @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN AMD_SPI_INSTANCE *Instance
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+ EFI_STATUS TempStatus;
+ UINTN BufferSize;
+ UINTN BufferSizeReqested;
+
+ BufferSizeReqested = sizeof(EFI_FIRMWARE_VOLUME_HEADER);
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)AllocatePool(BufferSizeReqested);
+ if (!FwVolHeader) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ BufferSize = BufferSizeReqested;
+ TempStatus = FvbRead (&Instance->FvbProtocol, 0, 0, &BufferSize, (UINT8 *)FwVolHeader);
+ if (EFI_ERROR (TempStatus) || BufferSizeReqested != BufferSize) {
+ FreePool (FwVolHeader);
+ return EFI_DEVICE_ERROR;
+ }
+
+ FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((EFI_D_INFO, "%a: No Firmware Volume header present\n", __FUNCTION__));
+ FreePool (FwVolHeader);
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((EFI_D_INFO, "%a: Firmware Volume Guid non-compatible\n", __FUNCTION__));
+ FreePool (FwVolHeader);
+ return EFI_NOT_FOUND;
+ }
+
+ BufferSizeReqested = FwVolHeader->HeaderLength;
+ FreePool (FwVolHeader);
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)AllocatePool(BufferSizeReqested);
+ if (!FwVolHeader) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ BufferSize = BufferSizeReqested;
+ TempStatus = FvbRead (&Instance->FvbProtocol, 0, 0, &BufferSize, (UINT8 *)FwVolHeader);
+ if (EFI_ERROR (TempStatus) || BufferSizeReqested != BufferSize) {
+ FreePool (FwVolHeader);
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((EFI_D_INFO, "%a: FV checksum is invalid (Checksum:0x%X)\n",
+ __FUNCTION__, Checksum));
+ FreePool (FwVolHeader);
+ return EFI_NOT_FOUND;
+ }
+
+ BufferSizeReqested = sizeof(VARIABLE_STORE_HEADER);
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)AllocatePool(BufferSizeReqested);
+ if (!VariableStoreHeader) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ BufferSize = BufferSizeReqested;
+ TempStatus = FvbRead (&Instance->FvbProtocol, 0, FwVolHeader->HeaderLength, &BufferSize, (UINT8 *)VariableStoreHeader);
+ if (EFI_ERROR (TempStatus) || BufferSizeReqested != BufferSize) {
+ FreePool (VariableStoreHeader);
+ FreePool (FwVolHeader);
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Check the Variable Store Guid
+ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
+ !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
+ DEBUG ((EFI_D_INFO, "%a: Variable Store Guid non-compatible\n",
+ __FUNCTION__));
+ FreePool (FwVolHeader);
+ FreePool (VariableStoreHeader);
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((EFI_D_INFO, "%a: Variable Store Length does not match\n",
+ __FUNCTION__));
+ FreePool (FwVolHeader);
+ FreePool (VariableStoreHeader);
+ return EFI_NOT_FOUND;
+ }
+
+ FreePool (FwVolHeader);
+ FreePool (VariableStoreHeader);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialise the headers
+
+**/
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN AMD_SPI_INSTANCE *Instance
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ EFI_STATUS Status;
+ VOID* Headers;
+ UINTN HeadersLength;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+
+ HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool(HeadersLength);
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase));
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase));
+
+ // Check if the size of the area is at least one block size
+ ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0);
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0);
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0);
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader,FirmwareVolumeHeader->HeaderLength);
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
+ VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the store
+ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+ FreePool (Headers);
+
+ return Status;
+}
+
+/**
+ The GetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
+ current settings are returned.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
+ AMD_SPI_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) (
+
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
+
+ );
+
+ // Check if it is write protected
+ if (Instance->Media.ReadOnly != TRUE) {
+
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The SetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
+ that contains the desired firmware volume settings.
+ On successful return, it contains the new settings of
+ the firmware volume.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
+ as declared in the firmware volume header.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attributes));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ ASSERT(Address != NULL);
+
+ *Address = mFlashNvStorageVariableBase;
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ EFI_STATUS Status;
+ AMD_SPI_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
+
+ if (Lba > Instance->Media.LastBlock) {
+ DEBUG ((EFI_D_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ *BlockSize = (UINTN) Instance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will be used
+ to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
+ in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ UINTN BlockSize;
+ AMD_SPI_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+
+ // The read must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize)) {
+ DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to read
+ if (*NumBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ return AmdSpiRead (Lba, Offset, NumBytes, Buffer);
+}
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
+
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+
+ UINTN BlockSize;
+ AMD_SPI_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbWrite(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ // The read must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize)) {
+ DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to write
+ if (*NumBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ return AmdSpiWrite (Lba, Offset, NumBytes, Buffer);
+}
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to erase.
+
+ The list is terminated with an EFI_LBA_LIST_TERMINATOR.
+ For example, the following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased:
+ EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request successfully completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
+ The firmware device may have been partially erased.
+
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
+ not exist in the firmware volume.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+
+ EFI_STATUS Status;
+ VA_LIST Args;
+ EFI_LBA StartingLba; // Lba from which we start erasing
+ UINTN NumOfLba; // Number of Lba blocks to erase
+ AMD_SPI_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ // Firmware volume is in WriteDisabled state
+ DEBUG ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
+
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ //Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINTN);
+
+ // All blocks must be within range
+ DEBUG ((
+ DEBUG_BLKIO,
+ "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
+ StartingLba,
+ (UINT64)NumOfLba,
+ Instance->Media.LastBlock
+ ));
+ if ((NumOfLba == 0) || ((StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
+ VA_END (Args);
+ DEBUG ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ } while (TRUE);
+ VA_END (Args);
+
+ //
+ // To get here, all must be ok, so start erasing
+ //
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINTN);
+
+ // Go through each one and erase it
+ while (NumOfLba > 0) {
+ // Erase it
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld\n", StartingLba));
+ Status = AmdSpiEraseBlock (StartingLba);
+ if (EFI_ERROR(Status)) {
+ VA_END (Args);
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Move to the next Lba
+ StartingLba++;
+ NumOfLba--;
+ }
+ } while (TRUE);
+ VA_END (Args);
+
+EXIT:
+ return Status;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+AmdSpiFvbInitialize (
+ IN AMD_SPI_INSTANCE* Instance
+ )
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
+ ASSERT((Instance != NULL));
+
+ mFlashNvStorageVariableBase = PcdGet32 (PcdFlashNvStorageVariableBase);
+
+ BootMode = GetBootModeHob ();
+ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // Determine if there is a valid header at the beginning of the NorFlash
+ Status = ValidateFvHeader (Instance);
+ }
+
+ // Install the Default FVB header if required
+ if (EFI_ERROR(Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((EFI_D_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
+ DEBUG ((EFI_D_INFO, "%a: Installing a correct one for this volume.\n",
+ __FUNCTION__));
+
+ // Erase all the NorFlash that is reserved for variable storage
+ FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
+
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // Install all appropriate headers
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_INFO, "%a: FVB header init failed\n", __FUNCTION__));
+ return Status;
+ }
+ } else {
+ DEBUG((DEBUG_INFO, "%a: FVB header is valid\n", __FUNCTION__));
+ }
+
+ //
+ // The driver implementing the variable read service can now be dispatched;
+ // the varstore headers are in place.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gImageHandle,
+ &gEdkiiNvVarStoreFormattedGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mFvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.c b/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.c
index 52b133670a35..b32c2bc4faf4 100644
--- a/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.c
+++ b/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.c
@@ -170,7 +170,8 @@ BlSMMSTOREInitialise (
//
// Find the SMMSTORE information guid hob
//
- GuidHob = GetFirstGuidHob (&gEfiSMMSTOREInfoHobGuid);
+ // GuidHob = GetFirstGuidHob (&gEfiSMMSTOREInfoHobGuid);
+ GuidHob = NULL;
if (GuidHob == NULL) {
DEBUG ((DEBUG_WARN, "SMMSTORE not supported! Skipping driver init.\n"));
PcdSetBoolS (PcdEmuVariableNvModeEnable, TRUE);
@@ -219,12 +220,12 @@ BlSMMSTOREInitialise (
}
// Update PCDs for Variable/RuntimeDxe
- PcdSet32S (PcdFlashNvStorageVariableBase,
- PcdGet32 (PcdFlashNvStorageVariableBase) + SMMStoreInfoHob->MmioAddress);
- PcdSet32S (PcdFlashNvStorageFtwWorkingBase,
- PcdGet32 (PcdFlashNvStorageFtwWorkingBase) + SMMStoreInfoHob->MmioAddress);
- PcdSet32S (PcdFlashNvStorageFtwSpareBase,
- PcdGet32 (PcdFlashNvStorageFtwSpareBase) + SMMStoreInfoHob->MmioAddress);
+ PcdSet32S(PcdFlashNvStorageVariableBase,
+ PcdGet32(PcdFlashNvStorageVariableBase) + SMMStoreInfoHob->MmioAddress);
+ PcdSet32S(PcdFlashNvStorageFtwWorkingBase,
+ PcdGet32(PcdFlashNvStorageFtwWorkingBase) + SMMStoreInfoHob->MmioAddress);
+ PcdSet32S(PcdFlashNvStorageFtwSpareBase,
+ PcdGet32(PcdFlashNvStorageFtwSpareBase) + SMMStoreInfoHob->MmioAddress);
mSMMStoreInstance = AllocateRuntimePool (sizeof(SMMSTORE_INSTANCE*));
if (!mSMMStoreInstance) {
diff --git a/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf b/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
index 49d5f1a3ff39..cf26a1a20cda 100644
--- a/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
+++ b/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
@@ -44,7 +44,7 @@
gEfiAuthenticatedVariableGuid
gEfiEventVirtualAddressChangeGuid
gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL
- gEfiSMMSTOREInfoHobGuid
+ # gEfiSMMSTOREInfoHobGuid
[Protocols]
gEfiBlockIoProtocolGuid
diff --git a/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreFvbDxe.c b/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreFvbDxe.c
index 9bfaafb72348..c15da69a7d3b 100644
--- a/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreFvbDxe.c
+++ b/UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreFvbDxe.c
@@ -49,6 +49,7 @@ InitializeFvAndVariableStoreHeaders (
IN SMMSTORE_INSTANCE *Instance
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
EFI_STATUS Status;
VOID* Headers;
UINTN HeadersLength;
@@ -129,6 +130,7 @@ ValidateFvHeader (
IN SMMSTORE_INSTANCE *Instance
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
UINT16 Checksum;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
VARIABLE_STORE_HEADER *VariableStoreHeader;
@@ -257,6 +259,7 @@ FvbGetAttributes(
OUT EFI_FVB_ATTRIBUTES_2 *Attributes
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
SMMSTORE_INSTANCE *Instance;
@@ -313,6 +316,7 @@ FvbSetAttributes(
IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attributes));
return EFI_UNSUPPORTED;
}
@@ -341,6 +345,7 @@ FvbGetPhysicalAddress (
OUT EFI_PHYSICAL_ADDRESS *Address
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
ASSERT(Address != NULL);
*Address = mFlashNvStorageVariableBase;
@@ -382,6 +387,7 @@ FvbGetBlockSize (
OUT UINTN *NumberOfBlocks
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
EFI_STATUS Status;
SMMSTORE_INSTANCE *Instance;
@@ -455,6 +461,7 @@ FvbRead (
IN OUT UINT8 *Buffer
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
UINTN BlockSize;
SMMSTORE_INSTANCE *Instance;
@@ -548,6 +555,7 @@ FvbWrite (
IN UINT8 *Buffer
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
UINTN BlockSize;
SMMSTORE_INSTANCE *Instance;
@@ -625,6 +633,7 @@ FvbEraseBlocks (
...
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
EFI_STATUS Status;
VA_LIST Args;
EFI_LBA StartingLba; // Lba from which we start erasing
@@ -731,6 +740,7 @@ FvbVirtualNotifyEvent (
IN VOID *Context
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
return;
}
@@ -741,6 +751,7 @@ SMMStoreFvbInitialize (
IN SMMSTORE_INSTANCE* Instance
)
{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
EFI_STATUS Status;
UINT32 FvbNumLba;
EFI_BOOT_MODE BootMode;
diff --git a/UefiPayloadPkg/BlSupportPei/BlSupportPei.c b/UefiPayloadPkg/BlSupportPei/BlSupportPei.c
index 4872870ef86d..c5693ffc4fcf 100644
--- a/UefiPayloadPkg/BlSupportPei/BlSupportPei.c
+++ b/UefiPayloadPkg/BlSupportPei/BlSupportPei.c
@@ -433,8 +433,8 @@ BlPeiEntryPoint (
SYSTEM_TABLE_INFO *NewSysTableInfo;
ACPI_BOARD_INFO AcpiBoardInfo;
ACPI_BOARD_INFO *NewAcpiBoardInfo;
- SMMSTORE_INFO SMMSTOREInfo;
- SMMSTORE_INFO *NewSMMSTOREInfo;
+ // SMMSTORE_INFO SMMSTOREInfo;
+ // SMMSTORE_INFO *NewSMMSTOREInfo;
EFI_PEI_GRAPHICS_INFO_HOB GfxInfo;
EFI_PEI_GRAPHICS_INFO_HOB *NewGfxInfo;
EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo;
@@ -588,13 +588,13 @@ BlPeiEntryPoint (
//
// Create guid hob for SMMSTORE
//
- Status = ParseSMMSTOREInfo (&SMMSTOREInfo);
- if (!EFI_ERROR (Status)) {
- NewSMMSTOREInfo = BuildGuidHob (&gEfiSMMSTOREInfoHobGuid, sizeof (SMMSTOREInfo));
- ASSERT (NewSMMSTOREInfo != NULL);
- CopyMem (NewSMMSTOREInfo, &SMMSTOREInfo, sizeof (SMMSTOREInfo));
- DEBUG ((DEBUG_INFO, "Created SMMSTORE info hob\n"));
- }
+ // Status = ParseSMMSTOREInfo (&SMMSTOREInfo);
+ // if (!EFI_ERROR (Status)) {
+ // NewSMMSTOREInfo = BuildGuidHob (&gEfiSMMSTOREInfoHobGuid, sizeof (SMMSTOREInfo));
+ // ASSERT (NewSMMSTOREInfo != NULL);
+ // CopyMem (NewSMMSTOREInfo, &SMMSTOREInfo, sizeof (SMMSTOREInfo));
+ // DEBUG ((DEBUG_INFO, "Created SMMSTORE info hob\n"));
+ // }
//
// Create guid hob for system tables like acpi table and smbios table
diff --git a/UefiPayloadPkg/BlSupportPei/BlSupportPei.h b/UefiPayloadPkg/BlSupportPei/BlSupportPei.h
index 705667627d7a..0100af216c98 100644
--- a/UefiPayloadPkg/BlSupportPei/BlSupportPei.h
+++ b/UefiPayloadPkg/BlSupportPei/BlSupportPei.h
@@ -28,7 +28,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include
#include
#include
-#include
+// #include
#include
#include
diff --git a/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf b/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
index 941c0f419bfa..90216e22f58e 100644
--- a/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
+++ b/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
@@ -56,7 +56,7 @@
gEfiGraphicsInfoHobGuid
gEfiGraphicsDeviceInfoHobGuid
gUefiAcpiBoardInfoGuid
- gEfiSMMSTOREInfoHobGuid
+ # gEfiSMMSTOREInfoHobGuid
[Ppis]
gEfiPeiMasterBootModePpiGuid
diff --git a/UefiPayloadPkg/Include/Guid/SMMSTOREInfoGuid.h b/UefiPayloadPkg/Include/Guid/SMMSTOREInfoGuid.h
index 552f86115b48..075eb14dbf33 100644
--- a/UefiPayloadPkg/Include/Guid/SMMSTOREInfoGuid.h
+++ b/UefiPayloadPkg/Include/Guid/SMMSTOREInfoGuid.h
@@ -12,7 +12,7 @@
///
/// System Table Information GUID
///
-extern EFI_GUID gEfiSMMSTOREInfoHobGuid;
+// extern EFI_GUID gEfiSMMSTOREInfoHobGuid;
typedef struct {
UINT64 ComBuffer;
diff --git a/UefiPayloadPkg/Include/Library/AmdSpiLib.h b/UefiPayloadPkg/Include/Library/AmdSpiLib.h
new file mode 100644
index 000000000000..010f3ec3cb10
--- /dev/null
+++ b/UefiPayloadPkg/Include/Library/AmdSpiLib.h
@@ -0,0 +1,88 @@
+/** @file AmdSpiLib.h
+
+ Copyright (c) 2020, 9elements Agency GmbH
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __AMD_SPI_LIB_H__
+#define __AMD_SPI_LIB_H__
+
+#include
+#include
+
+/**
+ Read from AMD SPI
+
+ @param[in] Lba The starting logical block index to read from.
+ @param[in] Offset Offset into the block at which to begin reading.
+ @param[in] NumBytes On input, indicates the requested read size. On
+ output, indicates the actual number of bytes read
+ @param[in] Buffer Pointer to the buffer to read into.
+
+**/
+EFI_STATUS
+AmdSpiRead (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+
+/**
+ Write to AMD SPI
+
+ @param[in] Lba The starting logical block index to write to.
+ @param[in] Offset Offset into the block at which to begin writing.
+ @param[in] NumBytes On input, indicates the requested write size. On
+ output, indicates the actual number of bytes written
+ @param[in] Buffer Pointer to the data to write.
+
+**/
+EFI_STATUS
+AmdSpiWrite (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+
+/**
+ Erase a block using the AMD SPI
+
+ @param Lba The logical block index to erase.
+
+**/
+EFI_STATUS
+AmdSpiEraseBlock (
+ IN EFI_LBA Lba
+ );
+
+
+/**
+ Notify the AMD SPI Library about a VirtualNotify
+
+**/
+
+VOID
+EFIAPI
+AmdSpiVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Initializes AMD SPI support
+ @retval EFI_WRITE_PROTECTED The AMD SPI is not present.
+ @retval EFI_SUCCESS The AMD SPI is supported.
+
+**/
+EFI_STATUS
+AmdSpiInitialize (
+ VOID
+ );
+
+#endif /* __AMD_SPI_LIB_H__ */
diff --git a/UefiPayloadPkg/Include/Library/BlParseLib.h b/UefiPayloadPkg/Include/Library/BlParseLib.h
index 542c714c555b..f705057f20da 100644
--- a/UefiPayloadPkg/Include/Library/BlParseLib.h
+++ b/UefiPayloadPkg/Include/Library/BlParseLib.h
@@ -12,7 +12,7 @@
#include
#include
#include
-#include
+//#include
#ifndef __BOOTLOADER_PARSE_LIB__
#define __BOOTLOADER_PARSE_LIB__
@@ -127,10 +127,10 @@ ParseGfxDeviceInfo (
@retval RETURN_NOT_FOUND Failed to find the SMM store buffer information .
**/
-RETURN_STATUS
-EFIAPI
-ParseSMMSTOREInfo (
- OUT SMMSTORE_INFO *SMMSTOREInfo
- );
+// RETURN_STATUS
+// EFIAPI
+// ParseSMMSTOREInfo (
+// OUT SMMSTORE_INFO *SMMSTOREInfo
+// );
#endif
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/Adesto.c b/UefiPayloadPkg/Library/AmdSpiLib/Adesto.c
new file mode 100644
index 000000000000..1711fe33e6c3
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/Adesto.c
@@ -0,0 +1,94 @@
+/*
+ * Driver for Adesto Technologies SPI flash
+ * based on Winbond.c
+ */
+
+
+#include "SPIFlashInternal.h"
+
+/* at25dfxx-specific commands */
+#define CMD_AT25DF_WREN 0x06 /* Write Enable */
+#define CMD_AT25DF_WRDI 0x04 /* Write Disable */
+#define CMD_AT25DF_RDSR 0x05 /* Read Status Register */
+#define CMD_AT25DF_WRSR 0x01 /* Write Status Register */
+#define CMD_AT25DF_READ 0x03 /* Read Data Bytes */
+#define CMD_AT25DF_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
+#define CMD_AT25DF_PP 0x02 /* Page Program */
+#define CMD_AT25DF_SE 0x20 /* Sector (4K) Erase */
+#define CMD_AT25DF_BE 0xd8 /* Block (64K) Erase */
+#define CMD_AT25DF_CE 0xc7 /* Chip Erase */
+#define CMD_AT25DF_DP 0xb9 /* Deep Power-down */
+#define CMD_AT25DF_RES 0xab /* Release from DP, and Read Signature */
+
+STATIC CONST struct spi_flash_part_id flash_table[] = {
+ {
+ /* AT25SL128A */
+ .id[0] = 0x4218,
+ .nr_sectors_shift = 12,
+ },
+ {
+ /* AT25DF081A Yes, 81A id < 81 */
+ .id[0] = 0x4501,
+ .nr_sectors_shift = 8,
+ },
+ {
+ /* AT25DF081 */
+ .id[0] = 0x4502,
+ .nr_sectors_shift = 8,
+ },
+ {
+ /* AT25DF161 */
+ .id[0] = 0x4602,
+ .nr_sectors_shift = 9,
+ },
+ {
+ /* AT25DL161 */
+ .id[0] = 0x4603,
+ .nr_sectors_shift = 9,
+ },
+ {
+ /* AT25DF321 */
+ .id[0] = 0x4700,
+ .nr_sectors_shift = 10,
+ },
+ {
+ /* AT25DF321A */
+ .id[0] = 0x4701,
+ .nr_sectors_shift = 10,
+ },
+ {
+ /* AT25DF641 */
+ .id[0] = 0x4800,
+ .nr_sectors_shift = 11,
+ },
+ {
+ /* AT25SF081 */
+ .id[0] = 0x8501,
+ .nr_sectors_shift = 8,
+ },
+ {
+ /* AT25DQ161 */
+ .id[0] = 0x8600,
+ .nr_sectors_shift = 9,
+ },
+ {
+ /* AT25SF161 */
+ .id[0] = 0x8601,
+ .nr_sectors_shift = 9,
+ },
+ {
+ /* AT25DQ321 */
+ .id[0] = 0x8700,
+ .nr_sectors_shift = 10,
+ },
+};
+
+CONST struct spi_flash_vendor_info spi_flash_adesto_vi = {
+ .id = VENDOR_ID_ADESTO,
+ .page_size_shift = 8,
+ .sector_size_kib_shift = 2,
+ .match_id_mask[0] = 0xffff,
+ .ids = flash_table,
+ .nr_part_ids = ARRAY_SIZE(flash_table),
+ .desc = &spi_flash_pp_0x20_sector_desc,
+};
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.c b/UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.c
new file mode 100644
index 000000000000..325f5c7e4c37
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.c
@@ -0,0 +1,83 @@
+#include
+#include
+#include
+#include "GenericSPI.h"
+#include "SPIFlashInternal.h"
+#include "Winbond.h"
+
+#define BLOCK_SIZE 0x10000
+#define VARIABLE_STORAGE_BLOCKS_OFFSET 6
+#define ADDRESS(Lba, Offset) (((BLOCK_SIZE) * ((Lba)+(VARIABLE_STORAGE_BLOCKS_OFFSET))) + (Offset))
+#define OFFSET_FROM_PAGE_START(Address) ((Address) % (PAGE_SIZE))
+#define REMAINING_SPACE(Offset, MaxSize) ((MaxSize) - (Offset))
+#define REMAINING_SPACE_IN_BLOCK(Offset) REMAINING_SPACE((Offset), (BLOCK_SIZE))
+#define REMAINING_SPACE_IN_PAGE(Offset) REMAINING_SPACE((Offset), (PAGE_SIZE))
+
+STATIC struct spi_flash flash;
+
+EFI_STATUS
+AmdSpiRead (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ UINTN address = ADDRESS(Lba, Offset);
+
+ if (address + *NumBytes > 0x90000 || address < 0x60000)
+ return EFI_ACCESS_DENIED;
+
+ if (*NumBytes == 0 || Buffer == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ return spi_flash_read(&flash, address, *NumBytes, Buffer);
+}
+
+EFI_STATUS
+AmdSpiWrite (
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ UINTN address = ADDRESS(Lba, Offset);
+
+ if (address + *NumBytes > 0x90000 || address < 0x60000)
+ return EFI_ACCESS_DENIED;
+
+ if (*NumBytes == 0 || Buffer == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ return spi_flash_write(&flash, address, *NumBytes, Buffer);
+}
+
+/**
+ Erase a block using the AMD SPI
+
+ @param Lba The logical block index to erase.
+
+**/
+EFI_STATUS
+AmdSpiEraseBlock (
+ IN EFI_LBA Lba
+ )
+{
+ UINTN address = ADDRESS(Lba, 0);
+
+ if (address > 0x90000 || address < 0x60000)
+ return EFI_ACCESS_DENIED;
+
+ return spi_flash_erase(&flash, address, BLOCK_SIZE);
+}
+
+EFI_STATUS
+AmdSpiInitialize (VOID)
+{
+ DEBUG((EFI_D_INFO, "%a\n", __FUNCTION__));
+
+ spi_init();
+
+ return spi_flash_probe(0, 0, &flash);
+}
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.inf b/UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.inf
new file mode 100644
index 000000000000..27d221cb8fb4
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.inf
@@ -0,0 +1,39 @@
+## @file
+# AMD SPI library
+#
+# Copyright (c) 2020 3mdeb Embedded Systems Consulting.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AmdSpi
+ FILE_GUID = c2c2e656-ee66-41e0-bee3-29c6f16f49c0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = AmdSpiLib
+
+[Sources]
+ Adesto.c
+ AmdSpiLib.c
+ FchSPICtrl.c
+ GenericSPI.c
+ GenericSPI.h
+ SPIFlashInternal.c
+ SPIFlashInternal.h
+ Winbond.c
+ Winbond.h
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ PciLib
+ TimerLib
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/FchSPICtrl.c b/UefiPayloadPkg/Library/AmdSpiLib/FchSPICtrl.c
new file mode 100644
index 000000000000..257afc2416e6
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/FchSPICtrl.c
@@ -0,0 +1,239 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include "GenericSPI.h"
+#include "SPIFlashInternal.h"
+
+#define GRANULARITY_TEST_4k 0x0000f000 /* bits 15-12 */
+#define WORD_TO_DWORD_UPPER(x) ((x << 16) & 0xffff0000)
+
+/* SPI MMIO registers */
+#define SPI_REG_OPCODE 0x00
+#define SPI_CNTRL0 0x00
+#define SPI_BUSY BIT31
+#define SPI_REG_CNTRL01 0x01
+#define SPI_REG_CNTRL02 0x02
+ #define CNTRL02_FIFO_RESET (1 << 4)
+ #define CNTRL02_EXEC_OPCODE (1 << 0)
+#define SPI_REG_CNTRL03 0x03
+ #define CNTRL03_SPIBUSY (1 << 7)
+#define SPI_RESTRICTED_CMD1 0x04
+#define SPI_RESTRICTED_CMD2 0x08
+#define SPI_REG_FIFO 0x0c
+#define SPI_REG_CNTRL11 0x0d
+ #define CNTRL11_FIFOPTR_MASK 0x07
+#define SPI_EXT_REG_INDX 0x1e
+#define SPI_EXT_REG_DATA 0x1f
+#define SPI_TX_BYTE_COUNT_IDX 0x05
+#define SPI_RX_BYTE_COUNT_IDX 0x06
+#define SPI_CMD_CODE 0x45
+#define SPI_CMD_TRIGGER 0x47
+#define SPI_CMD_TRIGGER_EXECUTE 0x80
+#define SPI_TX_BYTE_COUNT 0x48
+#define SPI_RX_BYTE_COUNT 0x4b
+#define SPI_STATUS 0x4c
+#define SPI_DONE_BYTE_COUNT_SHIFT 0
+#define SPI_DONE_BYTE_COUNT_MASK 0xff
+#define SPI_FIFO_WR_PTR_SHIFT 8
+#define SPI_FIFO_WR_PTR_MASK 0x7f
+#define SPI_FIFO_RD_PTR_SHIFT 16
+#define SPI_FIFO_RD_PTR_MASK 0x7f
+#define SPI_BUSY BIT31
+#define SPI_FIFO 0x80
+#define SPI_FIFO_LAST_BYTE 0xc7
+#define SPI_FIFO_DEPTH (SPI_FIFO_LAST_BYTE - SPI_FIFO)
+
+#define LPC_DEV 0x14
+#define LPC_FUNC 0x03
+
+#define SPIROM_BASE_ADDRESS_REGISTER 0xa0
+#define SPI_BASE_ALIGNMENT 0x00000040
+#define ALIGN_DOWN(x,a) ((x) & ~((typeof(x))(a)-1UL))
+
+STATIC UINTN spi_base = 0;
+
+STATIC UINTN lpc_get_spibase(VOID)
+{
+ UINT32 base;
+ base = PciRead32(
+ PCI_LIB_ADDRESS(0, LPC_DEV, LPC_FUNC, SPIROM_BASE_ADDRESS_REGISTER));
+ base = ALIGN_DOWN(base, SPI_BASE_ALIGNMENT);
+ return (UINTN)base;
+}
+
+STATIC VOID spi_set_base(UINTN base)
+{
+ spi_base = base;
+}
+
+STATIC UINTN spi_get_bar(VOID)
+{
+ if (spi_base == 0) {
+ spi_set_base(lpc_get_spibase());
+ }
+ return spi_base;
+}
+
+STATIC UINT8 spi_read8(UINT8 reg)
+{
+ return MmioRead8((spi_get_bar() + reg));
+}
+
+STATIC VOID spi_write8(UINT8 reg, UINT8 val)
+{
+ MmioWrite8((spi_get_bar() + reg), val);
+}
+
+STATIC VOID
+InternalDumpData (
+ IN UINT8 *Data,
+ IN UINTN Size
+ )
+{
+ UINTN Index;
+ for (Index = 0; Index < Size; Index++) {
+ DEBUG ((DEBUG_BLKIO, "%02x", (UINTN)Data[Index]));
+ }
+}
+
+STATIC VOID
+InternalDumpHex (
+ IN UINT8 *Data,
+ IN UINTN Size
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ UINTN Left;
+
+#define COLUME_SIZE (16 * 2)
+
+ Count = Size / COLUME_SIZE;
+ Left = Size % COLUME_SIZE;
+ for (Index = 0; Index < Count; Index++) {
+ DEBUG ((DEBUG_BLKIO, "%04x: ", Index * COLUME_SIZE));
+ InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
+ DEBUG ((DEBUG_BLKIO, "\n"));
+ }
+
+ if (Left != 0) {
+ DEBUG ((DEBUG_BLKIO, "%04x: ", Index * COLUME_SIZE));
+ InternalDumpData (Data + Index * COLUME_SIZE, Left);
+ DEBUG ((DEBUG_BLKIO, "\n"));
+ }
+}
+
+VOID spi_init(VOID)
+{
+ spi_get_bar();
+}
+
+STATIC VOID dump_state(UINT8 phase)
+{
+ UINT8 dump_size;
+ UINT32 addr;
+
+ if (phase == 0)
+ DEBUG ((DEBUG_BLKIO, "SPI: Before execute\n"));
+ else
+ DEBUG ((DEBUG_BLKIO, "SPI: After execute\n"));
+
+ DEBUG ((DEBUG_BLKIO, "Cntrl0: %08x\n", MmioRead32(spi_get_bar() + SPI_CNTRL0)));
+ DEBUG ((DEBUG_BLKIO, "Status: %08x\n", MmioRead32(spi_get_bar() + SPI_STATUS)));
+
+ addr = spi_get_bar() + SPI_FIFO;
+ if (phase == 0) {
+ dump_size = spi_read8(SPI_TX_BYTE_COUNT);
+ DEBUG ((DEBUG_BLKIO, "TxByteCount: %02x\n", dump_size));
+ DEBUG ((DEBUG_BLKIO, "CmdCode: %02x\n", spi_read8(SPI_CMD_CODE)));
+ } else {
+ dump_size = spi_read8(SPI_RX_BYTE_COUNT);
+ DEBUG ((DEBUG_BLKIO, "RxByteCount: %02x\n", dump_size));
+ addr += spi_read8(SPI_TX_BYTE_COUNT);
+ }
+
+ if (dump_size > 0)
+ InternalDumpHex((VOID *)addr, dump_size);
+}
+
+STATIC EFI_STATUS execute_command(void)
+{
+ dump_state(0);
+
+ spi_write8(SPI_REG_CNTRL02, spi_read8(SPI_REG_CNTRL02) | CNTRL02_EXEC_OPCODE);
+
+ while ((spi_read8(SPI_REG_CNTRL02) & CNTRL02_EXEC_OPCODE) ||
+ (spi_read8(SPI_REG_CNTRL03) & CNTRL03_SPIBUSY));
+
+ dump_state(1);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS spi_ctrlr_xfer(CONST struct spi_slave *slave, CONST VOID *dout,
+ __SIZE_TYPE__ bytesout, VOID *din, __SIZE_TYPE__ bytesin)
+{
+ __SIZE_TYPE__ count;
+ UINT8 cmd;
+ UINT8 *bufin = din;
+ CONST UINT8 *bufout = dout;
+
+ DEBUG((DEBUG_BLKIO, "%a(%x, %x)\n", __FUNCTION__, bytesout, bytesin));
+
+ /* First byte is cmd which cannot be sent through FIFO */
+ cmd = bufout[0];
+ bufout++;
+ bytesout--;
+
+ /*
+ * Check if this is a write command attempting to transfer more bytes
+ * than the controller can handle. Iterations for writes are not
+ * supported here because each SPI write command needs to be preceded
+ * and followed by other SPI commands.
+ */
+ if (bytesout + bytesin > SPI_FIFO_DEPTH) {
+ DEBUG((EFI_D_ERROR, "%a: FCH_SC: Too much to transfer, code error!\n", __FUNCTION__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ spi_write8(SPI_CMD_CODE, cmd);
+
+ spi_write8(SPI_TX_BYTE_COUNT, bytesout);
+ spi_write8(SPI_RX_BYTE_COUNT, bytesin);
+
+ for (count = 0; count < bytesout; count++)
+ spi_write8(SPI_FIFO + count, bufout[count]);
+
+ execute_command();
+
+ for (count = 0; count < bytesin; count++)
+ bufin[count] = spi_read8(SPI_FIFO + (count + bytesout) % SPI_FIFO_DEPTH);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS xfer_vectors(CONST struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count)
+{
+ return spi_flash_vector_helper(slave, vectors, count, spi_ctrlr_xfer);
+}
+
+CONST struct spi_ctrlr fch_spi_flash_ctrlr = {
+ .xfer = spi_ctrlr_xfer,
+ .xfer_vector = xfer_vectors,
+ .max_xfer_size = SPI_FIFO_DEPTH,
+ .flags = SPI_CNTRLR_DEDUCT_CMD_LEN | SPI_CNTRLR_DEDUCT_OPCODE_LEN,
+};
+
+CONST struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
+ {
+ .ctrlr = &fch_spi_flash_ctrlr,
+ .bus_start = 0,
+ .bus_end = 0,
+ },
+};
+
+CONST __SIZE_TYPE__ spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/GenericSPI.c b/UefiPayloadPkg/Library/AmdSpiLib/GenericSPI.c
new file mode 100644
index 000000000000..66f9bfbde983
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/GenericSPI.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include
+#include
+#include
+#include "GenericSPI.h"
+
+EFI_STATUS spi_claim_bus(CONST struct spi_slave *slave)
+{
+ CONST struct spi_ctrlr *ctrlr = slave->ctrlr;
+ if (ctrlr && ctrlr->claim_bus)
+ return ctrlr->claim_bus(slave);
+ return EFI_SUCCESS;
+}
+
+VOID spi_release_bus(CONST struct spi_slave *slave)
+{
+ CONST struct spi_ctrlr *ctrlr = slave->ctrlr;
+ if (ctrlr && ctrlr->release_bus)
+ ctrlr->release_bus(slave);
+}
+
+STATIC EFI_STATUS spi_xfer_single_op(CONST struct spi_slave *slave,
+ struct spi_op *op)
+{
+ CONST struct spi_ctrlr *ctrlr = slave->ctrlr;
+ EFI_STATUS status;
+
+ if (!ctrlr || !ctrlr->xfer)
+ return EFI_DEVICE_ERROR;
+
+ status = ctrlr->xfer(slave, op->dout, op->bytesout, op->din, op->bytesin);
+ if (status)
+ op->status = SPI_OP_FAILURE;
+ else
+ op->status = SPI_OP_SUCCESS;
+
+ return status;
+}
+
+STATIC EFI_STATUS spi_xfer_vector_default(CONST struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count)
+{
+ __SIZE_TYPE__ i;
+ EFI_STATUS status;
+
+ for (i = 0; i < count; i++) {
+ status = spi_xfer_single_op(slave, &vectors[i]);
+ if (status)
+ return status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS spi_xfer_vector(CONST struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count)
+{
+ CONST struct spi_ctrlr *ctrlr = slave->ctrlr;
+
+ if (ctrlr && ctrlr->xfer_vector)
+ return ctrlr->xfer_vector(slave, vectors, count);
+
+ return spi_xfer_vector_default(slave, vectors, count);
+}
+
+EFI_STATUS spi_xfer(CONST struct spi_slave *slave, CONST void *dout, __SIZE_TYPE__ bytesout,
+ VOID *din, __SIZE_TYPE__ bytesin)
+{
+ CONST struct spi_ctrlr *ctrlr = slave->ctrlr;
+
+ if (ctrlr && ctrlr->xfer) {
+ return ctrlr->xfer(slave, dout, bytesout, din, bytesin);
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+UINT32 spi_crop_chunk(CONST struct spi_slave *slave, UINT32 cmd_len,
+ UINT32 buf_len)
+{
+ CONST struct spi_ctrlr *ctrlr = slave->ctrlr;
+ UINT32 ctrlr_max;
+ BOOLEAN deduct_cmd_len;
+ BOOLEAN deduct_opcode_len;
+
+ if (!ctrlr)
+ return 0;
+
+ deduct_cmd_len = !!(ctrlr->flags & SPI_CNTRLR_DEDUCT_CMD_LEN);
+ deduct_opcode_len = !!(ctrlr->flags & SPI_CNTRLR_DEDUCT_OPCODE_LEN);
+ ctrlr_max = ctrlr->max_xfer_size;
+
+ /* Assume opcode is always one byte and deduct it from the cmd_len
+ as the hardware has a separate register for the opcode. */
+ if (deduct_opcode_len)
+ cmd_len--;
+
+ if (deduct_cmd_len && (ctrlr_max > cmd_len))
+ ctrlr_max -= cmd_len;
+
+ return MIN(ctrlr_max, buf_len);
+}
+
+EFI_STATUS spi_setup_slave(UINT32 bus, UINT32 cs, struct spi_slave *slave)
+{
+ __SIZE_TYPE__ i;
+
+ InternalMemZeroMem(slave, sizeof(*slave));
+
+ for (i = 0; i < spi_ctrlr_bus_map_count; i++) {
+ if ((spi_ctrlr_bus_map[i].bus_start <= bus) &&
+ (spi_ctrlr_bus_map[i].bus_end >= bus)) {
+ slave->ctrlr = spi_ctrlr_bus_map[i].ctrlr;
+ break;
+ }
+ }
+
+ if (slave->ctrlr == NULL)
+ return EFI_DEVICE_ERROR;
+
+ slave->bus = bus;
+ slave->cs = cs;
+
+ if (slave->ctrlr->setup)
+ return slave->ctrlr->setup(slave);
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/GenericSPI.h b/UefiPayloadPkg/Library/AmdSpiLib/GenericSPI.h
new file mode 100644
index 000000000000..7969f6b90f33
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/GenericSPI.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _SPI_GENERIC_H_
+#define _SPI_GENERIC_H_
+
+#include
+#include
+
+/* Common parameters -- kind of high, but they should only occur when there
+ * is a problem (and well your system already is broken), so err on the side
+ * of caution in case we're dealing with slower SPI buses and/or processors.
+ */
+#define SPI_FLASH_PROG_TIMEOUT_MS 200
+#define SPI_FLASH_PAGE_ERASE_TIMEOUT_MS 2000
+
+
+/* SPI vendor IDs */
+#define VENDOR_ID_ADESTO 0x1f
+#define VENDOR_ID_AMIC 0x37
+#define VENDOR_ID_ATMEL 0x1f
+#define VENDOR_ID_EON 0x1c
+#define VENDOR_ID_GIGADEVICE 0xc8
+#define VENDOR_ID_MACRONIX 0xc2
+#define VENDOR_ID_SPANSION 0x01
+#define VENDOR_ID_SST 0xbf
+#define VENDOR_ID_STMICRO 0x20
+#define VENDOR_ID_WINBOND 0xef
+
+/* Controller-specific definitions: */
+
+struct spi_ctrlr;
+
+struct region {
+ __SIZE_TYPE__ offset;
+ __SIZE_TYPE__ size;
+};
+
+/*-----------------------------------------------------------------------
+ * Representation of a SPI slave, i.e. what we're communicating with.
+ *
+ * bus: ID of the bus that the slave is attached to.
+ * cs: ID of the chip select connected to the slave.
+ * ctrlr: Pointer to SPI controller structure.
+ */
+struct spi_slave {
+ unsigned int bus;
+ unsigned int cs;
+ const struct spi_ctrlr *ctrlr;
+};
+
+/* Representation of SPI operation status. */
+enum spi_op_status {
+ SPI_OP_NOT_EXECUTED = 0,
+ SPI_OP_SUCCESS = 1,
+ SPI_OP_FAILURE = 2,
+};
+
+/*
+ * Representation of a SPI operation.
+ *
+ * dout: Pointer to data to send.
+ * bytesout: Count of data in bytes to send.
+ * din: Pointer to store received data.
+ * bytesin: Count of data in bytes to receive.
+ */
+struct spi_op {
+ const VOID *dout;
+ __SIZE_TYPE__ bytesout;
+ VOID *din;
+ __SIZE_TYPE__ bytesin;
+ enum spi_op_status status;
+};
+
+enum spi_clock_phase {
+ SPI_CLOCK_PHASE_FIRST,
+ SPI_CLOCK_PHASE_SECOND
+};
+
+enum spi_wire_mode {
+ SPI_4_WIRE_MODE,
+ SPI_3_WIRE_MODE
+};
+
+enum spi_polarity {
+ SPI_POLARITY_LOW,
+ SPI_POLARITY_HIGH
+};
+
+struct spi_cfg {
+ /* CLK phase - 0: Phase first, 1: Phase second */
+ enum spi_clock_phase clk_phase;
+ /* CLK polarity - 0: Low, 1: High */
+ enum spi_polarity clk_polarity;
+ /* CS polarity - 0: Low, 1: High */
+ enum spi_polarity cs_polarity;
+ /* Wire mode - 0: 4-wire, 1: 3-wire */
+ enum spi_wire_mode wire_mode;
+ /* Data bit length. */
+ unsigned int data_bit_length;
+};
+
+/*
+ * If there is no limit on the maximum transfer size for the controller,
+ * max_xfer_size can be set to SPI_CTRLR_DEFAULT_MAX_XFER_SIZE which is equal to
+ * UINT32_MAX.
+ */
+#define SPI_CTRLR_DEFAULT_MAX_XFER_SIZE (UINT32_MAX)
+
+struct spi_flash {
+ struct spi_slave spi;
+ UINT8 vendor;
+ union {
+ UINT8 raw;
+ struct {
+ UINT8 dual_spi : 1;
+ UINT8 _reserved : 7;
+ };
+ } flags;
+ UINT16 model;
+ UINT32 size;
+ UINT32 sector_size;
+ UINT32 page_size;
+ UINT8 erase_cmd;
+ UINT8 status_cmd;
+ UINT8 pp_cmd; /* Page program command. */
+ UINT8 wren_cmd; /* Write Enable command. */
+ const struct spi_flash_ops *ops;
+ /* If !NULL all protection callbacks exist. */
+ const struct spi_flash_part_id *part;
+};
+
+enum ctrlr_prot_type {
+ READ_PROTECT = 1,
+ WRITE_PROTECT = 2,
+ READ_WRITE_PROTECT = 3,
+};
+
+enum {
+ /* Deduct the command length from the spi_crop_chunk() calculation for
+ sizing a transaction. */
+ SPI_CNTRLR_DEDUCT_CMD_LEN = 1 << 0,
+ /* Remove the opcode size from the command length used in the
+ spi_crop_chunk() calculation. Controllers which have a dedicated
+ register for the command byte would set this flag which would
+ allow the use of the maximum transfer size. */
+ SPI_CNTRLR_DEDUCT_OPCODE_LEN = 1 << 1,
+};
+
+/*-----------------------------------------------------------------------
+ * Representation of a SPI controller. Note the xfer() and xfer_vector()
+ * callbacks are meant to process full duplex transactions. If the
+ * controller cannot handle these transactions then return an error when
+ * din and dout are both set. See spi_xfer() below for more details.
+ *
+ * claim_bus: Claim SPI bus and prepare for communication.
+ * release_bus: Release SPI bus.
+ * setup: Setup given SPI device bus.
+ * xfer: Perform one SPI transfer operation.
+ * xfer_vector: Vector of SPI transfer operations.
+ * xfer_dual: (optional) Perform one SPI transfer in Dual SPI mode.
+ * max_xfer_size: Maximum transfer size supported by the controller
+ * (0 = invalid,
+ * SPI_CTRLR_DEFAULT_MAX_XFER_SIZE = unlimited)
+ * flags: See SPI_CNTRLR_* enums above.
+ *
+ * Following member is provided by specialized SPI controllers that are
+ * actually SPI flash controllers.
+ *
+ * flash_probe: Specialized probe function provided by SPI flash
+ * controllers.
+ * flash_protect: Protect a region of flash using the SPI flash controller.
+ */
+struct spi_ctrlr {
+ EFI_STATUS (*claim_bus)(const struct spi_slave *slave);
+ VOID (*release_bus)(const struct spi_slave *slave);
+ EFI_STATUS (*setup)(const struct spi_slave *slave);
+ EFI_STATUS (*xfer)(const struct spi_slave *slave, const VOID *dout,
+ __SIZE_TYPE__ bytesout, VOID *din, __SIZE_TYPE__ bytesin);
+ EFI_STATUS (*xfer_vector)(const struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count);
+ EFI_STATUS (*xfer_dual)(const struct spi_slave *slave, const VOID *dout,
+ __SIZE_TYPE__ bytesout, VOID *din, __SIZE_TYPE__ bytesin);
+ UINT32 max_xfer_size;
+ UINT32 flags;
+ EFI_STATUS (*flash_probe)(const struct spi_slave *slave,
+ struct spi_flash *flash);
+};
+
+/*-----------------------------------------------------------------------
+ * Structure defining mapping of SPI buses to controller.
+ *
+ * ctrlr: Pointer to controller structure managing the given SPI buses.
+ * bus_start: Start bus number managed by the controller.
+ * bus_end: End bus number manager by the controller.
+ */
+struct spi_ctrlr_buses {
+ const struct spi_ctrlr *ctrlr;
+ UINT32 bus_start;
+ UINT32 bus_end;
+};
+
+/* Mapping of SPI buses to controllers - should be defined by platform. */
+extern const struct spi_ctrlr_buses spi_ctrlr_bus_map[];
+extern const __SIZE_TYPE__ spi_ctrlr_bus_map_count;
+
+/*-----------------------------------------------------------------------
+ * Initialization, must be called once on start up.
+ *
+ */
+__attribute__((__weak__))
+VOID spi_init(VOID);
+
+/*
+ * Get configuration of SPI bus.
+ *
+ * slave: Pointer to slave structure.
+ * cfg: Pointer to SPI configuration that needs to be filled.
+ *
+ * Returns:
+ * 0 on success, -1 on error
+ */
+EFI_STATUS spi_get_config(CONST struct spi_slave *slave, struct spi_cfg *cfg);
+
+/*-----------------------------------------------------------------------
+ * Set up communications parameters for a SPI slave.
+ *
+ * This must be called once for each slave. Note that this function
+ * usually doesn't touch any actual hardware, it only initializes the
+ * contents of spi_slave so that the hardware can be easily
+ * initialized later.
+ *
+ * bus: Bus ID of the slave chip.
+ * cs: Chip select ID of the slave chip on the specified bus.
+ * slave: Pointer to slave structure that needs to be initialized.
+ *
+ * Returns:
+ * 0 on success, -1 on error
+ */
+EFI_STATUS spi_setup_slave(UINT32 bus, UINT32 cs, struct spi_slave *slave);
+
+/*-----------------------------------------------------------------------
+ * Claim the bus and prepare it for communication with a given slave.
+ *
+ * This must be called before doing any transfers with a SPI slave. It
+ * will enable and initialize any SPI hardware as necessary, and make
+ * sure that the SCK line is in the correct idle state. It is not
+ * allowed to claim the same bus for several slaves without releasing
+ * the bus in between.
+ *
+ * slave: The SPI slave
+ *
+ * Returns: 0 if the bus was claimed successfully, or a negative value
+ * if it wasn't.
+ */
+EFI_STATUS spi_claim_bus(CONST struct spi_slave *slave);
+
+/*-----------------------------------------------------------------------
+ * Release the SPI bus
+ *
+ * This must be called once for every call to spi_claim_bus() after
+ * all transfers have finished. It may disable any SPI hardware as
+ * appropriate.
+ *
+ * slave: The SPI slave
+ */
+VOID spi_release_bus(CONST struct spi_slave *slave);
+
+/*-----------------------------------------------------------------------
+ * SPI transfer
+ *
+ * spi_xfer() interface:
+ * slave: The SPI slave which will be sending/receiving the data.
+ * dout: Pointer to a string of bytes to send out.
+ * bytesout: How many bytes to write.
+ * din: Pointer to a string of bytes that will be filled in.
+ * bytesin: How many bytes to read.
+ *
+ * Note that din and dout are transferred simultaneously in a full duplex
+ * transaction. The number of clocks within one transaction is calculated
+ * as: MAX(bytesout*8, bytesin*8).
+ *
+ * Returns: 0 on success, not 0 on failure
+ */
+EFI_STATUS spi_xfer(CONST struct spi_slave *slave, const VOID *dout, __SIZE_TYPE__ bytesout,
+ VOID *din, __SIZE_TYPE__ bytesin);
+
+/*-----------------------------------------------------------------------
+ * Vector of SPI transfer operations
+ *
+ * spi_xfer_vector() interface:
+ * slave: The SPI slave which will be sending/receiving the data.
+ * vectors: Array of SPI op structures.
+ * count: Number of SPI op vectors.
+ *
+ * Returns: 0 on success, not 0 on failure
+ */
+EFI_STATUS spi_xfer_vector(CONST struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count);
+
+/*-----------------------------------------------------------------------
+ * Given command length and length of remaining data, return the maximum data
+ * that can be transferred in next spi_xfer.
+ *
+ * Returns: 0 on error, non-zero data size that can be xfered on success.
+ */
+UINT32 spi_crop_chunk(CONST struct spi_slave *slave, UINT32 cmd_len,
+ UINT32 buf_len);
+
+/*-----------------------------------------------------------------------
+ * Write 8 bits, then read 8 bits.
+ * slave: The SPI slave we're communicating with
+ * byte: Byte to be written
+ *
+ * Returns: The value that was read, or a negative value on error.
+ *
+ * TODO: This function probably shouldn't be inlined.
+ */
+STATIC inline INT32 spi_w8r8(CONST struct spi_slave *slave, unsigned char byte)
+{
+ unsigned char dout[2];
+ unsigned char din[2];
+ UINT32 ret;
+
+ dout[0] = byte;
+ dout[1] = 0;
+
+ ret = (INT32)spi_xfer(slave, dout, 2, din, 2);
+ return ret < 0 ? ret : din[1];
+}
+
+#endif /* _SPI_GENERIC_H_ */
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/SPIFlashInternal.c b/UefiPayloadPkg/Library/AmdSpiLib/SPIFlashInternal.c
new file mode 100644
index 000000000000..22dca86e7b28
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/SPIFlashInternal.c
@@ -0,0 +1,468 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include
+#include
+#include
+#include
+#include "GenericSPI.h"
+#include "SPIFlashInternal.h"
+
+STATIC VOID spi_flash_addr(UINT32 addr, UINT8 *cmd)
+{
+ /* cmd[0] is actual command */
+ cmd[1] = addr >> 16;
+ cmd[2] = addr >> 8;
+ cmd[3] = addr >> 0;
+}
+
+STATIC EFI_STATUS do_spi_flash_cmd(CONST struct spi_slave *spi, CONST VOID *dout,
+ __SIZE_TYPE__ bytes_out, VOID *din, __SIZE_TYPE__ bytes_in)
+{
+ EFI_STATUS status;
+ /*
+ * SPI flash requires command-response kind of behavior. Thus, two
+ * separate SPI vectors are required -- first to transmit dout and other
+ * to receive in din. If some specialized SPI flash controllers
+ * (e.g. x86) can perform both command and response together, it should
+ * be handled at SPI flash controller driver level.
+ */
+ struct spi_op vectors[] = {
+ [0] = { .dout = dout, .bytesout = bytes_out,
+ .din = NULL, .bytesin = 0, },
+ [1] = { .dout = NULL, .bytesout = 0,
+ .din = din, .bytesin = bytes_in },
+ };
+ __SIZE_TYPE__ count = ARRAY_SIZE(vectors);
+ if (!bytes_in)
+ count = 1;
+
+ status = spi_claim_bus(spi);
+ if (EFI_ERROR(status))
+ return status;
+
+ status = spi_xfer_vector(spi, vectors, count);
+
+ spi_release_bus(spi);
+ return status;
+}
+
+EFI_STATUS spi_flash_cmd(CONST struct spi_slave *spi, UINT8 cmd, VOID *response, __SIZE_TYPE__ len)
+{
+ EFI_STATUS status = do_spi_flash_cmd(spi, &cmd, sizeof(cmd), response, len);
+ if (EFI_ERROR(status))
+ DEBUG((DEBUG_BLKIO, "%a SF: Failed to send command %02x: %d\n", __FUNCTION__, cmd, status));
+
+ return status;
+}
+
+/* TODO: This code is quite possibly broken and overflowing stacks. Fix ASAP! */
+#pragma GCC diagnostic push
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Wstack-usage="
+#endif
+#pragma GCC diagnostic ignored "-Wvla"
+EFI_STATUS spi_flash_cmd_write(CONST struct spi_slave *spi, CONST UINT8 *cmd,
+ __SIZE_TYPE__ cmd_len, CONST VOID *data, __SIZE_TYPE__ data_len)
+{
+ EFI_STATUS status;
+ UINT8 buff[cmd_len + data_len];
+ InternalMemCopyMem(buff, cmd, cmd_len);
+ InternalMemCopyMem(buff + cmd_len, data, data_len);
+
+ status = do_spi_flash_cmd(spi, buff, cmd_len + data_len, NULL, 0);
+ if (EFI_ERROR(status)) {
+ DEBUG((DEBUG_BLKIO, "%a SF: Failed to send write command (%zu bytes): %d\n",
+ __FUNCTION__, data_len, status));
+ }
+
+ return status;
+}
+#pragma GCC diagnostic pop
+
+/* Perform the read operation honoring spi controller fifo size, reissuing
+ * the read command until the full request completed. */
+EFI_STATUS spi_flash_cmd_read(CONST struct spi_flash *flash, UINT32 offset,
+ __SIZE_TYPE__ len, VOID *buf)
+{
+ UINT8 cmd[5];
+ EFI_STATUS status;
+ UINT8 cmd_len;
+
+ cmd_len = 4;
+ cmd[0] = CMD_READ_ARRAY_SLOW;
+
+ UINT8 *data = buf;
+ while (len) {
+ __SIZE_TYPE__ xfer_len = spi_crop_chunk(&flash->spi, cmd_len, len);
+ spi_flash_addr(offset, cmd);
+ status = do_spi_flash_cmd(&flash->spi, cmd, cmd_len, data, xfer_len);
+ if (EFI_ERROR(status)) {
+ DEBUG((DEBUG_BLKIO, "%a SF: Failed to send read command %#.2x(%#x, %#zx): %d\n",
+ __FUNCTION__, cmd[0], offset, xfer_len, status));
+ return status;
+ }
+ offset += xfer_len;
+ data += xfer_len;
+ len -= xfer_len;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS spi_flash_cmd_poll_bit(CONST struct spi_flash *flash, unsigned long timeout,
+ UINT8 cmd, UINT8 poll_bit)
+{
+ CONST struct spi_slave *spi = &flash->spi;
+ EFI_STATUS status = EFI_SUCCESS;
+ UINT8 spi_sr;
+
+ while (!EFI_ERROR(status)) {
+ status = do_spi_flash_cmd(spi, &cmd, 1, &spi_sr, 1);
+ if ((spi_sr & poll_bit) == 0)
+ return EFI_SUCCESS;
+
+ MicroSecondDelay(10);
+ } while (TRUE);
+
+ return status;
+}
+
+EFI_STATUS spi_flash_cmd_wait_ready(CONST struct spi_flash *flash,
+ unsigned long timeout)
+{
+ return spi_flash_cmd_poll_bit(flash, timeout,
+ CMD_READ_STATUS, STATUS_WIP);
+}
+
+EFI_STATUS spi_flash_cmd_erase(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len)
+{
+ UINT32 start, end, erase_size;
+ EFI_STATUS status = EFI_DEVICE_ERROR;
+ UINT8 cmd[4];
+
+ erase_size = flash->sector_size;
+ if (offset % erase_size || len % erase_size) {
+ DEBUG((DEBUG_BLKIO, "%a SF: Erase offset/length not multiple of erase size\n", __FUNCTION__));
+ return EFI_DEVICE_ERROR;
+ }
+ if (len == 0) {
+ DEBUG((DEBUG_BLKIO, "%a SF: Erase length cannot be 0\n", __FUNCTION__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ cmd[0] = flash->erase_cmd;
+ start = offset;
+ end = start + len;
+
+ while (offset < end) {
+ spi_flash_addr(offset, cmd);
+ offset += erase_size;
+
+ DEBUG((DEBUG_BLKIO, "%a SF: erase %2x %2x %2x %2x (%x)\n", __FUNCTION__,
+ cmd[0], cmd[1], cmd[2], cmd[3], offset));
+
+ status = spi_flash_cmd(&flash->spi, CMD_WRITE_ENABLE, NULL, 0);
+ if (EFI_ERROR(status))
+ goto out;
+
+ status = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd), NULL, 0);
+ if (EFI_ERROR(status))
+ goto out;
+
+ status = spi_flash_cmd_wait_ready(flash,
+ SPI_FLASH_PAGE_ERASE_TIMEOUT_MS);
+ if (EFI_ERROR(status))
+ goto out;
+ }
+
+ DEBUG((DEBUG_BLKIO, "%a SF: Successfully erased %u bytes @ %x\n",
+ __FUNCTION__, len, start));
+
+out:
+ return status;
+}
+
+EFI_STATUS spi_flash_cmd_status(CONST struct spi_flash *flash, UINT8 *reg)
+{
+ return spi_flash_cmd(&flash->spi, flash->status_cmd, reg, sizeof(*reg));
+}
+
+EFI_STATUS spi_flash_cmd_write_page_program(CONST struct spi_flash *flash, UINT32 offset,
+ __SIZE_TYPE__ len, CONST VOID *buf)
+{
+ unsigned long byte_addr;
+ unsigned long page_size;
+ __SIZE_TYPE__ chunk_len;
+ __SIZE_TYPE__ actual;
+ EFI_STATUS status = EFI_SUCCESS;
+ UINT8 cmd[4];
+
+ page_size = flash->page_size;
+ cmd[0] = flash->pp_cmd;
+
+ for (actual = 0; actual < len; actual += chunk_len) {
+ byte_addr = offset % page_size;
+ chunk_len = MIN(len - actual, page_size - byte_addr);
+ chunk_len = spi_crop_chunk(&flash->spi, sizeof(cmd), chunk_len);
+
+ spi_flash_addr(offset, cmd);
+ DEBUG((DEBUG_BLKIO, "%a PP: %x => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %u\n",
+ __FUNCTION__, buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len));
+
+ status = spi_flash_cmd(&flash->spi, flash->wren_cmd, NULL, 0);
+ if (EFI_ERROR(status)) {
+ DEBUG((DEBUG_BLKIO, "%a SF: Enabling Write failed\n", __FUNCTION__));
+ goto out;
+ }
+
+ status = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
+ buf + actual, chunk_len);
+ if (EFI_ERROR(status)) {
+ DEBUG((DEBUG_BLKIO, "%a SF: Page Program failed\n", __FUNCTION__));
+ goto out;
+ }
+
+ status = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT_MS);
+ if (EFI_ERROR(status))
+ goto out;
+
+ offset += chunk_len;
+ }
+ status = EFI_SUCCESS;
+
+out:
+ return status;
+}
+
+EFI_STATUS spi_flash_read(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len, VOID *buf)
+{
+ return flash->ops->read(flash, offset, len, buf);
+}
+
+EFI_STATUS spi_flash_write(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len, CONST VOID *buf)
+{
+ return flash->ops->write(flash, offset, len, buf);
+}
+
+EFI_STATUS spi_flash_erase(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len)
+{
+ return flash->ops->erase(flash, offset, len);
+}
+
+EFI_STATUS spi_flash_status(CONST struct spi_flash *flash, UINT8 *reg)
+{
+ if (flash->ops->status)
+ return flash->ops->status(flash, reg);
+
+ return EFI_DEVICE_ERROR;
+}
+
+EFI_STATUS spi_flash_vector_helper(CONST struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count,
+ EFI_STATUS (*func)(CONST struct spi_slave *slave, CONST VOID *dout,
+ __SIZE_TYPE__ bytesout, VOID *din, __SIZE_TYPE__ bytesin))
+{
+ EFI_STATUS status;
+ VOID *din;
+ __SIZE_TYPE__ bytes_in;
+
+ if (count < 1 || count > 2)
+ return -1;
+
+ /* SPI flash commands always have a command first... */
+ if (!vectors[0].dout || !vectors[0].bytesout)
+ return EFI_DEVICE_ERROR;
+ /* And not read any data during the command. */
+ if (vectors[0].din || vectors[0].bytesin)
+ return EFI_DEVICE_ERROR;
+
+ if (count == 2) {
+ /* If response bytes requested ensure the buffer is valid. */
+ if (vectors[1].bytesin && !vectors[1].din)
+ return EFI_DEVICE_ERROR;
+ /* No sends can accompany a receive. */
+ if (vectors[1].dout || vectors[1].bytesout)
+ return EFI_DEVICE_ERROR;
+ din = vectors[1].din;
+ bytes_in = vectors[1].bytesin;
+ } else {
+ din = NULL;
+ bytes_in = 0;
+ }
+
+ status = func(slave, vectors[0].dout, vectors[0].bytesout, din, bytes_in);
+
+ if (EFI_ERROR(status)) {
+ vectors[0].status = SPI_OP_FAILURE;
+ if (count == 2)
+ vectors[1].status = SPI_OP_FAILURE;
+ } else {
+ vectors[0].status = SPI_OP_SUCCESS;
+ if (count == 2)
+ vectors[1].status = SPI_OP_SUCCESS;
+ }
+
+ return status;
+}
+
+STATIC CONST struct spi_flash_vendor_info *spi_flash_vendors[] = {
+ &spi_flash_adesto_vi,
+ &spi_flash_winbond_vi,
+};
+
+#define IDCODE_LEN 5
+
+STATIC CONST struct spi_flash_part_id *find_part(CONST struct spi_flash_vendor_info *vi,
+ UINT16 id[2])
+{
+ __SIZE_TYPE__ i;
+ CONST UINT16 lid[2] = {
+ [0] = id[0] & vi->match_id_mask[0],
+ [1] = id[1] & vi->match_id_mask[1],
+ };
+
+ for (i = 0; i < vi->nr_part_ids; i++) {
+ CONST struct spi_flash_part_id *part = &vi->ids[i];
+
+ if (part->id[0] == lid[0] && part->id[1] == lid[1])
+ return part;
+ }
+
+ return NULL;
+}
+
+STATIC EFI_STATUS fill_spi_flash(const struct spi_slave *spi, struct spi_flash *flash,
+ CONST struct spi_flash_vendor_info *vi,
+ CONST struct spi_flash_part_id *part)
+{
+ InternalMemCopyMem(&flash->spi, spi, sizeof(*spi));
+ flash->vendor = vi->id;
+ flash->model = part->id[0];
+
+ flash->page_size = 1U << vi->page_size_shift;
+ flash->sector_size = (1U << vi->sector_size_kib_shift) * (1<<10); /* KiB */
+ flash->size = flash->sector_size * (1U << part->nr_sectors_shift);
+ flash->erase_cmd = vi->desc->erase_cmd;
+ flash->status_cmd = vi->desc->status_cmd;
+ flash->pp_cmd = vi->desc->pp_cmd;
+ flash->wren_cmd = vi->desc->wren_cmd;
+
+ flash->flags.dual_spi = part->fast_read_dual_output_support;
+
+ flash->ops = &vi->desc->ops;
+ flash->part = part;
+
+ if (vi->after_probe)
+ return vi->after_probe(flash);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS find_match(CONST struct spi_slave *spi, struct spi_flash *flash,
+ UINT8 manuf_id, UINT16 id[2])
+{
+ UINTN i;
+
+ for (i = 0; i < (UINTN)ARRAY_SIZE(spi_flash_vendors); i++) {
+ CONST struct spi_flash_vendor_info *vi;
+ CONST struct spi_flash_part_id *part;
+
+ vi = spi_flash_vendors[i];
+
+ if (manuf_id != vi->id)
+ continue;
+
+ part = find_part(vi, id);
+
+ if (part == NULL)
+ continue;
+
+ return fill_spi_flash(spi, flash, vi, part);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+STATIC EFI_STATUS spi_flash_generic_probe(CONST struct spi_slave *spi,
+ struct spi_flash *flash)
+{
+ EFI_STATUS status;
+ UINT8 idcode[IDCODE_LEN];
+ UINT8 manuf_id;
+ UINT16 id[2];
+
+ /* Read the ID codes */
+ status = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
+ if (EFI_ERROR(status))
+ return EFI_DEVICE_ERROR;
+
+ manuf_id = idcode[0];
+
+ DEBUG((DEBUG_BLKIO, "%a Manufacturer: %02x\n", __FUNCTION__, manuf_id));
+
+ id[0] = (idcode[1] << 8) | idcode[2];
+ id[1] = (idcode[3] << 8) | idcode[4];
+
+ return find_match(spi, flash, manuf_id, id);
+}
+
+EFI_STATUS spi_flash_probe(UINT32 bus, UINT32 cs, struct spi_flash *flash)
+{
+ struct spi_slave spi;
+ EFI_STATUS status = EFI_DEVICE_ERROR;
+
+ if (spi_setup_slave(bus, cs, &spi)) {
+ DEBUG((DEBUG_BLKIO, "SF: Failed to set up slave\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ /* Try special programmer probe if any. */
+ if (spi.ctrlr->flash_probe)
+ status = spi.ctrlr->flash_probe(&spi, flash);
+
+ /* If flash is not found, try generic spi flash probe. */
+ if (EFI_ERROR(status))
+ status = spi_flash_generic_probe(&spi, flash);
+
+ /* Give up -- nothing more to try if flash is not found. */
+ if (EFI_ERROR(status)) {
+ DEBUG((DEBUG_BLKIO, "SF: Unsupported manufacturer!\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CONST char *mode_string = "";
+ if (flash->flags.dual_spi && spi.ctrlr->xfer_dual)
+ mode_string = " (Dual SPI mode)";
+
+ DEBUG((DEBUG_BLKIO,
+ "SF: Detected %02x %04x with sector size 0x%x, total 0x%x%s\n",
+ flash->vendor, flash->model, flash->sector_size, flash->size, mode_string));
+
+ return EFI_SUCCESS;
+}
+
+CONST struct spi_flash_ops_descriptor spi_flash_pp_0x20_sector_desc = {
+ .erase_cmd = 0x20, /* Sector Erase */
+ .status_cmd = 0x05, /* Read Status */
+ .pp_cmd = 0x02, /* Page Program */
+ .wren_cmd = 0x06, /* Write Enable */
+ .ops = {
+ .read = spi_flash_cmd_read,
+ .write = spi_flash_cmd_write_page_program,
+ .erase = spi_flash_cmd_erase,
+ .status = spi_flash_cmd_status,
+ },
+};
+
+CONST struct spi_flash_ops_descriptor spi_flash_pp_0xd8_sector_desc = {
+ .erase_cmd = 0xd8, /* Sector Erase */
+ .status_cmd = 0x05, /* Read Status */
+ .pp_cmd = 0x02, /* Page Program */
+ .wren_cmd = 0x06, /* Write Enable */
+ .ops = {
+ .read = spi_flash_cmd_read,
+ .write = spi_flash_cmd_write_page_program,
+ .erase = spi_flash_cmd_erase,
+ .status = spi_flash_cmd_status,
+ },
+};
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/SPIFlashInternal.h b/UefiPayloadPkg/Library/AmdSpiLib/SPIFlashInternal.h
new file mode 100644
index 000000000000..7a566cf9c1f4
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/SPIFlashInternal.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * SPI flash internal definitions
+ */
+
+#ifndef __SPI_FLASH_INTERNAL_H__
+#define __SPI_FLASH_INTERNAL_H__
+
+#include
+#include
+#include "GenericSPI.h"
+
+
+/* Common commands */
+#define CMD_READ_ID 0x9f
+
+#define CMD_READ_ARRAY_SLOW 0x03
+#define CMD_READ_ARRAY_FAST 0x0b
+#define CMD_READ_ARRAY_LEGACY 0xe8
+#define CMD_READ_FAST_DUAL_OUTPUT 0x3b
+#define CMD_READ_STATUS 0x05
+#define CMD_WRITE_ENABLE 0x06
+#define CMD_BLOCK_ERASE 0xD8
+
+/* Common status */
+#define STATUS_WIP 0x01
+
+/*
+ * Representation of SPI flash operations:
+ * read: Flash read operation.
+ * write: Flash write operation.
+ * erase: Flash erase operation.
+ * status: Read flash status register.
+ */
+struct spi_flash_ops {
+ EFI_STATUS (*read)(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len,
+ VOID *buf);
+ EFI_STATUS (*write)(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len,
+ CONST VOID *buf);
+ EFI_STATUS (*erase)(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len);
+ EFI_STATUS (*status)(CONST struct spi_flash *flash, UINT8 *reg);
+};
+
+enum optype {
+ READ_NO_ADDR = 0,
+ WRITE_NO_ADDR = 1,
+ READ_WITH_ADDR = 2,
+ WRITE_WITH_ADDR = 3
+};
+
+/* Send a single-byte command to the device and read the response */
+EFI_STATUS spi_flash_cmd(CONST struct spi_slave *spi, UINT8 cmd, VOID *response, __SIZE_TYPE__ len);
+
+/*
+ * Send a multi-byte command to the device followed by (optional)
+ * data. Used for programming the flash array, etc.
+ */
+EFI_STATUS spi_flash_cmd_write(CONST struct spi_slave *spi, CONST UINT8 *cmd,
+ __SIZE_TYPE__ cmd_len, CONST VOID *data, __SIZE_TYPE__ data_len);
+
+/* Send a command to the device and wait for some bit to clear itself. */
+EFI_STATUS spi_flash_cmd_poll_bit(CONST struct spi_flash *flash, unsigned long timeout,
+ UINT8 cmd, UINT8 poll_bit);
+
+/*
+ * Send the read status command to the device and wait for the wip
+ * (write-in-progress) bit to clear itself.
+ */
+EFI_STATUS spi_flash_cmd_wait_ready(CONST struct spi_flash *flash, unsigned long timeout);
+
+/* Erase sectors. */
+EFI_STATUS spi_flash_cmd_erase(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len);
+
+/* Read status register. */
+EFI_STATUS spi_flash_cmd_status(CONST struct spi_flash *flash, UINT8 *reg);
+
+/* Write to flash utilizing page program semantics. */
+EFI_STATUS spi_flash_cmd_write_page_program(CONST struct spi_flash *flash, UINT32 offset,
+ __SIZE_TYPE__ len, CONST VOID *buf);
+
+/* Read len bytes into buf at offset. */
+EFI_STATUS spi_flash_cmd_read(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len, VOID *buf);
+
+EFI_STATUS spi_flash_vector_helper(CONST struct spi_slave *slave,
+ struct spi_op vectors[], __SIZE_TYPE__ count,
+ EFI_STATUS (*func)(CONST struct spi_slave *slave, CONST VOID *dout,
+ __SIZE_TYPE__ bytesout, VOID *din, __SIZE_TYPE__ bytesin));
+
+EFI_STATUS spi_flash_probe(UINT32 bus, UINT32 cs, struct spi_flash *flash);
+
+EFI_STATUS spi_flash_read(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len, VOID *buf);
+EFI_STATUS spi_flash_write(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len, CONST VOID *buf);
+EFI_STATUS spi_flash_erase(CONST struct spi_flash *flash, UINT32 offset, __SIZE_TYPE__ len);
+EFI_STATUS spi_flash_status(CONST struct spi_flash *flash, UINT8 *reg);
+
+struct spi_flash_part_id {
+ /* rdid command CONSTructs 2x 16-bit id using the following method
+ * for matching after reading 5 bytes (1st byte is manuf id):
+ * id[0] = (id[1] << 8) | id[2]
+ * id[1] = (id[3] << 8) | id[4]
+ */
+ UINT16 id[2];
+ /* Log based 2 total number of sectors. */
+ UINT16 nr_sectors_shift: 4;
+ UINT16 fast_read_dual_output_support : 1;
+ UINT16 _reserved_for_flags: 3;
+ /* Block protection. Currently used by Winbond. */
+ UINT16 protection_granularity_shift : 5;
+ UINT16 bp_bits : 3;
+};
+
+struct spi_flash_ops_descriptor {
+ UINT8 erase_cmd; /* Sector Erase */
+ UINT8 status_cmd; /* Read Status Register */
+ UINT8 pp_cmd; /* Page program command, if supported. */
+ UINT8 wren_cmd; /* Write Enable command. */
+ struct spi_flash_ops ops;
+};
+
+/* Vendor info represents a common set of organization and commands by a given
+ * vendor. One can implement multiple sets from a single vendor by having
+ * separate objects. */
+struct spi_flash_vendor_info {
+ UINT8 id;
+ UINT8 page_size_shift : 4; /* if page programming oriented. */
+ /* Log based 2 sector size */
+ UINT8 sector_size_kib_shift : 4;
+ UINT16 nr_part_ids;
+ CONST struct spi_flash_part_id *ids;
+ UINT16 match_id_mask[2]; /* matching bytes of the id for this set*/
+ CONST struct spi_flash_ops_descriptor *desc;
+ /* Returns 0 on success. !0 otherwise. */
+ int (*after_probe)(CONST struct spi_flash *flash);
+};
+
+union pci_bank {
+ UINT8 reg8[4096];
+ UINT16 reg16[4096 / sizeof(UINT16)];
+ UINT32 reg32[4096 / sizeof(UINT32)];
+};
+
+VOID spi_init(VOID);
+
+/* Manufacturer-specific probe information */
+extern CONST struct spi_flash_vendor_info spi_flash_adesto_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_amic_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_atmel_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_eon_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_gigadevice_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_macronix_vi;
+/* Probing order matters between the spansion sequence. */
+extern CONST struct spi_flash_vendor_info spi_flash_spansion_ext1_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_spansion_ext2_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_spansion_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_sst_ai_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_sst_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_stmicro1_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_stmicro2_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_stmicro3_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_stmicro4_vi;
+extern CONST struct spi_flash_vendor_info spi_flash_winbond_vi;
+
+/* Page Programming Command Set with 0x20 Sector Erase command. */
+extern CONST struct spi_flash_ops_descriptor spi_flash_pp_0x20_sector_desc;
+/* Page Programming Command Set with 0xd8 Sector Erase command. */
+extern CONST struct spi_flash_ops_descriptor spi_flash_pp_0xd8_sector_desc;
+
+#endif /* __SPI_FLASH_INTERNAL_H__ */
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/Winbond.c b/UefiPayloadPkg/Library/AmdSpiLib/Winbond.c
new file mode 100644
index 000000000000..a9a451a5bd64
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/Winbond.c
@@ -0,0 +1,211 @@
+#include
+#include "SPIFlashInternal.h"
+#include "Winbond.h"
+
+union status_reg1 {
+ UINT8 u;
+ struct {
+ UINT8 busy : 1;
+ UINT8 wel : 1;
+ UINT8 bp : 3;
+ UINT8 tb : 1;
+ UINT8 sec : 1;
+ UINT8 srp0 : 1;
+ } bp3;
+ struct {
+ UINT8 busy : 1;
+ UINT8 wel : 1;
+ UINT8 bp : 4;
+ UINT8 tb : 1;
+ UINT8 srp0 : 1;
+ } bp4;
+};
+
+union status_reg2 {
+ UINT8 u;
+ struct {
+ UINT8 srp1 : 1;
+ UINT8 qe : 1;
+ UINT8 res : 1;
+ UINT8 lb : 3;
+ UINT8 cmp : 1;
+ UINT8 sus : 1;
+ };
+};
+
+struct status_regs {
+ union {
+ struct {
+#if defined(__BIG_ENDIAN)
+ union status_reg2 reg2;
+ union status_reg1 reg1;
+#else
+ union status_reg1 reg1;
+ union status_reg2 reg2;
+#endif
+ };
+ UINT16 u;
+ };
+};
+
+static const struct spi_flash_part_id flash_table[] = {
+ {
+ /* W25P80 */
+ .id[0] = 0x2014,
+ .nr_sectors_shift = 8,
+ },
+ {
+ /* W25P16 */
+ .id[0] = 0x2015,
+ .nr_sectors_shift = 9,
+ },
+ {
+ /* W25P32 */
+ .id[0] = 0x2016,
+ .nr_sectors_shift = 10,
+ },
+ {
+ /* W25X80 */
+ .id[0] = 0x3014,
+ .nr_sectors_shift = 8,
+ .fast_read_dual_output_support = 1,
+ },
+ {
+ /* W25X16 */
+ .id[0] = 0x3015,
+ .nr_sectors_shift = 9,
+ .fast_read_dual_output_support = 1,
+ },
+ {
+ /* W25X32 */
+ .id[0] = 0x3016,
+ .nr_sectors_shift = 10,
+ .fast_read_dual_output_support = 1,
+ },
+ {
+ /* W25X64 */
+ .id[0] = 0x3017,
+ .nr_sectors_shift = 11,
+ .fast_read_dual_output_support = 1,
+ },
+ {
+ /* W25Q80_V */
+ .id[0] = 0x4014,
+ .nr_sectors_shift = 8,
+ .fast_read_dual_output_support = 1,
+ },
+ {
+ /* W25Q16_V */
+ .id[0] = 0x4015,
+ .nr_sectors_shift = 9,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 16,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q16DW */
+ .id[0] = 0x6015,
+ .nr_sectors_shift = 9,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 16,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q32_V */
+ .id[0] = 0x4016,
+ .nr_sectors_shift = 10,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 16,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q32DW */
+ .id[0] = 0x6016,
+ .nr_sectors_shift = 10,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 16,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q64_V */
+ .id[0] = 0x4017,
+ .nr_sectors_shift = 11,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 17,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q64DW */
+ .id[0] = 0x6017,
+ .nr_sectors_shift = 11,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 17,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q64JW */
+ .id[0] = 0x8017,
+ .nr_sectors_shift = 11,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 17,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q128_V */
+ .id[0] = 0x4018,
+ .nr_sectors_shift = 12,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 18,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q128FW */
+ .id[0] = 0x6018,
+ .nr_sectors_shift = 12,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 18,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q128J */
+ .id[0] = 0x7018,
+ .nr_sectors_shift = 12,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 18,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q128JW */
+ .id[0] = 0x8018,
+ .nr_sectors_shift = 12,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 18,
+ .bp_bits = 3,
+ },
+ {
+ /* W25Q256_V */
+ .id[0] = 0x4019,
+ .nr_sectors_shift = 13,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 16,
+ .bp_bits = 4,
+ },
+ {
+ /* W25Q256J */
+ .id[0] = 0x7019,
+ .nr_sectors_shift = 13,
+ .fast_read_dual_output_support = 1,
+ .protection_granularity_shift = 16,
+ .bp_bits = 4,
+ },
+};
+
+CONST struct spi_flash_vendor_info spi_flash_winbond_vi = {
+ .id = VENDOR_ID_WINBOND,
+ .page_size_shift = 8,
+ .sector_size_kib_shift = 2,
+ .match_id_mask[0] = 0xffff,
+ .ids = flash_table,
+ .nr_part_ids = ARRAY_SIZE(flash_table),
+ .desc = &spi_flash_pp_0x20_sector_desc,
+};
diff --git a/UefiPayloadPkg/Library/AmdSpiLib/Winbond.h b/UefiPayloadPkg/Library/AmdSpiLib/Winbond.h
new file mode 100644
index 000000000000..8ab1dc4122d9
--- /dev/null
+++ b/UefiPayloadPkg/Library/AmdSpiLib/Winbond.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* Winbond specific function */
+/* M25Pxx-specific commands */
+#define CMD_W25_WREN 0x06 /* Write Enable */
+#define CMD_W25_WRDI 0x04 /* Write Disable */
+#define CMD_W25_RDSR 0x05 /* Read Status Register */
+#define CMD_W25_WRSR 0x01 /* Write Status Register */
+#define CMD_W25_RDSR2 0x35 /* Read Status2 Register */
+#define CMD_W25_WRSR2 0x31 /* Write Status2 Register */
+#define CMD_W25_READ 0x03 /* Read Data Bytes */
+#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
+#define CMD_W25_PP 0x02 /* Page Program */
+#define CMD_W25_SE 0x20 /* Sector (4K) Erase */
+#define CMD_W25_RDID 0x9f /* Read ID */
+#define CMD_W25_BE 0xd8 /* Block (64K) Erase */
+#define CMD_W25_CE 0xc7 /* Chip Erase */
+#define CMD_W25_DP 0xb9 /* Deep Power-down */
+#define CMD_W25_RES 0xab /* Release from DP and Read Signature */
+#define CMD_VOLATILE_SREG_WREN 0x50 /* Write Enable for Volatile SREG */
+
+/* tw: Maximum time to write a flash cell in milliseconds */
+#define WINBOND_FLASH_TIMEOUT 30
diff --git a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c
index 0692e0b8004e..8bb7a581e4e5 100644
--- a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c
+++ b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c
@@ -595,36 +595,36 @@ ParseGfxDeviceInfo (
@retval RETURN_NOT_FOUND Failed to find the SMM store buffer information .
**/
-RETURN_STATUS
-EFIAPI
-ParseSMMSTOREInfo (
- OUT SMMSTORE_INFO *SMMSTOREInfo
- )
-{
- struct cb_smmstorev2 *CbSSRec;
-
- if (SMMSTOREInfo == NULL) {
- return RETURN_INVALID_PARAMETER;
- }
-
- CbSSRec = FindCbTag (CB_TAG_SMMSTOREV2);
- if (CbSSRec == NULL) {
- return RETURN_NOT_FOUND;
- }
-
- DEBUG ((DEBUG_INFO, "Found SMM Store information\n"));
- DEBUG ((DEBUG_INFO, "block size: 0x%x\n", CbSSRec->block_size));
- DEBUG ((DEBUG_INFO, "number of blocks: 0x%x\n", CbSSRec->num_blocks));
- DEBUG ((DEBUG_INFO, "communication buffer: 0x%x\n", CbSSRec->com_buffer));
- DEBUG ((DEBUG_INFO, "communication buffer size: 0x%x\n", CbSSRec->com_buffer_size));
- DEBUG ((DEBUG_INFO, "MMIO address of store: 0x%x\n", CbSSRec->mmap_addr));
-
- SMMSTOREInfo->ComBuffer = CbSSRec->com_buffer;
- SMMSTOREInfo->ComBufferSize = CbSSRec->com_buffer_size;
- SMMSTOREInfo->BlockSize = CbSSRec->block_size;
- SMMSTOREInfo->NumBlocks = CbSSRec->num_blocks;
- SMMSTOREInfo->MmioAddress = CbSSRec->mmap_addr;
- SMMSTOREInfo->ApmCmd = CbSSRec->apm_cmd;
-
- return RETURN_SUCCESS;
-}
+// RETURN_STATUS
+// EFIAPI
+// ParseSMMSTOREInfo (
+// OUT SMMSTORE_INFO *SMMSTOREInfo
+// )
+// {
+// struct cb_smmstorev2 *CbSSRec;
+
+// if (SMMSTOREInfo == NULL) {
+// return RETURN_INVALID_PARAMETER;
+// }
+
+// CbSSRec = FindCbTag (CB_TAG_SMMSTOREV2);
+// if (CbSSRec == NULL) {
+// return RETURN_NOT_FOUND;
+// }
+
+// DEBUG ((DEBUG_INFO, "Found SMM Store information\n"));
+// DEBUG ((DEBUG_INFO, "block size: 0x%x\n", CbSSRec->block_size));
+// DEBUG ((DEBUG_INFO, "number of blocks: 0x%x\n", CbSSRec->num_blocks));
+// DEBUG ((DEBUG_INFO, "communication buffer: 0x%x\n", CbSSRec->com_buffer));
+// DEBUG ((DEBUG_INFO, "communication buffer size: 0x%x\n", CbSSRec->com_buffer_size));
+// DEBUG ((DEBUG_INFO, "MMIO address of store: 0x%x\n", CbSSRec->mmap_addr));
+
+// SMMSTOREInfo->ComBuffer = CbSSRec->com_buffer;
+// SMMSTOREInfo->ComBufferSize = CbSSRec->com_buffer_size;
+// SMMSTOREInfo->BlockSize = CbSSRec->block_size;
+// SMMSTOREInfo->NumBlocks = CbSSRec->num_blocks;
+// SMMSTOREInfo->MmioAddress = CbSSRec->mmap_addr;
+// SMMSTOREInfo->ApmCmd = CbSSRec->apm_cmd;
+
+// return RETURN_SUCCESS;
+// }
diff --git a/UefiPayloadPkg/Library/CbSMMStoreLib/CorebootSMMStore.c b/UefiPayloadPkg/Library/CbSMMStoreLib/CorebootSMMStore.c
index 5cbb66b53fb6..b919dbef17fa 100644
--- a/UefiPayloadPkg/Library/CbSMMStoreLib/CorebootSMMStore.c
+++ b/UefiPayloadPkg/Library/CbSMMStoreLib/CorebootSMMStore.c
@@ -145,7 +145,7 @@ SMMStoreRead (
return EFI_NO_RESPONSE;
}
- CopyMem (Buffer, (VOID *)(mSmmStoreInfo->ComBuffer + Offset), *NumBytes);
+ CopyMem (Buffer, (VOID *)(UINTN)(mSmmStoreInfo->ComBuffer + Offset), *NumBytes);
return EFI_SUCCESS;
}
@@ -186,7 +186,7 @@ SMMStoreWrite (
mArgComBuf->raw_write.bufoffset = Offset;
mArgComBuf->raw_write.block_id = Lba;
- CopyMem ((VOID *)(mSmmStoreInfo->ComBuffer + Offset), Buffer, *NumBytes);
+ CopyMem ((VOID *)(UINTN)(mSmmStoreInfo->ComBuffer + Offset), Buffer, *NumBytes);
Result = call_smm(mSmmStoreInfo->ApmCmd, SMMSTORE_CMD_RAW_WRITE, mArgComBufPhys);
if (Result == SMMSTORE_RET_FAILURE) {
diff --git a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
index 9d7bcb35f2c4..e72389a8c602 100644
--- a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
+++ b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
@@ -319,7 +319,7 @@ SetPrimaryVideoOutput(
}
// Locate all GOPs
- Status = gBS->LocateHandleBuffer(ByProtocol,
+ Status = gBS->LocateHandleBuffer(ByProtocol,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&HandleCount,
@@ -456,7 +456,7 @@ SetPrimaryVideoOutput(
}
} // for loop
-
+
return;
}
@@ -485,7 +485,7 @@ PlatformBootManagerBeforeConsole (
//
// Map Escape to Boot Manager Menu
//
- Escape.ScanCode = SCAN_ESC;
+ Escape.ScanCode = SCAN_F9;
Escape.UnicodeChar = CHAR_NULL;
EfiBootManagerGetBootManagerMenu (&BootOption);
EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &Escape, NULL);
@@ -553,14 +553,14 @@ PlatformBootManagerAfterConsole (
//
// Register UEFI Shell
//
- PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);
+ //PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);
//
// Register iPXE
//
- PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), L"iPXE Network boot", LOAD_OPTION_ACTIVE);
+ //PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), L"iPXE Network boot", LOAD_OPTION_ACTIVE);
- Print (L"Pess ESC to enter Boot Manager Menu.\n");
+ Print (L"Press F9 to enter Boot Manager Menu.\n");
}
/**
diff --git a/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c b/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c
index 6354ef2b030c..61b8245f54ff 100644
--- a/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c
+++ b/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c
@@ -247,11 +247,11 @@ ParseGfxDeviceInfo (
@retval RETURN_NOT_FOUND Failed to find the SMM store buffer information .
**/
-RETURN_STATUS
-EFIAPI
-ParseSMMSTOREInfo (
- OUT SMMSTORE_INFO *SMMSTOREInfo
- )
-{
- return RETURN_NOT_FOUND;
-}
+// RETURN_STATUS
+// EFIAPI
+// ParseSMMSTOREInfo (
+// OUT SMMSTORE_INFO *SMMSTOREInfo
+// )
+// {
+// return RETURN_NOT_FOUND;
+// }
diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c
index 7b6cc4d7668d..b8ee57325878 100644
--- a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c
+++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c
@@ -203,7 +203,7 @@ EnrollListOfCerts (
UINT8 *Position;
Status = EFI_SUCCESS;
-
+ DEBUG ((DEBUG_INFO, "%a: enrolling for %a\n", __FUNCTION__, VariableName));
//
// compute total size first, for UINT32 range check, and allocation
//
@@ -461,11 +461,6 @@ InstallSecureBootHook (
return;
}
- if(Settings.SecureBootEnable != SECURE_BOOT_MODE_ENABLE) {
- DEBUG ((EFI_D_ERROR, "SecureBootSetup: SecureBootEnable is disabled.\n"));
- return;
- }
-
PrintSettings (&Settings);
if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) {
@@ -503,6 +498,8 @@ InstallSecureBootHook (
MicrosoftDbxSize, MicrosoftDbx);
ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "SecureBootSetup: enrolling certs.\n"));
+
Status = EnrollListOfCerts (
EFI_IMAGE_SECURITY_DATABASE,
&gEfiImageSecurityDatabaseGuid,
@@ -545,29 +542,6 @@ InstallSecureBootHook (
ASSERT_EFI_ERROR (Status);
}
- // FIXME: Force SecureBoot to ON. The AuthService will do this if authenticated variables
- // are supported, which aren't as the SMM handler isn't able to verify them.
-
- Settings.SecureBootEnable = SECURE_BOOT_ENABLE;
- Status = gRT->SetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- sizeof Settings.SecureBootEnable, &Settings.SecureBootEnable);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_ENABLE_NAME,
- &gEfiSecureBootEnableDisableGuid, Status));
- ASSERT_EFI_ERROR (Status);
- }
-
- Settings.SecureBoot = SECURE_BOOT_ENABLE;
- Status = gRT->SetVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof Settings.SecureBoot, &Settings.SecureBoot);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_MODE_NAME,
- &gEfiGlobalVariableGuid, Status));
- ASSERT_EFI_ERROR (Status);
- }
-
Status = GetSettings (&Settings, FALSE);
ASSERT_EFI_ERROR (Status);
diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf
index 153830f74363..a7b8e14a062c 100644
--- a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf
+++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf
@@ -34,6 +34,7 @@
gEfiCertX509Guid
gEfiCustomModeEnableGuid
gEfiGlobalVariableGuid
+ gEfiVendorKeysNvGuid
gEfiImageSecurityDatabaseGuid
gEfiSecureBootEnableDisableGuid
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec
index 2613daa52474..f6b35b0eab5e 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dec
+++ b/UefiPayloadPkg/UefiPayloadPkg.dec
@@ -30,11 +30,11 @@
#
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 } }
- gEfiSMMSTOREInfoHobGuid = { 0xf585ca19, 0x881b, 0x44fb, { 0x3f, 0x3d, 0x81, 0x89, 0x7c, 0x57, 0xbb, 0x01 }}
+ gUefiSystemTableInfoGuid = {0x16c8a6d0, 0xfe8a, 0x4082, {0xa2, 0x08, 0xcf, 0x89, 0xc4, 0x29, 0x04, 0x33}}
+ gUefiAcpiBoardInfoGuid = {0xad3d31b, 0xb3d8, 0x4506, {0xae, 0x71, 0x2e, 0xf1, 0x10, 0x06, 0xd9, 0x0f}}
+ gUefiSerialPortInfoGuid = {0x6c6872fe, 0x56a9, 0x4403, {0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1}}
+ gLoaderMemoryMapInfoGuid = {0xa1ff7424, 0x7a1a, 0x478e, {0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32}}
+ gUefiFvbSPIInfoGuid = {0x7d3b6dea, 0xd358, 0x440e, {0xb3, 0x5d, 0x36, 0x2f, 0x09, 0xf2, 0x8f, 0xec}}
[Ppis]
gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} }
diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf
index 52e72faedce6..e7573acfe821 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.fdf
+++ b/UefiPayloadPkg/UefiPayloadPkg.fdf
@@ -10,16 +10,16 @@
################################################################################
[FD.UefiPayload]
-BaseAddress = 0x800000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
-Size = 0x800000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
+BaseAddress = 0x440000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
+Size = 0x440000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
ErasePolarity = 1
BlockSize = 0x1000
-NumBlocks = 0x800
+NumBlocks = 0x440
0x00000000|0x040000
FV = PEIFV
-0x00040000|0x7C0000
+0x00040000|0x400000
FV = DXEFV
################################################################################
@@ -53,7 +53,7 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
!if $(TPM_ENABLE) == TRUE
INF UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
-INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
+#INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
!endif
@@ -83,14 +83,11 @@ APRIORI DXE {
INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
-!if $(BOOTLOADER) == "COREBOOT"
- # Initialize VariableStore and update PCDs before VariableRuntimeDxe
- INF UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
-!endif
- # Init Test Driver before Secure Boot
- # INF UefiPayloadPkg/TestDriverDxe/TestDriver.inf
- INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ INF UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.inf
+!endif
+ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
}
#
@@ -125,9 +122,9 @@ INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
INF UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
-INF MdeModulePkg/Logo/LogoDxe.inf
-!if $(BOOTLOADER) == "COREBOOT"
-INF UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ INF UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.inf
!endif
#
@@ -150,11 +147,9 @@ INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
#
INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
-INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
!if $(SERIAL_TERMINAL) == TRUE
INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
!endif
-INF UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
INF UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
#
@@ -166,50 +161,19 @@ 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/Pci/NvmExpressDxe/NvmExpressDxe.inf
INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
INF FatPkg/EnhancedFatDxe/Fat.inf
-#
-# Filesystem drivers
-#
-!if $(ARCH) == IA32
-INF RuleOverride=BINARY USE = IA32 FSDrivers/exfat.inf
-INF RuleOverride=BINARY USE = IA32 FSDrivers/ext2.inf
-INF RuleOverride=BINARY USE = IA32 FSDrivers/ntfs.inf
-INF RuleOverride=BINARY USE = IA32 FSDrivers/ext4.inf
-!else
-INF RuleOverride=BINARY USE = X64 FSDrivers/exfat.inf
-INF RuleOverride=BINARY USE = X64 FSDrivers/ext2.inf
-INF RuleOverride=BINARY USE = X64 FSDrivers/ntfs.inf
-INF RuleOverride=BINARY USE = X64 FSDrivers/ext4.inf
-!endif
-
-#
-# 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
-#
-# Network Support
-#
-!include NetworkPkg/Network.fdf.inc
-
-
#
# Network modules (only available on X64)
# Available at https://downloadcenter.intel.com/download/29137?v=t
@@ -244,17 +208,12 @@ INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
#
# iPXE support
#
-!if (NETWORK_IPXE)
+!if $(NETWORK_IPXE) == TRUE
FILE FREEFORM = B68653C7-EEA1-4435-A199-A44F59E4476C {
SECTION PE32 = UefiPayloadPkg/NetworkDrivers/ipxe.efi
}
!endif
-#
-# Random Number Generator
-#
-INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
-
#
# Security
#
@@ -290,7 +249,6 @@ INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
!endif
!if $(TPM_ENABLE) == TRUE
-INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
!endif
@@ -325,7 +283,7 @@ INF RuleOverride = BINARY USE = X64 ShellBinPkg/UefiShell/UefiShell.inf
# GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER))
DEFINE BLOCK_SIZE = 0x10000
-SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase = 0
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase = 0xFF860000
SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize = $(BLOCK_SIZE)
SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase = gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
index 988a59f576b7..28d5045f6526 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
@@ -31,7 +31,7 @@
# SBL: UEFI payload for Slim Bootloader
# COREBOOT: UEFI payload for coreboot
#
- DEFINE BOOTLOADER = SBL
+ DEFINE BOOTLOADER = COREBOOT
#
# CPU options
@@ -78,7 +78,7 @@
#
# Shell options: [BUILD_SHELL, MIN_BIN, NONE, UEFI_BIN]
#
- DEFINE SHELL_TYPE = BUILD_SHELL
+ DEFINE SHELL_TYPE = NONE
#
# Security options:
@@ -152,6 +152,8 @@
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
#
# UEFI & PI
@@ -224,41 +226,24 @@
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
-
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
-
-#
-# Network
-#
-!include NetworkPkg/NetworkLibs.dsc.inc
-
-!if $(NETWORK_TLS_ENABLE) == TRUE
- OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
- TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
-!else
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
-!endif
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ AmdSpiLib|UefiPayloadPkg/Library/AmdSpiLib/AmdSpiLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
-!if $(BOOTLOADER) == "COREBOOT"
- SmmStoreLib|UefiPayloadPkg/Library/CbSMMStoreLib/CbSMMStoreLib.inf
-!else
- SmmStoreLib|UefiPayloadPkg/Library/SblSMMStoreLib/SblSMMStoreLib.inf
-!endif
-
!if $(TPM_ENABLE) == TRUE
Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf
Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
- TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+ #TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
!endif
[LibraryClasses.IA32.SEC]
@@ -298,7 +283,6 @@
!endif
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
- SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
[LibraryClasses.common.DXE_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -312,7 +296,6 @@
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
- SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -377,7 +360,7 @@
# The following parameters are set by Library/PlatformHookLib
#
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x2f8
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|$(BAUD_RATE)
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1
@@ -438,6 +421,7 @@
#
################################################################################
[Components.IA32]
+
#
# SEC Core
#
@@ -463,7 +447,6 @@
!if $(TPM_ENABLE) == TRUE
UefiPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
- SecurityPkg/Tcg/TcgPei/TcgPei.inf
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
@@ -493,18 +476,16 @@
NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
!endif
!if $(TPM_ENABLE) == TRUE
- NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
!endif
}
!if $(SECURE_BOOT_ENABLE) == TRUE
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
- OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
+ UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf
!endif
UefiCpuPkg/CpuDxe/CpuDxe.inf
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
- MdeModulePkg/Logo/LogoDxe.inf
MdeModulePkg/Application/UiApp/UiApp.inf {
NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
@@ -542,7 +523,6 @@
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
- MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
@@ -575,25 +555,15 @@
MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
- MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.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
#
@@ -605,50 +575,23 @@
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
!endif
- #
- # SMBUS Support
- #
- UefiPayloadPkg/SmbusDxe/SMBusi801Dxe.inf
- UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf
-
#
# Console Support
#
MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
- MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
!if $(SERIAL_TERMINAL) == TRUE
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
!endif
- UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
- # SMMSTORE
- #
-!if $(BOOTLOADER) == "COREBOOT"
- UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
-!endif
-
#
- # Network Support
+ # AMD SPI
#
-!include NetworkPkg/NetworkComponents.dsc.inc
-
-!if $(NETWORK_TLS_ENABLE) == TRUE
- NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {
-
- NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf
- }
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ UefiPayloadPkg/AmdSpiDxe/AmdSpiDxe.inf
!endif
- #
- # Random Number Generator
- #
- SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf {
-
- RngLib|UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf
- }
-
!if $(TPM_ENABLE) == TRUE
SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf {
@@ -665,10 +608,6 @@
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
}
- SecurityPkg/Tcg/TcgDxe/TcgDxe.inf {
-
- Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf
- }
!endif
#------------------------------
diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
index 4c5bf2613e49..7faf2edf169a 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
@@ -257,11 +257,6 @@
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
-!if $(BOOTLOADER) == "COREBOOT"
- SmmStoreLib|UefiPayloadPkg/Library/CbSMMStoreLib/CbSMMStoreLib.inf
-!else
- SmmStoreLib|UefiPayloadPkg/Library/SblSMMStoreLib/SblSMMStoreLib.inf
-!endif
!if $(TPM_ENABLE) == TRUE
Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf
@@ -487,6 +482,7 @@
!endif
[Components.X64]
+ UefiPayloadPkg/SPI/SPI.inf
#
# DXE Core
#
@@ -629,13 +625,6 @@
UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf
- #
- # SMMSTORE
- #
-!if $(BOOTLOADER) == "COREBOOT"
- UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf
-!endif
-
#
# Network Support
#