AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Common / AmdS3Save.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD AGESA Basic Level Public APIs
6  *
7  * Contains basic Level Initialization routines.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  Interface
12  * @e \$Revision: 55552 $   @e \$Date: 2011-06-22 09:31:58 -0600 (Wed, 22 Jun 2011) $
13  *
14  */
15 /*****************************************************************************
16  *
17  * Copyright (C) 2012 Advanced Micro Devices, Inc.
18  * All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are met:
22  *     * Redistributions of source code must retain the above copyright
23  *       notice, this list of conditions and the following disclaimer.
24  *     * Redistributions in binary form must reproduce the above copyright
25  *       notice, this list of conditions and the following disclaimer in the
26  *       documentation and/or other materials provided with the distribution.
27  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
28  *       its contributors may be used to endorse or promote products derived
29  *       from this software without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  *
42  ******************************************************************************
43  */
44
45
46 /*----------------------------------------------------------------------------------------
47  *                             M O D U L E S    U S E D
48  *----------------------------------------------------------------------------------------
49  */
50 #include "AGESA.h"
51 #include "amdlib.h"
52 #include "Ids.h"
53 #include "mm.h"
54 #include "mn.h"
55 #include "S3.h"
56 #include "mfs3.h"
57 #include "CommonInits.h"
58 #include "AmdFch.h"
59 #include "Filecode.h"
60 #include "heapManager.h"
61 #include "CreateStruct.h"
62 CODE_GROUP (G3_DXE)
63 RDATA_GROUP (G3_DXE)
64
65 #define FILECODE PROC_COMMON_AMDS3SAVE_FILECODE
66
67 extern BLDOPT_FCH_FUNCTION  BldoptFchFunction;
68
69 /*----------------------------------------------------------------------------------------
70  *                   D E F I N I T I O N S    A N D    M A C R O S
71  *----------------------------------------------------------------------------------------
72  */
73
74
75 /*----------------------------------------------------------------------------------------
76  *                  T Y P E D E F S     A N D     S T R U C T U R E S
77  *----------------------------------------------------------------------------------------
78  */
79 CONST UINT32 ROMDATA S3LateHeapTable[] =
80 {
81   EVENT_LOG_BUFFER_HANDLE,
82   SOCKET_DIE_MAP_HANDLE,
83   NODE_ID_MAP_HANDLE,
84   LOCAL_AP_MAIL_BOX_CACHE_HANDLE,
85   IDS_CONTROL_HANDLE,
86   AMD_S3_SCRIPT_SAVE_TABLE_HANDLE,
87   AMD_PCIE_COMPLEX_DATA_HANDLE
88 };
89
90 #define S3LATE_TABLE_SIZE (sizeof (S3LateHeapTable) / sizeof (UINT32)) //(sizeof (S3LateHeapTable) / sizeof (S3LATE_HEAP_ELEMENT))
91
92
93 /*----------------------------------------------------------------------------------------
94  *           P R O T O T Y P E S     O F     L O C A L     F U N C T I O N S
95  *----------------------------------------------------------------------------------------
96  */
97 AGESA_STATUS
98 AmdS3SavePlatformConfigInit (
99   IN OUT   PLATFORM_CONFIGURATION    *PlatformConfig,
100   IN OUT   AMD_CONFIG_PARAMS         *StdHeader
101   );
102
103 /*----------------------------------------------------------------------------------------
104  *                          E X P O R T E D    F U N C T I O N S
105  *----------------------------------------------------------------------------------------
106  */
107 extern BUILD_OPT_CFG UserOptions;
108
109 /*---------------------------------------------------------------------------------------*/
110 /**
111  * Main entry point for the AMD_S3_SAVE function.
112  *
113  * This entry point is responsible for saving silicon component registers to the
114  * SMM save area in preparation of entering system suspend-to-RAM mode.
115  *
116  * @param[in,out] AmdS3SaveParams   Required input parameters for the AMD_S3_SAVE
117  *                                  entry point.
118  *
119  * @return        Aggregated status across all internal AMD S3 save calls invoked.
120  *
121  */
122 AGESA_STATUS
123 AmdS3Save (
124   IN OUT   AMD_S3SAVE_PARAMS *AmdS3SaveParams
125   )
126 {
127   UINTN  i;
128   UINT32 EarlyBufferSize;
129   UINT32 LateBufferSize;
130   UINT32 LateContextSize;
131   UINT32 HeapSize;
132   UINT8  *BufferPointer;
133   UINT8  HeapStatus;
134   ALLOCATE_HEAP_PARAMS HeapParams;
135   LOCATE_HEAP_PTR LocateHeap;
136   BUFFER_NODE *FreeSpaceNode;
137   ALLOCATE_HEAP_PARAMS AllocParams;
138   DEVICE_BLOCK_HEADER *MemoryRelatedDeviceList;
139   DEVICE_BLOCK_HEADER *NonMemoryRelatedDeviceList;
140   AGESA_STATUS ReturnStatus;
141   VOID   *HeapPtrs[S3LATE_TABLE_SIZE];
142   UINT32 HeapSizes[S3LATE_TABLE_SIZE];
143   UINT32 HeapBuffersPresent;
144   HEAP_MANAGER *HeapPtr;
145
146   AGESA_TESTPOINT (TpIfAmdS3SaveEntry, &AmdS3SaveParams->StdHeader);
147
148   ASSERT (AmdS3SaveParams != NULL);
149
150   HeapBuffersPresent = 0;
151   EarlyBufferSize = 0;
152   LateBufferSize = 0;
153   LateContextSize = 0;
154   HeapSize = 0;
155   NonMemoryRelatedDeviceList = NULL;
156   MemoryRelatedDeviceList = NULL;
157   ReturnStatus = AGESA_SUCCESS;
158
159   IDS_SKIP_HOOK (IDS_BEFORE_S3_SAVE, AmdS3SaveParams, &(AmdS3SaveParams->StdHeader)) {
160
161     // Get memory device list
162     MemFS3GetDeviceList (&MemoryRelatedDeviceList, &AmdS3SaveParams->StdHeader);
163     if (MemoryRelatedDeviceList != NULL) {
164       // Determine size needed
165       EarlyBufferSize = GetWorstCaseContextSize (MemoryRelatedDeviceList, INIT_RESUME, &AmdS3SaveParams->StdHeader);
166     }
167
168     if (UserOptions.CfgS3LateRestore) {
169       for (i = 0; i < S3LATE_TABLE_SIZE; i++) {
170         LocateHeap.BufferHandle = S3LateHeapTable[i];
171         if (HeapLocateBuffer (&LocateHeap, &AmdS3SaveParams->StdHeader) == AGESA_SUCCESS) {
172           HeapBuffersPresent++;
173           HeapSize += LocateHeap.BufferSize;
174           HeapPtrs[i] = LocateHeap.BufferPtr;
175           HeapSizes[i] = LocateHeap.BufferSize;
176         } else {
177           HeapPtrs[i] = NULL;
178           HeapSizes[i] = 0;
179         }
180       }
181
182       // Determine heap data size requirements
183       if (HeapBuffersPresent != 0) {
184         HeapSize += ((sizeof (HEAP_MANAGER)) + (HeapBuffersPresent * ((sizeof (BUFFER_NODE)) + (NUM_OF_SENTINEL * SIZE_OF_SENTINEL) + 0xF))); // reserve 0xF per buffer node for 16 byte alignment
185       }
186
187       // Get non memory device list
188       GetNonMemoryRelatedDeviceList (&NonMemoryRelatedDeviceList, &AmdS3SaveParams->StdHeader);
189
190       if (NonMemoryRelatedDeviceList != NULL) {
191         // Determine size needed
192         LateContextSize = GetWorstCaseContextSize (NonMemoryRelatedDeviceList, S3_LATE_RESTORE, &AmdS3SaveParams->StdHeader);
193       }
194       LateBufferSize = HeapSize + LateContextSize;
195       if (LateBufferSize != 0) {
196         LateBufferSize += sizeof (S3_VOLATILE_STORAGE_HEADER);
197       }
198     }
199
200     if ((EarlyBufferSize != 0) || (LateBufferSize != 0)) {
201       //
202       // Allocate a buffer
203       //
204       AllocParams.RequestedBufferSize = EarlyBufferSize + LateBufferSize;
205       AllocParams.BufferHandle = AMD_S3_INFO_BUFFER_HANDLE;
206       AllocParams.Persist = 0;
207
208       AGESA_TESTPOINT (TpIfBeforeAllocateS3SaveBuffer, &AmdS3SaveParams->StdHeader);
209       if (HeapAllocateBuffer (&AllocParams, &AmdS3SaveParams->StdHeader) != AGESA_SUCCESS) {
210         if (AGESA_ERROR > ReturnStatus) {
211           ReturnStatus = AGESA_ERROR;
212         }
213       }
214       AGESA_TESTPOINT (TpIfAfterAllocateS3SaveBuffer, &AmdS3SaveParams->StdHeader);
215
216       if (EarlyBufferSize != 0) {
217         AmdS3SaveParams->S3DataBlock.NvStorage = AllocParams.BufferPtr;
218         SaveDeviceListContext (MemoryRelatedDeviceList,
219                            AmdS3SaveParams->S3DataBlock.NvStorage,
220                            INIT_RESUME,
221                            &EarlyBufferSize,
222                            &AmdS3SaveParams->StdHeader);
223
224         AmdS3SaveParams->S3DataBlock.NvStorageSize = EarlyBufferSize;
225       }
226
227       if (LateBufferSize != 0) {
228         BufferPointer = AllocParams.BufferPtr;
229         AmdS3SaveParams->S3DataBlock.VolatileStorage = &(BufferPointer[EarlyBufferSize]);
230
231         ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->HeapOffset = 0;
232         ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->HeapSize = HeapSize;
233         ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->RegisterDataOffset = 0;
234         ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->RegisterDataSize = LateContextSize;
235
236         if (HeapSize != 0) {
237           // Transfer heap contents
238           ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->HeapOffset = sizeof (S3_VOLATILE_STORAGE_HEADER);
239           HeapPtr = (HEAP_MANAGER *) &BufferPointer[EarlyBufferSize + sizeof (S3_VOLATILE_STORAGE_HEADER)];
240           HeapPtr->UsedSize = sizeof (HEAP_MANAGER);
241           HeapPtr->Signature = HEAP_SIGNATURE_VALID;
242           HeapPtr->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
243           HeapPtr->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
244           FreeSpaceNode = (BUFFER_NODE *) ((UINT8 *) HeapPtr + sizeof (HEAP_MANAGER));
245           FreeSpaceNode->BufferSize = HeapSize - sizeof (HEAP_MANAGER) - sizeof (BUFFER_NODE);
246           FreeSpaceNode->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
247
248           HeapStatus = AmdS3SaveParams->StdHeader.HeapStatus;
249           AmdS3SaveParams->StdHeader.HeapStatus = HEAP_S3_RESUME;
250           AmdS3SaveParams->StdHeader.HeapBasePtr = (UINT64) HeapPtr;
251
252           for (i = 0; i < S3LATE_TABLE_SIZE; i++) {
253             if (HeapPtrs[i] != NULL) {
254               HeapParams.RequestedBufferSize = HeapSizes[i]; // S3LateHeapTable[i].BufferLength;
255               HeapParams.BufferHandle = S3LateHeapTable[i];
256               HeapParams.Persist = HEAP_S3_RESUME;
257               if (HeapAllocateBuffer (&HeapParams, &AmdS3SaveParams->StdHeader) == AGESA_SUCCESS) {
258                 LibAmdMemCopy ((VOID *) HeapParams.BufferPtr, HeapPtrs[i], HeapSizes[i], &AmdS3SaveParams->StdHeader);
259               }
260             }
261           }
262
263           AmdS3SaveParams->StdHeader.HeapStatus = HeapStatus;
264         }
265
266
267         if (LateContextSize != 0) {
268
269           ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->RegisterDataOffset = HeapSize + sizeof (S3_VOLATILE_STORAGE_HEADER);
270
271           SaveDeviceListContext (NonMemoryRelatedDeviceList,
272                                 &(BufferPointer[EarlyBufferSize + HeapSize + sizeof (S3_VOLATILE_STORAGE_HEADER)]),
273                                 S3_LATE_RESTORE,
274                                 &LateContextSize,
275                                 &AmdS3SaveParams->StdHeader);
276         }
277
278         AmdS3SaveParams->S3DataBlock.VolatileStorageSize = HeapSize + LateContextSize + sizeof (S3_VOLATILE_STORAGE_HEADER);
279       }
280     }
281   }
282
283   ReturnStatus = BldoptFchFunction.InitLate (AmdS3SaveParams);
284
285   IDS_OPTION_HOOK (IDS_AFTER_S3_SAVE, AmdS3SaveParams, &AmdS3SaveParams->StdHeader);
286   AGESA_TESTPOINT (TpIfAmdS3SaveExit, &AmdS3SaveParams->StdHeader);
287   return  ReturnStatus;
288 }
289
290 /*---------------------------------------------------------------------------------------*/
291 /**
292  * Constructor for the AMD_S3_SAVE function.
293  *
294  * This routine is responsible for setting default values for the
295  * input parameters needed by the AMD_S3_SAVE entry point.
296  *
297  * @param[in]    StdHeader       The standard header.
298  * @param[in,out] S3SaveParams   Required input parameters for the AMD_S3_SAVE
299  *                               entry point.
300  *
301  * @retval        AGESA_SUCCESS  Always Succeeds.
302  *
303  */
304 AGESA_STATUS
305 AmdS3SaveInitializer (
306   IN OUT   AMD_CONFIG_PARAMS *StdHeader,
307   IN OUT   AMD_S3SAVE_PARAMS *S3SaveParams
308   )
309 {
310   ASSERT (StdHeader != NULL);
311   ASSERT (S3SaveParams != NULL);
312
313   S3SaveParams->StdHeader = *StdHeader;
314
315   AmdS3ParamsInitializer (&S3SaveParams->S3DataBlock);
316
317   AmdS3SavePlatformConfigInit (&S3SaveParams->PlatformConfig, &S3SaveParams->StdHeader);
318   BldoptFchFunction.InitLateConstructor (S3SaveParams);
319
320   return AGESA_SUCCESS;
321 }
322
323 /*---------------------------------------------------------------------------------------*/
324 /**
325  * Destructor for the AMD_S3_SAVE function.
326  *
327  * This routine is responsible for deallocation of heap space allocated during
328  * AMD_S3_SAVE entry point.
329  *
330  * @param[in]     StdHeader       The standard header.
331  * @param[in,out] S3SaveParams   Required input parameters for the AMD_INIT_RESUME
332  *                               entry point.
333  *
334  * @retval        AGESA_STATUS
335  *
336  */
337 AGESA_STATUS
338 AmdS3SaveDestructor (
339   IN       AMD_CONFIG_PARAMS *StdHeader,
340   IN OUT   AMD_S3SAVE_PARAMS *S3SaveParams
341   )
342 {
343   AGESA_STATUS ReturnStatus;
344   AGESA_STATUS RetVal;
345
346   ASSERT (S3SaveParams != NULL);
347
348   ReturnStatus = AGESA_SUCCESS;
349
350   // Deallocate heap space allocated during memory S3 save
351   RetVal = MemS3Deallocate (&S3SaveParams->StdHeader);
352   if (RetVal > ReturnStatus) {
353     ReturnStatus = RetVal;
354   }
355
356   RetVal = HeapDeallocateBuffer (AMD_S3_NB_INFO_BUFFER_HANDLE, StdHeader);
357   if (RetVal > ReturnStatus) {
358     ReturnStatus = RetVal;
359   }
360
361   RetVal = HeapDeallocateBuffer (AMD_S3_INFO_BUFFER_HANDLE, StdHeader);
362   if (RetVal > ReturnStatus) {
363     ReturnStatus = RetVal;
364   }
365
366   return ReturnStatus;
367 }
368
369 /*------------------------------------------------------------------------------------*/
370 /**
371  * Initialize AmdS3Save stage platform profile and user option input.
372  *
373  * @param[in,out]   PlatformConfig   Platform profile/build option config structure
374  * @param[in,out]   StdHeader        AMD standard header config param
375  *
376  * @retval          AGESA_SUCCESS    Always Succeeds.
377  *
378  */
379 AGESA_STATUS
380 AmdS3SavePlatformConfigInit (
381   IN OUT   PLATFORM_CONFIGURATION    *PlatformConfig,
382   IN OUT   AMD_CONFIG_PARAMS         *StdHeader
383   )
384 {
385   CommonPlatformConfigInit (PlatformConfig, StdHeader);
386
387   return AGESA_SUCCESS;
388 }