blob: a05614151e2a008aff37f544db0f2ff9be2ac170 [file] [log] [blame]
Marc Jones1587dc82017-05-15 18:55:11 -06001/*
2 * This file is part of the coreboot project.
3 *
Richard Spiegel67c2a7b2017-11-09 16:04:35 -07004 * Copyright (C) 2012 - 2017 Advanced Micro Devices, Inc.
Kyösti Mälkki4cdd2f82018-06-14 06:49:38 +03005 * Copyright (C) 2018 Kyösti Mälkki
Marc Jones1587dc82017-05-15 18:55:11 -06006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
Aaron Durbina78319b2017-12-08 15:38:59 -070017#include <arch/early_variables.h>
Marshall Dawson857a3872017-12-13 20:01:59 -070018#include <arch/acpi.h>
19#include <cpu/x86/mtrr.h>
Marc Jones1587dc82017-05-15 18:55:11 -060020#include <cbfs.h>
21#include <cbmem.h>
Aaron Durbin64031672018-04-21 14:45:32 -060022#include <compiler.h>
Marc Jones1587dc82017-05-15 18:55:11 -060023#include <delay.h>
Justin TerAvest92261952017-12-22 15:15:02 -070024#include <rules.h>
Aaron Durbin931ed7f2017-12-22 17:13:17 -070025#include <rmodule.h>
Raul E Rangel8af20c62018-05-11 11:08:08 -060026#include <stage_cache.h>
Aaron Durbine3f7d442017-11-03 11:44:10 -060027#include <string.h>
Martin Rothbc5c3e72017-12-09 10:40:45 -070028#include <timestamp.h>
Marshall Dawsonc2f6da02017-12-04 15:28:10 -070029#include <amdblocks/s3_resume.h>
Marshall Dawson857a3872017-12-13 20:01:59 -070030#include <amdblocks/agesawrapper.h>
31#include <amdblocks/BiosCallOuts.h>
Marc Jones932b5bd2018-02-19 13:34:31 -070032#include <soc/southbridge.h>
Marc Jones1587dc82017-05-15 18:55:11 -060033
Aaron Durbin64031672018-04-21 14:45:32 -060034void __weak SetMemParams(AMD_POST_PARAMS *PostParams) {}
35void __weak OemPostParams(AMD_POST_PARAMS *PostParams) {}
Marc Jones1587dc82017-05-15 18:55:11 -060036
Marc Jones1587dc82017-05-15 18:55:11 -060037/* ACPI table pointers returned by AmdInitLate */
Aaron Durbin8dd40062017-11-03 11:50:14 -060038static void *DmiTable;
39static void *AcpiPstate;
40static void *AcpiSrat;
41static void *AcpiSlit;
Marc Jones1587dc82017-05-15 18:55:11 -060042
Aaron Durbin8dd40062017-11-03 11:50:14 -060043static void *AcpiWheaMce;
44static void *AcpiWheaCmc;
45static void *AcpiAlib;
46static void *AcpiIvrs;
47static void *AcpiCrat;
Marc Jones1587dc82017-05-15 18:55:11 -060048
Marshall Dawson8f6cd222017-12-15 12:01:41 -070049static AGESA_STATUS agesawrapper_readeventlog(UINT8 HeapStatus)
50{
51 AGESA_STATUS Status;
52 EVENT_PARAMS AmdEventParams = {
53 .StdHeader.CalloutPtr = &GetBiosCallout,
54 .StdHeader.HeapStatus = HeapStatus,
55 };
56
57 Status = AmdReadEventLog(&AmdEventParams);
58 if (AmdEventParams.EventClass)
59 printk(BIOS_DEBUG, "AGESA Event Log:\n");
60
61 while (AmdEventParams.EventClass != 0) {
62 printk(BIOS_DEBUG, " Class = %x, Info = %x,"
63 " Param1 = 0x%x, Param2 = 0x%x"
64 " Param3 = 0x%x, Param4 = 0x%x\n",
65 (u32)AmdEventParams.EventClass,
66 (u32)AmdEventParams.EventInfo,
67 (u32)AmdEventParams.DataParam1,
68 (u32)AmdEventParams.DataParam2,
69 (u32)AmdEventParams.DataParam3,
70 (u32)AmdEventParams.DataParam4);
71 Status = AmdReadEventLog(&AmdEventParams);
72 }
73
74 return Status;
75}
76
Marshall Dawson4c5a3b62018-01-25 11:13:35 -070077static AGESA_STATUS create_struct(AMD_INTERFACE_PARAMS *interface_struct)
78{
Kyösti Mälkki4cdd2f82018-06-14 06:49:38 +030079 /* Should clone entire StdHeader here. */
80 interface_struct->StdHeader.CalloutPtr = &GetBiosCallout;
81
Marshall Dawson4c5a3b62018-01-25 11:13:35 -070082 AGESA_STATUS status = AmdCreateStruct(interface_struct);
83 if (status == AGESA_SUCCESS)
84 return status;
85
86 printk(BIOS_ERR, "Error: AmdCreateStruct() for 0x%x returned 0x%x. "
87 "Proper system initialization may not be possible.\n",
88 interface_struct->AgesaFunctionName, status);
89
90 if (!interface_struct->NewStructPtr) /* Avoid NULL pointer usage */
91 die("No AGESA structure created");
92
93 return status;
94}
95
Marc Jones1587dc82017-05-15 18:55:11 -060096AGESA_STATUS agesawrapper_amdinitreset(void)
97{
98 AGESA_STATUS status;
Marshall Dawson857a3872017-12-13 20:01:59 -070099 AMD_RESET_PARAMS ResetParams;
100 AMD_INTERFACE_PARAMS AmdParamStruct = {
101 .AgesaFunctionName = AMD_INIT_RESET,
102 .AllocationMethod = ByHost,
103 .NewStructSize = sizeof(AMD_RESET_PARAMS),
104 .NewStructPtr = &ResetParams,
Marshall Dawson857a3872017-12-13 20:01:59 -0700105 };
Marshall Dawson4c5a3b62018-01-25 11:13:35 -0700106 create_struct(&AmdParamStruct);
Marshall Dawson857a3872017-12-13 20:01:59 -0700107 SetFchResetParams(&ResetParams.FchInterface);
Marc Jones1587dc82017-05-15 18:55:11 -0600108
Martin Rothbc5c3e72017-12-09 10:40:45 -0700109 timestamp_add_now(TS_AGESA_INIT_RESET_START);
Marshall Dawson857a3872017-12-13 20:01:59 -0700110 status = AmdInitReset(&ResetParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700111 timestamp_add_now(TS_AGESA_INIT_RESET_DONE);
112
Marshall Dawson3aed84a2017-12-13 20:59:23 -0700113 if (status != AGESA_SUCCESS)
114 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
Marshall Dawson857a3872017-12-13 20:01:59 -0700115 AmdReleaseStruct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600116 return status;
117}
118
119AGESA_STATUS agesawrapper_amdinitearly(void)
120{
121 AGESA_STATUS status;
Marshall Dawson857a3872017-12-13 20:01:59 -0700122 AMD_EARLY_PARAMS *EarlyParams;
123 AMD_INTERFACE_PARAMS AmdParamStruct = {
124 .AgesaFunctionName = AMD_INIT_EARLY,
125 .AllocationMethod = PreMemHeap,
Marshall Dawson857a3872017-12-13 20:01:59 -0700126 };
Marc Jones1587dc82017-05-15 18:55:11 -0600127
Marshall Dawson4c5a3b62018-01-25 11:13:35 -0700128 create_struct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600129
Marshall Dawson857a3872017-12-13 20:01:59 -0700130 EarlyParams = (AMD_EARLY_PARAMS *)AmdParamStruct.NewStructPtr;
131 OemCustomizeInitEarly(EarlyParams);
Marc Jones1587dc82017-05-15 18:55:11 -0600132
Marshall Dawson857a3872017-12-13 20:01:59 -0700133 EarlyParams->GnbConfig.PsppPolicy = PsppDisabled;
Martin Rothbc5c3e72017-12-09 10:40:45 -0700134
135 timestamp_add_now(TS_AGESA_INIT_EARLY_START);
Marshall Dawson857a3872017-12-13 20:01:59 -0700136 status = AmdInitEarly(EarlyParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700137 timestamp_add_now(TS_AGESA_INIT_EARLY_DONE);
Marc Jones1587dc82017-05-15 18:55:11 -0600138
Marshall Dawson3aed84a2017-12-13 20:59:23 -0700139 if (status != AGESA_SUCCESS)
140 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
Marshall Dawson857a3872017-12-13 20:01:59 -0700141 AmdReleaseStruct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600142
143 return status;
144}
145
Marshall Dawson972f8262017-12-14 09:08:02 -0700146static void print_init_post_settings(AMD_POST_PARAMS *parms)
147{
148 u64 syslimit, bottomio, uma_size, uma_start;
149 const char *mode;
150
151 switch (parms->MemConfig.UmaMode) {
152 case UMA_AUTO:
153 mode = "UMA_AUTO";
154 break;
155 case UMA_SPECIFIED:
156 mode = "UMA_SPECIFIED";
157 break;
158 case UMA_NONE:
159 mode = "UMA_NONE";
160 break;
161 default:
162 mode = "unknown!";
163 break;
164 }
165
166 syslimit = (u64)parms->MemConfig.SysLimit * 64 * KiB;
167 bottomio = (u64)parms->MemConfig.BottomIo * 64 * KiB;
168
169 uma_size = (u64)parms->MemConfig.UmaSize * 64 * KiB;
170 uma_start = (u64)parms->MemConfig.UmaBase * 64 * KiB;
171
172 printk(BIOS_SPEW, "AGESA set: umamode %s\n", mode);
173 printk(BIOS_SPEW, " : syslimit 0x%llx, bottomio 0x%08llx\n",
174 syslimit, bottomio);
175 printk(BIOS_SPEW, " : uma size %lluMB, uma start 0x%08llx\n",
176 uma_size / MiB, uma_start);
177}
178
Marc Jones1587dc82017-05-15 18:55:11 -0600179AGESA_STATUS agesawrapper_amdinitpost(void)
180{
181 AGESA_STATUS status;
Marshall Dawson857a3872017-12-13 20:01:59 -0700182 AMD_INTERFACE_PARAMS AmdParamStruct = {
183 .AgesaFunctionName = AMD_INIT_POST,
184 .AllocationMethod = PreMemHeap,
Marshall Dawson857a3872017-12-13 20:01:59 -0700185 };
186 AMD_POST_PARAMS *PostParams;
Marc Jones1587dc82017-05-15 18:55:11 -0600187
Marshall Dawson4c5a3b62018-01-25 11:13:35 -0700188 create_struct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600189
Marc Jones1587dc82017-05-15 18:55:11 -0600190 PostParams = (AMD_POST_PARAMS *)AmdParamStruct.NewStructPtr;
Marc Jones1587dc82017-05-15 18:55:11 -0600191 PostParams->MemConfig.UmaMode = CONFIG_GFXUMA ? UMA_AUTO : UMA_NONE;
192 PostParams->MemConfig.UmaSize = 0;
193 PostParams->MemConfig.BottomIo = (UINT16)
194 (CONFIG_BOTTOMIO_POSITION >> 24);
195
Richard Spiegel67c2a7b2017-11-09 16:04:35 -0700196 SetMemParams(PostParams);
Marc Jones1587dc82017-05-15 18:55:11 -0600197 OemPostParams(PostParams);
Richard Spiegel67c2a7b2017-11-09 16:04:35 -0700198 printk(BIOS_SPEW, "DRAM clear on reset: %s\n",
199 (PostParams->MemConfig.EnableMemClr == FALSE) ? "Keep" :
200 (PostParams->MemConfig.EnableMemClr == TRUE) ? "Clear" :
201 "unknown"
202 );
Marc Jones1587dc82017-05-15 18:55:11 -0600203
Martin Rothbc5c3e72017-12-09 10:40:45 -0700204 timestamp_add_now(TS_AGESA_INIT_POST_START);
Marshall Dawson857a3872017-12-13 20:01:59 -0700205 status = AmdInitPost(PostParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700206 timestamp_add_now(TS_AGESA_INIT_POST_DONE);
Marc Jones1587dc82017-05-15 18:55:11 -0600207
Marshall Dawson972f8262017-12-14 09:08:02 -0700208 /*
Marc Jones932b5bd2018-02-19 13:34:31 -0700209 * AGESA passes back the base and size of UMA. This is the only
210 * opportunity to get and save these settings to be used in resource
211 * allocation. We also need to allocate the top of low memory.
212 * If UMA is below 4GiB, UMA base is the top of low memory, otherwise
213 * Sub4GCachetop is the top of low memory.
214 * With UMA_NONE we see UmaBase==0.
Marshall Dawson972f8262017-12-14 09:08:02 -0700215 */
216 uintptr_t top;
Marc Jones932b5bd2018-02-19 13:34:31 -0700217 if (PostParams->MemConfig.UmaBase &&
218 (PostParams->MemConfig.UmaBase < ((4ull * GiB) >> 16)))
Marshall Dawson972f8262017-12-14 09:08:02 -0700219 top = PostParams->MemConfig.UmaBase << 16;
Marc Jones1587dc82017-05-15 18:55:11 -0600220 else
Marshall Dawson972f8262017-12-14 09:08:02 -0700221 top = PostParams->MemConfig.Sub4GCacheTop;
222 backup_top_of_low_cacheable(top);
Marc Jones1587dc82017-05-15 18:55:11 -0600223
Marc Jones932b5bd2018-02-19 13:34:31 -0700224 save_uma_size(PostParams->MemConfig.UmaSize * 64 * KiB);
225 save_uma_base((u64)PostParams->MemConfig.UmaBase * 64 * KiB);
226
Marshall Dawson972f8262017-12-14 09:08:02 -0700227 print_init_post_settings(PostParams);
Marc Jones1587dc82017-05-15 18:55:11 -0600228
Marshall Dawson3aed84a2017-12-13 20:59:23 -0700229 if (status != AGESA_SUCCESS)
230 agesawrapper_readeventlog(PostParams->StdHeader.HeapStatus);
Marshall Dawson857a3872017-12-13 20:01:59 -0700231 AmdReleaseStruct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600232
233 return status;
234}
235
236AGESA_STATUS agesawrapper_amdinitenv(void)
237{
238 AGESA_STATUS status;
Marshall Dawson857a3872017-12-13 20:01:59 -0700239 AMD_INTERFACE_PARAMS AmdParamStruct = {
240 .AgesaFunctionName = AMD_INIT_ENV,
241 .AllocationMethod = PostMemDram,
Marshall Dawson857a3872017-12-13 20:01:59 -0700242 };
243 AMD_ENV_PARAMS *EnvParams;
Marc Jones1587dc82017-05-15 18:55:11 -0600244
Marshall Dawson4c5a3b62018-01-25 11:13:35 -0700245 status = create_struct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600246
Marshall Dawson857a3872017-12-13 20:01:59 -0700247 EnvParams = (AMD_ENV_PARAMS *)AmdParamStruct.NewStructPtr;
248 SetFchEnvParams(&EnvParams->FchInterface);
249 SetNbEnvParams(&EnvParams->GnbEnvConfiguration);
Marc Jones1587dc82017-05-15 18:55:11 -0600250
Martin Rothbc5c3e72017-12-09 10:40:45 -0700251 timestamp_add_now(TS_AGESA_INIT_ENV_START);
Marshall Dawson857a3872017-12-13 20:01:59 -0700252 status = AmdInitEnv(EnvParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700253 timestamp_add_now(TS_AGESA_INIT_ENV_DONE);
254
Marshall Dawson3aed84a2017-12-13 20:59:23 -0700255 if (status != AGESA_SUCCESS)
Marshall Dawson857a3872017-12-13 20:01:59 -0700256 agesawrapper_readeventlog(EnvParams->StdHeader.HeapStatus);
Marshall Dawsondd2c7b12017-12-13 22:36:52 -0700257 AmdReleaseStruct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600258
259 return status;
260}
261
Marshall Dawson857a3872017-12-13 20:01:59 -0700262VOID *agesawrapper_getlateinitptr(int pick)
Marc Jones1587dc82017-05-15 18:55:11 -0600263{
264 switch (pick) {
265 case PICK_DMI:
266 return DmiTable;
267 case PICK_PSTATE:
268 return AcpiPstate;
269 case PICK_SRAT:
270 return AcpiSrat;
271 case PICK_SLIT:
272 return AcpiSlit;
273 case PICK_WHEA_MCE:
274 return AcpiWheaMce;
275 case PICK_WHEA_CMC:
276 return AcpiWheaCmc;
277 case PICK_ALIB:
278 return AcpiAlib;
279 case PICK_IVRS:
280 return AcpiIvrs;
281 case PICK_CRAT:
282 return AcpiCrat;
283 default:
284 return NULL;
285 }
286}
Marc Jones1587dc82017-05-15 18:55:11 -0600287
288AGESA_STATUS agesawrapper_amdinitmid(void)
289{
290 AGESA_STATUS status;
Marshall Dawson857a3872017-12-13 20:01:59 -0700291 AMD_INTERFACE_PARAMS AmdParamStruct = {
292 .AgesaFunctionName = AMD_INIT_MID,
293 .AllocationMethod = PostMemDram,
Marshall Dawson857a3872017-12-13 20:01:59 -0700294 };
295 AMD_MID_PARAMS *MidParams;
Marc Jones1587dc82017-05-15 18:55:11 -0600296
297 /* Enable MMIO on AMD CPU Address Map Controller */
Marshall Dawson857a3872017-12-13 20:01:59 -0700298 amd_initcpuio();
Marc Jones1587dc82017-05-15 18:55:11 -0600299
Marshall Dawson4c5a3b62018-01-25 11:13:35 -0700300 create_struct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600301
Marshall Dawson857a3872017-12-13 20:01:59 -0700302 MidParams = (AMD_MID_PARAMS *)AmdParamStruct.NewStructPtr;
303 SetFchMidParams(&MidParams->FchInterface);
304 SetNbMidParams(&MidParams->GnbMidConfiguration);
Marc Jones1587dc82017-05-15 18:55:11 -0600305
Martin Rothbc5c3e72017-12-09 10:40:45 -0700306 timestamp_add_now(TS_AGESA_INIT_MID_START);
Marshall Dawson857a3872017-12-13 20:01:59 -0700307 status = AmdInitMid(MidParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700308 timestamp_add_now(TS_AGESA_INIT_MID_DONE);
309
Marshall Dawson3aed84a2017-12-13 20:59:23 -0700310 if (status != AGESA_SUCCESS)
311 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
Marshall Dawson857a3872017-12-13 20:01:59 -0700312 AmdReleaseStruct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600313
314 return status;
315}
316
Marc Jones1587dc82017-05-15 18:55:11 -0600317AGESA_STATUS agesawrapper_amdinitlate(void)
318{
319 AGESA_STATUS Status;
Marshall Dawson857a3872017-12-13 20:01:59 -0700320 AMD_INTERFACE_PARAMS AmdParamStruct = {
321 .AgesaFunctionName = AMD_INIT_LATE,
322 .AllocationMethod = PostMemDram,
Marshall Dawson857a3872017-12-13 20:01:59 -0700323 };
324 AMD_LATE_PARAMS *LateParams;
Marc Jones1587dc82017-05-15 18:55:11 -0600325
Richard Spiegelfc511272017-12-11 16:23:58 -0700326 /*
327 * NOTE: if not call amdcreatestruct, the initializer
328 * (AmdInitLateInitializer) would not be called.
329 */
Marshall Dawson4c5a3b62018-01-25 11:13:35 -0700330 create_struct(&AmdParamStruct);
Marshall Dawson857a3872017-12-13 20:01:59 -0700331 LateParams = (AMD_LATE_PARAMS *)AmdParamStruct.NewStructPtr;
Martin Rothbc5c3e72017-12-09 10:40:45 -0700332
333 timestamp_add_now(TS_AGESA_INIT_LATE_START);
Marshall Dawson857a3872017-12-13 20:01:59 -0700334 Status = AmdInitLate(LateParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700335 timestamp_add_now(TS_AGESA_INIT_LATE_DONE);
336
Marc Jones1587dc82017-05-15 18:55:11 -0600337 if (Status != AGESA_SUCCESS) {
Marshall Dawson857a3872017-12-13 20:01:59 -0700338 agesawrapper_readeventlog(LateParams->StdHeader.HeapStatus);
Marc Jones1587dc82017-05-15 18:55:11 -0600339 ASSERT(Status == AGESA_SUCCESS);
340 }
341
Marshall Dawson857a3872017-12-13 20:01:59 -0700342 DmiTable = LateParams->DmiTable;
343 AcpiPstate = LateParams->AcpiPState;
Marc Jones1587dc82017-05-15 18:55:11 -0600344
Marshall Dawson857a3872017-12-13 20:01:59 -0700345 AcpiWheaMce = LateParams->AcpiWheaMce;
346 AcpiWheaCmc = LateParams->AcpiWheaCmc;
347 AcpiAlib = LateParams->AcpiAlib;
348 AcpiIvrs = LateParams->AcpiIvrs;
349 AcpiCrat = LateParams->AcpiCrat;
Marc Jones1587dc82017-05-15 18:55:11 -0600350
Marshall Dawson857a3872017-12-13 20:01:59 -0700351 printk(BIOS_DEBUG, "DmiTable:%p, AcpiPstatein: %p, AcpiSrat:%p,"
352 "AcpiSlit:%p, Mce:%p, Cmc:%p,"
353 "Alib:%p, AcpiIvrs:%p in %s\n",
354 DmiTable, AcpiPstate, AcpiSrat,
355 AcpiSlit, AcpiWheaMce, AcpiWheaCmc,
356 AcpiAlib, AcpiIvrs, __func__);
Marc Jones1587dc82017-05-15 18:55:11 -0600357
Marshall Dawsondd2c7b12017-12-13 22:36:52 -0700358 AmdReleaseStruct(&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600359 return Status;
360}
Marc Jones1587dc82017-05-15 18:55:11 -0600361
Marshall Dawson857a3872017-12-13 20:01:59 -0700362AGESA_STATUS agesawrapper_amdlaterunaptask(UINT32 Func, UINTN Data,
363 VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600364{
365 AGESA_STATUS Status;
366 AP_EXE_PARAMS ApExeParams;
367
Aaron Durbine3f7d442017-11-03 11:44:10 -0600368 memset(&ApExeParams, 0, sizeof(ApExeParams));
Marc Jones1587dc82017-05-15 18:55:11 -0600369
370 ApExeParams.StdHeader.AltImageBasePtr = 0;
371 ApExeParams.StdHeader.CalloutPtr = &GetBiosCallout;
372 ApExeParams.StdHeader.Func = 0;
373 ApExeParams.StdHeader.ImageBasePtr = 0;
374 ApExeParams.FunctionNumber = Func;
375 ApExeParams.RelatedDataBlock = ConfigPtr;
376
Marshall Dawson857a3872017-12-13 20:01:59 -0700377 Status = AmdLateRunApTask(&ApExeParams);
Marc Jones1587dc82017-05-15 18:55:11 -0600378 if (Status != AGESA_SUCCESS) {
Marshall Dawson3aed84a2017-12-13 20:59:23 -0700379 /* agesawrapper_readeventlog(); */
Marc Jones1587dc82017-05-15 18:55:11 -0600380 ASSERT(Status == AGESA_SUCCESS);
381 }
382
383 return Status;
384}
385
Marshall Dawsonc2f6da02017-12-04 15:28:10 -0700386AGESA_STATUS agesawrapper_amdinitrtb(void)
387{
388 AGESA_STATUS Status;
389 AMD_INTERFACE_PARAMS AmdParamStruct = {
390 .AgesaFunctionName = AMD_INIT_RTB,
391 .AllocationMethod = PostMemDram,
Marshall Dawsonc2f6da02017-12-04 15:28:10 -0700392 };
393 AMD_RTB_PARAMS *RtbParams;
394
395 create_struct(&AmdParamStruct);
396
397 RtbParams = (AMD_RTB_PARAMS *)AmdParamStruct.NewStructPtr;
398
399 timestamp_add_now(TS_AGESA_INIT_RTB_START);
400 Status = AmdInitRtb(RtbParams);
401 timestamp_add_now(TS_AGESA_INIT_RTB_DONE);
402
403 if (Status != AGESA_SUCCESS) {
404 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
405 ASSERT(Status == AGESA_SUCCESS);
406 }
407
408 if (save_s3_info(RtbParams->S3DataBlock.NvStorage,
409 RtbParams->S3DataBlock.NvStorageSize,
410 RtbParams->S3DataBlock.VolatileStorage,
411 RtbParams->S3DataBlock.VolatileStorageSize))
412 printk(BIOS_ERR, "S3 data not saved, resuming impossible\n");
413
414 AmdReleaseStruct(&AmdParamStruct);
415
416 return Status;
417}
418
419AGESA_STATUS agesawrapper_amdinitresume(void)
420{
421 AGESA_STATUS status;
422 AMD_INTERFACE_PARAMS AmdParamStruct = {
423 .AgesaFunctionName = AMD_INIT_RESUME,
424 .AllocationMethod = PreMemHeap,
Marshall Dawsonc2f6da02017-12-04 15:28:10 -0700425 };
426 AMD_RESUME_PARAMS *InitResumeParams;
427 size_t nv_size;
428
429 if (!acpi_s3_resume_allowed())
430 return AGESA_UNSUPPORTED;
431
432 create_struct(&AmdParamStruct);
433
434 InitResumeParams = (AMD_RESUME_PARAMS *)AmdParamStruct.NewStructPtr;
435
436 get_s3nv_info(&InitResumeParams->S3DataBlock.NvStorage, &nv_size);
437 InitResumeParams->S3DataBlock.NvStorageSize = nv_size;
438
439 timestamp_add_now(TS_AGESA_INIT_RESUME_START);
440 status = AmdInitResume(InitResumeParams);
441 timestamp_add_now(TS_AGESA_INIT_RESUME_DONE);
442
443 if (status != AGESA_SUCCESS)
444 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
445 AmdReleaseStruct(&AmdParamStruct);
446
447 return status;
448}
449
450AGESA_STATUS agesawrapper_amds3laterestore(void)
451{
452 AGESA_STATUS Status;
453 AMD_INTERFACE_PARAMS AmdParamStruct = {
454 .AgesaFunctionName = AMD_S3LATE_RESTORE,
455 .AllocationMethod = ByHost,
Marshall Dawsonc2f6da02017-12-04 15:28:10 -0700456 };
457 AMD_S3LATE_PARAMS *S3LateParams;
458 size_t vol_size;
459
460 if (!acpi_s3_resume_allowed())
461 return AGESA_UNSUPPORTED;
462
463 amd_initcpuio();
464
465 create_struct(&AmdParamStruct);
466
467 S3LateParams = (AMD_S3LATE_PARAMS *)AmdParamStruct.NewStructPtr;
468
469 get_s3vol_info(&S3LateParams->S3DataBlock.VolatileStorage, &vol_size);
470 S3LateParams->S3DataBlock.VolatileStorageSize = vol_size;
471
472 timestamp_add_now(TS_AGESA_S3_LATE_START);
473 Status = AmdS3LateRestore(S3LateParams);
474 timestamp_add_now(TS_AGESA_S3_LATE_DONE);
475
476 if (Status != AGESA_SUCCESS) {
477 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
478 ASSERT(Status == AGESA_SUCCESS);
479 }
480 AmdReleaseStruct(&AmdParamStruct);
481
482 return Status;
483}
484
485AGESA_STATUS agesawrapper_amds3finalrestore(void)
486{
487 AGESA_STATUS Status;
488 AMD_INTERFACE_PARAMS AmdParamStruct = {
489 .AgesaFunctionName = AMD_S3FINAL_RESTORE,
490 .AllocationMethod = ByHost,
Marshall Dawsonc2f6da02017-12-04 15:28:10 -0700491 };
492 AMD_S3FINAL_PARAMS *S3FinalParams;
493 size_t vol_size;
494
495 if (!acpi_s3_resume_allowed())
496 return AGESA_UNSUPPORTED;
497
498 create_struct(&AmdParamStruct);
499
500 S3FinalParams = (AMD_S3FINAL_PARAMS *)AmdParamStruct.NewStructPtr;
501
502 get_s3vol_info(&S3FinalParams->S3DataBlock.VolatileStorage, &vol_size);
503 S3FinalParams->S3DataBlock.VolatileStorageSize = vol_size;
504
505 timestamp_add_now(TS_AGESA_S3_FINAL_START);
506 Status = AmdS3FinalRestore(S3FinalParams);
507 timestamp_add_now(TS_AGESA_S3_FINAL_DONE);
508
509 if (Status != AGESA_SUCCESS) {
510 agesawrapper_readeventlog(AmdParamStruct.StdHeader.HeapStatus);
511 ASSERT(Status == AGESA_SUCCESS);
512 }
513 AmdReleaseStruct(&AmdParamStruct);
514
515 return Status;
516}
517
Aaron Durbin02b43aa2017-12-12 14:56:41 -0700518static int agesa_locate_file(const char *name, struct region_device *rdev,
519 uint32_t type)
520{
521 struct cbfsf fh;
522
523 if (cbfs_boot_locate(&fh, name, &type))
524 return -1;
525
526 cbfs_file_data(rdev, &fh);
527 return 0;
528}
529
530static int agesa_locate_raw_file(const char *name, struct region_device *rdev)
531{
532 return agesa_locate_file(name, rdev, CBFS_TYPE_RAW);
533}
534
Aaron Durbin931ed7f2017-12-22 17:13:17 -0700535static int agesa_locate_stage_file_early(const char *name,
536 struct region_device *rdev)
Aaron Durbin02b43aa2017-12-12 14:56:41 -0700537{
538 const size_t metadata_sz = sizeof(struct cbfs_stage);
539
540 if (agesa_locate_file(name, rdev, CBFS_TYPE_STAGE))
541 return -1;
542
543 /* Peel off the cbfs stage metadata. */
544 return rdev_chain(rdev, rdev, metadata_sz,
545 region_device_sz(rdev) - metadata_sz);
546}
547
Aaron Durbin931ed7f2017-12-22 17:13:17 -0700548static int agesa_locate_stage_file_ramstage(const char *name,
549 struct region_device *rdev)
550{
551 struct prog prog = PROG_INIT(PROG_REFCODE, name);
552 struct rmod_stage_load rmod_agesa = {
553 .cbmem_id = CBMEM_ID_REFCODE,
554 .prog = &prog,
555 };
556
Raul E Rangel8af20c62018-05-11 11:08:08 -0600557 if (acpi_is_wakeup_s3() && !IS_ENABLED(CONFIG_NO_STAGE_CACHE)) {
558 printk(BIOS_INFO, "AGESA: Loading stage from cache\n");
559 // There is no way to tell if this succeeded.
560 stage_cache_load_stage(STAGE_REFCODE, &prog);
561 } else {
562 if (prog_locate(&prog))
563 return -1;
564
565 if (rmodule_stage_load(&rmod_agesa) < 0)
566 return -1;
567
568 if (!IS_ENABLED(CONFIG_NO_STAGE_CACHE)) {
569 printk(BIOS_INFO, "AGESA: Saving stage to cache\n");
570 stage_cache_add(STAGE_REFCODE, &prog);
571 }
572 }
Aaron Durbin931ed7f2017-12-22 17:13:17 -0700573
574 return rdev_chain(rdev, prog_rdev(&prog), 0,
575 region_device_sz(prog_rdev(&prog)));
576}
577
578static int agesa_locate_stage_file(const char *name, struct region_device *rdev)
579{
Daniel Kurtz462e4702018-01-05 15:40:52 -0700580 if (!ENV_RAMSTAGE || !IS_ENABLED(CONFIG_AGESA_SPLIT_MEMORY_FILES))
Aaron Durbin931ed7f2017-12-22 17:13:17 -0700581 return agesa_locate_stage_file_early(name, rdev);
582 return agesa_locate_stage_file_ramstage(name, rdev);
583}
584
Justin TerAvest92261952017-12-22 15:15:02 -0700585static const char *get_agesa_cbfs_name(void)
586{
587 if (!IS_ENABLED(CONFIG_AGESA_SPLIT_MEMORY_FILES))
588 return CONFIG_AGESA_CBFS_NAME;
589 if (!ENV_RAMSTAGE)
590 return CONFIG_AGESA_PRE_MEMORY_CBFS_NAME;
591 return CONFIG_AGESA_POST_MEMORY_CBFS_NAME;
592}
593
Marshall Dawson857a3872017-12-13 20:01:59 -0700594const void *agesawrapper_locate_module(const CHAR8 name[8])
Marc Jones1587dc82017-05-15 18:55:11 -0600595{
Richard Spiegelfc511272017-12-11 16:23:58 -0700596 const void *agesa;
597 const AMD_IMAGE_HEADER *image;
Aaron Durbin02b43aa2017-12-12 14:56:41 -0700598 struct region_device rdev;
Marc Jones1587dc82017-05-15 18:55:11 -0600599 size_t file_size;
Justin TerAvest92261952017-12-22 15:15:02 -0700600 const char *fname;
Aaron Durbin02b43aa2017-12-12 14:56:41 -0700601 int ret;
Marc Jones1587dc82017-05-15 18:55:11 -0600602
Justin TerAvest92261952017-12-22 15:15:02 -0700603 fname = get_agesa_cbfs_name();
604
Aaron Durbin02b43aa2017-12-12 14:56:41 -0700605 if (IS_ENABLED(CONFIG_AGESA_BINARY_PI_AS_STAGE))
606 ret = agesa_locate_stage_file(fname, &rdev);
607 else
608 ret = agesa_locate_raw_file(fname, &rdev);
609
610 if (ret)
611 return NULL;
612
613 file_size = region_device_sz(&rdev);
614
615 /* Assume boot device is memory mapped so the mapping can leak. */
616 assert(IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED));
617
618 agesa = rdev_mmap_full(&rdev);
Marc Jones1587dc82017-05-15 18:55:11 -0600619
620 if (!agesa)
621 return NULL;
Marc Jones1587dc82017-05-15 18:55:11 -0600622
Aaron Durbin02b43aa2017-12-12 14:56:41 -0700623 image = LibAmdLocateImage(agesa, agesa + file_size, 4096, name);
624
625 if (!image)
626 return NULL;
627
628 return (AMD_MODULE_HEADER *)image->ModuleInfoOffset;
Marc Jones1587dc82017-05-15 18:55:11 -0600629}
Aaron Durbina78319b2017-12-08 15:38:59 -0700630
631static MODULE_ENTRY agesa_dispatcher CAR_GLOBAL;
632
633MODULE_ENTRY agesa_get_dispatcher(void)
634{
635 const AMD_MODULE_HEADER *module;
636 static const CHAR8 id[8] = AGESA_ID;
637 MODULE_ENTRY val = car_get_var(agesa_dispatcher);
638
639 if (val != NULL)
640 return val;
641
642 module = agesawrapper_locate_module(id);
643 if (!module)
644 return NULL;
645
646 val = module->ModuleDispatcher;
647 car_set_var(agesa_dispatcher, val);
648
649 return val;
650}