From f4d38e50c0f24eb78eb003a94f583025621c63db Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Thu, 3 Aug 2017 12:24:22 +0100 Subject: 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 --- .../Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c | 114 +++ .../Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf | 53 ++ Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c | 170 ++++ Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf | 53 ++ Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S | 87 ++ Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.c | 237 +++++ .../AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.inf | 62 ++ Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.c | 256 ++++++ .../AMD/Styx/Drivers/PlatInitPei/PlatInitPei.inf | 76 ++ .../Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c | 994 +++++++++++++++++++++ .../PlatformSmbiosDxe/PlatformSmbiosDxe.inf | 60 ++ Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.c | 189 ++++ Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.inf | 47 + .../Drivers/StyxSataPlatformDxe/InitController.c | 201 +++++ .../Drivers/StyxSataPlatformDxe/SataRegisters.h | 180 ++++ .../StyxSataPlatformDxe/StyxSataPlatformDxe.inf | 63 ++ .../AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c | 500 +++++++++++ .../AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf | 63 ++ 18 files changed, 3405 insertions(+) create mode 100644 Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c create mode 100644 Silicon/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf create mode 100644 Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c create mode 100644 Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf create mode 100644 Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S create mode 100644 Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.c create mode 100644 Silicon/AMD/Styx/Drivers/PlatInitDxe/PlatInitDxe.inf create mode 100644 Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.c create mode 100644 Silicon/AMD/Styx/Drivers/PlatInitPei/PlatInitPei.inf create mode 100644 Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c create mode 100644 Silicon/AMD/Styx/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf create mode 100644 Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.c create mode 100644 Silicon/AMD/Styx/Drivers/StyxRngDxe/StyxRngDxe.inf create mode 100644 Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/InitController.c create mode 100644 Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/SataRegisters.h create mode 100644 Silicon/AMD/Styx/Drivers/StyxSataPlatformDxe/StyxSataPlatformDxe.inf create mode 100644 Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.c create mode 100644 Silicon/AMD/Styx/Drivers/StyxSpiFvDxe/StyxSpiFvDxe.inf (limited to 'Silicon/AMD/Styx/Drivers') 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.
+ Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.
+ + 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 +#include + +#include +#include +#include +#include + +#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.
+# Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* 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.
+# +# 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.
+// +// 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 + +.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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/*---------------------------------------------------------------------------------------- + * 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.
+# +# 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.
+ Copyright (c) 2013, Linaro Ltd. All rights reserved.
+ Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------------------------- + * 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.
+# Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.
+# +# 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.
+ + 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 +#include +#include + +#include + +#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.
+# +# 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.
+ Copyright (c) 2016, Linaro, Ltd. All rights reserved.
+ + 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 +#include +#include +#include + +#include + +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.
+ Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.
+ + 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.
+# Copyright (c) 2016, Linaro, Ltd. All rights reserved.
+# +# 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.
+ + 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 + +#include +#include +#include +#include +#include + +#include +#include + +#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.
+# +# 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 -- cgit v1.2.3