AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Common / CreateStruct.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD AGESA Input Structure Creation
6  *
7  * Contains AGESA input structure creation support.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  Common
12  * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
13  *
14  */
15 /*
16  ******************************************************************************
17  *
18  * Copyright (C) 2012 Advanced Micro Devices, Inc.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions are met:
23  *     * Redistributions of source code must retain the above copyright
24  *       notice, this list of conditions and the following disclaimer.
25  *     * Redistributions in binary form must reproduce the above copyright
26  *       notice, this list of conditions and the following disclaimer in the
27  *       documentation and/or other materials provided with the distribution.
28  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
29  *       its contributors may be used to endorse or promote products derived
30  *       from this software without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 "GeneralServices.h"
54 #include "heapManager.h"
55 #include "CreateStruct.h"
56 #include "cpuFamilyTranslation.h"
57 #include "Filecode.h"
58 CODE_GROUP (G1_PEICC)
59 RDATA_GROUP (G2_PEI)
60
61 #define FILECODE PROC_COMMON_CREATESTRUCT_FILECODE
62 /*----------------------------------------------------------------------------------------
63  *                   D E F I N I T I O N S    A N D    M A C R O S
64  *----------------------------------------------------------------------------------------
65  */
66 extern CONST FUNCTION_PARAMS_INFO FuncParamsInfo[];
67 extern CONST UINTN InitializerCount;
68
69 /*----------------------------------------------------------------------------------------
70  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
71  *----------------------------------------------------------------------------------------
72  */
73
74 /*----------------------------------------------------------------------------------------
75  *           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
76  *----------------------------------------------------------------------------------------
77  */
78
79 /*----------------------------------------------------------------------------------------
80  *                          E X P O R T E D    F U N C T I O N S
81  *----------------------------------------------------------------------------------------
82  */
83 extern BUILD_OPT_CFG UserOptions;
84
85 /*---------------------------------------------------------------------------------------*/
86 /**
87  * Allocate and initialize Config headers and Service Interface structures.
88  *
89  * This function will be called for each AGESA public APIs.
90  * This function will do the following:
91  * -# Locate the AGESA API structure parameters initializer function information.
92  * -# Find the size of the structure that gets passed to each public APIs as
93  *    the entry parameter. Allocate heap space using the size for PreMemHeap, callout for
94  *    memory allocation for PostMemDram, and just set the config and service interface
95  *    pointers for ByHost.
96  * -# If the allocation is not ByHost, copy the AmdConfigParams into the newly created AmdConfigParams.
97  *    For ByHost, we're using the caller's existing config params.
98  * -# Call the initializer function, and pass a reference to the Config params and to
99  *    the Service Interface struct.  On return the constructor will have filled the
100  *    remaining structure with default values.
101  * -# Fill the remaining info in the newly created structure on heap in AMD_CONFIG_PARAMS
102  *    area (i.e. Fill *newStructPtr with the pointer to the newly created structure)
103  * -# Set the appropriate AGESA function number in the StdHeader member of the input
104  *    parameter structure.
105  *
106  * @param[in,out]  InterfaceParams         Pointer to structure containing the function call
107  *                                         whose parameter structure is to be created, the
108  *                                         allocation method, and a pointer to the newly
109  *                                         created structure.
110  *
111  * @retval         AGESA_SUCCESS           The interface struct is allocated and initialized.
112  * @retval         AGESA_UNSUPPORTED       The Service is not supported.
113  *
114  */
115 AGESA_STATUS
116 AmdCreateStruct (
117   IN OUT   AMD_INTERFACE_PARAMS *InterfaceParams
118   )
119 {
120   UINTN                     ServiceIndex;
121   ALLOCATE_HEAP_PARAMS      AllocHeapParams;
122   AMD_CONFIG_PARAMS         *NewlyCreatedConfig;
123   VOID                      *NewlyCreatedServiceInterface;
124   AGESA_STATUS              AgesaStatus;
125   AGESA_STATUS              TempStatus;
126   AGESA_STATUS              IgnoredSts;
127   CPU_SPECIFIC_SERVICES     *FamilySpecificServices;
128
129   AgesaStatus = AGESA_SUCCESS;
130
131   ASSERT (InterfaceParams != NULL);
132
133   switch (InterfaceParams->AgesaFunctionName) {
134   case AMD_INIT_RESET:
135     if (!IsBsp (&InterfaceParams->StdHeader, &IgnoredSts)) {
136       // APs must transfer their system core number from the mailbox to
137       // a local register while it is still valid.
138       GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &InterfaceParams->StdHeader);
139       FamilySpecificServices->TransferApCoreNumber (FamilySpecificServices, &InterfaceParams->StdHeader);
140     }
141     InterfaceParams->StdHeader.HeapStatus = HEAP_DO_NOT_EXIST_YET;
142     break;
143   case AMD_INIT_EARLY:
144   case AMD_INIT_RECOVERY:
145   case AMD_INIT_RESUME:
146   case AMD_INIT_POST:
147     InterfaceParams->StdHeader.HeapStatus = HEAP_LOCAL_CACHE;
148     break;
149   case AMD_INIT_ENV:
150     InterfaceParams->StdHeader.HeapStatus = HEAP_TEMP_MEM;
151     break;
152   case AMD_INIT_LATE:
153   case AMD_INIT_MID:
154   case AMD_S3_SAVE:
155   case AMD_LATE_RUN_AP_TASK:
156     InterfaceParams->StdHeader.HeapStatus = HEAP_SYSTEM_MEM;
157     break;
158   case AMD_S3LATE_RESTORE:
159     InterfaceParams->StdHeader.HeapStatus = HEAP_S3_RESUME;
160     break;
161   default:
162     ASSERT (FALSE);
163     InterfaceParams->StdHeader.HeapStatus = HEAP_LOCAL_CACHE;
164     break;
165   }
166
167   InterfaceParams->StdHeader.HeapBasePtr = HeapGetBaseAddress (&InterfaceParams->StdHeader);
168
169   if (InterfaceParams->AgesaFunctionName == AMD_INIT_RESET) {
170     AgesaStatus = HeapManagerInit (&InterfaceParams->StdHeader);
171   }
172
173   // Step 1
174   for (ServiceIndex = 0; ServiceIndex < InitializerCount; ServiceIndex++) {
175     if (FuncParamsInfo[ServiceIndex].AgesaFunctionName == InterfaceParams->AgesaFunctionName) {
176       break;
177     }
178   }
179   if (ServiceIndex >= InitializerCount) {
180     // A call was made to AGESA with an invalid function number.  This wrapper error may be due to the build target
181     // not containing the desired entry point.
182     return AGESA_UNSUPPORTED;
183   }
184
185   // Step 2
186   LibAmdMemFill (&AllocHeapParams, 0, (UINTN) (sizeof (ALLOCATE_HEAP_PARAMS)), &InterfaceParams->StdHeader);
187
188   if (InterfaceParams->AllocationMethod < ByHost) {
189     // Allocate one buffer to contain the config params and the service struct.
190     // The service struct begins immediately after the config params.
191     AllocHeapParams.RequestedBufferSize = FuncParamsInfo[ServiceIndex].CreateStructSize + sizeof (AMD_CONFIG_PARAMS);
192     AllocHeapParams.BufferHandle = FuncParamsInfo[ServiceIndex].BufferHandle;
193     AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
194     TempStatus = HeapAllocateBuffer (&AllocHeapParams, &(InterfaceParams->StdHeader));
195     AgesaStatus = ((AgesaStatus > TempStatus) ? AgesaStatus : TempStatus);
196     NewlyCreatedConfig = (AMD_CONFIG_PARAMS *)AllocHeapParams.BufferPtr;
197     NewlyCreatedConfig++;
198     NewlyCreatedServiceInterface =  NewlyCreatedConfig;
199     NewlyCreatedConfig = (AMD_CONFIG_PARAMS *)AllocHeapParams.BufferPtr;
200   } else {
201     // The caller (example, agesa basic interface implementation) already has a buffer to use.
202     NewlyCreatedConfig = (AMD_CONFIG_PARAMS *)InterfaceParams;
203     NewlyCreatedServiceInterface = InterfaceParams->NewStructPtr;
204     ASSERT (InterfaceParams->NewStructSize >= FuncParamsInfo[ServiceIndex].CreateStructSize);
205   }
206   ASSERT (NewlyCreatedConfig != NULL);
207   ASSERT (NewlyCreatedServiceInterface != NULL);
208
209   // Step 3
210   if (InterfaceParams->AllocationMethod != ByHost) {
211     *NewlyCreatedConfig = InterfaceParams->StdHeader;
212   }
213
214   // Step 4
215   TempStatus = FuncParamsInfo[ServiceIndex].AgesaFunction (NewlyCreatedConfig, NewlyCreatedServiceInterface);
216   AgesaStatus = ((AgesaStatus > TempStatus) ? AgesaStatus : TempStatus);
217
218   // Step 5
219   if (InterfaceParams->AllocationMethod != ByHost) {
220     InterfaceParams->NewStructPtr = (VOID *) NewlyCreatedServiceInterface;
221     InterfaceParams->NewStructSize = FuncParamsInfo[ServiceIndex].CreateStructSize;
222   }
223
224   // Step 6
225   ((AMD_CONFIG_PARAMS *) InterfaceParams->NewStructPtr)->Func = InterfaceParams->AgesaFunctionName;
226   return AgesaStatus;
227 }
228
229
230 /*---------------------------------------------------------------------------------------*/
231 /**
232  *  Clears storage space from allocation for a parameter block of an
233  *  AGESA software call entry.
234  *
235  *  @param[in,out]  InterfaceParams         Pointer to structure containing the function call
236  *                                          whose parameter structure is to be deallocated.
237  *
238  *  @retval         AGESA_STATUS
239  *
240  *---------------------------------------------------------------------------------------
241  **/
242 AGESA_STATUS
243 AmdReleaseStruct (
244   IN OUT   AMD_INTERFACE_PARAMS *InterfaceParams
245   )
246 {
247   UINT8 i;
248   UINT8 *BufferPtr;
249   VOID  *ServicePtr;
250   AGESA_STATUS  AgesaStatus;
251   AGESA_STATUS  TempStatus;
252   LOCATE_HEAP_PTR LocHeap;
253
254   AgesaStatus = AGESA_SUCCESS;
255
256   switch (InterfaceParams->AgesaFunctionName) {
257   case AMD_INIT_RESET:
258   case AMD_INIT_EARLY:
259   case AMD_INIT_RECOVERY:
260   case AMD_INIT_RESUME:
261     InterfaceParams->StdHeader.HeapStatus = HEAP_LOCAL_CACHE;
262     break;
263   case AMD_INIT_POST:
264     InterfaceParams->StdHeader.HeapStatus = HEAP_TEMP_MEM;
265     break;
266   case AMD_INIT_ENV:
267   case AMD_INIT_LATE:
268   case AMD_INIT_MID:
269   case AMD_S3_SAVE:
270   case AMD_LATE_RUN_AP_TASK:
271     InterfaceParams->StdHeader.HeapStatus = HEAP_SYSTEM_MEM;
272     break;
273   case AMD_S3LATE_RESTORE:
274     InterfaceParams->StdHeader.HeapStatus = HEAP_S3_RESUME;
275     break;
276   default:
277     ASSERT (FALSE);
278     InterfaceParams->StdHeader.HeapStatus = HEAP_LOCAL_CACHE;
279     break;
280   }
281
282   InterfaceParams->StdHeader.HeapBasePtr = HeapGetBaseAddress (&InterfaceParams->StdHeader);
283
284 // Step 1
285   for (i = 0; i < InitializerCount; i++) {
286     if (FuncParamsInfo[i].AgesaFunctionName == InterfaceParams->AgesaFunctionName) {
287       break;
288     }
289   }
290   if (i >= InitializerCount) {
291     return AGESA_BOUNDS_CHK;
292   }
293
294   // Step 2
295   if (InterfaceParams->AllocationMethod < ByHost) {
296     LocHeap.BufferHandle = FuncParamsInfo[i].BufferHandle;
297     if (HeapLocateBuffer (&LocHeap, &(InterfaceParams->StdHeader)) == AGESA_SUCCESS) {
298       BufferPtr = (UINT8 *) LocHeap.BufferPtr;
299       ServicePtr = &BufferPtr[sizeof (AMD_CONFIG_PARAMS)];
300       TempStatus = FuncParamsInfo[i].AgesaDestructor (&(InterfaceParams->StdHeader), ServicePtr);
301       AgesaStatus = ((AgesaStatus > TempStatus) ? AgesaStatus : TempStatus);
302     }
303   }
304
305   // Step 3
306   if (InterfaceParams->AllocationMethod < ByHost) {
307     TempStatus = HeapDeallocateBuffer (FuncParamsInfo[i].BufferHandle, &(InterfaceParams->StdHeader));
308     AgesaStatus = ((AgesaStatus > TempStatus) ? AgesaStatus : TempStatus);
309   } else {
310     // Unless we define service specific destructors, nothing to do for ByHost.
311     return AGESA_SUCCESS;
312   }
313   return AgesaStatus;
314 }