/* *--------------------------------------------------------------------------------------- * * AmdInitPostInitializer * * Initializer routine that will be invoked by the wrapper * to initialize the input structure for the AmdInitPost * * @param[in, out] IN OUT AMD_POST_PARAMS *PostParamsPtr * * @retval AGESA_STATUS * *--------------------------------------------------------------------------------------- */ AGESA_STATUS AmdInitPostInitializer ( IN AMD_CONFIG_PARAMS *StdHeader, IN OUT AMD_POST_PARAMS *PostParamsPtr ) { AGESA_STATUS AgesaStatus; ALLOCATE_HEAP_PARAMS AllocHeapParams; ASSERT (StdHeader != NULL); ASSERT (PostParamsPtr != NULL); PostParamsPtr->StdHeader = *StdHeader; AllocHeapParams.RequestedBufferSize = sizeof (MEM_DATA_STRUCT); AllocHeapParams.BufferHandle = AMD_MEM_DATA_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; AgesaStatus = HeapAllocateBuffer (&AllocHeapParams, &PostParamsPtr->StdHeader); if (AgesaStatus == AGESA_SUCCESS) { PostParamsPtr->MemConfig.MemData = (MEM_DATA_STRUCT *) AllocHeapParams.BufferPtr; PostParamsPtr->MemConfig.MemData->ParameterListPtr = &(PostParamsPtr->MemConfig); AmdPostPlatformConfigInit (&PostParamsPtr->PlatformConfig, &PostParamsPtr->StdHeader); AmdMemInitDataStructDef (PostParamsPtr->MemConfig.MemData, &PostParamsPtr->PlatformConfig); GnbInitDataStructAtPostDef (&PostParamsPtr->GnbPostConfig, PostParamsPtr); } return AgesaStatus; }
FCH_RESET_DATA_BLOCK* FchInitResetLoadPrivateDefault ( IN AMD_RESET_PARAMS *ResetParams ) { FCH_RESET_DATA_BLOCK *FchParams; ALLOCATE_HEAP_PARAMS AllocHeapParams; AGESA_STATUS AgesaStatus; // First allocate internal data block via heap manager AllocHeapParams.RequestedBufferSize = sizeof (FCH_RESET_DATA_BLOCK); AllocHeapParams.Persist = HEAP_SYSTEM_MEM; AllocHeapParams.BufferHandle = AMD_FCH_RESET_DATA_BLOCK_HANDLE; AgesaStatus = HeapAllocateBuffer (&AllocHeapParams, &ResetParams->StdHeader); ASSERT (!AgesaStatus); FchParams = (FCH_RESET_DATA_BLOCK *) AllocHeapParams.BufferPtr; ASSERT (FchParams != NULL); IDS_HDT_CONSOLE (FCH_TRACE, " FCH Reset Data Block Allocation: [0x%x], Ptr = 0x%08x\n", AgesaStatus, FchParams); *FchParams = InitResetCfgDefault; FchParams->Gpp.GppLinkConfig = UserOptions.FchBldCfg->CfgFchGppLinkConfig; FchParams->Gpp.PortCfg[0].PortPresent = UserOptions.FchBldCfg->CfgFchGppPort0Present; FchParams->Gpp.PortCfg[1].PortPresent = UserOptions.FchBldCfg->CfgFchGppPort1Present; FchParams->Gpp.PortCfg[2].PortPresent = UserOptions.FchBldCfg->CfgFchGppPort2Present; FchParams->Gpp.PortCfg[3].PortPresent = UserOptions.FchBldCfg->CfgFchGppPort3Present; FchParams->Gpp.PortCfg[0].PortHotPlug = UserOptions.FchBldCfg->CfgFchGppPort0HotPlug; FchParams->Gpp.PortCfg[1].PortHotPlug = UserOptions.FchBldCfg->CfgFchGppPort1HotPlug; FchParams->Gpp.PortCfg[2].PortHotPlug = UserOptions.FchBldCfg->CfgFchGppPort2HotPlug; FchParams->Gpp.PortCfg[3].PortHotPlug = UserOptions.FchBldCfg->CfgFchGppPort3HotPlug; return FchParams; }
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; }
/** * * Initialize defaults and options for Amd Init Reset. * * @param[in] StdHeader AMD standard header config param. * @param[in] AmdRecoveryParamsPtr The Reset Init interface to initialize. * * @retval AGESA_SUCCESS Always Succeeds. */ AGESA_STATUS AmdInitRecoveryInitializer ( IN AMD_CONFIG_PARAMS *StdHeader, IN OUT AMD_RECOVERY_PARAMS *AmdRecoveryParamsPtr ) { ALLOCATE_HEAP_PARAMS AllocHeapParams; ASSERT (StdHeader != NULL); ASSERT (AmdRecoveryParamsPtr != NULL); AmdRecoveryParamsPtr->StdHeader = *StdHeader; AllocHeapParams.RequestedBufferSize = sizeof (MEM_DATA_STRUCT); AllocHeapParams.BufferHandle = AMD_MEM_DATA_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, &AmdRecoveryParamsPtr->StdHeader) == AGESA_SUCCESS) { AmdRecoveryParamsPtr->MemConfig.MemData = (MEM_DATA_STRUCT *) AllocHeapParams.BufferPtr; AmdRecoveryParamsPtr->MemConfig.MemData->ParameterListPtr = &(AmdRecoveryParamsPtr->MemConfig); LibAmdMemCopy ((VOID *) AmdRecoveryParamsPtr->MemConfig.MemData, (VOID *) AmdRecoveryParamsPtr, (UINTN) sizeof (AmdRecoveryParamsPtr->StdHeader), &AmdRecoveryParamsPtr->StdHeader ); AmdMemInitDataStructDefRecovery (AmdRecoveryParamsPtr->MemConfig.MemData); return AGESA_SUCCESS; } else { return AGESA_ERROR; } }
static AGESA_STATUS OemInitEarly(AMD_EARLY_PARAMS * InitEarly) { AGESA_STATUS Status; PCIe_COMPLEX_DESCRIPTOR *PcieComplexListPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; /* GNB PCIe topology Porting */ /* */ /* Allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR */ /* */ AllocHeapParams.RequestedBufferSize = sizeof(PCIe_COMPLEX_DESCRIPTOR); AllocHeapParams.BufferHandle = AMD_MEM_MISC_HANDLES_START; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; Status = HeapAllocateBuffer (&AllocHeapParams, &InitEarly->StdHeader); ASSERT(Status == AGESA_SUCCESS); PcieComplexListPtr = (PCIe_COMPLEX_DESCRIPTOR *) AllocHeapParams.BufferPtr; LibAmdMemFill (PcieComplexListPtr, 0, sizeof(PCIe_COMPLEX_DESCRIPTOR), &InitEarly->StdHeader); PcieComplexListPtr->Flags = DESCRIPTOR_TERMINATE_LIST; PcieComplexListPtr->SocketId = 0; PcieComplexListPtr->PciePortList = PortList; PcieComplexListPtr->DdiLinkList = DdiList; InitEarly->GnbConfig.PcieComplexList = PcieComplexListPtr; return AGESA_SUCCESS; }
/*---------------------------------------------------------------------------------------*/ VOID OemCustomizeInitEarly ( IN OUT AMD_EARLY_PARAMS *InitEarly ) { AGESA_STATUS Status; VOID *TrinityPcieComplexListPtr; VOID *TrinityPciePortPtr; VOID *TrinityPcieDdiPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; // GNB PCIe topology Porting // // Allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR // AllocHeapParams.RequestedBufferSize = sizeof(Trinity) + sizeof(PortList) + sizeof(DdiList); AllocHeapParams.BufferHandle = AMD_MEM_MISC_HANDLES_START; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; Status = HeapAllocateBuffer (&AllocHeapParams, &InitEarly->StdHeader); if ( Status!= AGESA_SUCCESS) { // Could not allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR ASSERT(FALSE); return; } TrinityPcieComplexListPtr = (PCIe_COMPLEX_DESCRIPTOR *) AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += sizeof(Trinity); TrinityPciePortPtr = (PCIe_PORT_DESCRIPTOR *)AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += sizeof(PortList); TrinityPcieDdiPtr = (PCIe_DDI_DESCRIPTOR *) AllocHeapParams.BufferPtr; LibAmdMemFill (TrinityPcieComplexListPtr, 0, sizeof(Trinity), &InitEarly->StdHeader); LibAmdMemFill (TrinityPciePortPtr, 0, sizeof(PortList), &InitEarly->StdHeader); LibAmdMemFill (TrinityPcieDdiPtr, 0, sizeof(DdiList), &InitEarly->StdHeader); LibAmdMemCopy (TrinityPcieComplexListPtr, &Trinity, sizeof(Trinity), &InitEarly->StdHeader); LibAmdMemCopy (TrinityPciePortPtr, &PortList[0], sizeof(PortList), &InitEarly->StdHeader); LibAmdMemCopy (TrinityPcieDdiPtr, &DdiList[0], sizeof(DdiList), &InitEarly->StdHeader); ((PCIe_COMPLEX_DESCRIPTOR*)TrinityPcieComplexListPtr)->PciePortList = (PCIe_PORT_DESCRIPTOR*)TrinityPciePortPtr; ((PCIe_COMPLEX_DESCRIPTOR*)TrinityPcieComplexListPtr)->DdiLinkList = (PCIe_DDI_DESCRIPTOR*)TrinityPcieDdiPtr; InitEarly->GnbConfig.PcieComplexList = TrinityPcieComplexListPtr; }
/** * * 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; }
/** * Get new Socket and Node Maps. * * Put the Socket Die Table and the Node Table in heap with known handles. * * @param[out] SocketDieToNodeMap The Socket, Module to Node info map * @param[out] NodeToSocketDieMap The Node to Socket, Module map. * @param[in] StdHeader Header for library and services. */ VOID STATIC NewNodeAndSocketTablesRecovery ( OUT SOCKET_DIE_TO_NODE_MAP *SocketDieToNodeMap, OUT NODE_TO_SOCKET_DIE_MAP *NodeToSocketDieMap, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; UINT8 j; ALLOCATE_HEAP_PARAMS AllocHeapParams; // Allocate heap for the table AllocHeapParams.RequestedBufferSize = (((MAX_SOCKETS) * (MAX_DIES)) * sizeof (SOCKET_DIE_TO_NODE_ITEM)); AllocHeapParams.BufferHandle = SOCKET_DIE_MAP_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { // HeapAllocateBuffer must set BufferPtr to valid or NULL. *SocketDieToNodeMap = (SOCKET_DIE_TO_NODE_MAP)AllocHeapParams.BufferPtr; ASSERT (SocketDieToNodeMap != NULL); // Initialize shared data structures for (i = 0; i < MAX_SOCKETS; i++) { for (j = 0; j < MAX_DIES; j++) { (**SocketDieToNodeMap)[i][j].Node = HT_LIST_TERMINAL; (**SocketDieToNodeMap)[i][j].LowCore = HT_LIST_TERMINAL; (**SocketDieToNodeMap)[i][j].HighCore = HT_LIST_TERMINAL; } } } // Allocate heap for the table AllocHeapParams.RequestedBufferSize = (MAX_NODES * sizeof (NODE_TO_SOCKET_DIE_ITEM)); AllocHeapParams.BufferHandle = NODE_ID_MAP_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { // HeapAllocateBuffer must set BufferPtr to valid or NULL. *NodeToSocketDieMap = (NODE_TO_SOCKET_DIE_MAP)AllocHeapParams.BufferPtr; ASSERT (NodeToSocketDieMap != NULL); // Initialize shared data structures for (i = 0; i < MAX_NODES; i++) { (**NodeToSocketDieMap)[i].Socket = HT_LIST_TERMINAL; (**NodeToSocketDieMap)[i].Die = HT_LIST_TERMINAL; } } }
static AGESA_STATUS OemInitEarly(AMD_EARLY_PARAMS * InitEarly) { AGESA_STATUS Status; VOID *LlanoPcieComplexListPtr; VOID *LlanoPciePortPtr; VOID *LlanoPcieDdiPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; // GNB PCIe topology Porting // // Allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR // AllocHeapParams.RequestedBufferSize = sizeof(Llano) + sizeof(PortList) + sizeof(DdiList); AllocHeapParams.BufferHandle = AMD_MEM_MISC_HANDLES_START; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; Status = HeapAllocateBuffer (&AllocHeapParams, &InitEarly->StdHeader); ASSERT(Status == AGESA_SUCCESS); LlanoPcieComplexListPtr = (PCIe_COMPLEX_DESCRIPTOR *) AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += sizeof(Llano); LlanoPciePortPtr = (PCIe_PORT_DESCRIPTOR *)AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += sizeof(PortList); LlanoPcieDdiPtr = (PCIe_DDI_DESCRIPTOR *) AllocHeapParams.BufferPtr; LibAmdMemFill (LlanoPcieComplexListPtr, 0, sizeof(Llano), &InitEarly->StdHeader); LibAmdMemFill (LlanoPciePortPtr, 0, sizeof(PortList), &InitEarly->StdHeader); LibAmdMemFill (LlanoPcieDdiPtr, 0, sizeof(DdiList), &InitEarly->StdHeader); LibAmdMemCopy (LlanoPcieComplexListPtr, &Llano, sizeof(Llano), &InitEarly->StdHeader); LibAmdMemCopy (LlanoPciePortPtr, &PortList[0], sizeof(PortList), &InitEarly->StdHeader); LibAmdMemCopy (LlanoPcieDdiPtr, &DdiList[0], sizeof(DdiList), &InitEarly->StdHeader); ((PCIe_COMPLEX_DESCRIPTOR*)LlanoPcieComplexListPtr)->PciePortList = (PCIe_PORT_DESCRIPTOR*)LlanoPciePortPtr; ((PCIe_COMPLEX_DESCRIPTOR*)LlanoPcieComplexListPtr)->DdiLinkList = (PCIe_DDI_DESCRIPTOR*)LlanoPcieDdiPtr; InitEarly->GnbConfig.PcieComplexList = LlanoPcieComplexListPtr; InitEarly->GnbConfig.PsppPolicy = 0; return AGESA_SUCCESS; }
/** * Initialize S3 Script framework * * * * @param[in] StdHeader Pointer to standard header * @param[in,out] S3SaveTable S3 save table header */ STATIC AGESA_STATUS S3SaveStateExtendTableLenth ( IN AMD_CONFIG_PARAMS *StdHeader, IN OUT S3_SAVE_TABLE_HEADER **S3SaveTable ) { AGESA_STATUS Status; ALLOCATE_HEAP_PARAMS AllocHeapParams; VOID *TempBuffer; UINT16 NewTableLength; UINT16 CurrentTableLength; //Allocate temporary buffer NewTableLength = (*S3SaveTable)->TableLength + S3_TABLE_LENGTH_INCREMENT; AllocHeapParams.RequestedBufferSize = NewTableLength; AllocHeapParams.BufferHandle = AMD_S3_SCRIPT_TEMP_BUFFER_HANDLE; AllocHeapParams.Persist = StdHeader->HeapStatus; Status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (Status != AGESA_SUCCESS) { return Status; } //Save current table length CurrentTableLength = (*S3SaveTable)->TableLength; //Update table length (*S3SaveTable)->TableLength = NewTableLength; //Copy S3 save toable to temporary location LibAmdMemCopy (AllocHeapParams.BufferPtr, *S3SaveTable, CurrentTableLength, StdHeader); //Save pointer to temp buffer TempBuffer = AllocHeapParams.BufferPtr; // Free original S3 save buffer HeapDeallocateBuffer (AMD_S3_SCRIPT_SAVE_TABLE_HANDLE, StdHeader); AllocHeapParams.RequestedBufferSize = NewTableLength; AllocHeapParams.BufferHandle = AMD_S3_SCRIPT_SAVE_TABLE_HANDLE; AllocHeapParams.Persist = StdHeader->HeapStatus; Status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (Status != AGESA_SUCCESS) { return Status; } LibAmdMemCopy (AllocHeapParams.BufferPtr, TempBuffer, AllocHeapParams.RequestedBufferSize, StdHeader); *S3SaveTable = (S3_SAVE_TABLE_HEADER*) AllocHeapParams.BufferPtr; HeapDeallocateBuffer (AMD_S3_SCRIPT_TEMP_BUFFER_HANDLE, 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 a new Socket Die to Node Map. * * @HtInterfaceMethod{::F_NEW_NODE_AND_SOCKET_TABLES} * * Put the Socket Die Table in heap with a known handle. Content will be generated as * each node is discovered. * * @param[in,out] State global state */ VOID NewNodeAndSocketTables ( IN OUT STATE_DATA *State ) { UINT8 i; UINT8 j; ALLOCATE_HEAP_PARAMS AllocHeapParams; // Allocate heap for the table State->SocketDieToNodeMap = NULL; AllocHeapParams.RequestedBufferSize = (((MAX_SOCKETS) * (MAX_DIES)) * sizeof (SOCKET_DIE_TO_NODE_ITEM)); AllocHeapParams.BufferHandle = SOCKET_DIE_MAP_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, State->ConfigHandle) == AGESA_SUCCESS) { State->SocketDieToNodeMap = (SOCKET_DIE_TO_NODE_MAP)AllocHeapParams.BufferPtr; // Initialize shared data structures for (i = 0; i < MAX_SOCKETS; i++) { for (j = 0; j < MAX_DIES; j++) { (*State->SocketDieToNodeMap)[i][j].Node = HT_LIST_TERMINAL; (*State->SocketDieToNodeMap)[i][j].LowCore = HT_LIST_TERMINAL; (*State->SocketDieToNodeMap)[i][j].HighCore = HT_LIST_TERMINAL; } } } // Allocate heap for the table State->NodeToSocketDieMap = NULL; AllocHeapParams.RequestedBufferSize = (MAX_NODES * sizeof (NODE_TO_SOCKET_DIE_ITEM)); AllocHeapParams.BufferHandle = NODE_ID_MAP_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, State->ConfigHandle) == AGESA_SUCCESS) { State->NodeToSocketDieMap = (NODE_TO_SOCKET_DIE_MAP)AllocHeapParams.BufferPtr; // Initialize shared data structures for (i = 0; i < MAX_NODES; i++) { (*State->NodeToSocketDieMap)[i].Socket = HT_LIST_TERMINAL; (*State->NodeToSocketDieMap)[i].Die = HT_LIST_TERMINAL; } } }
/** * * 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; }
/** * * * This function initialize the northbridge block and apply for heap space * before any function call is made to memory component during S3 resume. * * @param[in] *StdHeader - Config handle for library and services * @return AGESA_STATUS * - AGESA_ALERT * - AGESA_FATAL * - AGESA_SUCCESS * - AGESA_WARNING */ AGESA_STATUS MemS3ResumeInitNB ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS RetVal; MEM_MAIN_DATA_BLOCK mmData; S3_MEM_NB_BLOCK *S3NBPtr; MEM_DATA_STRUCT *MemData; UINT8 Die; UINT8 DieCount; UINT8 SpecialCaseHeapSize; ALLOCATE_HEAP_PARAMS AllocHeapParams; S3_SPECIAL_CASE_HEAP_HEADER SpecialHeapHeader[MAX_NODES_SUPPORTED]; SpecialCaseHeapSize = 0; //--------------------------------------------- // Creation of NB Block for S3 resume //--------------------------------------------- RetVal = MemS3InitNB (&S3NBPtr, &MemData, &mmData, StdHeader); if (RetVal == AGESA_FATAL) { return RetVal; } DieCount = mmData.DieCount; //-------------------------------------------------- // Apply for heap space for special case registers //-------------------------------------------------- for (Die = 0; Die < DieCount; Die ++) { // Construct the header for the special case heap. SpecialHeapHeader[Die].Node = S3NBPtr[Die].NBPtr->Node; SpecialHeapHeader[Die].Offset = SpecialCaseHeapSize + (DieCount * (sizeof (S3_SPECIAL_CASE_HEAP_HEADER))); SpecialCaseHeapSize = SpecialCaseHeapSize + S3NBPtr->MemS3SpecialCaseHeapSize; } AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (S3_SPECIAL_CASE_HEAP_HEADER))) + SpecialCaseHeapSize; AllocHeapParams.BufferHandle = AMD_MEM_S3_DATA_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_S3_SPECIAL_CASE_REGISTERS, S3NBPtr[Die].NBPtr->Node, 0, 0, 0, StdHeader); SetMemError (AGESA_FATAL, S3NBPtr[Die].NBPtr->MCTPtr); ASSERT(FALSE); // Could not allocate heap space for "S3_SPECIAL_CASE_HEAP_HEADER" return AGESA_FATAL; } LibAmdMemCopy ((VOID *) AllocHeapParams.BufferPtr, (VOID *) SpecialHeapHeader, (sizeof (S3_SPECIAL_CASE_HEAP_HEADER) * DieCount), StdHeader); return AGESA_SUCCESS; }
/** * Initialize S3 Script framework * * * * @param[in] StdHeader Pointer to standard header */ AGESA_STATUS S3ScriptInitState ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; ALLOCATE_HEAP_PARAMS AllocHeapParams; AllocHeapParams.RequestedBufferSize = S3_TABLE_LENGTH; AllocHeapParams.BufferHandle = AMD_S3_SCRIPT_SAVE_TABLE_HANDLE; AllocHeapParams.Persist = StdHeader->HeapStatus; Status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (Status == AGESA_SUCCESS) { ((S3_SAVE_TABLE_HEADER *) AllocHeapParams.BufferPtr)->TableLength = S3_TABLE_LENGTH; ((S3_SAVE_TABLE_HEADER *) AllocHeapParams.BufferPtr)->SaveOffset = sizeof (S3_SAVE_TABLE_HEADER); } return Status; }
VOID * GnbAllocateHeapBuffer ( IN UINT32 Handle, IN UINTN Length, IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; ALLOCATE_HEAP_PARAMS AllocHeapParams; AllocHeapParams.RequestedBufferSize = (UINT32) Length; AllocHeapParams.BufferHandle = Handle; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; Status = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (Status != AGESA_SUCCESS) { return NULL; } return AllocHeapParams.BufferPtr; }
/** * * This function prepares the Event Log for use. * * Allocate the memory for an event log on the heap. Set the read pointer, write pointer, * and count to reflect the log is empty. * * @param[in] StdHeader Our configuration, for passing to services. * * @retval AGESA_SUCCESS The event log is initialized. * @retval AGESA_ERROR Allocate Heap Buffer returned an error. * */ AGESA_STATUS EventLogInitialization ( IN AMD_CONFIG_PARAMS *StdHeader ) { ALLOCATE_HEAP_PARAMS AllocateHeapParams; AGESA_STRUCT_BUFFER *AgesaEventAlloc; AGESA_STATUS Status; AllocateHeapParams.BufferHandle = EVENT_LOG_BUFFER_HANDLE; AllocateHeapParams.RequestedBufferSize = sizeof (AGESA_STRUCT_BUFFER); AllocateHeapParams.Persist = HEAP_SYSTEM_MEM; Status = HeapAllocateBuffer (&AllocateHeapParams, StdHeader); AgesaEventAlloc = (AGESA_STRUCT_BUFFER *) AllocateHeapParams.BufferPtr; AgesaEventAlloc->Count = 0; AgesaEventAlloc->ReadRecordPtr = 0; AgesaEventAlloc->WriteRecordPtr = 0; AgesaEventAlloc->ReadWriteFlag = 1; return Status; }
/** * Initialize the Node and Socket maps for an AP Core. * * In each core's local heap, create a Node to Socket map and a Socket/Module to Node map. * The mapping is filled in by reading the AP Mailboxes from PCI config on each node. * * @param[in] StdHeader global state, input data * * @retval AGESA_SUCCESS Always succeeds. */ AGESA_STATUS AmdHtInitRecovery ( IN AMD_CONFIG_PARAMS *StdHeader ) { AP_MAILBOXES NodeApMailBox; ALLOCATE_HEAP_PARAMS AllocHeapParams; SOCKET_DIE_TO_NODE_MAP SocketDieToNodeMap = NULL; NODE_TO_SOCKET_DIE_MAP NodeToSocketDieMap = NULL; NodeApMailBox.ApMailInfo.Info = 0; NodeApMailBox.ApMailExtInfo.Info = 0; // Allocate heap for caching the mailboxes AllocHeapParams.RequestedBufferSize = sizeof (AP_MAILBOXES); AllocHeapParams.BufferHandle = LOCAL_AP_MAIL_BOX_CACHE_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { *(AP_MAILBOXES *)AllocHeapParams.BufferPtr = NodeApMailBox; } NewNodeAndSocketTablesRecovery (&SocketDieToNodeMap, &NodeToSocketDieMap, StdHeader); // HeapAllocateBuffer must set BufferPtr to valid or NULL, so the checks below are ok. // There is no option to not have socket - node maps, if they aren't allocated that is a fatal bug. ASSERT (SocketDieToNodeMap != NULL); ASSERT (NodeToSocketDieMap != NULL); (*SocketDieToNodeMap)[0][0].Node = 0; (*SocketDieToNodeMap)[0][0].LowCore = 0; (*SocketDieToNodeMap)[0][0].HighCore = 0; // We lie about being Socket 0 and Module 0 always, it isn't necessarily true. (*NodeToSocketDieMap)[0].Socket = (UINT8)0; (*NodeToSocketDieMap)[0].Die = (UINT8)0; return AGESA_SUCCESS; }
VOID STATIC MemRecSPDDataProcess ( IN OUT MEM_DATA_STRUCT *MemPtr ) { BOOLEAN FindSocketWithMem; UINT8 Channel; UINT8 Dimm; UINT8 MaxSockets; UINT8 *SocketWithMem; UINT8 Socket; AGESA_STATUS AgesaStatus; SPD_DEF_STRUCT *DimmSPDPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; AGESA_READ_SPD_PARAMS SpdParam; ASSERT (MemPtr != NULL); FindSocketWithMem = FALSE; // // Allocate heap to save socket number with memory on it. // AllocHeapParams.RequestedBufferSize = sizeof (UINT8); AllocHeapParams.BufferHandle = AMD_REC_MEM_SOCKET_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) == AGESA_SUCCESS) { SocketWithMem = (UINT8 *) AllocHeapParams.BufferPtr; *SocketWithMem = 0; // // Allocate heap for the table // MaxSockets = (UINT8) GetPlatformNumberOfSockets (); AllocHeapParams.RequestedBufferSize = (MaxSockets * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL * sizeof (SPD_DEF_STRUCT)); AllocHeapParams.BufferHandle = AMD_MEM_SPD_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) == AGESA_SUCCESS) { MemPtr->SpdDataStructure = (SPD_DEF_STRUCT *) AllocHeapParams.BufferPtr; // // Initialize SpdParam Structure // LibAmdMemCopy ((VOID *)&SpdParam, (VOID *)MemPtr, (UINTN)sizeof (SpdParam.StdHeader), &MemPtr->StdHeader); // // Populate SPDDataBuffer // SpdParam.MemData = MemPtr; for (Socket = 0; Socket < MaxSockets; Socket ++) { SpdParam.SocketId = Socket; for (Channel = 0; Channel < MAX_CHANNELS_PER_SOCKET; Channel++) { SpdParam.MemChannelId = Channel; for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { SpdParam.DimmId = Dimm; DimmSPDPtr = &(MemPtr->SpdDataStructure[(Socket * MAX_CHANNELS_PER_SOCKET + Channel) * MAX_DIMMS_PER_CHANNEL + Dimm]); SpdParam.Buffer = DimmSPDPtr->Data; AgesaStatus = AgesaReadSpdRecovery (0, &SpdParam); if (AgesaStatus == AGESA_SUCCESS) { DimmSPDPtr->DimmPresent = TRUE; if (!FindSocketWithMem) { FindSocketWithMem = TRUE; } } else { DimmSPDPtr->DimmPresent = FALSE; } } } if (FindSocketWithMem) { *SocketWithMem = Socket; break; } } } } }
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); }
/** * * * MemSocketScan - Scan all nodes, recording the physical Socket number, * Die Number (relative to the socket), and PCI Device address of each * populated socket. * * This information is used by the northbridge block to map a dram * channel on a particular DCT, on a particular CPU Die, in a particular * socket to a the DRAM SPD Data for the DIMMS physically connected to * that channel. * * Also, the customer socket map is populated with pointers to the * appropriate channel structures, so that the customer can locate the * appropriate channel configuration data. * * This socket scan will always result in Die 0 as the BSP. * * @param[in,out] *mmPtr - Pointer to the MEM_MAIN_DATA_BLOCK * */ AGESA_STATUS MemSocketScan ( IN OUT MEM_MAIN_DATA_BLOCK *mmPtr ) { MEM_DATA_STRUCT *MemPtr; UINT8 DieIndex; UINT8 DieCount; UINT32 SocketId; UINT32 DieId; UINT8 Die; PCI_ADDR Address; AGESA_STATUS AgesaStatus; ALLOCATE_HEAP_PARAMS AllocHeapParams; ASSERT (mmPtr != NULL); ASSERT (mmPtr->MemPtr != NULL); MemPtr = mmPtr->MemPtr; // // Count the number of dies in the system // DieCount = 0; for (Die = 0; Die < MAX_NODES_SUPPORTED; Die++) { if (GetSocketModuleOfNode ((UINT32)Die, &SocketId, &DieId, (VOID *)MemPtr)) { DieCount++; } } MemPtr->DieCount = DieCount; mmPtr->DieCount = DieCount; if (DieCount > 0) { // // Allocate buffer for DIE_STRUCTs // AllocHeapParams.RequestedBufferSize = ((UINT16)DieCount * 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) { MemPtr->DiesPerSystem = (DIE_STRUCT *)AllocHeapParams.BufferPtr; // // Find SocketId, DieId, and PCI address of each node // DieIndex = 0; for (Die = 0; Die < MAX_NODES_SUPPORTED; Die++) { if (GetSocketModuleOfNode ((UINT32)Die, &SocketId, &DieId, (VOID *)MemPtr)) { if (GetPciAddress ((VOID *)MemPtr, (UINT8)SocketId, (UINT8)DieId, &Address, &AgesaStatus)) { MemPtr->DiesPerSystem[DieIndex].SocketId = (UINT8)SocketId; MemPtr->DiesPerSystem[DieIndex].DieId = (UINT8)DieId; MemPtr->DiesPerSystem[DieIndex].PciAddr.AddressValue = Address.AddressValue; DieIndex++; } } } AgesaStatus = AGESA_SUCCESS; } else { ASSERT(FALSE); // Heap allocation failed for DIE_STRUCTs AgesaStatus = AGESA_FATAL; } } else { ASSERT(FALSE); // No die in the system AgesaStatus = AGESA_FATAL; } return AgesaStatus; }
/** * * * 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; }
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; }
/** * * * * * @param[in,out] *mmPtr - Pointer to the MEM_MAIN_DATA_BLOCK * * @return TRUE - No fatal error occurs. * @return FALSE - Fatal error occurs. */ BOOLEAN MemMParallelTraining ( IN OUT MEM_MAIN_DATA_BLOCK *mmPtr ) { AMD_CONFIG_PARAMS *StdHeader; MEM_DATA_STRUCT *MemPtr; MEM_NB_BLOCK *NBPtr; DIE_INFO TrainInfo[MAX_NODES_SUPPORTED]; AP_DATA_TRANSFER ReturnData; AGESA_STATUS Status; UINT8 ApSts; UINT8 Die; UINT8 Socket; UINT32 Module; UINT32 LowCore; UINT32 HighCore; UINT32 Time; UINT32 TimeOut; UINT32 TargetApicId; BOOLEAN StillTraining; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT8 *BufferPtr; BOOLEAN TimeoutEn; NBPtr = mmPtr->NBPtr; MemPtr = mmPtr->MemPtr; StdHeader = &(mmPtr->MemPtr->StdHeader); Time = 0; TimeOut = PARALLEL_TRAINING_TIMEOUT; TimeoutEn = TRUE; IDS_TIMEOUT_CTL (&TimeoutEn); IDS_HDT_CONSOLE (MEM_STATUS, "\nStart parallel training\n"); AGESA_TESTPOINT (TpProcMemBeforeAnyTraining, StdHeader); // // Initialize Training Info Array // for (Die = 0; Die < mmPtr->DieCount; Die ++) { Socket = TrainInfo[Die].Socket = NBPtr[Die].MCTPtr->SocketId; Module = NBPtr[Die].MCTPtr->DieId; GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader); TrainInfo[Die].Core = (UINT8) (LowCore & 0x000000FF); IDS_HDT_CONSOLE (MEM_FLOW, "\tLaunch core %d of socket %d\n", LowCore, Socket); TrainInfo[Die].Training = FALSE; } // // Start Training on Each remote die. // for (Die = 0; Die < mmPtr->DieCount; Die ++ ) { if (Die != BSP_DIE) { NBPtr[Die].BeforeDqsTraining (&(mmPtr->NBPtr[Die])); if (NBPtr[Die].MCTPtr->NodeMemSize != 0) { if (!NBPtr[Die].FeatPtr->Training (&(mmPtr->NBPtr[Die]))) { // Fail to launch code on AP PutEventLog (AGESA_ERROR, MEM_ERROR_PARALLEL_TRAINING_LAUNCH_FAIL, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); SetMemError (AGESA_ERROR, NBPtr[Die].MCTPtr); MemPtr->ErrorHandling (NBPtr[Die].MCTPtr, EXCLUDE_ALL_DCT, EXCLUDE_ALL_CHIPSEL, &MemPtr->StdHeader); } else { TrainInfo[Die].Training = TRUE; } } } } // // Call training on BSP // IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", NBPtr[BSP_DIE].Node); NBPtr[BSP_DIE].BeforeDqsTraining (&(mmPtr->NBPtr[BSP_DIE])); NBPtr[BSP_DIE].TrainingFlow (&(mmPtr->NBPtr[BSP_DIE])); NBPtr[BSP_DIE].AfterDqsTraining (&(mmPtr->NBPtr[BSP_DIE])); // // Get Results from remote processors training // do { StillTraining = FALSE; for (Die = 0; Die < mmPtr->DieCount; Die ++ ) { // // For each Die that is training, read the status // if (TrainInfo[Die].Training == TRUE) { GetLocalApicIdForCore (TrainInfo[Die].Socket, TrainInfo[Die].Core, &TargetApicId, StdHeader); ApSts = ApUtilReadRemoteControlByte (TargetApicId, StdHeader); if ((ApSts & 0x80) == 0) { // // Allocate buffer for received data // AllocHeapParams.RequestedBufferSize = ( sizeof (DIE_STRUCT) + NBPtr[Die].DctCount * ( sizeof (DCT_STRUCT) + ( NBPtr[Die].ChannelCount * ( sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK) + ( (NBPtr[Die].MCTPtr->DctData[0].ChData[0].RowCount * NBPtr[Die].MCTPtr->DctData[0].ChData[0].ColumnCount * NUMBER_OF_DELAY_TABLES) + (MAX_BYTELANES_PER_CHANNEL * MAX_CS_PER_CHANNEL * NUMBER_OF_FAILURE_MASK_TABLES) ) ) ) ) ) + 3; AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_PAR_TRN_HANDLE, Die, 0, 0); AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { // // Receive Training Results // ReturnData.DataPtr = AllocHeapParams.BufferPtr; ReturnData.DataSizeInDwords = (UINT16) AllocHeapParams.RequestedBufferSize / 4; ReturnData.DataTransferFlags = 0; Status = ApUtilReceiveBuffer (TrainInfo[Die].Socket, TrainInfo[Die].Core, &ReturnData, StdHeader); if (Status != AGESA_SUCCESS) { SetMemError (Status, NBPtr[Die].MCTPtr); } BufferPtr = AllocHeapParams.BufferPtr; LibAmdMemCopy (NBPtr[Die].MCTPtr, BufferPtr, sizeof (DIE_STRUCT), StdHeader); BufferPtr += sizeof (DIE_STRUCT); LibAmdMemCopy ( NBPtr[Die].MCTPtr->DctData, BufferPtr, NBPtr[Die].DctCount * (sizeof (DCT_STRUCT) + NBPtr[Die].ChannelCount * sizeof (CH_DEF_STRUCT)), StdHeader); BufferPtr += NBPtr[Die].DctCount * (sizeof (DCT_STRUCT) + NBPtr[Die].ChannelCount * sizeof (CH_DEF_STRUCT)); LibAmdMemCopy ( NBPtr[Die].PSBlock, BufferPtr, NBPtr[Die].DctCount * NBPtr[Die].ChannelCount * sizeof (MEM_PS_BLOCK), StdHeader); BufferPtr += NBPtr[Die].DctCount * NBPtr[Die].ChannelCount * sizeof (MEM_PS_BLOCK); LibAmdMemCopy ( NBPtr[Die].MCTPtr->DctData[0].ChData[0].RcvEnDlys, BufferPtr, (NBPtr[Die].DctCount * NBPtr[Die].ChannelCount) * ((NBPtr[Die].MCTPtr->DctData[0].ChData[0].RowCount * NBPtr[Die].MCTPtr->DctData[0].ChData[0].ColumnCount * NUMBER_OF_DELAY_TABLES) + (MAX_BYTELANES_PER_CHANNEL * MAX_CS_PER_CHANNEL * NUMBER_OF_FAILURE_MASK_TABLES) ), StdHeader); HeapDeallocateBuffer (AllocHeapParams.BufferHandle, StdHeader); NBPtr[Die].AfterDqsTraining (&(mmPtr->NBPtr[Die])); TrainInfo[Die].Training = FALSE; } else { PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_RECEIVED_DATA, NBPtr[Die].Node, 0, 0, 0, StdHeader); SetMemError (AGESA_FATAL, NBPtr[Die].MCTPtr); ASSERT(FALSE); // Insufficient Heap Space allocation for parallel training buffer } } else if (ApSts == CORE_IDLE) { // AP does not have buffer to transmit to BSP // AP fails to locate a buffer for data transfer TrainInfo[Die].Training = FALSE; } else { // Signal to loop through again StillTraining = TRUE; } } } // Wait for 1 us MemUWait10ns (100, NBPtr->MemPtr); Time ++; } while ((StillTraining) && ((Time < TimeOut) || !TimeoutEn)); // Continue until all Dies are finished // if cannot finish in 1 s, do fatal exit if (StillTraining && TimeoutEn) { // Parallel training time out, do fatal exit, as there is at least one AP hangs. PutEventLog (AGESA_FATAL, MEM_ERROR_PARALLEL_TRAINING_TIME_OUT, 0, 0, 0, 0, &NBPtr->MemPtr->StdHeader); SetMemError (AGESA_FATAL, NBPtr[BSP_DIE].MCTPtr); ASSERT(FALSE); // Timeout occurred while still training } for (Die = 0; Die < mmPtr->DieCount; Die ++ ) { if (NBPtr[Die].MCTPtr->ErrCode == AGESA_FATAL) { return FALSE; } } return TRUE; }
/** * 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; }
BOOLEAN MemConstructNBBlockDA ( IN OUT MEM_NB_BLOCK *NBPtr, IN OUT MEM_DATA_STRUCT *MemPtr, IN MEM_FEAT_BLOCK_NB *FeatPtr, IN MEM_SHARED_DATA *SharedPtr, IN UINT8 NodeID ) { UINT8 Dct; UINT8 Channel; UINT8 SpdSocketIndex; UINT8 SpdChannelIndex; DIE_STRUCT *MCTPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; // // Determine if this is the expected NB Type // GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader)); if (!MemNIsIdSupportedDA (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) { return FALSE; } NBPtr->MemPtr = MemPtr; NBPtr->RefPtr = MemPtr->ParameterListPtr; NBPtr->SharedPtr = SharedPtr; MCTPtr = &(MemPtr->DiesPerSystem[NodeID]); NBPtr->MCTPtr = MCTPtr; NBPtr->MCTPtr->NodeId = NodeID; NBPtr->PciAddr.AddressValue = MCTPtr->PciAddr.AddressValue; NBPtr->VarMtrrHiMsk = GetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader)); // // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs // AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_DA * ( sizeof (DCT_STRUCT) + ( MAX_CHANNELS_PER_DCT_DA * (sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK)) ) ); AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0); AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) { PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_DCT_STRUCT_AND_CH_DEF_STRUCTs, NBPtr->Node, 0, 0, 0, &MemPtr->StdHeader); SetMemError (AGESA_FATAL, MCTPtr); return FALSE; } MCTPtr->DctCount = MAX_DCTS_PER_NODE_DA; MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_DA * sizeof (DCT_STRUCT); for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DA; Dct++) { MCTPtr->DctData[Dct].Dct = Dct; MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_DA; MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_DA * sizeof (CH_DEF_STRUCT); } NBPtr->PSBlock = (MEM_PS_BLOCK *) AllocHeapParams.BufferPtr; // // Initialize Socket List // for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DA; Dct++) { MemPtr->SocketList[MCTPtr->SocketId].ChannelPtr[Dct] = &(MCTPtr->DctData[Dct].ChData[0]); MemPtr->SocketList[MCTPtr->SocketId].TimingsPtr[Dct] = &(MCTPtr->DctData[Dct].Timings); MCTPtr->DctData[Dct].ChData[0].ChannelID = Dct; } MemNInitNBDataDA (NBPtr); FeatPtr->InitCPG (NBPtr); NBPtr->FeatPtr = FeatPtr; FeatPtr->InitHwRxEn (NBPtr); // // Calculate SPD Offsets per channel and assign pointers to the data. At this point, we calculate the Node-Dct-Channel // centric offsets and store the pointers to the first DIMM of each channel in the Channel Definition struct for that // channel. This pointer is then used later to calculate the offsets to be used for each logical dimm once the // dimm types(QR or not) are known. This is done in the Technology block constructor. // // Calculate the SpdSocketIndex separately from the SpdChannelIndex. // This will facilitate modifications due to some processors that might // map the DCT-CHANNEL differently. // SpdSocketIndex = GetSpdSocketIndex (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, &MemPtr->StdHeader); // // Traverse the Dct/Channel structures // for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DA; Dct++) { for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_DA; Channel++) { // // Calculate the number of Dimms on this channel using the // die/dct/channel to Socket/channel conversion. // SpdChannelIndex = GetSpdChannelIndex (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, MemNGetSocketRelativeChannelNb (NBPtr, Dct, Channel), &MemPtr->StdHeader); NBPtr->MCTPtr->DctData[Dct].ChData[Channel].SpdPtr = &(MemPtr->SpdDataStructure[SpdSocketIndex + SpdChannelIndex]); } } MemNSwitchDCTNb (NBPtr, 0); return TRUE; }
/** * * It will create the ACPI tale of WHEA and return the pointer to the table. * * @param[in, out] StdHeader Standard Head Pointer * @param[in, out] WheaMcePtr Point to Whea Hest Mce table * @param[in, out] WheaCmcPtr Point to Whea Hest Cmc table * * @retval UINT32 AGESA_STATUS */ AGESA_STATUS GetAcpiWheaMain ( IN OUT AMD_CONFIG_PARAMS *StdHeader, IN OUT VOID **WheaMcePtr, IN OUT VOID **WheaCmcPtr ) { UINT8 BankNum; UINT8 Entries; UINT16 HestMceTableSize; UINT16 HestCmcTableSize; UINT64 MsrData; AMD_HEST_MCE_TABLE *HestMceTablePtr; AMD_HEST_CMC_TABLE *HestCmcTablePtr; AMD_HEST_BANK *HestBankPtr; AMD_WHEA_INIT_DATA *WheaInitDataPtr; ALLOCATE_HEAP_PARAMS AllocParams; CPU_SPECIFIC_SERVICES *FamilySpecificServices; FamilySpecificServices = NULL; IDS_HDT_CONSOLE (CPU_TRACE, " WHEA is created\n"); // step 1: calculate Hest table size LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader); BankNum = (UINT8) (((MSR_MCG_CAP_STRUCT *) (&MsrData))->Count); if (BankNum == 0) { return AGESA_ERROR; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetWheaInitData (FamilySpecificServices, &WheaInitDataPtr, &Entries, StdHeader); ASSERT (WheaInitDataPtr->HestBankNum <= BankNum); HestMceTableSize = sizeof (AMD_HEST_MCE_TABLE) + WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK); HestCmcTableSize = sizeof (AMD_HEST_CMC_TABLE) + WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK); HestMceTablePtr = (AMD_HEST_MCE_TABLE *) *WheaMcePtr; HestCmcTablePtr = (AMD_HEST_CMC_TABLE *) *WheaCmcPtr; // step 2: allocate a buffer by callback function if ((HestMceTablePtr == NULL) || (HestCmcTablePtr == NULL)) { AllocParams.RequestedBufferSize = (UINT32) (HestMceTableSize + HestCmcTableSize); AllocParams.BufferHandle = AMD_WHEA_BUFFER_HANDLE; AllocParams.Persist = HEAP_SYSTEM_MEM; AGESA_TESTPOINT (TpProcCpuBeforeAllocateWheaBuffer, StdHeader); if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) { return AGESA_ERROR; } AGESA_TESTPOINT (TpProcCpuAfterAllocateWheaBuffer, StdHeader); HestMceTablePtr = (AMD_HEST_MCE_TABLE *) AllocParams.BufferPtr; HestCmcTablePtr = (AMD_HEST_CMC_TABLE *) ((UINT8 *) (HestMceTablePtr + 1) + (WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK))); } // step 3: fill in Hest MCE table HestMceTablePtr->TblLength = HestMceTableSize; HestMceTablePtr->GlobCapInitDataLSD = WheaInitDataPtr->GlobCapInitDataLSD; HestMceTablePtr->GlobCapInitDataMSD = WheaInitDataPtr->GlobCapInitDataMSD; HestMceTablePtr->GlobCtrlInitDataLSD = WheaInitDataPtr->GlobCtrlInitDataLSD; HestMceTablePtr->GlobCtrlInitDataMSD = WheaInitDataPtr->GlobCtrlInitDataMSD; HestMceTablePtr->NumHWBanks = WheaInitDataPtr->HestBankNum; HestBankPtr = (AMD_HEST_BANK *) (HestMceTablePtr + 1); CreateHestBank (HestBankPtr, WheaInitDataPtr->HestBankNum, WheaInitDataPtr); // step 4: fill in Hest CMC table HestCmcTablePtr->NumHWBanks = WheaInitDataPtr->HestBankNum; HestCmcTablePtr->TblLength = HestCmcTableSize; HestBankPtr = (AMD_HEST_BANK *) (HestCmcTablePtr + 1); CreateHestBank (HestBankPtr, WheaInitDataPtr->HestBankNum, WheaInitDataPtr); // step 5: fill in the incoming structure *WheaMcePtr = HestMceTablePtr; *WheaCmcPtr = HestCmcTablePtr; return (AGESA_SUCCESS); }
AGESA_STATUS AmdIdsCtrlInitialize ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; UINT16 NvTblSize; UINT16 i; IDS_NV_ITEM IdsNvTable[IDS_NUM_NV_ITEM]; IDS_NV_ITEM *NvTable; IDS_NV_ITEM *NvPtr; IDS_CONTROL_STRUCT *IdsCtrlPtr; IDS_CALLOUT_STRUCT IdsCalloutData; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT16 MemTblSize; UINT8 HeapPersist; NvTblSize = 0; MemTblSize = 0; HeapPersist = HEAP_SYSTEM_MEM; //Heap status with HEAP_LOCAL_CACHE, will allocate heap with HEAP_LOCAL_CACHE //with HEAP_TEMP_MEM HEAP_SYSTEM_MEM HEAP_DO_NOT_EXIST_ANYMORE HEAP_S3_RESUME // with allocate with HEAP_SYSTEM_MEM if (StdHeader->HeapStatus == HEAP_LOCAL_CACHE) { MemTblSize = IDS_MAX_MEM_ITEMS; HeapPersist = IDS_HEAP_PERSIST_EARLY; } else if ((StdHeader->HeapStatus == HEAP_DO_NOT_EXIST_YET) || (StdHeader->HeapStatus == HEAP_DO_NOT_EXIST_ANYMORE)) { return AGESA_ERROR; } else { IDS_HEAP_ASSERTION_LATE; } IdsCalloutData.IdsNvPtr = IdsNvTable; IdsCalloutData.StdHeader = *StdHeader; //init IDS_CALLOUT_STRUCT before calling out, give NVITEM default value for (i = AGESA_IDS_EXT_ID_START; i < IDS_NUM_NV_ITEM; i++) { IdsNvTable[i].IdsNvId = i; IdsNvTable[i].IdsNvValue = AGESA_IDS_DFT_VAL; } AGESA_TESTPOINT (TpIfBeforeGetIdsData, StdHeader); if (AgesaGetIdsData (IDS_CALLOUT_INIT, &IdsCalloutData) == AGESA_SUCCESS) { NvTable = IdsCalloutData.IdsNvPtr; NvPtr = NvTable; while (NvPtr->IdsNvId != AGESA_IDS_NV_END) { NvTblSize ++; NvPtr ++; } NvTblSize ++; AllocHeapParams.RequestedBufferSize = sizeof (IDS_CONTROL_STRUCT); AllocHeapParams.RequestedBufferSize += NvTblSize * sizeof (IDS_NV_ITEM); AllocHeapParams.RequestedBufferSize += MemTblSize * sizeof (MEM_TABLE_ALIAS); AllocHeapParams.RequestedBufferSize += IDS_EXTENDED_HEAP_SIZE; AllocHeapParams.BufferHandle = IDS_CONTROL_HANDLE; AllocHeapParams.Persist = HeapPersist; // // Allocate data buffer in heap // if (HeapAllocateBuffer (&AllocHeapParams, (AMD_CONFIG_PARAMS *) StdHeader) == AGESA_SUCCESS) { // // Initialize IDS Date Buffer // IdsCtrlPtr = (IDS_CONTROL_STRUCT *) AllocHeapParams.BufferPtr; IdsCtrlPtr->IdsHeapMemSize = AllocHeapParams.RequestedBufferSize; IdsCtrlPtr->IdsNvTableOffset = sizeof (IDS_CONTROL_STRUCT); IdsCtrlPtr->IdsMemTableOffset = IdsCtrlPtr->IdsNvTableOffset + NvTblSize * sizeof (IDS_NV_ITEM); IdsCtrlPtr->IdsExtendOffset = IdsCtrlPtr->IdsMemTableOffset + MemTblSize * sizeof (MEM_TABLE_ALIAS); NvPtr = (IDS_NV_ITEM *) (AllocHeapParams.BufferPtr + IdsCtrlPtr->IdsNvTableOffset); for (i = 0; i < NvTblSize ; i++) { NvPtr->IdsNvId = NvTable->IdsNvId; NvPtr->IdsNvValue = NvTable->IdsNvValue; NvPtr ++; NvTable ++; } status = AGESA_SUCCESS; } else { status = AGESA_ERROR; } } else { status = AGESA_ERROR; } AGESA_TESTPOINT (TpIfAfterGetIdsData, StdHeader); return status; }
/*---------------------------------------------------------------------------------------*/ VOID OemCustomizeInitEarly ( IN OUT AMD_EARLY_PARAMS *InitEarly ) { AGESA_STATUS Status; VOID *BrazosPcieComplexListPtr; VOID *BrazosPciePortPtr; VOID *BrazosPcieDdiPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; PCIe_PORT_DESCRIPTOR PortList [] = { // Initialize Port descriptor (PCIe port, Lanes 4, PCI Device Number 4, ...) { 0, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 4, 4), PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT4_PORT_PRESENT, GNB_GPP_PORT4_CHANNEL_TYPE, 4, GNB_GPP_PORT4_HOTPLUG_SUPPORT, GNB_GPP_PORT4_SPEED_MODE, GNB_GPP_PORT4_SPEED_MODE, GNB_GPP_PORT4_LINK_ASPM, 0) }, #if 1 // Initialize Port descriptor (PCIe port, Lanes 5, PCI Device Number 5, ...) { 0, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 5, 5), PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT5_PORT_PRESENT, GNB_GPP_PORT5_CHANNEL_TYPE, 5, GNB_GPP_PORT5_HOTPLUG_SUPPORT, GNB_GPP_PORT5_SPEED_MODE, GNB_GPP_PORT5_SPEED_MODE, GNB_GPP_PORT5_LINK_ASPM, 0) }, // Initialize Port descriptor (PCIe port, Lanes 6, PCI Device Number 6, ...) { 0, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 6, 6), PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT6_PORT_PRESENT, GNB_GPP_PORT6_CHANNEL_TYPE, 6, GNB_GPP_PORT6_HOTPLUG_SUPPORT, GNB_GPP_PORT6_SPEED_MODE, GNB_GPP_PORT6_SPEED_MODE, GNB_GPP_PORT6_LINK_ASPM, 0) }, // Initialize Port descriptor (PCIe port, Lanes 7, PCI Device Number 7, ...) { 0, PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 7, 7), PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT7_PORT_PRESENT, GNB_GPP_PORT7_CHANNEL_TYPE, 7, GNB_GPP_PORT7_HOTPLUG_SUPPORT, GNB_GPP_PORT7_SPEED_MODE, GNB_GPP_PORT7_SPEED_MODE, GNB_GPP_PORT7_LINK_ASPM, 0) }, #endif // Initialize Port descriptor (PCIe port, Lanes 8, PCI Device Number 8, ...) { DESCRIPTOR_TERMINATE_LIST, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 0, 3), PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT8_PORT_PRESENT, GNB_GPP_PORT8_CHANNEL_TYPE, 8, GNB_GPP_PORT8_HOTPLUG_SUPPORT, GNB_GPP_PORT8_SPEED_MODE, GNB_GPP_PORT8_SPEED_MODE, GNB_GPP_PORT8_LINK_ASPM, 0) } }; PCIe_DDI_DESCRIPTOR DdiList [] = { // Initialize Ddi descriptor (DDI interface Lanes 8:11, DdA, ...) { 0, //Descriptor flags PCIE_ENGINE_DATA_INITIALIZER (PcieDdiEngine, 8, 11), //PCIE_DDI_DATA_INITIALIZER (ConnectorTypeDP, Aux1, Hdp1) {ConnectorTypeDP, Aux1, Hdp1} }, // Initialize Ddi descriptor (DDI interface Lanes 12:15, DdB, ...) { DESCRIPTOR_TERMINATE_LIST, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array PCIE_ENGINE_DATA_INITIALIZER (PcieDdiEngine, 12, 15), //PCIE_DDI_DATA_INITIALIZER (ConnectorTypeDP, Aux2, Hdp2) {ConnectorTypeDP, Aux2, Hdp2} } }; PCIe_COMPLEX_DESCRIPTOR Brazos = { DESCRIPTOR_TERMINATE_LIST, 0, &PortList[0], &DdiList[0] }; // GNB PCIe topology Porting // // Allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR // AllocHeapParams.RequestedBufferSize = sizeof(Brazos) + sizeof(PortList) + sizeof(DdiList); AllocHeapParams.BufferHandle = AMD_MEM_MISC_HANDLES_START; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; Status = HeapAllocateBuffer (&AllocHeapParams, &InitEarly->StdHeader); if ( Status!= AGESA_SUCCESS) { // Could not allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR ASSERT(FALSE); return; } BrazosPcieComplexListPtr = (PCIe_COMPLEX_DESCRIPTOR *) AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += sizeof(Brazos); BrazosPciePortPtr = (PCIe_PORT_DESCRIPTOR *)AllocHeapParams.BufferPtr; AllocHeapParams.BufferPtr += sizeof(PortList); BrazosPcieDdiPtr = (PCIe_DDI_DESCRIPTOR *) AllocHeapParams.BufferPtr; LibAmdMemFill (BrazosPcieComplexListPtr, 0, sizeof(Brazos), &InitEarly->StdHeader); LibAmdMemFill (BrazosPciePortPtr, 0, sizeof(PortList), &InitEarly->StdHeader); LibAmdMemFill (BrazosPcieDdiPtr, 0, sizeof(DdiList), &InitEarly->StdHeader); LibAmdMemCopy (BrazosPcieComplexListPtr, &Brazos, sizeof(Brazos), &InitEarly->StdHeader); LibAmdMemCopy (BrazosPciePortPtr, &PortList[0], sizeof(PortList), &InitEarly->StdHeader); LibAmdMemCopy (BrazosPcieDdiPtr, &DdiList[0], sizeof(DdiList), &InitEarly->StdHeader); ((PCIe_COMPLEX_DESCRIPTOR*)BrazosPcieComplexListPtr)->PciePortList = (PCIe_PORT_DESCRIPTOR*)BrazosPciePortPtr; ((PCIe_COMPLEX_DESCRIPTOR*)BrazosPcieComplexListPtr)->DdiLinkList = (PCIe_DDI_DESCRIPTOR*)BrazosPcieDdiPtr; InitEarly->GnbConfig.PcieComplexList = BrazosPcieComplexListPtr; InitEarly->GnbConfig.PsppPolicy = 0; }
/** * * Initial function for HDT out Function. * * Init required Debug register & heap, and will also fire a HDTOUT * Command to let hdtout script do corresponding things. * * @param[in,out] StdHeader The Pointer of AGESA Header * **/ VOID AmdIdsHdtOutInit ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { ALLOCATE_HEAP_PARAMS AllocHeapParams; HDTOUT_HEADER HdtoutHeader; UINT8 Persist; AGESA_STATUS IgnoreSts; HDTOUT_HEADER *pHdtoutHeader; IDS_FUNCLIST_EXTERN (); if (AmdIdsHdtOutSupport ()) { AmdIdsHdtOutRegisterInit (StdHeader); // Initialize HDTOUT Header HdtoutHeader.Signature = HDTOUT_HEADER_SIGNATURE; HdtoutHeader.Version = HDTOUT_VERSION; HdtoutHeader.BufferSize = HDTOUT_DEFAULT_BUFFER_SIZE; HdtoutHeader.DataIndex = 0; HdtoutHeader.PrintCtrl = HDTOUT_PRINTCTRL_ON; HdtoutHeader.NumBreakpointUnit = 0; HdtoutHeader.FuncListAddr = (UINTN)IDS_FUNCLIST_ADDR; HdtoutHeader.StatusStr[0] = 0; HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_ON; HdtoutHeader.EnableMask = 0; HdtoutHeader.ConsoleFilter = IDS_DEBUG_PRINT_MASK; // Trigger HDTOUT breakpoint to get inputs from script IdsOutPort (HDTOUT_INIT, (UINTN) &HdtoutHeader, 0); // Disable AP HDTOUT if set BspOnlyFlag if (HdtoutHeader.BspOnlyFlag == HDTOUT_BSP_ONLY) { if (!IsBsp (StdHeader, &IgnoreSts)) { AmdIdsHdtOutRegisterRestore (StdHeader); return; } } // Convert legacy EnableMask to new ConsoleFilter HdtoutHeader.ConsoleFilter |= HdtoutHeader.EnableMask; // Disable the buffer if the size is not large enough if (HdtoutHeader.BufferSize < 128) { HdtoutHeader.BufferSize = 0; HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_OFF; } else { HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_ON; } // Check if Hdtout header have been initialed, if so it must 2nd time come here if (AmdIdsHdtoutGetHeader (&pHdtoutHeader, StdHeader)) { Persist = HEAP_SYSTEM_MEM; } else { Persist = HEAP_LOCAL_CACHE; } // Allocate heap do { AllocHeapParams.RequestedBufferSize = HdtoutHeader.BufferSize + sizeof (HdtoutHeader) - 2; AllocHeapParams.BufferHandle = IDS_HDT_OUT_BUFFER_HANDLE; AllocHeapParams.Persist = Persist; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { break; } else { IdsOutPort (HDTOUT_ERROR, HDTOUT_ERROR_HEAP_ALLOCATION, AllocHeapParams.RequestedBufferSize); HdtoutHeader.BufferSize -= 256; } } while ((HdtoutHeader.BufferSize & 0x8000) == 0); // If the buffer have been successfully allocated? if ((HdtoutHeader.BufferSize & 0x8000) == 0) { LibAmdWriteCpuReg (DR3_REG, (UINTN)AllocHeapParams.BufferPtr); LibAmdMemCopy (AllocHeapParams.BufferPtr, &HdtoutHeader, sizeof (HdtoutHeader) - 2, StdHeader); } else { /// Clear DR3_REG IdsOutPort ((UINT32)HDTOUT_ERROR, (UINT32)HDTOUT_ERROR_HEAP_AllOCATE_FAIL, (UINT32)IDS_DEBUG_PRINT_MASK); LibAmdWriteCpuReg (DR3_REG, 0); } } }