/* $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); }