BOOLEAN MemNWritePmuSramMsgBlockKV ( IN OUT MEM_NB_BLOCK *NBPtr ) { UINT16 i; UINT16 *ImagePtr; LOCATE_HEAP_PTR LocHeap; LocHeap.BufferHandle = AMD_MEM_PMU_SRAM_MSG_BLOCK_HANDLE; if (HeapLocateBuffer (&LocHeap, &(NBPtr->MemPtr->StdHeader)) != AGESA_SUCCESS) { return FALSE; // Could not locate heap for PMU SRAM Message BLock. } ImagePtr = (UINT16 *) LocHeap.BufferPtr; MemNSetBitFieldNb (NBPtr, BFPmuReset, 0); // Write the word to D18F2x[B,0]9C_x0005_[27FF:0800]_dct[3:0] (using the broadcast port for all phys at // D18F2xB98_dct[MaxDctMstr:0], and using the autoincrement feature). IDS_HDT_CONSOLE (MEM_FLOW, "\t\tStart writing PMU SRAM Message Block...\n"); MemNSetBitFieldNb (NBPtr, RegDctAddlOffset, PMU_FIRMWARE_SRAM_START | DCT_ACCESS_WRITE | DCT_OFFSET_AUTO_INC_EN); for (i = 0; i < sizeof (PMU_SRAM_MSG_BLOCK_KV) / sizeof (ImagePtr[0]); i++) { MemNSetBitFieldNb (NBPtr, RegDctAddlData, ImagePtr[i]); IDS_HDT_CONSOLE (MEM_SETREG, "~F2_9C_%x = %04x\n", PMU_FIRMWARE_SRAM_START + i, ImagePtr[i]); } IDS_HDT_CONSOLE (MEM_FLOW, "\t\tEnd writing PMU SRAM Message Block!\n"); MemNSetBitFieldNb (NBPtr, RegDctAddlOffset, 0); return TRUE; }
STATIC VOID RetrieveDataBlockFromInitReset ( IN FCH_DATA_BLOCK *FchParams ) { LOCATE_HEAP_PTR LocHeapPtr; FCH_RESET_DATA_BLOCK *ResetDb; AGESA_STATUS AgesaStatus; LocHeapPtr.BufferHandle = AMD_FCH_RESET_DATA_BLOCK_HANDLE; AgesaStatus = HeapLocateBuffer (&LocHeapPtr, FchParams->StdHeader); if (AgesaStatus == AGESA_SUCCESS) { ASSERT (LocHeapPtr.BufferPtr != NULL); ResetDb = (FCH_RESET_DATA_BLOCK *) (LocHeapPtr.BufferPtr - sizeof (ResetDb) + sizeof (UINT32)); // Override FchParams with contents in ResetDb FchParams->Usb.Xhci0Enable = ResetDb->FchReset.Xhci0Enable; FchParams->Usb.Xhci1Enable = ResetDb->FchReset.Xhci1Enable; FchParams->Spi.SpiFastSpeed = ResetDb->FastSpeed; FchParams->Spi.WriteSpeed = ResetDb->WriteSpeed; FchParams->Spi.SpiMode = ResetDb->Mode; FchParams->Spi.AutoMode = ResetDb->AutoMode; FchParams->Spi.SpiBurstWrite = ResetDb->BurstWrite; FchParams->Sata.SataMode.Sata6AhciCap = (UINT8) ResetDb->Sata6AhciCap; FchParams->Misc.Cg2Pll = ResetDb->Cg2Pll; FchParams->Sata.SataMode.SataSetMaxGen2 = ResetDb->SataSetMaxGen2; FchParams->Sata.SataMode.SataClkMode = ResetDb->SataClkMode; FchParams->Sata.SataMode.SataModeReg = ResetDb->SataModeReg; FchParams->Sata.SataInternal100Spread = (UINT8) ResetDb->SataInternal100Spread; FchParams->Spi.SpiSpeed = ResetDb->SpiSpeed; FchParams->Gpp = ResetDb->Gpp; } }
BOOLEAN MemNInitPmuSramMsgBlockKV ( IN OUT MEM_NB_BLOCK *NBPtr ) { LOCATE_HEAP_PTR LocHeap; ALLOCATE_HEAP_PARAMS AllocHeapParams; PMU_SRAM_MSG_BLOCK_KV *PmuSramMsgBlockPtr; LocHeap.BufferHandle = AMD_MEM_PMU_SRAM_MSG_BLOCK_HANDLE; if (HeapLocateBuffer (&LocHeap, &(NBPtr->MemPtr->StdHeader)) == AGESA_SUCCESS) { PmuSramMsgBlockPtr = (PMU_SRAM_MSG_BLOCK_KV *) LocHeap.BufferPtr; } else { // Allocate temporary buffer for PMU SRAM Message Block AllocHeapParams.RequestedBufferSize = sizeof (PMU_SRAM_MSG_BLOCK_KV); AllocHeapParams.BufferHandle = AMD_MEM_PMU_SRAM_MSG_BLOCK_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, &(NBPtr->MemPtr->StdHeader)) != AGESA_SUCCESS) { return FALSE; // Could not allocate heap for PMU SRAM Message BLock. } PmuSramMsgBlockPtr = (PMU_SRAM_MSG_BLOCK_KV *) AllocHeapParams.BufferPtr; } LibAmdMemFill ((VOID *)PmuSramMsgBlockPtr, 0, (UINTN)sizeof (PMU_SRAM_MSG_BLOCK_KV), &(NBPtr->MemPtr->StdHeader)); return TRUE; }
// // Private Function Declaration // FCH_DATA_BLOCK* FchLocateHeapBuffer ( VOID ) { LOCATE_HEAP_PTR LocateHeapPtr; AMD_CONFIG_PARAMS StdHeader; AGESA_STATUS AgesaStatus; EFI_STATUS Status; Status = gBS->LocateProtocol ( &gAmdBufferManagerProtocolGuid, NULL, &mBufferMgr ); if (EFI_ERROR (Status)) { return NULL; } mDxeBufferManager = mBufferMgr->DxeBufferManager; StdHeader = mBufferMgr->StdHeader; StdHeader.HeapStatus = HEAP_SYSTEM_MEM; LocateHeapPtr.BufferHandle = AMD_FCH_DATA_BLOCK_HANDLE; AgesaStatus = HeapLocateBuffer (&LocateHeapPtr, &StdHeader); ASSERT (!AgesaStatus); return (FCH_DATA_BLOCK *) LocateHeapPtr.BufferPtr; }
/** * * * This function determines if the revision S3 data blob matches the S3 engine * * @param[in] Storage - Beginning of the device list. * @param[in] *StdHeader - Config handle for library and services. * * @return AGESA_STATUS * - AGESA_FATAL * - AGESA_SUCCESS */ AGESA_STATUS AmdMemS3DatablobRevMatch ( IN VOID *Storage, IN AMD_CONFIG_PARAMS *StdHeader ) { S3_MEM_NB_BLOCK *S3NBPtr; LOCATE_HEAP_PTR LocHeap; DEVICE_BLOCK_HEADER *DeviceList; DeviceList = (DEVICE_BLOCK_HEADER *) Storage; LocHeap.BufferHandle = AMD_MEM_S3_NB_HANDLE; S3NBPtr = NULL; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { S3NBPtr = (S3_MEM_NB_BLOCK *)LocHeap.BufferPtr; } else { ASSERT (FALSE) ; // No match for heap status, but could not locate "AMD_MEM_S3_NB_HANDLE" in heap for S3GetMsr return AGESA_FATAL; } if (S3NBPtr[BSP_DIE].S3DatablobRev == DeviceList->Revision) { return AGESA_SUCCESS; } else { ASSERT (FALSE); return AGESA_FATAL; } }
/** * * * This function determines if the PSP is present * * @param[in] *StdHeader - Config handle for library and services. * * @return AGESA_STATUS * - AGESA_FATAL * - AGESA_SUCCESS */ AGESA_STATUS AmdMemDoResume ( IN AMD_CONFIG_PARAMS *StdHeader ) { S3_MEM_NB_BLOCK *S3NBPtr; MEM_NB_BLOCK *NBPtr; LOCATE_HEAP_PTR LocHeap; LocHeap.BufferHandle = AMD_MEM_S3_NB_HANDLE; S3NBPtr = NULL; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { S3NBPtr = (S3_MEM_NB_BLOCK *)LocHeap.BufferPtr; NBPtr = ((S3_MEM_NB_BLOCK *)S3NBPtr)->NBPtr; } else { ASSERT (FALSE) ; // No match for heap status, but could not locate "AMD_MEM_S3_NB_HANDLE" in heap for S3GetMsr return AGESA_FATAL; } if (S3NBPtr[BSP_DIE].MemS3PspPlatformSecureBootEn (S3NBPtr[BSP_DIE].NBPtr) == NBPtr->MemRunningOnPsp (NBPtr)) { return AGESA_SUCCESS; } else { return AGESA_FATAL; } }
/** * * * This function returns the conditional MSR device register list according * to the register list ID. * * @param[in] *Device - pointer to the CONDITIONAL_PCI_DEVICE_DESCRIPTOR * @param[out] **RegisterHdr - pointer to the address of the register list * @param[in] *StdHeader - Config handle for library and services * * @return AGESA_STATUS * - AGESA_ALERT * - AGESA_FATAL * - AGESA_SUCCESS * - AGESA_WARNING */ AGESA_STATUS MemFS3GetCMsrDeviceRegisterList ( IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device, OUT CMSR_REGISTER_BLOCK_HEADER **RegisterHdr, IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS RetVal; S3_MEM_NB_BLOCK *S3NBPtr; VOID *RegisterHeader; LOCATE_HEAP_PTR LocHeap; AGESA_BUFFER_PARAMS LocBufferParams; LibAmdMemCopy (&LocBufferParams.StdHeader, StdHeader, sizeof (AMD_CONFIG_PARAMS), StdHeader); LocHeap.BufferHandle = AMD_MEM_S3_NB_HANDLE; LocBufferParams.BufferHandle = AMD_MEM_S3_NB_HANDLE; AGESA_TESTPOINT (TpIfBeforeLocateS3CMsrBuffer, StdHeader); if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { S3NBPtr = (S3_MEM_NB_BLOCK *)LocHeap.BufferPtr; } else { ASSERT(FALSE) ; // No match for heap status, but could not locate "AMD_MEM_S3_NB_HANDLE" in heap for S3GetMsr return AGESA_FATAL; } AGESA_TESTPOINT (TpIfAfterLocateS3CMsrBuffer, StdHeader); // NB block has already been constructed by main block. // No need to construct it here. RetVal = S3NBPtr[BSP_DIE].MemS3GetDeviceRegLst (Device->RegisterListID, &RegisterHeader); *RegisterHdr = (CMSR_REGISTER_BLOCK_HEADER *)RegisterHeader; return RetVal; }
/** * * Get Ids Performance analysis table pointer in the AGESA Heap. * * @param[in,out] StdHeader The Pointer of AGESA Header * @param[in] TestPoint Progress indicator value, see @ref AGESA_TP * * @retval AGESA_SUCCESS Success to get the pointer of Performance analysis Table. * @retval AGESA_ERROR Fail to get the pointer of Performance analysis Table. * @retval AGESA_UNSUPPORTED Get an exclude testpoint * **/ AGESA_STATUS IdsPerfTimestamp ( IN OUT AMD_CONFIG_PARAMS *StdHeader, IN AGESA_TP TestPoint ) { AGESA_STATUS status; UINT8 Index; UINT8 i; TP_Perf_STRUCT *PerfTableEntry; ALLOCATE_HEAP_PARAMS AllocHeapParams; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT64 CurrentTsc; // Exclude some testpoint which may cause deadloop for (i = 0; i < (sizeof (IdsPerfExcludeTp) / sizeof (AGESA_TP)); i++) { if (TestPoint == IdsPerfExcludeTp[i]) { return AGESA_UNSUPPORTED; } } //if heap is not ready yet, don't invoke locate buffer, or else will cause event log & locate heap dead loop if (StdHeader->HeapStatus != HEAP_DO_NOT_EXIST_YET ) { LibAmdMsrRead (TSC, &CurrentTsc, StdHeader); LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status == AGESA_SUCCESS) { PerfTableEntry = (TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr); } else { AllocHeapParams.RequestedBufferSize = sizeof (TP_Perf_STRUCT); AllocHeapParams.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (status != AGESA_SUCCESS) { return status; } PerfTableEntry = (TP_Perf_STRUCT *) (AllocHeapParams.BufferPtr); LibAmdMemFill (PerfTableEntry, 0, sizeof (TP_Perf_STRUCT), StdHeader); } Index = PerfTableEntry ->Index; //TPPerfUnit doesn't need to check, it may used for multiple time, used to check the time // consumption of each perf measure routine. if ((TestPoint != TpPerfUnit)) { for (i = 0; i < Index; i++) { if ((UINT8) TestPoint == PerfTableEntry ->TP[i].TestPoint) { return AGESA_SUCCESS; } } } PerfTableEntry ->TP[Index].TestPoint = (UINT8) TestPoint; PerfTableEntry ->TP[Index].StartTsc = CurrentTsc; PerfTableEntry ->Index = ++Index; } return AGESA_SUCCESS; }
/** * Output Test Point function . * * @param[in,out] StdHeader The Pointer of Standard Header. * * @retval AGESA_SUCCESS Success to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * @retval AGESA_ERROR Fail to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * **/ AGESA_STATUS IdsPerfAnalyseTimestamp ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT32 TscRateInMhz; CPU_SPECIFIC_SERVICES *FamilySpecificServices; IDS_CALLOUT_STRUCT IdsCalloutData; AGESA_STATUS Status; PERFREGBACKUP PerfReg; UINT32 CR4reg; UINT64 SMsr; LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status != AGESA_SUCCESS) { return status; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &TscRateInMhz, StdHeader); ((TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr)) ->TscInMhz = TscRateInMhz; ((TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr)) ->Version = IDS_PERF_VERSION; IdsCalloutData.IdsNvPtr = NULL; IdsCalloutData.StdHeader = *StdHeader; IdsCalloutData.Reserved = 0; Status = AgesaGetIdsData (IDS_CALLOUT_GET_PERF_BUFFER, &IdsCalloutData); //Check if Platform BIOS provide a buffer to copy if ((Status == AGESA_SUCCESS) && (IdsCalloutData.Reserved != 0)) { LibAmdMemCopy ((VOID *)IdsCalloutData.Reserved, LocateHeapStructPtr.BufferPtr, sizeof (TP_Perf_STRUCT), StdHeader); } else { //No platform performance buffer provide, use the default HDTOUT output if (AmdIdsHdtOutSupport () == FALSE) { //Init break point IdsPerfSaveReg (&PerfReg, StdHeader); LibAmdMsrRead (0xC001100A, (UINT64 *)&SMsr, StdHeader); SMsr |= 1; LibAmdMsrWrite (0xC001100A, (UINT64 *)&SMsr, StdHeader); LibAmdWriteCpuReg (DR2_REG, 0x99cc); LibAmdWriteCpuReg (DR7_REG, 0x02000420); LibAmdReadCpuReg (CR4_REG, &CR4reg); LibAmdWriteCpuReg (CR4_REG, CR4reg | ((UINT32)1 << 3)); IdsPerfHdtOut (1, (UINT32) (UINT64) LocateHeapStructPtr.BufferPtr, StdHeader); IdsPerfRestoreReg (&PerfReg, StdHeader); } } return status; }
/** * * Get Ids Performance analysis table pointer in the AGESA Heap. * * @param[in] LineInFile ((FILECODE) shift 16)+ Line number * @param[in] Description ID for Description define idsperf.h * @param[in,out] StdHeader The Pointer of AGESA Header * * @retval AGESA_SUCCESS Success to get the pointer of Performance analysis Table. * @retval AGESA_ERROR Fail to get the pointer of Performance analysis Table. * @retval AGESA_UNSUPPORTED Get an exclude testpoint * **/ AGESA_STATUS IdsPerfTimestamp ( IN UINT32 LineInFile, IN UINT32 Description, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; UINT32 Index; TP_Perf_STRUCT *PerfTableEntry; ALLOCATE_HEAP_PARAMS AllocHeapParams; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT64 TscAtBegining; UINT64 TscAtEnd; //if heap is not ready yet, don't invoke locate buffer, or else will cause event log & locate heap dead loop if (StdHeader->HeapStatus != HEAP_DO_NOT_EXIST_YET ) { IdsGetGtsc (&TscAtBegining, StdHeader); LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status == AGESA_SUCCESS) { PerfTableEntry = (TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr); } else { AllocHeapParams.RequestedBufferSize = sizeof (TP_Perf_STRUCT); AllocHeapParams.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (status != AGESA_SUCCESS) { return status; } PerfTableEntry = (TP_Perf_STRUCT *) (AllocHeapParams.BufferPtr); LibAmdMemFill (PerfTableEntry, 0, sizeof (TP_Perf_STRUCT), StdHeader); PerfTableEntry->Signature = 'FREP'; PerfTableEntry->Version = IDS_PERF_VERSION; } Index = PerfTableEntry ->Index; if (Index >= MAX_PERFORMANCE_UNIT_NUM - 1) { ASSERT (FALSE); return AGESA_WARNING; } // Read GTSC again, so we could calculate the time consumed by this routine IdsGetGtsc (&TscAtEnd, StdHeader); PerfTableEntry ->TP[Index].LineInFile = LineInFile; PerfTableEntry ->TP[Index].Description = Description; PerfTableEntry ->TP[Index].StartTsc = TscAtBegining - PerfTableEntry ->TP[MAX_PERFORMANCE_UNIT_NUM - 1].StartTsc; PerfTableEntry ->TP[MAX_PERFORMANCE_UNIT_NUM - 1].StartTsc += TscAtEnd - TscAtBegining; // Using the last TP to record the total time consumed by this routine PerfTableEntry ->Index = ++Index; } return AGESA_SUCCESS; }
/** * * Get Ids Performance analysis table pointer in the AGESA Heap. * * @param[in] LineInFile ((FILECODE) shift 16)+ Line number * @param[in] Description ID for Description define idsperf.h * @param[in,out] StdHeader The Pointer of AGESA Header * * @retval AGESA_SUCCESS Success to get the pointer of Performance analysis Table. * @retval AGESA_ERROR Fail to get the pointer of Performance analysis Table. * @retval AGESA_UNSUPPORTED Get an exclude testpoint * **/ AGESA_STATUS IdsPerfTimestamp ( IN UINT32 LineInFile, IN UINT32 Description, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; UINT32 Index; TP_Perf_STRUCT *PerfTableEntry; ALLOCATE_HEAP_PARAMS AllocHeapParams; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT64 CurrentTsc; //if heap is not ready yet, don't invoke locate buffer, or else will cause event log & locate heap dead loop if (StdHeader->HeapStatus != HEAP_DO_NOT_EXIST_YET ) { LibAmdMsrRead (TSC, &CurrentTsc, StdHeader); LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status == AGESA_SUCCESS) { PerfTableEntry = (TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr); } else { AllocHeapParams.RequestedBufferSize = sizeof (TP_Perf_STRUCT); AllocHeapParams.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (status != AGESA_SUCCESS) { return status; } PerfTableEntry = (TP_Perf_STRUCT *) (AllocHeapParams.BufferPtr); LibAmdMemFill (PerfTableEntry, 0, sizeof (TP_Perf_STRUCT), StdHeader); PerfTableEntry->Signature = 'FREP'; PerfTableEntry->Version = IDS_PERF_VERSION; } Index = PerfTableEntry ->Index; if (Index >= MAX_PERFORMANCE_UNIT_NUM) { return AGESA_WARNING; } ASSERT (Index < MAX_PERFORMANCE_UNIT_NUM); PerfTableEntry ->TP[Index].LineInFile = LineInFile; PerfTableEntry ->TP[Index].Description = Description; PerfTableEntry ->TP[Index].StartTsc = CurrentTsc; PerfTableEntry ->Index = ++Index; } return AGESA_SUCCESS; }
VOID * GnbLocateHeapBuffer ( IN UINT32 Handle, IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; LOCATE_HEAP_PTR LocHeapParams; LocHeapParams.BufferHandle = Handle; Status = HeapLocateBuffer (&LocHeapParams, StdHeader); if (Status != AGESA_SUCCESS) { return NULL; } return LocHeapParams.BufferPtr; }
/** * * Find out the pointer to the BufferHandle which contains * Node Topology information * * @param[in, out] StdHeader Standard Head Pointer * @param[in] SocketTopologyPtr Point to the address of Socket Topology * */ VOID STATIC AcpiCditHBufferFind ( IN OUT AMD_CONFIG_PARAMS *StdHeader, IN UINT8 **SocketTopologyPtr ) { LOCATE_HEAP_PTR LocateBuffer; LocateBuffer.BufferHandle = HOP_COUNT_TABLE_HANDLE; if (HeapLocateBuffer (&LocateBuffer, StdHeader) == AGESA_SUCCESS) { *SocketTopologyPtr = (UINT8 *) LocateBuffer.BufferPtr; } return; }
/** * Family 15h Trinity core 0 entry point for performing the necessary steps after * a warm reset has occurred. * * The steps are as follows: * * 1. Temp1=D18F5x170[SwNbPstateLoDis]. * 2. Temp2=D18F5x170[NbPstateDisOnP0]. * 3. Temp3=D18F5x170[NbPstateThreshold]. * 4. Temp4=D18F5x170[NbPstateGnbSlowDis]. * 5. If MSRC001_0070[NbPstate]=0, go to step 6. If MSRC001_0070[NbPstate]=1, go to step 11. * 6. Write 1 to D18F5x170[NbPstateGnbSlowDis]. * 7. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold]. * 8. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo]. * 9. Set D18F5x170[SwNbPstateLoDis]=1. * 10. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi]. Go to step 15. * 11. Write 1 to D18F5x170[SwNbPstateLoDis]. * 12. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi]. * 13. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold]. * 14. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo]. * 15. Set D18F5x170[SwNbPstateLoDis]=Temp1, D18F5x170[NbPstateDisOnP0]=Temp2, D18F5x170[NbP- * stateThreshold]=Temp3, and D18F5x170[NbPstateGnbSlowDis]=Temp4. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F15TnPmNbAfterReset ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 TaskedCore; UINT32 Ignored; AP_TASK TaskPtr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredSts; LOCATE_HEAP_PTR Locate; IDS_HDT_CONSOLE (CPU_TRACE, " F15TnPmNbAfterReset\n"); IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ASSERT (Core == 0); if (FamilySpecificServices->IsNbPstateEnabled (FamilySpecificServices, &CpuEarlyParamsPtr->PlatformConfig, StdHeader)) { PciAddress.AddressValue = NB_PSTATE_CTRL_PCI_ADDR; Locate.BufferHandle = AMD_CPU_NB_PSTATE_FIXUP_HANDLE; if (HeapLocateBuffer (&Locate, StdHeader) == AGESA_SUCCESS) { LibAmdPciWrite (AccessWidth32, PciAddress, Locate.BufferPtr, StdHeader); } else { ASSERT (FALSE); } } // Launch one core per node. TaskPtr.FuncAddress.PfApTask = F15TnPmNbAfterResetOnCore; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetGivenModuleCoreRange (Socket, Module, &TaskedCore, &Ignored, StdHeader)) { if (TaskedCore != 0) { ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) TaskedCore, &TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr); }
/** * Initialize S3 Script framework * * * * @param[in] StdHeader Pointer to standard header * @param[out] S3SaveTable S3 save table header */ AGESA_STATUS S3ScriptGetS3SaveTable ( IN AMD_CONFIG_PARAMS *StdHeader, OUT S3_SAVE_TABLE_HEADER **S3SaveTable ) { AGESA_STATUS Status; LOCATE_HEAP_PTR LocHeapParams; LocHeapParams.BufferHandle = AMD_S3_SCRIPT_SAVE_TABLE_HANDLE; Status = HeapLocateBuffer (&LocHeapParams, StdHeader); if (Status != AGESA_SUCCESS) { *S3SaveTable = NULL; return Status; } *S3SaveTable = (S3_SAVE_TABLE_HEADER *) LocHeapParams.BufferPtr; return AGESA_SUCCESS; }
/** * * This function gets the Event Log pointer. * * It will locate the Event Log on the heap using the heap locate service. If the Event * Log is not located, NULL is returned. * * @param[out] EventLog Pointer to the Event Log, or NULL. * @param[in] StdHeader Our Configuration, for passing to services. * */ VOID STATIC GetEventLogHeapPointer ( OUT AGESA_STRUCT_BUFFER **EventLog, IN AMD_CONFIG_PARAMS *StdHeader ) { LOCATE_HEAP_PTR LocateHeapStruct; LocateHeapStruct.BufferHandle = EVENT_LOG_BUFFER_HANDLE; LocateHeapStruct.BufferPtr = NULL; if ((HeapLocateBuffer (&LocateHeapStruct, StdHeader)) == AGESA_SUCCESS) { *EventLog = (AGESA_STRUCT_BUFFER *)LocateHeapStruct.BufferPtr; } else { *EventLog = NULL; } }
/** * * * This function stores special case register on the heap. * * @param[in,out] *NBPtr - Pointer to the northbridge block. * @param[in,out] *StdHeader - Config handle for library and services. * @return none */ VOID STATIC MemNS3ExitSelfRefRegC32 ( IN OUT MEM_NB_BLOCK *NBPtr, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { LOCATE_HEAP_PTR LocateBufferPtr; UINT8 i; PCI_ADDR PciAddr; UINT32 Value; UINT8 NodeID; UINT8 Offset; S3_SPECIAL_CASE_HEAP_HEADER *SpecialHeapHeader; Offset = 0; PciAddr.Address.Device = NBPtr->PciAddr.Address.Device; PciAddr.Address.Bus = NBPtr->PciAddr.Address.Bus; PciAddr.Address.Segment = NBPtr->PciAddr.Address.Segment; PciAddr.Address.Function = 2; LocateBufferPtr.BufferHandle = AMD_MEM_S3_DATA_HANDLE; if (HeapLocateBuffer (&LocateBufferPtr, StdHeader) == AGESA_SUCCESS) { SpecialHeapHeader = (S3_SPECIAL_CASE_HEAP_HEADER *) LocateBufferPtr.BufferPtr; // Get the node ID of the target die. NodeID = (UINT8) (PciAddr.Address.Device - 24); for (i = 0; i < MAX_NODES_SUPPORTED_C32; i ++) { if (SpecialHeapHeader[i].Node == NodeID) { // Get the offset in the heap for the target die. Offset = SpecialHeapHeader[i].Offset; break; } } ASSERT (i < MAX_NODES_SUPPORTED_C32); // Restore the value one by one in the sequence of the special case register array. if (Offset != 0) { for (i = 0; i < (sizeof (SpecialCasePCIRegC32) / sizeof (UINT16)); i ++) { PciAddr.Address.Register = SpecialCasePCIRegC32[i]; Value = *(UINT32 *) (LocateBufferPtr.BufferPtr + Offset + (i << 2)); MemNS3SetCSRNb (AccessS3SaveWidth32, PciAddr, &Value, StdHeader); } } } }
/** * * Get IDS NV table pointer in the AGESA Heap. * * @param[in,out] IdsNvTable The Pointer of IDS NV Table. * @param[in,out] StdHeader The Pointer of Standard Header. * * @retval AGESA_SUCCESS Success to get the pointer of NV Table. * @retval AGESA_ERROR Fail to get the pointer of NV Table. **/ AGESA_STATUS AmdGetIdsNvTable ( IN OUT VOID **IdsNvTable, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; IDS_CONTROL_STRUCT *IdsCtrlPtr; LocateHeapStructPtr.BufferHandle = IDS_CONTROL_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status == AGESA_SUCCESS) { IdsCtrlPtr = (IDS_CONTROL_STRUCT *) LocateHeapStructPtr.BufferPtr; *IdsNvTable = LocateHeapStructPtr.BufferPtr + IdsCtrlPtr->IdsNvTableOffset; } return status; }
/** * * Read IDS NV value in NV table. * * It searches the table until the Nv Id is found and return the NV value * in the table. Otherwise, return IDS_UNSUPPORTED. * * @param[in] IdsNvId IDS NV ID * @param[in] NvTablePtr NV Table pointer. * @param[in,out] StdHeader The Pointer of Standard Header. * * @retval IDS_UNSUPPORTED NV ID is not found in the table * Other Value The NV value * **/ IDS_STATUS AmdIdsNvReader ( IN UINT16 IdsNvId, IN IDS_NV_ITEM *NvTablePtr, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { IDS_STATUS Status; IDS_NV_ITEM *NvPtr; BOOLEAN IgnoreIdsDefault; AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; IDS_CONTROL_STRUCT *IdsCtrlPtr; IgnoreIdsDefault = FALSE; Status = IDS_UNSUPPORTED; NvPtr = NvTablePtr; if (NvPtr != NULL) { while (NvPtr->IdsNvId != AGESA_IDS_NV_END) { if (NvPtr->IdsNvId == IdsNvId) { break; } else { NvPtr ++; } } if ((NvPtr->IdsNvId != AGESA_IDS_NV_END)) { //Get IgnoreIdsDefault from heap LocateHeapStructPtr.BufferHandle = IDS_CONTROL_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status == AGESA_SUCCESS) { IdsCtrlPtr = (IDS_CONTROL_STRUCT *) LocateHeapStructPtr.BufferPtr; IgnoreIdsDefault = IdsCtrlPtr->IgnoreIdsDefault; } if (IgnoreIdsDefault || (NvPtr->IdsNvValue != AGESA_IDS_DFT_VAL)) { Status = NvPtr->IdsNvValue; } } } return Status; }
AGESA_STATUS AmdGetIdsImagebase ( IN OUT UINT64 *IdsImageBase, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; IDS_CONTROL_STRUCT *IdsCtrlPtr; LocateHeapStructPtr.BufferHandle = IDS_CONTROL_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status == AGESA_SUCCESS) { IdsCtrlPtr = (IDS_CONTROL_STRUCT *) LocateHeapStructPtr.BufferPtr; *IdsImageBase = IdsCtrlPtr->IdsImageBase; } return status; }
/** * * * This function stores special case register on the heap. * * @param[in] AccessWidth - Access width of the register * @param[in] Address - address of the CSR register in PCI_ADDR format. * @param[in, out] *Value - Pointer to the value be read. * @param[in, out] *ConfigPtr - Pointer to Config handle. * @return none */ VOID STATIC MemNS3SetSpecialPCIRegC32 ( IN ACCESS_WIDTH AccessWidth, IN PCI_ADDR Address, IN VOID *Value, IN OUT VOID *ConfigPtr ) { LOCATE_HEAP_PTR LocateBufferPtr; UINT8 i; UINT8 NodeID; UINT8 Offset; S3_SPECIAL_CASE_HEAP_HEADER *SpecialHeapHeader; Offset = 0; LocateBufferPtr.BufferHandle = AMD_MEM_S3_DATA_HANDLE; if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) { SpecialHeapHeader = (S3_SPECIAL_CASE_HEAP_HEADER *) LocateBufferPtr.BufferPtr; // Get the node ID of the target die. NodeID = (UINT8) (Address.Address.Device - 24); for (i = 0; i < MAX_NODES_SUPPORTED_C32; i ++) { if (SpecialHeapHeader[i].Node == NodeID) { // Get the offset in the heap for the target die. Offset = SpecialHeapHeader[i].Offset; break; } } ASSERT (i < MAX_NODES_SUPPORTED_C32); // Save the value in the heap at appropriate offset based on the index // of the target register in the special case array. if (Offset != 0) { for (i = 0; i < (sizeof (SpecialCasePCIRegC32) / sizeof (UINT16)); i ++) { if (SpecialCasePCIRegC32[i] == Address.Address.Register) { *(UINT32 *) (LocateBufferPtr.BufferPtr + Offset + (i << 2)) = *(UINT32 *) Value; } } } } }
/** * Output Test Point function . * * @param[in,out] StdHeader The Pointer of Standard Header. * * @retval AGESA_SUCCESS Success to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * @retval AGESA_ERROR Fail to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * **/ AGESA_STATUS IdsPerfAnalyseTimestamp ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT32 TscRateInMhz; CPU_SPECIFIC_SERVICES *FamilySpecificServices; PERFREGBACKUP PerfReg; UINT32 CR4reg; UINT64 SMsr; LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status != AGESA_SUCCESS) { return status; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &TscRateInMhz, StdHeader); ((TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr)) ->TscInMhz = TscRateInMhz; //Init break point IdsPerfSaveReg (&PerfReg, StdHeader); LibAmdMsrRead (0xC001100A, (UINT64 *)&SMsr, StdHeader); SMsr |= 1; LibAmdMsrWrite (0xC001100A, (UINT64 *)&SMsr, StdHeader); LibAmdWriteCpuReg (DR0_REG, 0x8899); LibAmdWriteCpuReg (DR7_REG, 0x00020402); LibAmdReadCpuReg (CR4_REG, &CR4reg); LibAmdWriteCpuReg (CR4_REG, CR4reg | ((UINT32)1 << 3)); IdsPerfHdtOut (1, (UINT32) LocateHeapStructPtr.BufferPtr, StdHeader); IdsPerfRestoreReg (&PerfReg, StdHeader); return status; }
FCH_DATA_BLOCK* FchInitLoadDataBlock ( IN FCH_INTERFACE *FchInterface, IN AMD_CONFIG_PARAMS *StdHeader ) { FCH_DATA_BLOCK *FchParams; LOCATE_HEAP_PTR LocHeapPtr; AMD_CONFIG_PARAMS TempStdHeader; AGESA_STATUS AgesaStatus; TempStdHeader = *StdHeader; TempStdHeader.HeapStatus = HEAP_SYSTEM_MEM; // Locate the internal data block via heap manager LocHeapPtr.BufferHandle = AMD_FCH_DATA_BLOCK_HANDLE; AgesaStatus = HeapLocateBuffer (&LocHeapPtr, &TempStdHeader); ASSERT (!AgesaStatus); FchParams = (FCH_DATA_BLOCK *) LocHeapPtr.BufferPtr; ASSERT (FchParams != NULL); FchParams->StdHeader = StdHeader; return FchParams; }
AGESA_STATUS AmdMemRecovery ( IN OUT MEM_DATA_STRUCT *MemPtr ) { UINT8 Socket; UINT8 Module; UINT8 i; AGESA_STATUS AgesaStatus; PCI_ADDR Address; MEM_NB_BLOCK NBBlock; MEM_TECH_BLOCK TechBlock; LOCATE_HEAP_PTR SocketWithMem; ALLOCATE_HEAP_PARAMS AllocHeapParams; // // Read SPD data // MemRecSPDDataProcess (MemPtr); // // Get the socket id from heap. // SocketWithMem.BufferHandle = AMD_REC_MEM_SOCKET_HANDLE; if (HeapLocateBuffer (&SocketWithMem, &MemPtr->StdHeader) == AGESA_SUCCESS) { Socket = *(UINT8 *) SocketWithMem.BufferPtr; } else { ASSERT(FALSE); // Socket handle not found return AGESA_FATAL; } // // Allocate buffer for memory init structures // AllocHeapParams.RequestedBufferSize = MAX_DIES_PER_SOCKET * sizeof (DIE_STRUCT); AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DIE_STRUCT_HANDLE, 0, 0, 0); AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Heap allocation failed to allocate Die struct return AGESA_FATAL; } MemPtr->DiesPerSystem = (DIE_STRUCT *)AllocHeapParams.BufferPtr; // // Discover populated CPUs // for (Module = 0; Module < MAX_DIES_PER_SOCKET; Module++) { if (GetPciAddress ((VOID *)MemPtr, Socket, Module, &Address, &AgesaStatus)) { MemPtr->DiesPerSystem[Module].SocketId = Socket; MemPtr->DiesPerSystem[Module].DieId = Module; MemPtr->DiesPerSystem[Module].PciAddr.AddressValue = Address.AddressValue; } } i = 0; while (MemRecNBInstalled[i] != NULL) { if (MemRecNBInstalled[i] (&NBBlock, MemPtr, 0) == TRUE) { break; } i++; }; if (MemRecNBInstalled[i] == NULL) { ASSERT(FALSE); // No NB installed return AGESA_FATAL; } MemRecTechInstalled[0] (&TechBlock, &NBBlock); NBBlock.TechPtr = &TechBlock; return NBBlock.InitRecovery (&NBBlock); }
/** * * * This function initialize needed data structures for S3 resume. * * @param[in, out] **S3NBPtr - Pointer to the pointer of northbridge block. * @param[in, out] *MemPtr - Pointer to MEM_DATA_STRUCT. * @param[in, out] *mmData - Pointer to MEM_MAIN_DATA_BLOCK. * @param[in] *StdHeader - Config handle for library and services. * * @return AGESA_STATUS * - AGESA_ALERT * - AGESA_FATAL * - AGESA_SUCCESS * - AGESA_WARNING */ AGESA_STATUS MemS3InitNB ( IN OUT S3_MEM_NB_BLOCK **S3NBPtr, IN OUT MEM_DATA_STRUCT **MemPtr, IN OUT MEM_MAIN_DATA_BLOCK *mmData, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; AGESA_STATUS RetVal; LOCATE_HEAP_PTR LocHeap; MEM_NB_BLOCK *NBPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT8 Die; UINT8 DieCount; BOOLEAN SkipScan; SkipScan = FALSE; LocHeap.BufferHandle = AMD_MEM_DATA_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. *MemPtr = (MEM_DATA_STRUCT *)LocHeap.BufferPtr; SkipScan = TRUE; } else { AllocHeapParams.RequestedBufferSize = sizeof (MEM_DATA_STRUCT); AllocHeapParams.BufferHandle = AMD_MEM_DATA_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Allocate failed for MEM_DATA_STRUCT return AGESA_FATAL; } *MemPtr = (MEM_DATA_STRUCT *)AllocHeapParams.BufferPtr; } LibAmdMemCopy (&(*MemPtr)->StdHeader, StdHeader, sizeof (AMD_CONFIG_PARAMS), StdHeader); mmData->MemPtr = *MemPtr; if (!SkipScan) { RetVal = MemSocketScan (mmData); if (RetVal == AGESA_FATAL) { return RetVal; } } else { // We already have initialize data block, no need to do it again. mmData->DieCount = mmData->MemPtr->DieCount; } DieCount = mmData->DieCount; //--------------------------------------------- // Creation of NB Block for S3 resume //--------------------------------------------- // Search for AMD_MEM_AUTO_HANDLE on the heap first. // Only apply for space on the heap if cannot find AMD_MEM_AUTO_HANDLE on the heap. LocHeap.BufferHandle = AMD_MEM_S3_NB_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. *S3NBPtr = (S3_MEM_NB_BLOCK *)LocHeap.BufferPtr; } else { AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (S3_MEM_NB_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_S3_NB_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Could not allocate space for "S3_MEM_NB_BLOCK" return AGESA_FATAL; } *S3NBPtr = (S3_MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; LocHeap.BufferHandle = AMD_MEM_AUTO_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. NBPtr = (MEM_NB_BLOCK *)LocHeap.BufferPtr; } else { AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (MEM_NB_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_AUTO_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Allocate failed for "MEM_NB_BLOCK" return AGESA_FATAL; } NBPtr = (MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; } // Construct each die. for (Die = 0; Die < DieCount; Die ++) { i = 0; ((*S3NBPtr)[Die]).NBPtr = &NBPtr[Die]; while (memNBInstalled[i].MemS3ResumeConstructNBBlock != 0) { if (memNBInstalled[i].MemS3ResumeConstructNBBlock ((VOID *)&((*S3NBPtr)[Die]), *MemPtr, Die)) { break; } i++; }; if (memNBInstalled[i].MemS3ResumeConstructNBBlock == 0) { ASSERT(FALSE); // S3 resume NB constructor not found return AGESA_FATAL; } } } return AGESA_SUCCESS; }
/** * * This function handle errors occur in memory code. * * * @param[in,out] *MCTPtr - pointer to DIE_STRUCT. * @param[in,out] DCT - DCT that needs to be handled. * @param[in,out] ChipSelMask - Chip select mask that needs to be handled * @param[in,out] *StdHeader - pointer to AMD_CONFIG_PARAMS * * @return TRUE - No fatal error occurs. * @return FALSE - Fatal error occurs. */ BOOLEAN MemErrHandle ( IN DIE_STRUCT *MCTPtr, IN UINT8 DCT, IN UINT16 ChipSelMask, IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN ErrorRecovery; BOOLEAN IgnoreErr; DCT_STRUCT *DCTPtr; UINT8 CurrentDCT; LOCATE_HEAP_PTR LocHeap; MEM_NB_BLOCK *NBPtr; MEM_MAIN_DATA_BLOCK mmData; DCTPtr = MCTPtr->DctData; ErrorRecovery = TRUE; IgnoreErr = FALSE; IDS_OPTION_HOOK (IDS_MEM_ERROR_RECOVERY, &ErrorRecovery, StdHeader); if (ErrorRecovery) { if (DCT == EXCLUDE_ALL_DCT) { // Exclude all DCTs on a node for (CurrentDCT = 0; CurrentDCT < MCTPtr->DctCount; CurrentDCT++) { DCTPtr[CurrentDCT].Timings.CsTestFail = DCTPtr[CurrentDCT].Timings.CsPresent; } } else if (ChipSelMask == EXCLUDE_ALL_CHIPSEL) { // Exclude the specified DCT DCTPtr[DCT].Timings.CsTestFail = DCTPtr[DCT].Timings.CsPresent; } else { // Exclude the chip select that has been marked out DCTPtr[DCT].Timings.CsTestFail |= ChipSelMask & DCTPtr[DCT].Timings.CsPresent; IDS_OPTION_HOOK (IDS_LOADCARD_ERROR_RECOVERY, &DCTPtr[DCT], StdHeader); } // Exclude the failed dimm to recovery from error if (MCTPtr->NodeMemSize != 0) { LocHeap.BufferHandle = AMD_MEM_AUTO_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. NBPtr = (MEM_NB_BLOCK *)LocHeap.BufferPtr; if (!NBPtr->SharedPtr->NodeMap[MCTPtr->NodeId].IsValid) { // Memory map has not been calculated, no need to remap memory across node here. // Only need to remap memory within the node. NBPtr = &NBPtr[MCTPtr->NodeId]; NBPtr->FeatPtr->ExcludeDIMM (NBPtr); } else { // Need to remap memory across the whole system. mmData.MemPtr = NBPtr->MemPtr; mmData.mmSharedPtr = NBPtr->SharedPtr; mmData.NBPtr = NBPtr; mmData.TechPtr = (MEM_TECH_BLOCK *) (&NBPtr[NBPtr->MemPtr->DieCount]); mmData.DieCount = NBPtr->MemPtr->DieCount; if (!MemFeatMain.ExcludeDIMM (&mmData)) { return FALSE; } } } // If allocation fails, that means the code is not running at BSP. // Parallel training is in process. // Remap for parallel training will be done when control returns to BSP. } return TRUE; } else { IDS_OPTION_HOOK (IDS_MEM_IGNORE_ERROR, &IgnoreErr, StdHeader); if (IgnoreErr) { return TRUE; } SetMemError (AGESA_FATAL, MCTPtr); ASSERT(FALSE); // ErrorRecovery is FALSE return FALSE; } }
AGESA_STATUS AmdIdentifyDimm ( IN OUT AMD_IDENTIFY_DIMM *AmdDimmIdentify ) { UINT8 i; AGESA_STATUS RetVal; MEM_MAIN_DATA_BLOCK mmData; // Main Data block MEM_NB_BLOCK *NBPtr; MEM_DATA_STRUCT MemData; LOCATE_HEAP_PTR LocHeap; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT8 Node; UINT8 Dct; UINT8 Die; UINT8 DieCount; LibAmdMemCopy (&(MemData.StdHeader), &(AmdDimmIdentify->StdHeader), sizeof (AMD_CONFIG_PARAMS), &(AmdDimmIdentify->StdHeader)); mmData.MemPtr = &MemData; RetVal = MemSocketScan (&mmData); if (RetVal == AGESA_FATAL) { return RetVal; } DieCount = mmData.DieCount; // Search for AMD_MEM_AUTO_HANDLE on the heap first. // Only apply for space on the heap if cannot find AMD_MEM_AUTO_HANDLE on the heap. LocHeap.BufferHandle = AMD_MEM_AUTO_HANDLE; if (HeapLocateBuffer (&LocHeap, &AmdDimmIdentify->StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. NBPtr = (MEM_NB_BLOCK *)LocHeap.BufferPtr; mmData.NBPtr = NBPtr; } else { AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (MEM_NB_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_AUTO_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, &AmdDimmIdentify->StdHeader) != AGESA_SUCCESS) { PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_IDENTIFY_DIMM_MEM_NB_BLOCK, 0, 0, 0, 0, &AmdDimmIdentify->StdHeader); ASSERT(FALSE); // Could not allocate heap space for NB block for Identify DIMM return AGESA_FATAL; } NBPtr = (MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; mmData.NBPtr = NBPtr; // Construct each die. for (Die = 0; Die < DieCount; Die ++) { i = 0; while (memNBInstalled[i].MemIdentifyDimmConstruct != 0) { if (memNBInstalled[i].MemIdentifyDimmConstruct (&NBPtr[Die], &MemData, Die)) { break; } i++; }; if (memNBInstalled[i].MemIdentifyDimmConstruct == 0) { PutEventLog (AGESA_FATAL, MEM_ERROR_NO_CONSTRUCTOR_FOR_IDENTIFY_DIMM, Die, 0, 0, 0, &AmdDimmIdentify->StdHeader); ASSERT(FALSE); // No Identify DIMM constructor found return AGESA_FATAL; } } } i = 0; while (memNBInstalled[i].MemIdentifyDimmConstruct != 0) { if ((RetVal = memNBInstalled[i].MemTransSysAddrToCs (AmdDimmIdentify, &mmData)) == AGESA_SUCCESS) { // Translate Node, DCT and Chip select number to Socket, Channel and Dimm number. Node = AmdDimmIdentify->SocketId; Dct = AmdDimmIdentify->MemChannelId; AmdDimmIdentify->SocketId = MemData.DiesPerSystem[Node].SocketId; AmdDimmIdentify->MemChannelId = NBPtr[Node].GetSocketRelativeChannel (&NBPtr[Node], Dct, 0); AmdDimmIdentify->DimmId = AmdDimmIdentify->ChipSelect / 2; AmdDimmIdentify->ChipSelect %= 2; break; } i++; }; return RetVal; }
/** * Save and Restore or Initialize the content of the mailbox registers. * * The registers used for AP mailbox should have the content related to their function * preserved. * * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config Handle for library, services. * * @return AGESA_SUCCESS Always succeeds. * */ AGESA_STATUS STATIC PreserveMailboxes ( IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { PRESERVE_MAILBOX_FAMILY_SERVICES *FamilySpecificServices; UINT32 Socket; UINT32 Module; PCI_ADDR BaseAddress; PCI_ADDR MailboxRegister; PCI_ADDR *NextRegister; AGESA_STATUS IgnoredStatus; AGESA_STATUS HeapStatus; UINT32 Value; ALLOCATE_HEAP_PARAMS AllocateParams; LOCATE_HEAP_PTR LocateParams; UINT32 RegisterEntryIndex; BaseAddress.AddressValue = ILLEGAL_SBDFO; if (EntryPoint == CPU_FEAT_AFTER_COHERENT_DISCOVERY) { // The save step. Save either the register content or zero (for cold boot, if family specifies that). AllocateParams.BufferHandle = PRESERVE_MAIL_BOX_HANDLE; AllocateParams.RequestedBufferSize = (sizeof (UINT32) * (MAX_PRESERVE_REGISTER_ENTRIES * (MAX_SOCKETS * MAX_DIES))); AllocateParams.Persist = HEAP_SYSTEM_MEM; HeapStatus = HeapAllocateBuffer (&AllocateParams, StdHeader); ASSERT ((HeapStatus == AGESA_SUCCESS) && (AllocateParams.BufferPtr != NULL)); LibAmdMemFill (AllocateParams.BufferPtr, 0xFF, AllocateParams.RequestedBufferSize, StdHeader); RegisterEntryIndex = 0; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &BaseAddress, &IgnoredStatus)) { GetFeatureServicesOfSocket (&PreserveMailboxFamilyServiceTable, Socket, (const VOID **)&FamilySpecificServices, StdHeader); ASSERT (FamilySpecificServices != NULL); NextRegister = FamilySpecificServices->RegisterList; while (NextRegister->AddressValue != ILLEGAL_SBDFO) { ASSERT (RegisterEntryIndex < (MAX_PRESERVE_REGISTER_ENTRIES * GetPlatformNumberOfSockets () * GetPlatformNumberOfModules ())); if (FamilySpecificServices->IsZeroOnCold && (!IsWarmReset (StdHeader))) { Value = 0; } else { MailboxRegister = BaseAddress; MailboxRegister.Address.Function = NextRegister->Address.Function; MailboxRegister.Address.Register = NextRegister->Address.Register; LibAmdPciRead (AccessWidth32, MailboxRegister, &Value, StdHeader); } (* (MAILBOX_REGISTER_SAVE_ENTRY) AllocateParams.BufferPtr) [RegisterEntryIndex] = Value; RegisterEntryIndex++; NextRegister++; } } } } } else if ((EntryPoint == CPU_FEAT_INIT_LATE_END) || (EntryPoint == CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) { // The restore step. Just write out the saved content in the buffer. LocateParams.BufferHandle = PRESERVE_MAIL_BOX_HANDLE; HeapStatus = HeapLocateBuffer (&LocateParams, StdHeader); ASSERT ((HeapStatus == AGESA_SUCCESS) && (LocateParams.BufferPtr != NULL)); RegisterEntryIndex = 0; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &BaseAddress, &IgnoredStatus)) { GetFeatureServicesOfSocket (&PreserveMailboxFamilyServiceTable, Socket, (const VOID **)&FamilySpecificServices, StdHeader); NextRegister = FamilySpecificServices->RegisterList; while (NextRegister->AddressValue != ILLEGAL_SBDFO) { ASSERT (RegisterEntryIndex < (MAX_PRESERVE_REGISTER_ENTRIES * GetPlatformNumberOfSockets () * GetPlatformNumberOfModules ())); MailboxRegister = BaseAddress; MailboxRegister.Address.Function = NextRegister->Address.Function; MailboxRegister.Address.Register = NextRegister->Address.Register; Value = (* (MAILBOX_REGISTER_SAVE_ENTRY) LocateParams.BufferPtr) [RegisterEntryIndex]; LibAmdPciWrite (AccessWidth32, MailboxRegister, &Value, StdHeader); RegisterEntryIndex++; NextRegister++; } } } } HeapStatus = HeapDeallocateBuffer (PRESERVE_MAIL_BOX_HANDLE, StdHeader); } return AGESA_SUCCESS; }