diff mbox

[Linaro-uefi,1/4] Platforms/AMD/Styx: implement SPI flash runtime driver to back the varstore

Message ID 1462545180-7941-2-git-send-email-ard.biesheuvel@linaro.org
State Superseded
Headers show

Commit Message

Ard Biesheuvel May 6, 2016, 2:32 p.m. UTC
This implements a firmware volume block I/O protocol driver on top of the
SPI flash that is exposed by the SCP. Since the generic FTW and variable
drivers cannot deal with non-memorymapped flash, this driver uses a
RuntimeServicesData buffer to expose the varstore slice of the SPI flash,
and keeps it in sync when the Write() or Erase() methods are called.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 Platforms/AMD/Styx/AmdStyx.dec                           |   6 +
 Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c   | 503 ++++++++++++++++++++
 Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf |  63 +++
 3 files changed, 572 insertions(+)
diff mbox

Patch

diff --git a/Platforms/AMD/Styx/AmdStyx.dec b/Platforms/AMD/Styx/AmdStyx.dec
index 0ce16cb3baff..3e5f5e8a8f2d 100644
--- a/Platforms/AMD/Styx/AmdStyx.dec
+++ b/Platforms/AMD/Styx/AmdStyx.dec
@@ -112,3 +112,9 @@ 
   gAmdStyxTokenSpaceGuid.PcdParkingProtocolBase|0x8000E80000|UINT64|0x000b0001
   gAmdStyxTokenSpaceGuid.PcdParkingProtocolSize|0x0000008000|UINT64|0x000b0002
 
