diff options
Diffstat (limited to 'src/vendorcode/amd/pi/00660F01/Proc/Psp/PspBaseLib/PspBaseLib.c')
-rw-r--r-- | src/vendorcode/amd/pi/00660F01/Proc/Psp/PspBaseLib/PspBaseLib.c | 464 |
1 files changed, 464 insertions, 0 deletions
diff --git a/src/vendorcode/amd/pi/00660F01/Proc/Psp/PspBaseLib/PspBaseLib.c b/src/vendorcode/amd/pi/00660F01/Proc/Psp/PspBaseLib/PspBaseLib.c new file mode 100644 index 0000000000..20a359ad0e --- /dev/null +++ b/src/vendorcode/amd/pi/00660F01/Proc/Psp/PspBaseLib/PspBaseLib.c @@ -0,0 +1,464 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * PSP Base Library + * + * Contains interface to the PSP library + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: PSP + * @e \$Revision: 309090 $ @e \$Date: 2014-12-09 12:28:05 -0600 (Tue, 09 Dec 2014) $ + * + */ + /***************************************************************************** + * + * Copyright (c) 2008 - 2015, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices, Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ + + +/*---------------------------------------------------------------------------------------- + * M O D U L E S U S E D + *---------------------------------------------------------------------------------------- + */ +#include "AGESA.h" +#include "Filecode.h" +#include "PspBaseLib.h" + +#define FILECODE PROC_PSP_PSPBASELIB_PSPBASELIB_FILECODE +#define PSP_BAR1_TMP_BASE 0xFEA00000ul + +#define GET_PCI_BUS(Reg) (((UINT32) Reg >> 16) & 0xFF) +#define GET_PCI_DEV(Reg) (((UINT32) Reg >> 11) & 0x1F) +#define GET_PCI_FUNC(Reg) (((UINT32) Reg >> 8) & 0x7) +#define GET_PCI_OFFSET(Reg) ((UINT32)Reg & 0xFF) + +#define PCI_CONFIG_SMU_INDIRECT_INDEX 0xB8 ///< Gnb Offset index for SMU mbox +#define PCI_CONFIG_SMU_INDIRECT_DATA 0xBC ///< Gnb Offset data for SMU mbox + +#define SMU_CC_PSP_FUSES_STATUS 0xC0018000ul ///< offset in GNB to find PSP fusing +#define SMU_CC_PSP_FUSES_SECURE BIT0 ///< BIT0 +#define SMU_CC_PSP_FUSES_FRA_ENABLE BIT1 ///< BIT1 +#define SMU_CC_PSP_FUSES_PROTO BIT2 ///< BIT2 +#define PLATFORM_SECURE_BOOT_EN BIT4 ///< BIT4 + + +#define PSP_BLANK_PART 0 ///< Blank part +#define PSP_PROTO_PART SMU_CC_PSP_FUSES_PROTO ///< Proto Part +#define PSP_NON_SECURE_PART (SMU_CC_PSP_FUSES_PROTO + SMU_CC_PSP_FUSES_PCPU_DIS) ///< Non Secure Part +#define PSP_SECURE_PART (SMU_CC_PSP_FUSES_PROTO + SMU_CC_PSP_FUSES_SECURE) ///< Secure Part +#define PSP_FRA_MODE (SMU_CC_PSP_FUSES_FRA_ENABLE + SMU_CC_PSP_FUSES_PROTO + SMU_CC_PSP_FUSES_SECURE) ///< FRA Part + +/*---------------------------------------------------------------------------------------- + * D E F I N I T I O N S A N D M A C R O S + *---------------------------------------------------------------------------------------- + */ + + +/*---------------------------------------------------------------------------------------- + * T Y P E D E F S A N D S T R U C T U R E S + *---------------------------------------------------------------------------------------- + */ + + +/*---------------------------------------------------------------------------------------- + * P R O T O T Y P E S O F L O C A L F U N C T I O N S + *---------------------------------------------------------------------------------------- + */ + + + +UINT32 +PspLibPciReadConfig ( + IN UINT32 Register + ) +{ + UINT32 Value; + PCI_ADDR PciAddr; + + Value = 0; + PciAddr.AddressValue = MAKE_SBDFO (0, GET_PCI_BUS (Register), GET_PCI_DEV (Register), GET_PCI_FUNC (Register), GET_PCI_OFFSET (Register)); + + LibAmdPciRead (AccessWidth32, PciAddr, &Value, NULL); + + return Value; +} + +VOID +PspLibPciWriteConfig ( + IN UINT32 Register, + IN UINT32 Value + ) +{ + PCI_ADDR PciAddr; + PciAddr.AddressValue = MAKE_SBDFO (0, GET_PCI_BUS (Register), GET_PCI_DEV (Register), GET_PCI_FUNC (Register), GET_PCI_OFFSET (Register)); + + LibAmdPciWrite (AccessWidth32, PciAddr, &Value, NULL); + +} + +UINT32 +PspLibPciReadPspConfig ( + IN UINT16 Offset + ) +{ + return (PspLibPciReadConfig ((UINT32) (PSP_PCI_BDA + Offset))); +} + +VOID +PspLibPciWritePspConfig ( + IN UINT16 Offset, + IN UINT32 Value + ) +{ + PspLibPciWriteConfig ((UINT32) (PSP_PCI_BDA + Offset), Value); +} + +BOOLEAN +GetPspDirBase ( + IN OUT UINT32 *Address + ) +{ + UINTN i; + FIRMWARE_ENTRY_TABLE *FirmwareTableBase; + CONST UINT32 RomSigAddrTable[] = + { + 0xFFFA0000, // --> 512KB base + 0xFFF20000, // --> 1MB base + 0xFFE20000, // --> 2MB base + 0xFFC20000, // --> 4MB base + 0xFF820000, // --> 8MB base + 0xFF020000 // --> 16MB base + }; + + for (i = 0; i < sizeof (RomSigAddrTable) / sizeof (UINT32); i++) { + FirmwareTableBase = (FIRMWARE_ENTRY_TABLE *) (UINTN) RomSigAddrTable[i]; + // Search flash for unique signature 0x55AA55AA + if (FirmwareTableBase->Signature == FIRMWARE_TABLE_SIGNATURE) { + *Address = FirmwareTableBase->PspDirBase; + return TRUE; + } + } + + return (FALSE); +} + +BOOLEAN +PSPEntryInfo ( + IN PSP_DIRECTORY_ENTRY_TYPE EntryType, + IN OUT UINT64 *EntryAddress, + IN UINT32 *EntrySize + ) +{ + PSP_DIRECTORY *PspDir; + UINTN i; + + if (GetPspDirBase ((UINT32 *)&PspDir ) != TRUE) { + return FALSE; + } + + for (i = 0; i < PspDir->Header.TotalEntries; i++) { + if (PspDir->PspEntry[i].Type == EntryType) { + *EntryAddress = PspDir->PspEntry[i].Location; + *EntrySize = PspDir->PspEntry[i].Size; + return (TRUE); + } + } + + return (FALSE); +} + +/** + Check if PSP device is present + + @retval BOOLEAN 0: PSP Disabled, 1: PSP Enabled + +**/ +BOOLEAN +CheckPspDevicePresent ( + VOID + ) +{ + UINT32 SecureFuseReg; + PspLibPciWriteConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_INDEX, (UINT32)SMU_CC_PSP_FUSES_STATUS); + SecureFuseReg = PspLibPciReadConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_DATA); + + if (SecureFuseReg &= SMU_CC_PSP_FUSES_PROTO) { + return (TRUE); + } + return (FALSE); +} + +/** + Check PSP Platform Seucre Enable State + HVB & Secure S3 (Resume vector set to Dram, & core content will restore by uCode) + will be applied if Psp Plaform Secure is enabled + + @retval BOOLEAN 0: PSP Platform Secure Disabled, 1: PSP Platform Secure Enabled + +**/ +BOOLEAN +CheckPspPlatformSecureEnable ( + VOID + ) +{ + UINT32 SecureFuseReg; + PspLibPciWriteConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_INDEX, (UINT32)SMU_CC_PSP_FUSES_STATUS); + SecureFuseReg = PspLibPciReadConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_DATA); + + if (SecureFuseReg &= PLATFORM_SECURE_BOOT_EN) { + return (TRUE); + } + return (FALSE); +} + +/** + Check PSP Recovery Flag + Target will set Recovery flag if some PSP entry point by PSP directory has been corrupted. + + @retval BOOLEAN 0: Recovery Flag is cleared, 1: Recovery Flag has been set + +**/ +BOOLEAN +CheckPspRecoveryFlag ( + VOID + ) +{ + MBOX_STATUS *MboxStatus; + + //Init PSP MMIO + PspBarInitEarly (); + + GetPspMboxStatus (&MboxStatus); + + return (BOOLEAN) (MboxStatus->Recovery); +} + +/** + Return the PspMbox MMIO location + + + @retval BOOLEAN FALSE: ERROR, TRUE: SUCCEED + +**/ +BOOLEAN +GetPspMboxStatus ( + IN OUT MBOX_STATUS **MboxStatus + ) +{ + UINT32 PspMmio; + + if (GetPspBar1Addr (&PspMmio) == FALSE) { + return (FALSE); + } + + *MboxStatus = (MBOX_STATUS *)( (UINTN)PspMmio + PSP_MAILBOX_BASE + PSP_MAILBOX_STATUS_OFFSET); // PSPMbox base is at offset CP2MSG_28 ie. offset 28*4 = 0x70 + + return (TRUE); +} + +BOOLEAN +PspBarInitEarly (void) +{ + UINT32 PspMmioSize; + UINT32 Value32; + + if (PspLibPciReadPspConfig (PSP_PCI_DEVID_REG) == 0xffffffff) { + return (FALSE); + } + + //Check if PSP BAR has been assigned, if not do the PSP BAR initialation + if (PspLibPciReadPspConfig (PSP_PCI_BAR1_REG) == 0) { + /// Get PSP BAR1 Size + PspLibPciWritePspConfig (PSP_PCI_BAR1_REG, 0xFFFFFFFF); + PspMmioSize = PspLibPciReadPspConfig (PSP_PCI_BAR1_REG); + PspMmioSize = ~PspMmioSize + 1; + /// Assign BAR1 Temporary Address + PspLibPciWritePspConfig (PSP_PCI_BAR1_REG, PSP_BAR1_TMP_BASE); + PspLibPciWritePspConfig ( PSP_PCI_CMD_REG, 0x06); + + /// Enable GNB redirection to this space @todo use equate & also find proper fix + PspLibPciWriteConfig ( ( (0x18 << 11) + (1 << 8) + 0xBC), ((PSP_BAR1_TMP_BASE + PspMmioSize -1) >> 8) & ~0xFF); + PspLibPciWriteConfig ( ( (0x18 << 11) + (1 << 8) + 0xB8), (PSP_BAR1_TMP_BASE >> 8) | 3); + /// Enable MsixBarEn, Bar1En, Bar3En + PspLibPciWritePspConfig ( PSP_PCI_EXTRAPCIHDR_REG, 0x34); + /// Capability chain update + Value32 = PspLibPciReadPspConfig (PSP_PCI_MIRRORCTRL1_REG); + Value32 &= ~D8F0x44_PmNxtPtrW_MASK; + Value32 |= 0xA4; + PspLibPciWritePspConfig (PSP_PCI_MIRRORCTRL1_REG, Value32); + } + + return (TRUE); +} + +/** + Return the PspMMIO MMIO location + + @param[in] PspMmio Pointer to Psp MMIO address + + @retval BOOLEAN 0: Error, 1 Success +**/ +BOOLEAN +GetPspBar1Addr ( + IN OUT UINT32 *PspMmio + ) +{ + if (CheckPspDevicePresent () == FALSE) { + return (FALSE); + } + + *PspMmio = PspLibPciReadPspConfig (PSP_PCI_BAR1_REG); + + if ((*PspMmio) == 0xffffffff) { + return (FALSE); + } + + return (TRUE); +} + +/** + Return the PspMMIO MMIO location + + @param[in] PspMmio Pointer to Psp MMIO address + + @retval BOOLEAN 0: Error, 1 Success +**/ +BOOLEAN +GetPspBar3Addr ( + IN OUT UINT32 *PspMmio + ) +{ + if (CheckPspDevicePresent () == FALSE) { + return (FALSE); + } + + *PspMmio = PspLibPciReadPspConfig (PSP_PCI_BAR3_REG); + + if ((*PspMmio) == 0xffffffff) { + return (FALSE); + } + + return (TRUE); +} + +/*---------------------------------------------------------------------------------------*/ +/** + * Returns the access width mask for the processor + * + * + * @param[in] AccessWidth Access width + * @retval Width in number of bytes + */ + + +UINT8 +PspLibAccessWidth ( + IN ACCESS_WIDTH AccessWidth + ) +{ + UINT8 Width; + + switch (AccessWidth) { + case AccessWidth8: + case AccessS3SaveWidth8: + Width = 1; + break; + case AccessWidth16: + case AccessS3SaveWidth16: + Width = 2; + break; + case AccessWidth32: + case AccessS3SaveWidth32: + Width = 4; + break; + case AccessWidth64: + case AccessS3SaveWidth64: + Width = 8; + break; + default: + Width = 0; + } + return Width; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Read GNB indirect registers + * + * + * + * @param[in] Address PCI address of indirect register + * @param[in] IndirectAddress Offset of indirect register + * @param[in] Width Width + * @param[out] Value Pointer to value + */ +VOID +PspLibPciIndirectRead ( + IN PCI_ADDR Address, + IN UINT32 IndirectAddress, + IN ACCESS_WIDTH Width, + OUT VOID *Value + ) +{ + UINT32 IndexOffset; + + IndexOffset = PspLibAccessWidth (Width); + LibAmdPciWrite (Width, Address, &IndirectAddress, NULL); + Address.AddressValue += IndexOffset; + LibAmdPciRead (Width, Address, Value, NULL); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Write GNB indirect registers + * + * + * + * @param[in] Address PCI address of indirect register + * @param[in] IndirectAddress Offset of indirect register + * @param[in] Width Width + * @param[in] Value Pointer to value + */ +VOID +PspLibPciIndirectWrite ( + IN PCI_ADDR Address, + IN UINT32 IndirectAddress, + IN ACCESS_WIDTH Width, + IN VOID *Value + ) +{ + UINT32 IndexOffset; + + IndexOffset = PspLibAccessWidth (Width); + LibAmdPciWrite (Width, Address, &IndirectAddress, NULL); + Address.AddressValue += IndexOffset; + LibAmdPciWrite (Width, Address, Value, NULL); +} + + |