summaryrefslogtreecommitdiff
path: root/Silicon/AMD/Styx/Drivers
diff options
context:
space:
mode:
authorLeif Lindholm <leif.lindholm@linaro.org>2017-08-03 12:24:22 +0100
committerLeif Lindholm <leif.lindholm@linaro.org>2017-08-03 12:24:22 +0100
commitf4d38e50c0f24eb78eb003a94f583025621c63db (patch)
tree1022985e88897b7bf0065905b5cb26f9a71fff25 /Silicon/AMD/Styx/Drivers
parent430bc861413cb2e8f0e50e42b56da9860584c49a (diff)
downloadedk2-platforms-f4d38e50c0f24eb78eb003a94f583025621c63db.tar.xz
Platform,Silicon: import AMD Styx SoC support and platforms
Common files for AMD Overdrive, SoftIron Overdrive 1000 and LeMaker Cello, as well as actual platform support. Imported from commit efd798c1eb of https://git.linaro.org/uefi/OpenPlatformPkg.git Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Diffstat (limited to 'Silicon/AMD/Styx/Drivers')
-rw-r--r--Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c114
-rw-r--r--Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf53
-rw-r--r--Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c170
-rw-r--r--Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf53
-rw-r--r--Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S87
-rw-r--r--Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.c237
-rw-r--r--Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.inf62
-rw-r--r--Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.c256
-rw-r--r--Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.inf76
-rw-r--r--Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c994
-rw-r--r--Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf60
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.c189
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.inf47
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c201
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h180
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf63
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c500
-rw-r--r--Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf63
18 files changed, 3405 insertions, 0 deletions
diff --git a/Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c b/Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..15b38bbf89
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,114 @@
+/** @file
+
+ Sample ACPI Platform Driver
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2016, AMD Inc. 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.
+
+**/
+/**
+ Derived from:
+ MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c
+**/
+
+#include <AmdStyxAcpiLib.h>
+#include <Protocol/AcpiTable.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define MAX_ACPI_TABLES 12
+
+EFI_ACPI_DESCRIPTION_HEADER *AcpiTableList[MAX_ACPI_TABLES];
+
+
+/**
+ Entrypoint of Acpi Platform driver.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ UINTN TableHandle;
+ UINTN TableIndex;
+
+ ZeroMem(AcpiTableList, sizeof(AcpiTableList));
+
+ TableIndex = 0;
+ AcpiTableList[TableIndex++] = FadtTable();
+ AcpiTableList[TableIndex++] = DsdtHeader();
+ AcpiTableList[TableIndex++] = MadtHeader();
+ AcpiTableList[TableIndex++] = GtdtHeader();
+ AcpiTableList[TableIndex++] = Dbg2Header();
+ AcpiTableList[TableIndex++] = SpcrHeader();
+ AcpiTableList[TableIndex++] = McfgHeader();
+ AcpiTableList[TableIndex++] = CsrtHeader();
+ if (PcdGetBool (PcdEnableSmmus)) {
+ AcpiTableList[TableIndex++] = IortHeader();
+ }
+ AcpiTableList[TableIndex++] = NULL;
+
+ DEBUG((DEBUG_INFO, "%a(): ACPI Table installer\n", __FUNCTION__));
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "Failed to locate AcpiTable protocol. Status = %r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ TableIndex = 0;
+ while (AcpiTableList[TableIndex] != NULL) {
+ //
+ // Install ACPI table
+ //
+ DEBUG ((EFI_D_ERROR, "Installing %c%c%c%c Table (Revision %d, Length %d) ...\n",
+ *((UINT8*)&AcpiTableList[TableIndex]->Signature),
+ *((UINT8*)&AcpiTableList[TableIndex]->Signature + 1),
+ *((UINT8*)&AcpiTableList[TableIndex]->Signature + 2),
+ *((UINT8*)&AcpiTableList[TableIndex]->Signature + 3),
+ AcpiTableList[TableIndex]->Revision,
+ AcpiTableList[TableIndex]->Length));
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ AcpiTableList[TableIndex],
+ (AcpiTableList[TableIndex])->Length,
+ &TableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR,"Error adding ACPI Table. Status = %r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+ }
+ TableIndex++;
+ ASSERT( TableIndex < MAX_ACPI_TABLES );
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..3c484c43ac
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,53 @@
+#/** @file
+# Sample ACPI Platform Driver
+#
+# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2016, AMD Inc. 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.
+#
+#**/
+#/**
+# Derived from:
+# MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = f229c831-6a35-440b-9c84-dd3bc71e3865
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+[Sources]
+ AcpiPlatform.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ AmdStyxAcpiLib
+ DebugLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Pcd]
+ gAmdStyxTokenSpaceGuid.PcdEnableSmmus
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## ALWAYS_CONSUMED
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
diff --git a/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c
new file mode 100644
index 0000000000..bd7244648a
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c
@@ -0,0 +1,170 @@
+/** @file
+
+ Copyright (c) 2016, AMD Inc. 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 <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Guid/ArmMpCoreInfo.h>
+#include <Protocol/AmdMpBoot.h>
+
+
+/* These externs are used to relocate our Pen code into pre-allocated memory */
+extern VOID *SecondariesPenStart;
+extern VOID *SecondariesPenEnd;
+extern UINTN *AsmParkingBase;
+extern UINTN *AsmMailboxBase;
+
+
+STATIC
+EFI_PHYSICAL_ADDRESS
+ConfigurePen (
+ IN EFI_PHYSICAL_ADDRESS MpParkingBase,
+ IN UINTN MpParkingSize,
+ IN ARM_CORE_INFO *ArmCoreInfoTable,
+ IN UINTN ArmCoreCount
+ )
+{
+ EFI_PHYSICAL_ADDRESS PenBase;
+ UINTN PenSize;
+ UINTN MailboxBase;
+ UINTN CoreNum;
+ UINTN CoreMailbox;
+ UINTN CoreParking;
+
+ //
+ // Set Pen at the 2K-offset of the Parking area, skipping an 8-byte slot for the Core#.
+ // For details, refer to the "Multi-processor Startup for ARM Platforms" document:
+ // https://acpica.org/sites/acpica/files/MP%20Startup%20for%20ARM%20platforms.docx
+ //
+ PenBase = (EFI_PHYSICAL_ADDRESS)((UINTN)MpParkingBase + SIZE_2KB + sizeof(UINT64));
+ PenSize = (UINTN)&SecondariesPenEnd - (UINTN)&SecondariesPenStart;
+
+ // Relocate the Pen code
+ CopyMem ((VOID*)(PenBase), (VOID*)&SecondariesPenStart, PenSize);
+
+ // Put spin-table mailboxes below the pen code so we know where they are relative to code.
+ // Make sure this is 8 byte aligned.
+ MailboxBase = (UINTN)PenBase + ((UINTN)&SecondariesPenEnd - (UINTN)&SecondariesPenStart);
+ if (MailboxBase % sizeof(UINT64) != 0) {
+ MailboxBase += sizeof(UINT64) - MailboxBase % sizeof(UINT64);
+ }
+
+ // Update variables used in the Pen code
+ *(UINTN*)(PenBase + ((UINTN)&AsmMailboxBase - (UINTN)&SecondariesPenStart)) = MailboxBase;
+ *(UINTN*)(PenBase + ((UINTN)&AsmParkingBase - (UINTN)&SecondariesPenStart)) = (UINTN)MpParkingBase;
+
+ for (CoreNum = 0; CoreNum < ArmCoreCount; CoreNum++) {
+ // Clear the jump address at spin-table slot
+ CoreMailbox = MailboxBase + CoreNum * sizeof (UINT64);
+ *((UINTN*)(CoreMailbox)) = 0x0;
+
+ // Clear the jump address and set Core# at mp-parking slot
+ CoreParking = (UINTN)MpParkingBase + CoreNum * SIZE_4KB;
+ *((UINTN*)(CoreParking + sizeof (UINT64))) = 0x0;
+ *((UINTN*)(CoreParking + SIZE_2KB)) = CoreNum;
+
+ // Update table entry to be consumed by FDT parser
+ ArmCoreInfoTable[CoreNum].MailboxSetAddress = CoreMailbox;
+ }
+
+ // flush the cache before launching secondary cores
+ WriteBackDataCacheRange ((VOID *)MpParkingBase, MpParkingSize);
+
+ return PenBase;
+}
+
+
+EFI_STATUS
+EFIAPI
+MpBootDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ AMD_MP_BOOT_PROTOCOL *MpBootProtocol;
+ EFI_PHYSICAL_ADDRESS MpParkingBase;
+ UINTN MpParkingSize;
+ ARM_CORE_INFO *ArmCoreInfoTable;
+ UINTN ArmCoreCount;
+ UINTN CoreNum;
+ EFI_PHYSICAL_ADDRESS PenBase;
+
+ DEBUG ((EFI_D_ERROR, "MpBootDxe Loaded\n"));
+
+ MpBootProtocol = NULL;
+ Status = gBS->LocateProtocol (
+ &gAmdMpBootProtocolGuid,
+ NULL,
+ (VOID **)&MpBootProtocol
+ );
+ if (EFI_ERROR (Status) || MpBootProtocol == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: Failed to locate MP-Boot Protocol.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((VOID *)MpBootProtocol->MpBootInfo == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpBootInfo not allocated.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ MpParkingBase = MpBootProtocol->MpBootInfo->MpParkingBase;
+ if ((VOID *)MpParkingBase == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpParkingBase not allocated.\n"));
+ return EFI_UNSUPPORTED;
+ }
+ if (((UINTN)MpParkingBase & (SIZE_4KB -1)) != 0) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpParkingBase not 4K aligned.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ ArmCoreInfoTable = MpBootProtocol->MpBootInfo->ArmCoreInfoTable;
+ if (ArmCoreInfoTable == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: ArmCoreInfoTable not allocated.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ ArmCoreCount = MpBootProtocol->MpBootInfo->ArmCoreCount;
+ if (ArmCoreCount < 2) {
+ DEBUG ((EFI_D_ERROR, "Warning: Found %d cores.\n", ArmCoreCount));
+ return EFI_UNSUPPORTED;
+ }
+
+ MpParkingSize = ArmCoreCount * SIZE_4KB;
+ if (MpParkingSize > MpBootProtocol->MpBootInfo->MpParkingSize) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpParkingSize = 0x%lX, not large enough for %d cores.\n",
+ MpBootProtocol->MpBootInfo->MpParkingSize, ArmCoreCount));
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((VOID *)MpBootProtocol->ParkSecondaryCore == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: ParkSecondaryCore() not supported.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Move secondary cores to our new Pen
+ PenBase = ConfigurePen (MpParkingBase, MpParkingSize, ArmCoreInfoTable, ArmCoreCount);
+ for (CoreNum = 0; CoreNum < ArmCoreCount; CoreNum++) {
+ MpBootProtocol->ParkSecondaryCore (&ArmCoreInfoTable[CoreNum], PenBase);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf
new file mode 100644
index 0000000000..ec63cd36e8
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf
@@ -0,0 +1,53 @@
+#/* @file
+#
+# Copyright (c) 2016, AMD Inc. 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 = MpBootDxe
+ FILE_GUID = ff3f9c9b-6d36-4787-9144-6b22acba5e9b
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MpBootDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+#
+
+[Sources.common]
+ MpBootDxe.c
+
+[Sources.AARCH64]
+ MpBootHelper.S
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ CacheMaintenanceLib
+ BaseMemoryLib
+ DebugLib
+
+[Protocols]
+ gAmdMpBootProtocolGuid ## CONSUMED
+
+[Depex]
+ gAmdMpBootProtocolGuid
diff --git a/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S
new file mode 100644
index 0000000000..c16cc59a1e
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+// Copyright (c) 2014 - 2016, AMD Inc. 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.
+//
+//**
+// Derived from:
+// ArmPkg/Library/BdsLib/AArch64/BdsLinuxLoaderHelper.S
+//
+//**
+
+/* Secondary core pens for AArch64 Linux booting.
+
+ This code is placed in Linux kernel memory and marked reserved. UEFI ensures
+ that the secondary cores get to this pen and the kernel can then start the
+ cores from here.
+ NOTE: This code must be self-contained.
+*/
+
+#include <Library/ArmLib.h>
+
+.text
+.align 3
+
+GCC_ASM_EXPORT(SecondariesPenStart)
+ASM_GLOBAL SecondariesPenEnd
+
+ASM_PFX(SecondariesPenStart):
+ // Registers x0-x3 are reserved for future use and should be set to zero.
+ mov x0, xzr
+ mov x1, xzr
+ mov x2, xzr
+ mov x3, xzr
+
+ mrs x4, mpidr_el1 // Get MPCore register
+ and x5, x4, #ARM_CORE_MASK // Get core number
+ and x4, x4, #ARM_CLUSTER_MASK // Get cluster number
+
+ add x4, x5, x4, LSR #7 // Add scaled cluster number to core number
+ mov x6, x4 // Save a copy to compute mp-parking offset
+
+ ldr x5, AsmMailboxBase // Get mailbox addr relative to PC
+ lsl x4, x4, 3 // Add 8-byte offset for this core
+ add x4, x4, x5 //
+
+ ldr x5, AsmParkingBase // Get mp-parking addr relative to PC
+ lsl x6, x6, 12 // Add 4K-byte offset for this core
+ add x6, x6, x5 //
+
+ mov x5, 1 // Get mp-parking id# at 2K offset
+ lsl x5, x5, 11 //
+ add x5, x5, x6 //
+ ldr x10, [x5] //
+
+1: ldr x5, [x4] // Load jump-addr from spin-table mailbox
+ cmp xzr, x5 // Has the value been set?
+ b.ne 4f // If so, break out of loop
+
+ ldr x5, [x6] // Load mp-parking id#
+ cmp w10, w5 // Is it my id?
+ b.ne 2f // If not, continue polling
+
+ ldr x5, [x6, 8] // Load jump-addr from mp-parking
+ cmp xzr, x5 // Has the value been set?
+ b.ne 3f // If so, break out of loop
+
+2: wfe // Wait a bit
+ b 1b // Wait over, check again
+
+3: str xzr, [x6, 8] // Clear to acknowledge
+ mov x0, x6 // Return mp-parking address
+4: br x5 // Jump to new addr
+
+.align 3 // Make sure the variable below is 8 byte aligned.
+ .global AsmParkingBase
+AsmParkingBase: .xword 0xdeaddeadbeefbeef
+ .global AsmMailboxBase
+AsmMailboxBase: .xword 0xdeaddeadbeefbeef
+
+SecondariesPenEnd:
diff --git a/Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.c b/Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.c
new file mode 100644
index 0000000000..fd5bb96f7c
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.c
@@ -0,0 +1,237 @@
+/** @file
+
+ Copyright (c) 2016, AMD Inc. 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 <Base.h>
+#include <PiDxe.h>
+#include <Uefi.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Common/CoreState.h>
+#include <Library/ArmSmcLib.h>
+#include <IndustryStandard/ArmStdSmc.h>
+#include <Guid/ArmMpCoreInfo.h>
+
+#include <Protocol/AmdMpCoreInfo.h>
+#include <Protocol/AmdMpBoot.h>
+
+
+STATIC AMD_MP_CORE_INFO_PROTOCOL mAmdMpCoreInfoProtocol = { 0 };
+STATIC AMD_MP_BOOT_PROTOCOL mAmdMpBootProtocol = { 0 };
+STATIC AMD_MP_BOOT_INFO mAmdMpBootInfo = { 0 };
+
+
+STATIC
+ARM_CORE_INFO *
+AmdStyxGetArmCoreInfoTable (
+ OUT UINTN *NumEntries
+ );
+
+STATIC
+EFI_STATUS
+AmdStyxGetPmuSpiFromMpId (
+ IN UINT32 MpId,
+ OUT UINT32 *PmuSpi
+ );
+
+STATIC
+EFI_PHYSICAL_ADDRESS
+AmdStyxGetMpParkingBase (
+ OUT UINTN *MpParkingSize
+ );
+
+STATIC
+VOID
+AmdStyxParkSecondaryCore (
+ ARM_CORE_INFO *ArmCoreInfo,
+ EFI_PHYSICAL_ADDRESS SecondaryEntry
+ );
+
+
+#pragma pack(push, 1)
+typedef struct _PMU_INFO {
+ UINT32 MpId;
+ UINT32 PmuSpi;
+} PMU_INFO;
+
+STATIC
+PMU_INFO mPmuInfo[] = {
+ {0x000, 7},
+ {0x001, 8},
+ {0x100, 9},
+ {0x101, 10},
+ {0x200, 11},
+ {0x201, 12},
+ {0x300, 13},
+ {0x301, 14}
+};
+#pragma pack(pop)
+
+#define MAX_CPUS sizeof(mPmuInfo) / sizeof(PMU_INFO)
+
+
+EFI_STATUS
+EFIAPI
+PlatInitDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MpParkingBase;
+ UINTN MpParkingSize;
+ ARM_CORE_INFO *ArmCoreInfoTable;
+ UINTN ArmCoreCount;
+ EFI_HANDLE Handle = NULL;
+
+ DEBUG ((EFI_D_ERROR, "PlatInitDxe Loaded\n"));
+
+ // Get core information
+ ArmCoreCount = 0;
+ ArmCoreInfoTable = AmdStyxGetArmCoreInfoTable (&ArmCoreCount);
+ ASSERT (ArmCoreInfoTable != NULL);
+ ASSERT (ArmCoreCount != 0);
+
+ // Install CoreInfo Protocol
+ mAmdMpCoreInfoProtocol.GetArmCoreInfoTable = AmdStyxGetArmCoreInfoTable;
+ mAmdMpCoreInfoProtocol.GetPmuSpiFromMpId = AmdStyxGetPmuSpiFromMpId;
+ mAmdMpCoreInfoProtocol.GetMpParkingBase = AmdStyxGetMpParkingBase;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gAmdMpCoreInfoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mAmdMpCoreInfoProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Install MP-Boot Protocol
+ if (!FixedPcdGetBool (PcdPsciOsSupport) &&
+ FixedPcdGetBool (PcdTrustedFWSupport)) {
+ // Allocate Parking area (4KB-aligned, 4KB per core) as Reserved memory
+ MpParkingBase = 0;
+ MpParkingSize = ArmCoreCount * SIZE_4KB;
+ Status = gBS->AllocatePages (AllocateAnyPages, EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (MpParkingSize),
+ &MpParkingBase);
+ if (EFI_ERROR (Status) || MpParkingBase == 0) {
+ DEBUG ((EFI_D_ERROR, "Warning: Failed to allocate MpParkingBase."));
+ } else {
+ mAmdMpBootInfo.MpParkingBase = MpParkingBase;
+ mAmdMpBootInfo.MpParkingSize = MpParkingSize;
+ mAmdMpBootInfo.ArmCoreInfoTable = ArmCoreInfoTable;
+ mAmdMpBootInfo.ArmCoreCount = ArmCoreCount;
+
+ mAmdMpBootProtocol.ParkSecondaryCore = AmdStyxParkSecondaryCore;
+ mAmdMpBootProtocol.MpBootInfo = &mAmdMpBootInfo;
+
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gAmdMpBootProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mAmdMpBootProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Warning: Failed to install MP-Boot Protocol."));
+ gBS->FreePages (MpParkingBase, EFI_SIZE_TO_PAGES (MpParkingSize));
+ }
+ }
+ }
+
+ return Status;
+}
+
+
+STATIC
+ARM_CORE_INFO *
+AmdStyxGetArmCoreInfoTable (
+ OUT UINTN *NumEntries
+ )
+{
+ EFI_HOB_GUID_TYPE *Hob;
+
+ ASSERT (NumEntries != NULL);
+
+ Hob = GetFirstGuidHob (&gAmdStyxMpCoreInfoGuid);
+ if (Hob == NULL) {
+ return NULL;
+ }
+
+ *NumEntries = GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (ARM_CORE_INFO);
+ return GET_GUID_HOB_DATA (Hob);
+}
+
+
+STATIC
+EFI_STATUS
+AmdStyxGetPmuSpiFromMpId (
+ IN UINT32 MpId,
+ OUT UINT32 *PmuSpi
+ )
+{
+ UINT32 i;
+
+ for (i = 0; i < MAX_CPUS; ++i) {
+ if (mPmuInfo[ i ].MpId == MpId) {
+ *PmuSpi = mPmuInfo[ i ].PmuSpi;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+STATIC
+EFI_PHYSICAL_ADDRESS
+AmdStyxGetMpParkingBase (
+ OUT UINTN *MpParkingSize
+ )
+{
+ ASSERT (MpParkingSize != NULL);
+
+ *MpParkingSize = mAmdMpBootInfo.MpParkingBase;
+ return mAmdMpBootInfo.MpParkingBase;
+}
+
+
+STATIC
+VOID
+AmdStyxParkSecondaryCore (
+ ARM_CORE_INFO *ArmCoreInfo,
+ EFI_PHYSICAL_ADDRESS SecondaryEntry
+ )
+{
+ ARM_SMC_ARGS SmcRegs = {0};
+ UINTN MpId;
+
+ MpId = GET_MPID (ArmCoreInfo->ClusterId, ArmCoreInfo->CoreId);
+
+ SmcRegs.Arg0 = ARM_SMC_ID_PSCI_CPU_ON_AARCH64;
+ SmcRegs.Arg1 = MpId;
+ SmcRegs.Arg2 = SecondaryEntry;
+ SmcRegs.Arg3 = FixedPcdGet64 (PcdPsciCpuOnContext);
+ ArmCallSmc (&SmcRegs);
+
+ if (SmcRegs.Arg0 == ARM_SMC_PSCI_RET_SUCCESS ||
+ SmcRegs.Arg0 == ARM_SMC_PSCI_RET_ALREADY_ON) {
+ DEBUG ((EFI_D_ERROR, "CPU[MpId] = 0x%X at RUN state.\n", MpId));
+ } else {
+ DEBUG ((EFI_D_ERROR, "Warning: Could not transition CPU[MpId] = 0x%X to RUN state.\n", MpId));
+ }
+}
diff --git a/Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.inf b/Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.inf
new file mode 100644
index 0000000000..15f46be651
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.inf
@@ -0,0 +1,62 @@
+#/* @file
+#
+# Copyright (c) 2016, AMD Inc. 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 = PlatInitDxe
+ FILE_GUID = 6ae8bdbc-c0eb-40c5-9b3e-18119c0e2710
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatInitDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+#
+
+[Sources.common]
+ PlatInitDxe.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ ArmSmcLib
+ HobLib
+ PcdLib
+ DebugLib
+
+[Guids]
+ gAmdStyxMpCoreInfoGuid
+
+[Protocols]
+ gAmdMpCoreInfoProtocolGuid ## PRODUCER
+ gAmdMpBootProtocolGuid ## PRODUCER
+
+[FixedPcd]
+ gAmdStyxTokenSpaceGuid.PcdPsciOsSupport
+ gAmdStyxTokenSpaceGuid.PcdPsciCpuOnContext
+ gAmdStyxTokenSpaceGuid.PcdTrustedFWSupport
+
+[Depex]
+ TRUE
diff --git a/Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.c b/Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.c
new file mode 100644
index 0000000000..61e373406b
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.c
@@ -0,0 +1,256 @@
+/** @file
+
+ Copyright (c) 2014 - 2016, AMD Inc. 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 <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/ArmLib.h>
+#include <Guid/ArmMpCoreInfo.h>
+
+#include <Ppi/IscpPpi.h>
+#include <Iscp.h>
+
+/*----------------------------------------------------------------------------------------
+ * G L O B A L S
+ *----------------------------------------------------------------------------------------
+ */
+//
+// CoreInfo table
+//
+STATIC ARM_CORE_INFO mAmdMpCoreInfoTable[] = {
+ {
+ // Cluster 0, Core 0
+ 0x0, 0x0,
+ },
+ {
+ // Cluster 0, Core 1
+ 0x0, 0x1,
+ },
+ {
+ // Cluster 1, Core 0
+ 0x1, 0x0,
+ },
+ {
+ // Cluster 1, Core 1
+ 0x1, 0x1,
+ },
+ {
+ // Cluster 2, Core 0
+ 0x2, 0x0,
+ },
+ {
+ // Cluster 2, Core 1
+ 0x2, 0x1,
+ },
+ {
+ // Cluster 3, Core 0
+ 0x3, 0x0,
+ },
+ {
+ // Cluster 3, Core 1
+ 0x3, 0x1,
+ }
+};
+
+//
+// Core count
+//
+STATIC UINTN mAmdCoreCount = sizeof (mAmdMpCoreInfoTable) / sizeof (ARM_CORE_INFO);
+
+
+/*----------------------------------------------------------------------------------------
+ * P P I L I S T
+ *----------------------------------------------------------------------------------------
+ */
+STATIC EFI_PEI_ISCP_PPI *PeiIscpPpi;
+
+
+/*----------------------------------------------------------------------------------------
+ * P P I D E S C R I P T O R
+ *----------------------------------------------------------------------------------------
+ */
+STATIC EFI_PEI_PPI_DESCRIPTOR mPlatInitPpiDescriptor =
+{
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gAmdStyxPlatInitPpiGuid,
+ NULL
+};
+
+
+/**
+ *---------------------------------------------------------------------------------------
+ * PlatInitPeiEntryPoint
+ *
+ * Description:
+ * Entry point of the PlatInit PEI module.
+ *
+ * Control flow:
+ * Query platform parameters via ISCP.
+ *
+ * Parameters:
+ * @param[in] FfsHeader EFI_PEI_FILE_HANDLE
+ * @param[in] **PeiServices Pointer to the PEI Services Table.
+ *
+ * @return EFI_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ */
+EFI_STATUS
+EFIAPI
+PlatInitPeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FfsHeader,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ AMD_MEMORY_RANGE_DESCRIPTOR IscpMemDescriptor = {0};
+ ISCP_FUSE_INFO IscpFuseInfo = {0};
+ ISCP_CPU_RESET_INFO CpuResetInfo = {0};
+#if DO_XGBE == 1
+ ISCP_MAC_INFO MacAddrInfo = {0};
+ UINT64 MacAddr0, MacAddr1;
+#endif
+ UINTN CpuCoreCount, CpuMap, CpuMapSize;
+ UINTN Index, CoreNum;
+ UINT32 *CpuIdReg = (UINT32 *)FixedPcdGet32 (PcdCpuIdRegister);
+
+ DEBUG ((EFI_D_ERROR, "PlatInit PEIM Loaded\n"));
+
+ // CPUID
+ PcdSet32 (PcdSocCpuId, *CpuIdReg);
+ DEBUG ((EFI_D_ERROR, "SocCpuId = 0x%X\n", PcdGet32 (PcdSocCpuId)));
+
+ // Update core count based on PCD option
+ if (mAmdCoreCount > PcdGet32 (PcdSocCoreCount)) {
+ mAmdCoreCount = PcdGet32 (PcdSocCoreCount);
+ }
+
+ if (FixedPcdGetBool (PcdIscpSupport)) {
+ Status = PeiServicesLocatePpi (&gPeiIscpPpiGuid, 0, NULL, (VOID**)&PeiIscpPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ // Get fuse information from ISCP
+ Status = PeiIscpPpi->ExecuteFuseTransaction (PeiServices, &IscpFuseInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ CpuMap = IscpFuseInfo.SocConfiguration.CpuMap;
+ CpuCoreCount = IscpFuseInfo.SocConfiguration.CpuCoreCount;
+ CpuMapSize = sizeof (IscpFuseInfo.SocConfiguration.CpuMap) * 8;
+
+ ASSERT (CpuMap != 0);
+ ASSERT (CpuCoreCount != 0);
+ ASSERT (CpuCoreCount <= CpuMapSize);
+
+ // Update core count based on fusing
+ if (mAmdCoreCount > CpuCoreCount) {
+ mAmdCoreCount = CpuCoreCount;
+ }
+ }
+
+ //
+ // Update per-core information from ISCP
+ //
+ if (!FixedPcdGetBool (PcdIscpSupport)) {
+ DEBUG ((EFI_D_ERROR, "Warning: Could not get CPU info via ISCP, using default values.\n"));
+ } else {
+ //
+ // Walk CPU map to enumerate active cores
+ //
+ for (CoreNum = 0, Index = 0; CoreNum < CpuMapSize && Index < mAmdCoreCount; ++CoreNum) {
+ if (CpuMap & 1) {
+ CpuResetInfo.CoreNum = CoreNum;
+ Status = PeiIscpPpi->ExecuteCpuRetrieveIdTransaction (
+ PeiServices, &CpuResetInfo );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (CpuResetInfo.CoreStatus.Status != CPU_CORE_DISABLED);
+ ASSERT (CpuResetInfo.CoreStatus.Status != CPU_CORE_UNDEFINED);
+
+ mAmdMpCoreInfoTable[Index].ClusterId = CpuResetInfo.CoreStatus.ClusterId;
+ mAmdMpCoreInfoTable[Index].CoreId = CpuResetInfo.CoreStatus.CoreId;
+
+ DEBUG ((EFI_D_ERROR, "Core[%d]: ClusterId = %d CoreId = %d\n",
+ Index, mAmdMpCoreInfoTable[Index].ClusterId,
+ mAmdMpCoreInfoTable[Index].CoreId));
+
+ // Next core in Table
+ ++Index;
+ }
+ // Next core in Map
+ CpuMap >>= 1;
+ }
+
+ // Update core count based on CPU map
+ if (mAmdCoreCount > Index) {
+ mAmdCoreCount = Index;
+ }
+ }
+
+ // Update SocCoreCount on Dynamic PCD
+ if (PcdGet32 (PcdSocCoreCount) != mAmdCoreCount) {
+ PcdSet32 (PcdSocCoreCount, mAmdCoreCount);
+ }
+
+ DEBUG ((EFI_D_ERROR, "SocCoreCount = %d\n", PcdGet32 (PcdSocCoreCount)));
+
+ // Build AmdMpCoreInfo HOB
+ BuildGuidDataHob (&gAmdStyxMpCoreInfoGuid, mAmdMpCoreInfoTable, sizeof (ARM_CORE_INFO) * mAmdCoreCount);
+
+ // Get SystemMemorySize from ISCP
+ IscpMemDescriptor.Size0 = 0;
+ if (FixedPcdGetBool (PcdIscpSupport)) {
+ Status = PeiIscpPpi->ExecuteMemoryTransaction (PeiServices, &IscpMemDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ // Update SystemMemorySize on Dynamic PCD
+ if (IscpMemDescriptor.Size0) {
+ PcdSet64 (PcdSystemMemorySize, IscpMemDescriptor.Size0);
+ }
+ }
+ if (IscpMemDescriptor.Size0 == 0) {
+ DEBUG ((EFI_D_ERROR, "Warning: Could not get SystemMemorySize via ISCP, using default value.\n"));
+ }
+
+ DEBUG ((EFI_D_ERROR, "SystemMemorySize = %ld\n", PcdGet64 (PcdSystemMemorySize)));
+
+#if DO_XGBE == 1
+ // Get MAC Address from ISCP
+ if (FixedPcdGetBool (PcdIscpSupport)) {
+ Status = PeiIscpPpi->ExecuteGetMacAddressTransaction (
+ PeiServices, &MacAddrInfo );
+ ASSERT_EFI_ERROR (Status);
+
+ MacAddr0 = MacAddr1 = 0;
+ for (Index = 0; Index < 6; ++Index) {
+ MacAddr0 |= (UINT64)MacAddrInfo.MacAddress0[Index] << (Index * 8);
+ MacAddr1 |= (UINT64)MacAddrInfo.MacAddress1[Index] << (Index * 8);
+ }
+ PcdSet64 (PcdEthMacA, MacAddr0);
+ PcdSet64 (PcdEthMacB, MacAddr1);
+ }
+
+ DEBUG ((EFI_D_ERROR, "EthMacA = 0x%lX\n", PcdGet64 (PcdEthMacA)));
+ DEBUG ((EFI_D_ERROR, "EthMacB = 0x%lX\n", PcdGet64 (PcdEthMacB)));
+#endif
+
+ // Let other PEI modules know we're done!
+ Status = (*PeiServices)->InstallPpi (PeiServices, &mPlatInitPpiDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.inf b/Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.inf
new file mode 100644
index 0000000000..9f141946ae
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.inf
@@ -0,0 +1,76 @@
+#/* @file
+#
+# Copyright (c) 2014 - 2016, AMD Inc. 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 = PlatInitPei
+ FILE_GUID = 769694a4-2572-4f29-a5bb-33d7df7be001
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PlatInitPeiEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+#
+
+[Sources]
+ PlatInitPei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PeiServicesLib
+ PeiServicesTablePointerLib
+ BaseMemoryLib
+ HobLib
+ PcdLib
+ DebugLib
+ ArmLib
+ ArmSmcLib
+
+[Ppis]
+ gPeiIscpPpiGuid ## CONSUMER
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMER
+ gAmdStyxPlatInitPpiGuid ## PRODUCER
+
+[Guids]
+ gAmdStyxMpCoreInfoGuid ## PRODUCER
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+ gAmdStyxTokenSpaceGuid.PcdSocCoreCount
+ gAmdStyxTokenSpaceGuid.PcdSocCpuId
+
+ gAmdStyxTokenSpaceGuid.PcdEthMacA
+ gAmdStyxTokenSpaceGuid.PcdEthMacB
+
+[FixedPcd]
+ gAmdStyxTokenSpaceGuid.PcdIscpSupport
+ gAmdStyxTokenSpaceGuid.PcdTrustedFWSupport
+ gAmdStyxTokenSpaceGuid.PcdCpuIdRegister
+
+[Depex]
+ gPeiIscpPpiGuid
+
diff --git a/Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c b/Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
new file mode 100644
index 0000000000..4bf9fc3994
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c
@@ -0,0 +1,994 @@
+/** @file
+ Static SMBIOS Table for ARM platform
+ Derived from EmulatorPkg package
+
+ Note SMBIOS 2.7.1 Required structures:
+ BIOS Information (Type 0)
+ System Information (Type 1)
+ Board Information (Type 2)
+ System Enclosure (Type 3)
+ Processor Information (Type 4) - CPU Driver
+ Cache Information (Type 7) - For cache that is external to processor
+ System Slots (Type 9) - If system has slots
+ Physical Memory Array (Type 16)
+ Memory Device (Type 17) - For each socketed system-memory Device
+ Memory Array Mapped Address (Type 19) - One per contiguous block per Physical Memroy Array
+ System Boot Information (Type 32)
+
+ Copyright (c) 2012, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2013, Linaro Ltd. All rights reserved.<BR>
+ Copyright (c) 2014 - 2016, AMD Inc. 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.
+
+**/
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Guid/SmBios.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/AmdIscpDxeProtocol.h>
+
+/*----------------------------------------------------------------------------------------
+ * E X T E R N S
+ *----------------------------------------------------------------------------------------
+ */
+extern EFI_BOOT_SERVICES *gBS;
+
+
+/*----------------------------------------------------------------------------------------
+ * G L O B A L S
+ *----------------------------------------------------------------------------------------
+ */
+STATIC EFI_SMBIOS_PROTOCOL *mSmbiosProtocol;
+STATIC AMD_ISCP_DXE_PROTOCOL *mIscpDxeProtocol;
+STATIC ISCP_SMBIOS_INFO mSmbiosInfo;
+
+
+/***********************************************************************
+ SMBIOS data definition TYPE0 BIOS Information
+************************************************************************/
+STATIC CONST SMBIOS_TABLE_TYPE0 mBIOSInfoType0 = {
+ { EFI_SMBIOS_TYPE_BIOS_INFORMATION, sizeof (SMBIOS_TABLE_TYPE0), 0 },
+ 1, // Vendor String
+ 2, // BiosVersion String
+ 0xE000, // BiosSegment
+ 3, // BiosReleaseDate String
+ 0x7F, // BiosSize
+ { // BiosCharacteristics
+ 0, // Reserved :2; ///< Bits 0-1.
+ 0, // Unknown :1;
+ 0, // BiosCharacteristicsNotSupported :1;
+ 0, // IsaIsSupported :1;
+ 0, // McaIsSupported :1;
+ 0, // EisaIsSupported :1;
+ 0, // PciIsSupported :1;
+ 0, // PcmciaIsSupported :1;
+ 0, // PlugAndPlayIsSupported :1;
+ 0, // ApmIsSupported :1;
+ 1, // BiosIsUpgradable :1;
+ 1, // BiosShadowingAllowed :1;
+ 0, // VlVesaIsSupported :1;
+ 0, // EscdSupportIsAvailable :1;
+ 0, // BootFromCdIsSupported :1;
+ 1, // SelectableBootIsSupported :1;
+ 0, // RomBiosIsSocketed :1;
+ 0, // BootFromPcmciaIsSupported :1;
+ 0, // EDDSpecificationIsSupported :1;
+ 0, // JapaneseNecFloppyIsSupported :1;
+ 0, // JapaneseToshibaFloppyIsSupported :1;
+ 0, // Floppy525_360IsSupported :1;
+ 0, // Floppy525_12IsSupported :1;
+ 0, // Floppy35_720IsSupported :1;
+ 0, // Floppy35_288IsSupported :1;
+ 0, // PrintScreenIsSupported :1;
+ 0, // Keyboard8042IsSupported :1;
+ 0, // SerialIsSupported :1;
+ 0, // PrinterIsSupported :1;
+ 0, // CgaMonoIsSupported :1;
+ 0, // NecPc98 :1;
+ 0 // ReservedForVendor :32; ///< Bits 32-63. Bits 32-47 reserved for BIOS vendor
+ ///< and bits 48-63 reserved for System Vendor.
+ },
+ { // BIOSCharacteristicsExtensionBytes[]
+ 0x81, // AcpiIsSupported :1;
+ // UsbLegacyIsSupported :1;
+ // AgpIsSupported :1;
+ // I2OBootIsSupported :1;
+ // Ls120BootIsSupported :1;
+ // AtapiZipDriveBootIsSupported :1;
+ // Boot1394IsSupported :1;
+ // SmartBatteryIsSupported :1;
+ // BIOSCharacteristicsExtensionBytes[1]
+ 0x0a, // BiosBootSpecIsSupported :1;
+ // FunctionKeyNetworkBootIsSupported :1;
+ // TargetContentDistributionEnabled :1;
+ // UefiSpecificationSupported :1;
+ // VirtualMachineSupported :1;
+ // ExtensionByte2Reserved :3;
+ },
+ 0x00, // SystemBiosMajorRelease
+ 0x01, // SystemBiosMinorRelease
+ 0xFF, // EmbeddedControllerFirmwareMajorRelease
+ 0xFF, // EmbeddedControllerFirmwareMinorRelease
+};
+
+STATIC CHAR8 CONST * CONST mBIOSInfoType0Strings[] = {
+ "github.com/tianocore/", // Vendor String
+ __TIME__, // BiosVersion String
+ __DATE__, // BiosReleaseDate String
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE1 System Information
+************************************************************************/
+STATIC CONST SMBIOS_TABLE_TYPE1 mSysInfoType1 = {
+ { EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, sizeof (SMBIOS_TABLE_TYPE1), 0 },
+ 1, // Manufacturer String
+ 2, // ProductName String
+ 3, // Version String
+ 4, // SerialNumber String
+ { 0x25EF0280, 0xEC82, 0x42B0, { 0x8F, 0xB6, 0x10, 0xAD, 0xCC, 0xC6, 0x7C, 0x02 } },
+ SystemWakeupTypePowerSwitch,
+ 5, // SKUNumber String
+ 6, // Family String
+};
+STATIC CHAR8 CONST * CONST mSysInfoType1Strings[] = {
+ "AMD",
+ "Seattle",
+ "1.0",
+ "System Serial#",
+ "System SKU#",
+ "edk2",
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE2 Board Information
+************************************************************************/
+STATIC CONST SMBIOS_TABLE_TYPE2 mBoardInfoType2 = {
+ { EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, sizeof (SMBIOS_TABLE_TYPE2), 0 },
+ 1, // Manufacturer String
+ 2, // ProductName String
+ 3, // Version String
+ 4, // SerialNumber String
+ 5, // AssetTag String
+ { // FeatureFlag
+ 1, // Motherboard :1;
+ 0, // RequiresDaughterCard :1;
+ 0, // Removable :1;
+ 0, // Replaceable :1;
+ 0, // HotSwappable :1;
+ 0, // Reserved :3;
+ },
+ 6, // LocationInChassis String
+ 0, // ChassisHandle;
+ BaseBoardTypeMotherBoard, // BoardType;
+ 0, // NumberOfContainedObjectHandles;
+ { 0 } // ContainedObjectHandles[1];
+};
+STATIC CHAR8 CONST * CONST mBoardInfoType2Strings[] = {
+ "AMD",
+ "Seattle",
+ "1.0",
+ "Base Board Serial#",
+ "Base Board Asset Tag#",
+ "Part Component",
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE3 Enclosure Information
+************************************************************************/
+STATIC CONST SMBIOS_TABLE_TYPE3 mEnclosureInfoType3 = {
+ { EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, sizeof (SMBIOS_TABLE_TYPE3), 0 },
+ 1, // Manufacturer String
+ MiscChassisTypeLapTop, // Type;
+ 2, // Version String
+ 3, // SerialNumber String
+ 4, // AssetTag String
+ ChassisStateSafe, // BootupState;
+ ChassisStateSafe, // PowerSupplyState;
+ ChassisStateSafe, // ThermalState;
+ ChassisSecurityStatusNone,// SecurityStatus;
+ { 0, 0, 0, 0 }, // OemDefined[4];
+ 0, // Height;
+ 0, // NumberofPowerCords;
+ 0, // ContainedElementCount;
+ 0, // ContainedElementRecordLength;
+ { { 0 } }, // ContainedElements[1];
+};
+STATIC CHAR8 CONST * CONST mEnclosureInfoType3Strings[] = {
+ "AMD",
+ "1.0",
+ "Chassis Board Serial#",
+ "Chassis Board Asset Tag#",
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE4 Processor Information
+************************************************************************/
+STATIC SMBIOS_TABLE_TYPE4 mProcessorInfoType4 = {
+ { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE4), 0},
+ 1, // Socket String
+ ProcessorOther, // ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA.
+ ProcessorFamilyIndicatorFamily2, // ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY2_DATA.
+ 2, // ProcessorManufacture String;
+ { // ProcessorId;
+ { // PROCESSOR_SIGNATURE
+ 0, // ProcessorSteppingId:4;
+ 0, // ProcessorModel: 4;
+ 0, // ProcessorFamily: 4;
+ 0, // ProcessorType: 2;
+ 0, // ProcessorReserved1: 2;
+ 0, // ProcessorXModel: 4;
+ 0, // ProcessorXFamily: 8;
+ 0, // ProcessorReserved2: 4;
+ },
+
+ { // PROCESSOR_FEATURE_FLAGS
+ 0, // ProcessorFpu :1;
+ 0, // ProcessorVme :1;
+ 0, // ProcessorDe :1;
+ 0, // ProcessorPse :1;
+ 0, // ProcessorTsc :1;
+ 0, // ProcessorMsr :1;
+ 0, // ProcessorPae :1;
+ 0, // ProcessorMce :1;
+ 0, // ProcessorCx8 :1;
+ 0, // ProcessorApic :1;
+ 0, // ProcessorReserved1 :1;
+ 0, // ProcessorSep :1;
+ 0, // ProcessorMtrr :1;
+ 0, // ProcessorPge :1;
+ 0, // ProcessorMca :1;
+ 0, // ProcessorCmov :1;
+ 0, // ProcessorPat :1;
+ 0, // ProcessorPse36 :1;
+ 0, // ProcessorPsn :1;
+ 0, // ProcessorClfsh :1;
+ 0, // ProcessorReserved2 :1;
+ 0, // ProcessorDs :1;
+ 0, // ProcessorAcpi :1;
+ 0, // ProcessorMmx :1;
+ 0, // ProcessorFxsr :1;
+ 0, // ProcessorSse :1;
+ 0, // ProcessorSse2 :1;
+ 0, // ProcessorSs :1;
+ 0, // ProcessorReserved3 :1;
+ 0, // ProcessorTm :1;
+ 0, // ProcessorReserved4 :2;
+ }
+ },
+ 3, // ProcessorVersion String;
+ { // Voltage;
+ 1, // ProcessorVoltageCapability5V :1;
+ 1, // ProcessorVoltageCapability3_3V :1;
+ 1, // ProcessorVoltageCapability2_9V :1;
+ 0, // ProcessorVoltageCapabilityReserved :1; ///< Bit 3, must be zero.
+ 0, // ProcessorVoltageReserved :3; ///< Bits 4-6, must be zero.
+ 0 // ProcessorVoltageIndicateLegacy :1;
+ },
+ 0, // ExternalClock;
+ 0, // MaxSpeed;
+ 0, // CurrentSpeed;
+ 0x41, // Status;
+ ProcessorUpgradeOther, // ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE.
+ 0, // L1CacheHandle;
+ 0, // L2CacheHandle;
+ 0, // L3CacheHandle;
+ 4, // SerialNumber;
+ 5, // AssetTag;
+ 6, // PartNumber;
+ 0, // CoreCount;
+ 0, // EnabledCoreCount;
+ 0, // ThreadCount;
+ 0, // ProcessorCharacteristics;
+ ProcessorFamilyARM, // ARM Processor Family;
+};
+
+STATIC CHAR8 CONST * CONST mProcessorInfoType4Strings[] = {
+ "Socket",
+ "ARM",
+#ifdef ARM_CPU_AARCH64
+ "v8",
+#else
+ "v7",
+#endif
+ "1.0",
+ "1.0",
+ "1.0",
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE7 Cache Information
+************************************************************************/
+STATIC SMBIOS_TABLE_TYPE7 mCacheInfoType7 = {
+ { EFI_SMBIOS_TYPE_CACHE_INFORMATION, sizeof (SMBIOS_TABLE_TYPE7), 0 },
+ 1, // SocketDesignation String
+ 0x018A, // Cache Configuration
+ 0x00FF, // Maximum Size 256k
+ 0x00FF, // Install Size 256k
+ { // Supported SRAM Type
+ 0, //Other :1
+ 0, //Unknown :1
+ 0, //NonBurst :1
+ 1, //Burst :1
+ 0, //PiplelineBurst :1
+ 1, //Synchronous :1
+ 0, //Asynchronous :1
+ 0 //Reserved :9
+ },
+ { // Current SRAM Type
+ 0, //Other :1
+ 0, //Unknown :1
+ 0, //NonBurst :1
+ 1, //Burst :1
+ 0, //PiplelineBurst :1
+ 1, //Synchronous :1
+ 0, //Asynchronous :1
+ 0 //Reserved :9
+ },
+ 0, // Cache Speed unknown
+ CacheErrorMultiBit, // Error Correction Multi
+ CacheTypeUnknown, // System Cache Type
+ CacheAssociativity2Way // Associativity
+};
+STATIC CONST CHAR8 *mCacheInfoType7Strings[] = {
+ "Cache1",
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE9 System Slot Information
+************************************************************************/
+STATIC CONST SMBIOS_TABLE_TYPE9 mSysSlotInfoType9 = {
+ { EFI_SMBIOS_TYPE_SYSTEM_SLOTS, sizeof (SMBIOS_TABLE_TYPE9), 0 },
+ 1, // SlotDesignation String
+ SlotTypeOther, // SlotType; ///< The enumeration value from MISC_SLOT_TYPE.
+ SlotDataBusWidthOther, // SlotDataBusWidth; ///< The enumeration value from MISC_SLOT_DATA_BUS_WIDTH.
+ SlotUsageAvailable, // CurrentUsage; ///< The enumeration value from MISC_SLOT_USAGE.
+ SlotLengthOther, // SlotLength; ///< The enumeration value from MISC_SLOT_LENGTH.
+ 0, // SlotID;
+ { // SlotCharacteristics1;
+ 1, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 0, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0, // ModemRingResumeSupported:1;
+ },
+ { // SlotCharacteristics2;
+ 0, // PmeSignalSupported :1;
+ 0, // HotPlugDevicesSupported :1;
+ 0, // SmbusSignalSupported :1;
+ 0, // Reserved :5; ///< Set to 0.
+ },
+ 0, // SegmentGroupNum;
+ 0, // BusNum;
+ 0, // DevFuncNum;
+};
+STATIC CHAR8 CONST * CONST mSysSlotInfoType9Strings[] = {
+ "SD Card",
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE16 Physical Memory ArrayInformation
+************************************************************************/
+STATIC SMBIOS_TABLE_TYPE16 mPhyMemArrayInfoType16 = {
+ { EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, sizeof (SMBIOS_TABLE_TYPE16), 0 },
+ MemoryArrayLocationSystemBoard, // Location; ///< The enumeration value from MEMORY_ARRAY_LOCATION.
+ MemoryArrayUseSystemMemory, // Use; ///< The enumeration value from MEMORY_ARRAY_USE.
+ MemoryErrorCorrectionUnknown, // MemoryErrorCorrection; ///< The enumeration value from MEMORY_ERROR_CORRECTION.
+ 0x80000000, // MaximumCapacity;
+ 0xFFFE, // MemoryErrorInformationHandle;
+ 1, // NumberOfMemoryDevices;
+ 0x3fffffffffffffffULL, // ExtendedMaximumCapacity;
+};
+STATIC CHAR8 CONST * CONST mPhyMemArrayInfoType16Strings[] = {
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE17 Memory Device Information
+************************************************************************/
+STATIC SMBIOS_TABLE_TYPE17 mMemDevInfoType17 = {
+ { EFI_SMBIOS_TYPE_MEMORY_DEVICE, sizeof (SMBIOS_TABLE_TYPE17), 0 },
+ 0, // MemoryArrayHandle;
+ 0xFFFE, // MemoryErrorInformationHandle;
+ 0xFFFF, // TotalWidth;
+ 0xFFFF, // DataWidth;
+ 0xFFFF, // Size;
+ MemoryFormFactorUnknown, // FormFactor; ///< The enumeration value from MEMORY_FORM_FACTOR.
+ 0xff, // DeviceSet;
+ 1, // DeviceLocator String
+ 2, // BankLocator String
+ MemoryTypeDram, // MemoryType; ///< The enumeration value from MEMORY_DEVICE_TYPE.
+ { // TypeDetail;
+ 0, // Reserved :1;
+ 0, // Other :1;
+ 1, // Unknown :1;
+ 0, // FastPaged :1;
+ 0, // StaticColumn :1;
+ 0, // PseudoStatic :1;
+ 0, // Rambus :1;
+ 0, // Synchronous :1;
+ 0, // Cmos :1;
+ 0, // Edo :1;
+ 0, // WindowDram :1;
+ 0, // CacheDram :1;
+ 0, // Nonvolatile :1;
+ 0, // Registered :1;
+ 0, // Unbuffered :1;
+ 0, // Reserved1 :1;
+ },
+ 0, // Speed;
+ 3, // Manufacturer String
+ 0, // SerialNumber String
+ 0, // AssetTag String
+ 0, // PartNumber String
+ 0, // Attributes;
+ 0, // ExtendedSize;
+ 0, // ConfiguredMemoryClockSpeed;
+};
+
+#if (FixedPcdGetBool (PcdIscpSupport))
+STATIC CHAR8 CONST *mMemDevInfoType17Strings[ 7 ] = {0};
+#else
+STATIC CHAR8 CONST * CONST mMemDevInfoType17Strings[] = {
+ "OS Virtual Memory",
+ "malloc",
+ "OSV",
+ NULL
+};
+#endif
+
+/***********************************************************************
+ SMBIOS data definition TYPE19 Memory Array Mapped Address Information
+************************************************************************/
+STATIC SMBIOS_TABLE_TYPE19 mMemArrMapInfoType19 = {
+ { EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, sizeof (SMBIOS_TABLE_TYPE19), 0 },
+ 0x80000000, // StartingAddress;
+ 0xbfffffff, // EndingAddress;
+ 0, // MemoryArrayHandle;
+ 1, // PartitionWidth;
+ 0, // ExtendedStartingAddress;
+ 0, // ExtendedEndingAddress;
+};
+STATIC CHAR8 CONST * CONST mMemArrMapInfoType19Strings[] = {
+ NULL
+};
+
+/***********************************************************************
+ SMBIOS data definition TYPE32 Boot Information
+************************************************************************/
+STATIC CONST SMBIOS_TABLE_TYPE32 mBootInfoType32 = {
+ { EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, sizeof (SMBIOS_TABLE_TYPE32), 0 },
+ { 0, 0, 0, 0, 0, 0 }, // Reserved[6];
+ BootInformationStatusNoError // BootStatus
+};
+
+STATIC CHAR8 CONST * CONST mBootInfoType32Strings[] = {
+ NULL
+};
+
+
+/**
+
+ Create SMBIOS record.
+
+ Converts a fixed SMBIOS structure and an array of pointers to strings into
+ an SMBIOS record where the strings are cat'ed on the end of the fixed record
+ and terminated via a double NULL and add to SMBIOS table.
+
+ SMBIOS_TABLE_TYPE32 gSmbiosType12 = {
+ { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },
+ 1 // StringCount
+ };
+
+ CHAR8 *gSmbiosType12Strings[] = {
+ "Not Found",
+ NULL
+ };
+
+ ...
+
+ LogSmbiosData (
+ (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12,
+ gSmbiosType12Strings
+ );
+
+ @param Template Fixed SMBIOS structure, required.
+ @param StringArray Array of strings to convert to an SMBIOS string pack.
+ NULL is OK.
+**/
+
+STATIC
+EFI_STATUS
+EFIAPI
+LogSmbiosData (
+ IN EFI_SMBIOS_TABLE_HEADER *Template,
+ IN CONST CHAR8* CONST *StringPack
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TABLE_HEADER *Record;
+ UINTN Index;
+ UINTN StringSize;
+ UINTN Size;
+ CHAR8 *Str;
+
+
+ // Calculate the size of the fixed record and optional string pack
+ Size = Template->Length;
+ if (StringPack == NULL) {
+ // At least a double null is required
+ Size += 2;
+ } else {
+ for (Index = 0; StringPack[Index] != NULL; Index++) {
+ StringSize = AsciiStrSize (StringPack[Index]);
+ Size += StringSize;
+ }
+ if (StringPack[0] == NULL) {
+ // At least a double null is required
+ Size += 1;
+ }
+
+ // Don't forget the terminating double null
+ Size += 1;
+ }
+
+ // Copy over Template
+ Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size);
+ if (Record == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Record, Template, Template->Length);
+
+ // Append string pack
+ Str = ((CHAR8 *)Record) + Record->Length;
+ for (Index = 0; StringPack[Index] != NULL; Index++) {
+ StringSize = AsciiStrSize (StringPack[Index]);
+ CopyMem (Str, StringPack[Index], StringSize);
+ Str += StringSize;
+ }
+ *Str = 0;
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbiosProtocol->Add (
+ mSmbiosProtocol,
+ gImageHandle,
+ &SmbiosHandle,
+ Record
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ FreePool (Record);
+ return Status;
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE0 BIOS Information
+************************************************************************/
+STATIC
+VOID
+BIOSInfoUpdateSmbiosType0 (
+ VOID
+ )
+{
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mBIOSInfoType0, mBIOSInfoType0Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE1 System Information
+************************************************************************/
+STATIC
+VOID
+SysInfoUpdateSmbiosType1 (
+ VOID
+ )
+{
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mSysInfoType1, mSysInfoType1Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE2 Board Information
+************************************************************************/
+STATIC
+VOID
+BoardInfoUpdateSmbiosType2 (
+ VOID
+ )
+{
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mBoardInfoType2, mBoardInfoType2Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE3 Enclosure Information
+************************************************************************/
+STATIC
+VOID
+EnclosureInfoUpdateSmbiosType3 (
+ VOID
+ )
+{
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mEnclosureInfoType3, mEnclosureInfoType3Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE4 Processor Information
+************************************************************************/
+STATIC
+VOID
+ProcessorInfoUpdateSmbiosType4 (
+ VOID
+ )
+{
+#if (FixedPcdGetBool (PcdIscpSupport))
+ ISCP_TYPE4_SMBIOS_INFO *SmbiosT4 = &mSmbiosInfo.SmbiosCpuBuffer.T4[0];
+
+ DEBUG ((EFI_D_ERROR, "Logging SmbiosType4 from ISCP.\n"));
+
+ mProcessorInfoType4.ProcessorType = SmbiosT4->T4ProcType;
+ mProcessorInfoType4.ProcessorFamily = SmbiosT4->T4ProcFamily;
+ mProcessorInfoType4.ProcessorFamily2 = SmbiosT4->T4ProcFamily2;
+ mProcessorInfoType4.ProcessorCharacteristics = SmbiosT4->T4ProcCharacteristics;
+ mProcessorInfoType4.MaxSpeed = SmbiosT4->T4MaxSpeed;
+ mProcessorInfoType4.CurrentSpeed = SmbiosT4->T4CurrentSpeed;
+ mProcessorInfoType4.CoreCount = SmbiosT4->T4CoreCount;
+ mProcessorInfoType4.EnabledCoreCount = SmbiosT4->T4CoreEnabled;
+ mProcessorInfoType4.ThreadCount = SmbiosT4->T4ThreadCount;
+ mProcessorInfoType4.ProcessorUpgrade = SmbiosT4->T4ProcUpgrade;
+ mProcessorInfoType4.Status= (UINT8)SmbiosT4->T4Status;
+ mProcessorInfoType4.ExternalClock = SmbiosT4->T4ExternalClock;
+ CopyMem (&mProcessorInfoType4.ProcessorId.Signature,
+ &SmbiosT4->T4ProcId.ProcIDLsd, sizeof(UINT32));
+ CopyMem (&mProcessorInfoType4.ProcessorId.FeatureFlags,
+ &SmbiosT4->T4ProcId.ProcIDMsd, sizeof(UINT32));
+ CopyMem (&mProcessorInfoType4.Voltage,
+ &SmbiosT4->T4Voltage, sizeof(UINT8));
+#else
+ mProcessorInfoType4.ProcessorType = CentralProcessor;
+ mProcessorInfoType4.ProcessorFamily = ProcessorFamilyIndicatorFamily2;
+ mProcessorInfoType4.ProcessorFamily2 = ProcessorFamilyARM;
+ #ifdef ARM_CPU_AARCH64
+ mProcessorInfoType4.ProcessorCharacteristics = 0x6C;
+ #else
+ mProcessorInfoType4.ProcessorCharacteristics = 0x68;
+ #endif
+ mProcessorInfoType4.MaxSpeed = PcdGet32(PcdArmArchTimerFreqInHz)/1000000; // In MHz
+ mProcessorInfoType4.CurrentSpeed = PcdGet32(PcdArmArchTimerFreqInHz)/1000000; // In MHz
+ mProcessorInfoType4.CoreCount = PcdGet32(PcdCoreCount);
+ mProcessorInfoType4.EnabledCoreCount = PcdGet32(PcdCoreCount);
+ mProcessorInfoType4.ThreadCount = PcdGet32(PcdCoreCount);
+ mProcessorInfoType4.ProcessorUpgrade = ProcessorUpgradeDaughterBoard;
+#endif
+
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mProcessorInfoType4, mProcessorInfoType4Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE7 Cache Information
+************************************************************************/
+STATIC
+VOID
+CacheInfoUpdateSmbiosType7 (
+ VOID
+ )
+{
+#if (FixedPcdGetBool (PcdIscpSupport))
+ ISCP_TYPE7_SMBIOS_INFO *SmbiosT7;
+ SMBIOS_TABLE_TYPE7 dstType7 = {{0}};
+
+ DEBUG ((EFI_D_ERROR, "Logging SmbiosType7 from ISCP.\n"));
+
+ CopyMem ((VOID *) &dstType7.Hdr, (VOID *) &mCacheInfoType7.Hdr, sizeof (SMBIOS_STRUCTURE));
+ dstType7.SocketDesignation = 1; // "L# Cache"
+
+ // L1 cache settings
+ mCacheInfoType7Strings[0] = "L1 Cache";
+ SmbiosT7 = &mSmbiosInfo.SmbiosCpuBuffer.T7L1[0];
+ dstType7.CacheConfiguration = SmbiosT7->T7CacheCfg;
+ dstType7.MaximumCacheSize = SmbiosT7->T7MaxCacheSize;
+ dstType7.InstalledSize = SmbiosT7->T7InstallSize;
+ CopyMem (&dstType7.SupportedSRAMType,
+ &SmbiosT7->T7SupportedSramType, sizeof(UINT16));
+ CopyMem (&dstType7.CurrentSRAMType,
+ &SmbiosT7->T7CurrentSramType, sizeof(UINT16));
+ dstType7.CacheSpeed = SmbiosT7->T7CacheSpeed;
+ dstType7.ErrorCorrectionType = SmbiosT7->T7ErrorCorrectionType;
+ dstType7.SystemCacheType = SmbiosT7->T7SystemCacheType;
+ dstType7.Associativity = SmbiosT7->T7Associativity;
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&dstType7, mCacheInfoType7Strings);
+
+ // L2 cache settings
+ mCacheInfoType7Strings[0] = "L2 Cache";
+ SmbiosT7 = &mSmbiosInfo.SmbiosCpuBuffer.T7L2[0];
+ dstType7.CacheConfiguration = SmbiosT7->T7CacheCfg;
+ dstType7.MaximumCacheSize = SmbiosT7->T7MaxCacheSize;
+ dstType7.InstalledSize = SmbiosT7->T7InstallSize;
+ CopyMem (&dstType7.SupportedSRAMType,
+ &SmbiosT7->T7SupportedSramType, sizeof(UINT16));
+ CopyMem (&dstType7.CurrentSRAMType,
+ &SmbiosT7->T7CurrentSramType, sizeof(UINT16));
+ dstType7.CacheSpeed = SmbiosT7->T7CacheSpeed;
+ dstType7.ErrorCorrectionType = SmbiosT7->T7ErrorCorrectionType;
+ dstType7.SystemCacheType = SmbiosT7->T7SystemCacheType;
+ dstType7.Associativity = SmbiosT7->T7Associativity;
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&dstType7, mCacheInfoType7Strings);
+
+ // L3 cache settings
+ mCacheInfoType7Strings[0] = "L3 Cache";
+ SmbiosT7 = &mSmbiosInfo.SmbiosCpuBuffer.T7L3[0];
+ dstType7.CacheConfiguration = SmbiosT7->T7CacheCfg;
+ dstType7.MaximumCacheSize = SmbiosT7->T7MaxCacheSize;
+ dstType7.InstalledSize = SmbiosT7->T7InstallSize;
+ CopyMem (&dstType7.SupportedSRAMType,
+ &SmbiosT7->T7SupportedSramType, sizeof(UINT16));
+ CopyMem (&dstType7.CurrentSRAMType,
+ &SmbiosT7->T7CurrentSramType, sizeof(UINT16));
+ dstType7.CacheSpeed = SmbiosT7->T7CacheSpeed;
+ dstType7.ErrorCorrectionType = SmbiosT7->T7ErrorCorrectionType;
+ dstType7.SystemCacheType = SmbiosT7->T7SystemCacheType;
+ dstType7.Associativity = SmbiosT7->T7Associativity;
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&dstType7, mCacheInfoType7Strings);
+#else
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mCacheInfoType7, mCacheInfoType7Strings);
+#endif
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE9 System Slot Information
+************************************************************************/
+STATIC
+VOID
+SysSlotInfoUpdateSmbiosType9 (
+ VOID
+ )
+{
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mSysSlotInfoType9, mSysSlotInfoType9Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE16 Physical Memory Array Information
+************************************************************************/
+STATIC
+VOID
+PhyMemArrayInfoUpdateSmbiosType16 (
+ VOID
+ )
+{
+#if (FixedPcdGetBool (PcdIscpSupport))
+ ISCP_TYPE16_SMBIOS_INFO *SmbiosT16 = &mSmbiosInfo.SmbiosMemBuffer.T16;
+
+ DEBUG ((EFI_D_ERROR, "Logging SmbiosType16 from ISCP.\n"));
+
+ mPhyMemArrayInfoType16.Location = SmbiosT16->Location;
+ mPhyMemArrayInfoType16.Use = SmbiosT16->Use;
+ mPhyMemArrayInfoType16.MemoryErrorCorrection = SmbiosT16->MemoryErrorCorrection;
+ mPhyMemArrayInfoType16.NumberOfMemoryDevices = SmbiosT16->NumberOfMemoryDevices;
+#endif
+
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mPhyMemArrayInfoType16, mPhyMemArrayInfoType16Strings);
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE17 Memory Device Information
+************************************************************************/
+STATIC
+VOID
+MemDevInfoUpdatedstType17 (
+ VOID
+ )
+{
+#if (FixedPcdGetBool (PcdIscpSupport))
+ SMBIOS_TABLE_TYPE17 dstType17 = {{0}};
+ ISCP_TYPE17_SMBIOS_INFO *srcType17;
+ UINTN i, j, StrIndex, LastIndex;
+
+ DEBUG ((EFI_D_ERROR, "Logging SmbiosType17 from ISCP.\n"));
+
+ LastIndex = (sizeof(mMemDevInfoType17Strings) / sizeof (CHAR8 *)) - 1;
+ for (i = 0; i < 2; ++i) {
+ for (j = 0; j < 2; ++j) {
+ srcType17 = &mSmbiosInfo.SmbiosMemBuffer.T17[i][j];
+
+ CopyMem ((VOID *) &dstType17.Hdr, (VOID *) &mMemDevInfoType17.Hdr, sizeof (SMBIOS_STRUCTURE));
+ dstType17.MemoryArrayHandle = srcType17->Handle;
+ dstType17.TotalWidth = srcType17->TotalWidth;
+ dstType17.DataWidth = srcType17->DataWidth;
+ dstType17.Size = srcType17->MemorySize;
+ dstType17.FormFactor = srcType17->FormFactor;
+ dstType17.DeviceSet = srcType17->DeviceSet;
+ dstType17.MemoryType = srcType17->MemoryType;
+
+ CopyMem ((VOID *) &dstType17.TypeDetail, (VOID *) &mMemDevInfoType17.TypeDetail, sizeof (UINT16));
+ dstType17.Speed = srcType17->Speed;
+ dstType17.Attributes = srcType17->Attributes;
+ dstType17.ExtendedSize = srcType17->ExtSize;
+ dstType17.ConfiguredMemoryClockSpeed = srcType17->ConfigSpeed;
+
+ // Build table of TYPE17 strings
+ StrIndex = 0;
+
+ if (AsciiStrLen ((CHAR8 *)srcType17->DeviceLocator) && StrIndex < LastIndex) {
+ mMemDevInfoType17Strings[StrIndex++] = (CHAR8 *)srcType17->DeviceLocator;
+ dstType17.DeviceLocator = (SMBIOS_TABLE_STRING) StrIndex;
+ } else {
+ dstType17.DeviceLocator = 0;
+ }
+
+ if (AsciiStrLen ((CHAR8 *)srcType17->BankLocator) && StrIndex < LastIndex) {
+ mMemDevInfoType17Strings[StrIndex++] = (CHAR8 *)srcType17->BankLocator;
+ dstType17.BankLocator = (SMBIOS_TABLE_STRING) StrIndex;
+ } else {
+ dstType17.BankLocator = 0;
+ }
+
+ if (AsciiStrLen ((CHAR8 *)srcType17->ManufacturerIdCode) && StrIndex < LastIndex) {
+ mMemDevInfoType17Strings[StrIndex++] = (CHAR8 *)srcType17->ManufacturerIdCode;
+ dstType17.Manufacturer = (SMBIOS_TABLE_STRING) StrIndex;
+ } else {
+ dstType17.Manufacturer = 0;
+ }
+
+ if (AsciiStrLen ((CHAR8 *)srcType17->SerialNumber) && StrIndex < LastIndex) {
+ mMemDevInfoType17Strings[StrIndex++] = (CHAR8 *)srcType17->SerialNumber;
+ dstType17.SerialNumber = (SMBIOS_TABLE_STRING) StrIndex;
+ } else {
+ dstType17.SerialNumber = 0;
+ }
+
+ if (AsciiStrLen ((CHAR8 *)srcType17->PartNumber) && StrIndex < LastIndex) {
+ mMemDevInfoType17Strings[StrIndex++] = (CHAR8 *)srcType17->PartNumber;
+ dstType17.PartNumber = (SMBIOS_TABLE_STRING) StrIndex;
+ } else {
+ dstType17.PartNumber = 0;
+ }
+
+ mMemDevInfoType17Strings[StrIndex] = NULL;
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&dstType17, mMemDevInfoType17Strings);
+ }
+ }
+#else
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mMemDevInfoType17, mMemDevInfoType17Strings);
+#endif
+}
+
+/***********************************************************************
+ SMBIOS data update TYPE19 Memory Array Map Information
+************************************************************************/
+STATIC
+VOID
+MemArrMapInfoUpdateSmbiosType19 (
+ VOID
+ )
+{
+#if (FixedPcdGetBool (PcdIscpSupport))
+ ISCP_TYPE19_SMBIOS_INFO *SmbiosT19 = &mSmbiosInfo.SmbiosMemBuffer.T19;
+
+ DEBUG ((EFI_D_ERROR, "Logging SmbiosType19 from ISCP.\n"));
+
+ mMemArrMapInfoType19.StartingAddress = SmbiosT19->StartingAddr;
+ mMemArrMapInfoType19.EndingAddress = SmbiosT19->EndingAddr;
+ mMemArrMapInfoType19.MemoryArrayHandle = SmbiosT19->MemoryArrayHandle;
+ mMemArrMapInfoType19.PartitionWidth = SmbiosT19->PartitionWidth;
+ mMemArrMapInfoType19.ExtendedStartingAddress = SmbiosT19->ExtStartingAddr;
+ mMemArrMapInfoType19.ExtendedEndingAddress = SmbiosT19->ExtEndingAddr;
+#endif
+
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mMemArrMapInfoType19, mMemArrMapInfoType19Strings);
+}
+
+
+/***********************************************************************
+ SMBIOS data update TYPE32 Boot Information
+************************************************************************/
+STATIC
+VOID
+BootInfoUpdateSmbiosType32 (
+ VOID
+ )
+{
+ LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mBootInfoType32, mBootInfoType32Strings);
+}
+
+/***********************************************************************
+ Driver Entry
+************************************************************************/
+EFI_STATUS
+EFIAPI
+PlatformSmbiosDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_ERROR, "PlatformSmbiosDxe Loaded\n"));
+
+ //
+ // Locate Smbios protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiSmbiosProtocolGuid,
+ NULL,
+ (VOID **)&mSmbiosProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ mSmbiosProtocol = NULL;
+ DEBUG ((EFI_D_ERROR, "Failed to Locate SMBIOS Protocol"));
+ return Status;
+ }
+
+#if (FixedPcdGetBool (PcdIscpSupport))
+ Status = gBS->LocateProtocol (
+ &gAmdIscpDxeProtocolGuid,
+ NULL,
+ (VOID **)&mIscpDxeProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ mIscpDxeProtocol = NULL;
+ DEBUG ((EFI_D_ERROR, "Failed to Locate ISCP DXE Protocol"));
+ return Status;
+ }
+
+ Status = mIscpDxeProtocol-> AmdExecuteSmbiosInfoDxe (
+ mIscpDxeProtocol,
+ &mSmbiosInfo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Failed to get SMBIOS data via ISCP"));
+ return Status;
+ }
+#endif
+
+ BIOSInfoUpdateSmbiosType0();
+
+ SysInfoUpdateSmbiosType1();
+
+ BoardInfoUpdateSmbiosType2();
+
+ EnclosureInfoUpdateSmbiosType3();
+
+ ProcessorInfoUpdateSmbiosType4();
+
+ CacheInfoUpdateSmbiosType7();
+
+ SysSlotInfoUpdateSmbiosType9();
+
+ PhyMemArrayInfoUpdateSmbiosType16();
+
+ MemDevInfoUpdatedstType17();
+
+ MemArrMapInfoUpdateSmbiosType19();
+
+ BootInfoUpdateSmbiosType32();
+
+ return Status;
+}
diff --git a/Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf b/Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
new file mode 100644
index 0000000000..0027d79031
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
@@ -0,0 +1,60 @@
+#/** @file
+# SMBIOS Table for ARM platform
+#
+# Copyright (c) 2013, Linaro Ltd. All rights reserved.<BR>
+# Copyright (c) 2014 - 2016, AMD Inc. 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 = PlatformSmbiosDxe
+ FILE_GUID = 3847D23F-1D95-4772-B60C-4BBFBC4D532F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformSmbiosDriverEntryPoint
+
+[Sources]
+ PlatformSmbiosDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ BaseLib
+ UefiLib
+ UefiDriverEntryPoint
+ DebugLib
+
+
+[Protocols]
+ gEfiSmbiosProtocolGuid ## CONSUMER
+ gAmdIscpDxeProtocolGuid ## CONSUMER
+
+[Guids]
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+ gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
+ gAmdStyxTokenSpaceGuid.PcdIscpSupport
+
+[Depex]
+ gEfiSmbiosProtocolGuid AND
+ gAmdIscpDxeProtocolGuid
+
diff --git a/Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.c b/Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.c
new file mode 100644
index 0000000000..be6cf9eda5
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.c
@@ -0,0 +1,189 @@
+/** @file
+
+ This driver produces an EFI_RNG_PROTOCOL instance for the AMD Seattle CCP
+
+ 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 <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+
+#include <Protocol/Rng.h>
+
+#define CCP_TRNG_OFFSET 0xc
+#define CCP_TNRG_RETRIES 5
+
+STATIC EFI_PHYSICAL_ADDRESS mCcpRngOutputReg;
+
+STATIC EFI_HANDLE mHandle;
+
+/**
+ Returns information about the random number generation implementation.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL
+ instance.
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
+ RNGAlgorithmList.
+ On output with a return code of
+ EFI_SUCCESS, the size in bytes of the
+ data returned in RNGAlgorithmList. On
+ output with a return code of
+ EFI_BUFFER_TOO_SMALL, the size of
+ RNGAlgorithmList required to obtain the
+ list.
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled
+ by the driver with one EFI_RNG_ALGORITHM
+ element for each supported RNG algorithm.
+ The list must not change across multiple
+ calls to the same driver. The first
+ algorithm in the list is the default
+ algorithm for the driver.
+
+ @retval EFI_SUCCESS The RNG algorithm list was returned
+ successfully.
+ @retval EFI_UNSUPPORTED The services is not supported by this
+ driver.
+ @retval EFI_DEVICE_ERROR The list of algorithms could not be
+ retrieved due to a hardware or firmware
+ error.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are
+ incorrect.
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small
+ to hold the result.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StyxRngGetInfo (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ if (This == NULL || RNGAlgorithmListSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (RNGAlgorithmList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
+ CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Produces and returns an RNG value using either the default or specified RNG
+ algorithm.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL
+ instance.
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that
+ identifies the RNG algorithm to use. May
+ be NULL in which case the function will
+ use its default RNG algorithm.
+ @param[in] RNGValueLength The length in bytes of the memory buffer
+ pointed to by RNGValue. The driver shall
+ return exactly this numbers of bytes.
+ @param[out] RNGValue A caller-allocated memory buffer filled
+ by the driver with the resulting RNG
+ value.
+
+ @retval EFI_SUCCESS The RNG value was returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm
+ is not supported by this driver.
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due
+ to a hardware or firmware error.
+ @retval EFI_NOT_READY There is not enough random data available
+ to satisfy the length requested by
+ RNGValueLength.
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is
+ zero.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StyxRngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ UINT32 Val;
+ UINT32 Retries;
+ UINT32 Loop;
+
+ if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // We only support the raw algorithm, so reject requests for anything else
+ //
+ if (RNGAlgorithm != NULL &&
+ !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ do {
+ Retries = CCP_TNRG_RETRIES;
+ do {
+ Val = MmioRead32 (mCcpRngOutputReg);
+ } while (!Val && Retries-- > 0);
+
+ if (!Val) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ for (Loop = 0; Loop < 4 && RNGValueLength > 0; Loop++, RNGValueLength--) {
+ *RNGValue++ = (UINT8)Val;
+ Val >>= 8;
+ }
+ } while (RNGValueLength > 0);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_RNG_PROTOCOL mStyxRngProtocol = {
+ StyxRngGetInfo,
+ StyxRngGetRNG
+};
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+StyxRngEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ mCcpRngOutputReg = PcdGet64 (PcdCCPBase) + CCP_TRNG_OFFSET;
+
+ return SystemTable->BootServices->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiRngProtocolGuid, &mStyxRngProtocol,
+ NULL
+ );
+}
diff --git a/Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.inf b/Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.inf
new file mode 100644
index 0000000000..e63656037e
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.inf
@@ -0,0 +1,47 @@
+## @file
+# This driver produces an EFI_RNG_PROTOCOL instance for the AMD Seattle CCP
+#
+# 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 = StyxRngDxe
+ FILE_GUID = 58E26F0D-CBAC-4BBA-B70F-18221415665A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = StyxRngEntryPoint
+
+[Sources]
+ StyxRngDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ IoLib
+ PcdLib
+ UefiDriverEntryPoint
+
+[Pcd]
+ gAmdModulePkgTokenSpaceGuid.PcdCCPBase
+
+[Protocols]
+ gEfiRngProtocolGuid ## PRODUCES
+
+[Guids]
+ gEfiRngAlgorithmRaw
+
+[Depex]
+ TRUE
diff --git a/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c
new file mode 100644
index 0000000000..1958d918d9
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c
@@ -0,0 +1,201 @@
+/** @file
+ Initialize SATA Phy, Serdes, and Controller.
+
+ Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.<BR>
+ 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 "SataRegisters.h"
+
+#include <Library/AmdSataInitLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+
+#include <Protocol/NonDiscoverableDevice.h>
+
+STATIC
+VOID
+ResetSataController (
+ EFI_PHYSICAL_ADDRESS AhciBaseAddr
+ )
+{
+ // Make a minimal global reset for HBA regiser
+ MmioOr32 (AhciBaseAddr + EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
+
+ // Clear all interrupts
+ MmioWrite32 (AhciBaseAddr + EFI_AHCI_PORT_IS, EFI_AHCI_PORT_IS_CLEAR);
+
+ // Turn on interrupts and ensure that the HBA is working in AHCI mode
+ MmioOr32 (AhciBaseAddr + EFI_AHCI_GHC_OFFSET,
+ EFI_AHCI_GHC_IE | EFI_AHCI_GHC_ENABLE);
+}
+
+STATIC
+VOID
+SetSataCapabilities (
+ EFI_PHYSICAL_ADDRESS AhciBaseAddr
+ )
+{
+ UINT32 Capability;
+
+ Capability = 0;
+ if (FixedPcdGetBool (PcdSataSssSupport)) // Staggered Spin-Up Support bit
+ Capability |= EFI_AHCI_CAP_SSS;
+ if (FixedPcdGetBool (PcdSataSmpsSupport)) // Mechanical Presence Support bit
+ Capability |= EFI_AHCI_CAP_SMPS;
+
+ MmioOr32 (AhciBaseAddr + EFI_AHCI_CAPABILITY_OFFSET, Capability);
+}
+
+STATIC
+VOID
+InitializeSataPorts (
+ EFI_PHYSICAL_ADDRESS AhciBaseAddr,
+ UINTN PortCount
+ )
+{
+ INTN PortNum;
+ BOOLEAN IsCpd;
+ BOOLEAN IsMpsp;
+ UINT32 PortRegAddr;
+ UINT32 RegVal;
+
+ // Set Ports Implemented (PI)
+ MmioWrite32 (AhciBaseAddr + EFI_AHCI_PI_OFFSET, (1 << PortCount) - 1);
+
+ IsCpd = FixedPcdGetBool (PcdSataPortCpd);
+ IsMpsp = FixedPcdGetBool (PcdSataPortMpsp);
+ if (!IsCpd && !IsMpsp) {
+ return;
+ }
+
+ for (PortNum = 0; PortNum < PortCount; PortNum++) {
+ PortRegAddr = EFI_AHCI_PORT_OFFSET (PortNum) + EFI_AHCI_PORT_CMD;
+ RegVal = MmioRead32(AhciBaseAddr + PortRegAddr);
+ if (IsCpd)
+ RegVal |= EFI_AHCI_PORT_CMD_CPD;
+ else
+ RegVal &= ~EFI_AHCI_PORT_CMD_CPD;
+ if (IsMpsp)
+ RegVal |= EFI_AHCI_PORT_CMD_MPSP;
+ else
+ RegVal &= ~EFI_AHCI_PORT_CMD_MPSP;
+ RegVal |= EFI_AHCI_PORT_CMD_HPCP;
+ MmioWrite32(AhciBaseAddr + PortRegAddr, RegVal);
+ }
+}
+
+STATIC
+EFI_STATUS
+InitializeSataController (
+ EFI_PHYSICAL_ADDRESS AhciBaseAddr,
+ UINTN SataPortCount,
+ UINTN StartPort
+ )
+{
+ UINT8 SataChPerSerdes;
+ UINT32 PortNum;
+ UINT32 EvenPort;
+ UINT32 OddPort;
+
+ SataChPerSerdes = FixedPcdGet8 (PcdSataNumChPerSerdes);
+
+ for (PortNum = 0; PortNum < SataPortCount; PortNum += SataChPerSerdes) {
+ EvenPort = (UINT32)(FixedPcdGet16 (PcdSataPortMode) >> (PortNum * 2)) & 3;
+ OddPort = (UINT32)(FixedPcdGet16 (PcdSataPortMode) >> ((PortNum+1) * 2)) & 3;
+ SataPhyInit ((StartPort + PortNum) / SataChPerSerdes, EvenPort, OddPort);
+ }
+
+ //
+ // Reset SATA controller
+ //
+ ResetSataController (AhciBaseAddr);
+
+ //
+ // Set SATA capabilities
+ //
+ SetSataCapabilities (AhciBaseAddr);
+
+ //
+ // Set and intialize the Sata ports
+ //
+ InitializeSataPorts (AhciBaseAddr, SataPortCount);
+
+ return RegisterNonDiscoverableMmioDevice (
+ NonDiscoverableDeviceTypeAhci,
+ NonDiscoverableDeviceDmaTypeCoherent,
+ NULL,
+ NULL,
+ 1,
+ AhciBaseAddr, SIZE_4KB);
+}
+
+#define STYX_SOC_VERSION_MASK 0xFFF
+#define STYX_SOC_VERSION_A0 0x000
+#define STYX_SOC_VERSION_B0 0x010
+#define STYX_SOC_VERSION_B1 0x011
+
+EFI_STATUS
+EFIAPI
+StyxSataPlatformDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT32 PortNum;
+ EFI_STATUS Status;
+
+ //
+ // Perform SATA workarounds
+ //
+ for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata0PortCount); PortNum++) {
+ SetCwMinSata0 (PortNum);
+ }
+
+ Status = InitializeSataController (FixedPcdGet32(PcdSata0CtrlAxiSlvPort),
+ FixedPcdGet8(PcdSata0PortCount), 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: failed to initialize primary SATA controller!\n",
+ __FUNCTION__));
+ return Status;
+ }
+
+ for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata0PortCount); PortNum++) {
+ SetPrdSingleSata0 (PortNum);
+ }
+
+ //
+ // Ignore the second SATA controller on pre-B1 silicon
+ //
+ if ((PcdGet32 (PcdSocCpuId) & STYX_SOC_VERSION_MASK) < STYX_SOC_VERSION_B1) {
+ return EFI_SUCCESS;
+ }
+
+ if (FixedPcdGet8(PcdSata1PortCount) > 0) {
+ for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata1PortCount); PortNum++) {
+ SetCwMinSata1 (PortNum);
+ }
+
+ Status = InitializeSataController (FixedPcdGet32(PcdSata1CtrlAxiSlvPort),
+ FixedPcdGet8(PcdSata1PortCount),
+ FixedPcdGet8(PcdSata0PortCount));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: failed to initialize secondary SATA controller!\n",
+ __FUNCTION__));
+ } else {
+ for (PortNum = 0; PortNum < FixedPcdGet8(PcdSata1PortCount); PortNum++) {
+ SetPrdSingleSata1 (PortNum);
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h
new file mode 100644
index 0000000000..ff78f4ac3c
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h
@@ -0,0 +1,180 @@
+/** @file
+ Header file for AHCI mode of ATA host controller.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2016, AMD Inc. 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.
+
+**/
+#ifndef __SATA_REGISTERS_H__
+#define __SATA_REGISTERS_H__
+
+#define EFI_AHCI_BAR_INDEX 0x05
+
+#define EFI_AHCI_CAPABILITY_OFFSET 0x0000
+#define EFI_AHCI_CAP_SSS BIT27
+#define EFI_AHCI_CAP_SMPS BIT28
+#define EFI_AHCI_CAP_S64A BIT31
+#define EFI_AHCI_GHC_OFFSET 0x0004
+#define EFI_AHCI_GHC_RESET BIT0
+#define EFI_AHCI_GHC_IE BIT1
+#define EFI_AHCI_GHC_ENABLE BIT31
+#define EFI_AHCI_IS_OFFSET 0x0008
+#define EFI_AHCI_PI_OFFSET 0x000C
+
+#define EFI_AHCI_MAX_PORTS 32
+
+//
+// Refer SATA1.0a spec section 5.2, the Phy detection time should be less than 10ms.
+//
+#define EFI_AHCI_BUS_PHY_DETECT_TIMEOUT 10
+//
+// Refer SATA1.0a spec, the FIS enable time should be less than 500ms.
+//
+#define EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT EFI_TIMER_PERIOD_MILLISECONDS(500)
+//
+// Refer SATA1.0a spec, the bus reset time should be less than 1s.
+//
+#define EFI_AHCI_BUS_RESET_TIMEOUT EFI_TIMER_PERIOD_SECONDS(1)
+
+#define EFI_AHCI_ATAPI_DEVICE_SIG 0xEB140000
+#define EFI_AHCI_ATA_DEVICE_SIG 0x00000000
+#define EFI_AHCI_PORT_MULTIPLIER_SIG 0x96690000
+#define EFI_AHCI_ATAPI_SIG_MASK 0xFFFF0000
+
+//
+// Each PRDT entry can point to a memory block up to 4M byte
+//
+#define EFI_AHCI_MAX_DATA_PER_PRDT 0x400000
+
+#define EFI_AHCI_FIS_REGISTER_H2D 0x27 //Register FIS - Host to Device
+#define EFI_AHCI_FIS_REGISTER_H2D_LENGTH 20
+#define EFI_AHCI_FIS_REGISTER_D2H 0x34 //Register FIS - Device to Host
+#define EFI_AHCI_FIS_REGISTER_D2H_LENGTH 20
+#define EFI_AHCI_FIS_DMA_ACTIVATE 0x39 //DMA Activate FIS - Device to Host
+#define EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH 4
+#define EFI_AHCI_FIS_DMA_SETUP 0x41 //DMA Setup FIS - Bi-directional
+#define EFI_AHCI_FIS_DMA_SETUP_LENGTH 28
+#define EFI_AHCI_FIS_DATA 0x46 //Data FIS - Bi-directional
+#define EFI_AHCI_FIS_BIST 0x58 //BIST Activate FIS - Bi-directional
+#define EFI_AHCI_FIS_BIST_LENGTH 12
+#define EFI_AHCI_FIS_PIO_SETUP 0x5F //PIO Setup FIS - Device to Host
+#define EFI_AHCI_FIS_PIO_SETUP_LENGTH 20
+#define EFI_AHCI_FIS_SET_DEVICE 0xA1 //Set Device Bits FIS - Device to Host
+#define EFI_AHCI_FIS_SET_DEVICE_LENGTH 8
+
+#define EFI_AHCI_D2H_FIS_OFFSET 0x40
+#define EFI_AHCI_DMA_FIS_OFFSET 0x00
+#define EFI_AHCI_PIO_FIS_OFFSET 0x20
+#define EFI_AHCI_SDB_FIS_OFFSET 0x58
+#define EFI_AHCI_FIS_TYPE_MASK 0xFF
+#define EFI_AHCI_U_FIS_OFFSET 0x60
+
+//
+// Port register
+//
+#define EFI_AHCI_PORT_START 0x0100
+#define EFI_AHCI_PORT_REG_WIDTH 0x0080
+#define EFI_AHCI_PORT_CLB 0x0000
+#define EFI_AHCI_PORT_CLBU 0x0004
+#define EFI_AHCI_PORT_FB 0x0008
+#define EFI_AHCI_PORT_FBU 0x000C
+#define EFI_AHCI_PORT_IS 0x0010
+#define EFI_AHCI_PORT_IS_DHRS BIT0
+#define EFI_AHCI_PORT_IS_PSS BIT1
+#define EFI_AHCI_PORT_IS_SSS BIT2
+#define EFI_AHCI_PORT_IS_SDBS BIT3
+#define EFI_AHCI_PORT_IS_UFS BIT4
+#define EFI_AHCI_PORT_IS_DPS BIT5
+#define EFI_AHCI_PORT_IS_PCS BIT6
+#define EFI_AHCI_PORT_IS_DIS BIT7
+#define EFI_AHCI_PORT_IS_PRCS BIT22
+#define EFI_AHCI_PORT_IS_IPMS BIT23
+#define EFI_AHCI_PORT_IS_OFS BIT24
+#define EFI_AHCI_PORT_IS_INFS BIT26
+#define EFI_AHCI_PORT_IS_IFS BIT27
+#define EFI_AHCI_PORT_IS_HBDS BIT28
+#define EFI_AHCI_PORT_IS_HBFS BIT29
+#define EFI_AHCI_PORT_IS_TFES BIT30
+#define EFI_AHCI_PORT_IS_CPDS BIT31
+#define EFI_AHCI_PORT_IS_CLEAR 0xFFFFFFFF
+#define EFI_AHCI_PORT_IS_FIS_CLEAR 0x0000000F
+
+#define EFI_AHCI_PORT_OFFSET(PortNum) \
+ (EFI_AHCI_PORT_START + ((PortNum) * EFI_AHCI_PORT_REG_WIDTH))
+
+#define EFI_AHCI_PORT_IE 0x0014
+#define EFI_AHCI_PORT_CMD 0x0018
+#define EFI_AHCI_PORT_CMD_ST_MASK 0xFFFFFFFE
+#define EFI_AHCI_PORT_CMD_ST BIT0
+#define EFI_AHCI_PORT_CMD_SUD BIT1
+#define EFI_AHCI_PORT_CMD_POD BIT2
+#define EFI_AHCI_PORT_CMD_CLO BIT3
+#define EFI_AHCI_PORT_CMD_CR BIT15
+#define EFI_AHCI_PORT_CMD_FRE BIT4
+#define EFI_AHCI_PORT_CMD_FR BIT14
+#define EFI_AHCI_PORT_CMD_MASK ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL)
+#define EFI_AHCI_PORT_CMD_PMA BIT17
+#define EFI_AHCI_PORT_CMD_HPCP BIT18
+#define EFI_AHCI_PORT_CMD_MPSP BIT19
+#define EFI_AHCI_PORT_CMD_CPD BIT20
+#define EFI_AHCI_PORT_CMD_ESP BIT21
+#define EFI_AHCI_PORT_CMD_ATAPI BIT24
+#define EFI_AHCI_PORT_CMD_DLAE BIT25
+#define EFI_AHCI_PORT_CMD_ALPE BIT26
+#define EFI_AHCI_PORT_CMD_ASP BIT27
+#define EFI_AHCI_PORT_CMD_ICC_MASK (BIT28 | BIT29 | BIT30 | BIT31)
+#define EFI_AHCI_PORT_CMD_ACTIVE (1 << 28 )
+#define EFI_AHCI_PORT_TFD 0x0020
+#define EFI_AHCI_PORT_TFD_MASK (BIT7 | BIT3 | BIT0)
+#define EFI_AHCI_PORT_TFD_BSY BIT7
+#define EFI_AHCI_PORT_TFD_DRQ BIT3
+#define EFI_AHCI_PORT_TFD_ERR BIT0
+#define EFI_AHCI_PORT_TFD_ERR_MASK 0x00FF00
+#define EFI_AHCI_PORT_SIG 0x0024
+#define EFI_AHCI_PORT_SSTS 0x0028
+#define EFI_AHCI_PORT_SSTS_DET_MASK 0x000F
+#define EFI_AHCI_PORT_SSTS_DET 0x0001
+#define EFI_AHCI_PORT_SSTS_DET_PCE 0x0003
+#define EFI_AHCI_PORT_SSTS_SPD_MASK 0x00F0
+#define EFI_AHCI_PORT_SCTL 0x002C
+#define EFI_AHCI_PORT_SCTL_DET_MASK 0x000F
+#define EFI_AHCI_PORT_SCTL_MASK (~EFI_AHCI_PORT_SCTL_DET_MASK)
+#define EFI_AHCI_PORT_SCTL_DET_INIT 0x0001
+#define EFI_AHCI_PORT_SCTL_DET_PHYCOMM 0x0003
+#define EFI_AHCI_PORT_SCTL_SPD_MASK 0x00F0
+#define EFI_AHCI_PORT_SCTL_IPM_MASK 0x0F00
+#define EFI_AHCI_PORT_SCTL_IPM_INIT 0x0300
+#define EFI_AHCI_PORT_SCTL_IPM_PSD 0x0100
+#define EFI_AHCI_PORT_SCTL_IPM_SSD 0x0200
+#define EFI_AHCI_PORT_SERR 0x0030
+#define EFI_AHCI_PORT_SERR_RDIE BIT0
+#define EFI_AHCI_PORT_SERR_RCE BIT1
+#define EFI_AHCI_PORT_SERR_TDIE BIT8
+#define EFI_AHCI_PORT_SERR_PCDIE BIT9
+#define EFI_AHCI_PORT_SERR_PE BIT10
+#define EFI_AHCI_PORT_SERR_IE BIT11
+#define EFI_AHCI_PORT_SERR_PRC BIT16
+#define EFI_AHCI_PORT_SERR_PIE BIT17
+#define EFI_AHCI_PORT_SERR_CW BIT18
+#define EFI_AHCI_PORT_SERR_BDE BIT19
+#define EFI_AHCI_PORT_SERR_DE BIT20
+#define EFI_AHCI_PORT_SERR_CRCE BIT21
+#define EFI_AHCI_PORT_SERR_HE BIT22
+#define EFI_AHCI_PORT_SERR_LSE BIT23
+#define EFI_AHCI_PORT_SERR_TSTE BIT24
+#define EFI_AHCI_PORT_SERR_UFT BIT25
+#define EFI_AHCI_PORT_SERR_EX BIT26
+#define EFI_AHCI_PORT_ERR_CLEAR 0xFFFFFFFF
+#define EFI_AHCI_PORT_SACT 0x0034
+#define EFI_AHCI_PORT_CI 0x0038
+#define EFI_AHCI_PORT_SNTF 0x003C
+
+#endif
diff --git a/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf
new file mode 100644
index 0000000000..8a4deb9185
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf
@@ -0,0 +1,63 @@
+## @file
+#
+# Component description file for the Styx SATA platform driver.
+#
+# Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.<BR>
+# 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 = 0x00010019
+ BASE_NAME = StyxSataPlatformDxe
+ FILE_GUID = 4703fac4-9de9-4010-87d1-11402894296a
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = StyxSataPlatformDxeEntryPoint
+
+[Sources]
+ InitController.c
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ AmdSataInit
+ BaseLib
+ DebugLib
+ IoLib
+ NonDiscoverableDeviceRegistrationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[FixedPcd]
+ gAmdModulePkgTokenSpaceGuid.PcdSataSerdesBase
+ gAmdModulePkgTokenSpaceGuid.PcdSataSerdesOffset
+ gAmdModulePkgTokenSpaceGuid.PcdSataNumChPerSerdes
+
+ gAmdStyxTokenSpaceGuid.PcdSata0CtrlAxiSlvPort
+ gAmdStyxTokenSpaceGuid.PcdSata0PortCount
+ gAmdStyxTokenSpaceGuid.PcdSata1CtrlAxiSlvPort
+ gAmdStyxTokenSpaceGuid.PcdSata1PortCount
+ gAmdStyxTokenSpaceGuid.PcdSataPortMode
+ gAmdStyxTokenSpaceGuid.PcdSataSmpsSupport
+ gAmdStyxTokenSpaceGuid.PcdSataSssSupport
+ gAmdStyxTokenSpaceGuid.PcdSataPortCpd
+ gAmdStyxTokenSpaceGuid.PcdSataPortMpsp
+
+[Pcd]
+ gAmdStyxTokenSpaceGuid.PcdSocCpuId
+
+[Depex]
+ TRUE
diff --git a/Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c b/Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c
new file mode 100644
index 0000000000..f544af3eeb
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c
@@ -0,0 +1,500 @@
+/** @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>
+
+#define SPI_BASE (FixedPcdGet64 (PcdFdBaseAddress))
+#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)) {
+ 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/Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf b/Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf
new file mode 100644
index 0000000000..76042ab301
--- /dev/null
+++ b/Silicon/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
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/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