+  # The original offset in memory of the NV store firmware volume, before
+  # relocating it to a dynamically allocated buffer. We need this to correlate
+  # flash accesses to the in-memory copy with LBAs in the actual SPI flash
+  gAmdStyxTokenSpaceGuid.PcdFlashNvStorageOriginalBase|0|UINT64|0x000c0000
+  # block size to use when invoking the ISCP FV methods
+  gAmdStyxTokenSpaceGuid.PcdFlashNvStorageBlockSize|0x1000|UINT32|0x000c0001
diff --git a/Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c b/Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c
new file mode 100644
index 000000000000..e27d9afd6c22
--- /dev/null
+++ b/Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c
@@ -0,0 +1,503 @@ 
+/** @file
+
+  FV block I/O protocol driver for Styx SPI flash exposed via ISCP
+
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Protocol/AmdIscpDxeProtocol.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+// TODO: replace with FixedPcdGet64 (PcdFdBaseAddress) once we have updated
+// the .FDF to let STYX_EFI.fd cover the entire SPI flash
+#define SPI_BASE                0x8000C80000UL
+#define BLOCK_SIZE              (FixedPcdGet32 (PcdFlashNvStorageBlockSize))
+
+STATIC AMD_ISCP_DXE_PROTOCOL    *mIscpDxeProtocol;
+STATIC EFI_HANDLE               mStyxSpiFvHandle;
+
+STATIC EFI_EVENT                mVirtualAddressChangeEvent;
+
+STATIC UINT64 mNvStorageBase;
+STATIC UINT64 mNvStorageLbaOffset;
+
+STATIC CONST UINT64 mNvStorageSize = FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
+                                     FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+                                     FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+
+/**
+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+  It convers pointer to new virtual address.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+STATIC
+VOID
+EFIAPI
+VariableClassAddressChangeEvent (
+  IN EFI_EVENT                            Event,
+  IN VOID                                 *Context
+  )
+{
+  EfiConvertPointer (0x0, (VOID **)&mIscpDxeProtocol);
+  EfiConvertPointer (0x0, (VOID **)&mNvStorageBase);
+}
+
+/**
+  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.
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeGetAttributes (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  OUT       EFI_FVB_ATTRIBUTES_2                *Attributes
+  )
+{
+  *Attributes = EFI_FVB2_READ_ENABLED_CAP   | // Reads may be enabled
+                EFI_FVB2_READ_STATUS        | // Reads are currently enabled
+                EFI_FVB2_WRITE_STATUS       | // Writes are currently enabled
+                EFI_FVB2_WRITE_ENABLED_CAP  | // Writes may be 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')
+
+  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.
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeSetAttributes (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  IN OUT    EFI_FVB_ATTRIBUTES_2                *Attributes
+  )
+{
+  return EFI_SUCCESS;  // ignore for now
+}
+
+/**
+  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_UNSUPPORTED   The firmware volume is not memory mapped.
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeGetPhysicalAddress (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  OUT       EFI_PHYSICAL_ADDRESS                *Address
+  )
+{
+  *Address = (EFI_PHYSICAL_ADDRESS)mNvStorageBase;
+  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.
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeGetBlockSize (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  IN        EFI_LBA                             Lba,
+  OUT       UINTN                               *BlockSize,
+  OUT       UINTN                               *NumberOfBlocks
+  )
+{
+  *BlockSize = BLOCK_SIZE;
+  *NumberOfBlocks = mNvStorageSize / BLOCK_SIZE - (UINTN)Lba;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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.
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeRead (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  IN        EFI_LBA                             Lba,
+  IN        UINTN                               Offset,
+  IN OUT    UINTN                               *NumBytes,
+  IN OUT    UINT8                               *Buffer
+  )
+{
+  VOID            *Base;
+
+  if (Offset + *NumBytes > BLOCK_SIZE) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  Base = (VOID *)mNvStorageBase + Lba * BLOCK_SIZE + Offset;
+
+  //
+  // Copy the data from the in-memory image
+  //
+  CopyMem (Buffer, Base, *NumBytes);
+
+  DEBUG_CODE_BEGIN ();
+    EFI_STATUS      Status;
+
+    if (!EfiAtRuntime ()) {
+      Lba += mNvStorageLbaOffset;
+      Status = mIscpDxeProtocol->AmdExecuteLoadFvBlockDxe (mIscpDxeProtocol,
+                                   Lba * BLOCK_SIZE + Offset, Buffer, *NumBytes);
+      ASSERT_EFI_ERROR (Status);
+
+      ASSERT (CompareMem (Base, Buffer, *NumBytes) == 0);
+    }
+  DEBUG_CODE_END ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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.
+
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeWrite (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  IN        EFI_LBA                             Lba,
+  IN        UINTN                               Offset,
+  IN OUT    UINTN                               *NumBytes,
+  IN        UINT8                               *Buffer
+  )
+{
+  EFI_STATUS      Status;
+  VOID            *Base;
+
+  if (Offset + *NumBytes > BLOCK_SIZE) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  Base = (VOID *)mNvStorageBase + Lba * BLOCK_SIZE + Offset;
+
+  Lba += mNvStorageLbaOffset;
+  Status = mIscpDxeProtocol->AmdExecuteUpdateFvBlockDxe (mIscpDxeProtocol,
+                               Lba * BLOCK_SIZE + Offset, Buffer, *NumBytes);
+  if (!EFI_ERROR (Status)) {
+    //
+    // Copy the data we just wrote to the in-memory copy of the
+    // firmware volume
+    //
+    CopyMem (Base, Buffer, *NumBytes);
+  }
+  return Status;
+}
+
+/**
+  Erases and initializes 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.
+
+**/
+STATIC
+EFI_STATUS
+StyxSpiFvDxeErase (
+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+  ...
+  )
+{
+  VA_LIST       Args;
+  EFI_LBA       Start;
+  UINTN         Length;
+  EFI_STATUS    Status;
+
+  VA_START (Args, This);
+
+  for (Start = VA_ARG (Args, EFI_LBA);
+       Start != EFI_LBA_LIST_TERMINATOR;
+       Start = VA_ARG (Args, EFI_LBA)) {
+    Start += mNvStorageLbaOffset;
+    Length = VA_ARG (Args, UINTN);
+    Status = mIscpDxeProtocol->AmdExecuteEraseFvBlockDxe (mIscpDxeProtocol,
+                                 (Start + mNvStorageLbaOffset) * BLOCK_SIZE,
+                                 Length * BLOCK_SIZE);
+    if (!EFI_ERROR (Status)) {
+      SetMem64 ((VOID *)mNvStorageBase + Start * BLOCK_SIZE,
+                Length * BLOCK_SIZE, ~0UL);
+    }
+  }
+
+  VA_END (Args);
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mStyxSpiFvProtocol = {
+  StyxSpiFvDxeGetAttributes,
+  StyxSpiFvDxeSetAttributes,
+  StyxSpiFvDxeGetPhysicalAddress,
+  StyxSpiFvDxeGetBlockSize,
+  StyxSpiFvDxeRead,
+  StyxSpiFvDxeWrite,
+  StyxSpiFvDxeErase
+};
+
+EFI_STATUS
+EFIAPI
+StyxSpiFvDxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS      Status;
+
+  mNvStorageBase = PcdGet64 (PcdFlashNvStorageVariableBase64);
+  mNvStorageLbaOffset = (FixedPcdGet64 (PcdFlashNvStorageOriginalBase) -
+                         SPI_BASE) / BLOCK_SIZE;
+
+  DEBUG ((EFI_D_INFO,
+    "%a: Using NV store FV in-memory copy at 0x%lx, LBA offset == 0x%lx\n",
+    __FUNCTION__, mNvStorageBase, mNvStorageLbaOffset));
+
+  Status = gBS->LocateProtocol (&gAmdIscpDxeProtocolGuid, NULL,
+                  (VOID **)&mIscpDxeProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                  VariableClassAddressChangeEvent, NULL,
+                  &gEfiEventVirtualAddressChangeGuid, 
+                  &mVirtualAddressChangeEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  return gBS->InstallMultipleProtocolInterfaces (&mStyxSpiFvHandle,
+                &gEfiFirmwareVolumeBlockProtocolGuid, &mStyxSpiFvProtocol,
+                NULL);
+}
diff --git a/Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf b/Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf
new file mode 100644
index 000000000000..2c1f243c76e9
--- /dev/null
+++ b/Platforms/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf
@@ -0,0 +1,63 @@ 
+#/** @file
+#
+#  Component description file for StyxSpiFvDxe module
+#
+#  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = StyxSpiFvDxe
+  FILE_GUID                      = F549FC67-C4A6-4E92-B9BA-297E1F82A1A8
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = StyxSpiFvDxeInitialize
+
+[Sources]
+  StyxSpiFvDxe.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  AmdModulePkg/AmdModulePkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OpenPlatformPkg/Platforms/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  UefiLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  UefiRuntimeLib
+  DxeServicesTableLib
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+  gAmdStyxTokenSpaceGuid.PcdFlashNvStorageOriginalBase
+  gAmdStyxTokenSpaceGuid.PcdFlashNvStorageBlockSize
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+
+[Protocols]
+  gAmdIscpDxeProtocolGuid                         ## CONSUMES
+  gEfiFirmwareVolumeBlockProtocolGuid             ## PRODUCES
+
+[Depex]
+  gAmdIscpDxeProtocolGuid