blob: b1f03cb178dad4e53d90525324061a8d415277a8 [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.
Marc Jones1587dc82017-05-15 18:55:11 -06005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070016#include <amdblocks/agesawrapper.h>
Aaron Durbina78319b2017-12-08 15:38:59 -070017#include <arch/early_variables.h>
Marc Jones1587dc82017-05-15 18:55:11 -060018#include <cbfs.h>
19#include <cbmem.h>
20#include <delay.h>
21#include <cpu/x86/mtrr.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070022#include <amdblocks/BiosCallOuts.h>
Aaron Durbine3f7d442017-11-03 11:44:10 -060023#include <string.h>
Martin Rothbc5c3e72017-12-09 10:40:45 -070024#include <timestamp.h>
Marc Jones1587dc82017-05-15 18:55:11 -060025
Richard Spiegel67c2a7b2017-11-09 16:04:35 -070026void __attribute__((weak)) SetMemParams(AMD_POST_PARAMS *PostParams) {}
Marc Jones1587dc82017-05-15 18:55:11 -060027void __attribute__((weak)) OemPostParams(AMD_POST_PARAMS *PostParams) {}
28
Marc Jones1587dc82017-05-15 18:55:11 -060029#ifndef __PRE_RAM__
30/* ACPI table pointers returned by AmdInitLate */
Aaron Durbin8dd40062017-11-03 11:50:14 -060031static void *DmiTable;
32static void *AcpiPstate;
33static void *AcpiSrat;
34static void *AcpiSlit;
Marc Jones1587dc82017-05-15 18:55:11 -060035
Aaron Durbin8dd40062017-11-03 11:50:14 -060036static void *AcpiWheaMce;
37static void *AcpiWheaCmc;
38static void *AcpiAlib;
39static void *AcpiIvrs;
40static void *AcpiCrat;
Marc Jones1587dc82017-05-15 18:55:11 -060041#endif /* #ifndef __PRE_RAM__ */
42
43AGESA_STATUS agesawrapper_amdinitreset(void)
44{
45 AGESA_STATUS status;
46 AMD_INTERFACE_PARAMS AmdParamStruct;
47 AMD_RESET_PARAMS AmdResetParams;
48
Aaron Durbine3f7d442017-11-03 11:44:10 -060049 memset(&AmdParamStruct, 0, sizeof(AmdParamStruct));
50 memset(&AmdResetParams, 0, sizeof(AmdResetParams));
Marc Jones1587dc82017-05-15 18:55:11 -060051
52 AmdParamStruct.AgesaFunctionName = AMD_INIT_RESET;
53 AmdParamStruct.AllocationMethod = ByHost;
54 AmdParamStruct.NewStructSize = sizeof(AMD_RESET_PARAMS);
55 AmdParamStruct.NewStructPtr = &AmdResetParams;
56 AmdParamStruct.StdHeader.AltImageBasePtr = 0;
57 AmdParamStruct.StdHeader.CalloutPtr = &GetBiosCallout;
58 AmdParamStruct.StdHeader.Func = 0;
59 AmdParamStruct.StdHeader.ImageBasePtr = 0;
60 AmdCreateStruct (&AmdParamStruct);
61
62 AmdResetParams.FchInterface.Xhci0Enable = IS_ENABLED(CONFIG_STONEYRIDGE_XHCI_ENABLE);
63
64 AmdResetParams.FchInterface.SataEnable = !((CONFIG_STONEYRIDGE_SATA_MODE == 0) || (CONFIG_STONEYRIDGE_SATA_MODE == 3));
65 AmdResetParams.FchInterface.IdeEnable = (CONFIG_STONEYRIDGE_SATA_MODE == 0) || (CONFIG_STONEYRIDGE_SATA_MODE == 3);
66
Martin Rothbc5c3e72017-12-09 10:40:45 -070067 timestamp_add_now(TS_AGESA_INIT_RESET_START);
Marc Jones1587dc82017-05-15 18:55:11 -060068 status = AmdInitReset(&AmdResetParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -070069 timestamp_add_now(TS_AGESA_INIT_RESET_DONE);
70
Marc Jones1587dc82017-05-15 18:55:11 -060071 if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(AmdParamStruct.StdHeader.HeapStatus);
72 AmdReleaseStruct (&AmdParamStruct);
73 return status;
74}
75
76AGESA_STATUS agesawrapper_amdinitearly(void)
77{
78 AGESA_STATUS status;
79 AMD_INTERFACE_PARAMS AmdParamStruct;
80 AMD_EARLY_PARAMS *AmdEarlyParamsPtr;
81
Aaron Durbine3f7d442017-11-03 11:44:10 -060082 memset(&AmdParamStruct, 0, sizeof(AmdParamStruct));
Marc Jones1587dc82017-05-15 18:55:11 -060083
84 AmdParamStruct.AgesaFunctionName = AMD_INIT_EARLY;
85 AmdParamStruct.AllocationMethod = PreMemHeap;
86 AmdParamStruct.StdHeader.AltImageBasePtr = 0;
87 AmdParamStruct.StdHeader.CalloutPtr = &GetBiosCallout;
88 AmdParamStruct.StdHeader.Func = 0;
89 AmdParamStruct.StdHeader.ImageBasePtr = 0;
90 AmdCreateStruct (&AmdParamStruct);
91
92 AmdEarlyParamsPtr = (AMD_EARLY_PARAMS *)AmdParamStruct.NewStructPtr;
93 OemCustomizeInitEarly (AmdEarlyParamsPtr);
94
95 AmdEarlyParamsPtr->GnbConfig.PsppPolicy = PsppDisabled;
Martin Rothbc5c3e72017-12-09 10:40:45 -070096
97 timestamp_add_now(TS_AGESA_INIT_EARLY_START);
Marc Jones1587dc82017-05-15 18:55:11 -060098 status = AmdInitEarly ((AMD_EARLY_PARAMS *)AmdParamStruct.NewStructPtr);
Martin Rothbc5c3e72017-12-09 10:40:45 -070099 timestamp_add_now(TS_AGESA_INIT_EARLY_DONE);
Marc Jones1587dc82017-05-15 18:55:11 -0600100
101 if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(AmdParamStruct.StdHeader.HeapStatus);
102 AmdReleaseStruct (&AmdParamStruct);
103
104 return status;
105}
106
107AGESA_STATUS agesawrapper_amdinitpost(void)
108{
109 AGESA_STATUS status;
110 AMD_INTERFACE_PARAMS AmdParamStruct;
111 AMD_POST_PARAMS *PostParams;
112
Aaron Durbine3f7d442017-11-03 11:44:10 -0600113 memset(&AmdParamStruct, 0, sizeof(AmdParamStruct));
Marc Jones1587dc82017-05-15 18:55:11 -0600114
115 AmdParamStruct.AgesaFunctionName = AMD_INIT_POST;
116 AmdParamStruct.AllocationMethod = PreMemHeap;
Martin Roth29600432017-10-16 16:11:05 -0600117 AmdParamStruct.StdHeader.AltImageBasePtr = 0;
Marc Jones1587dc82017-05-15 18:55:11 -0600118 AmdParamStruct.StdHeader.CalloutPtr = &GetBiosCallout;
119 AmdParamStruct.StdHeader.Func = 0;
120 AmdParamStruct.StdHeader.ImageBasePtr = 0;
121
122 AmdCreateStruct (&AmdParamStruct);
123 PostParams = (AMD_POST_PARAMS *)AmdParamStruct.NewStructPtr;
124
Marc Jones1587dc82017-05-15 18:55:11 -0600125 PostParams->MemConfig.UmaMode = CONFIG_GFXUMA ? UMA_AUTO : UMA_NONE;
126 PostParams->MemConfig.UmaSize = 0;
127 PostParams->MemConfig.BottomIo = (UINT16)
128 (CONFIG_BOTTOMIO_POSITION >> 24);
129
Richard Spiegel67c2a7b2017-11-09 16:04:35 -0700130 SetMemParams(PostParams);
Marc Jones1587dc82017-05-15 18:55:11 -0600131 OemPostParams(PostParams);
Richard Spiegel67c2a7b2017-11-09 16:04:35 -0700132 printk(BIOS_SPEW, "DRAM clear on reset: %s\n",
133 (PostParams->MemConfig.EnableMemClr == FALSE) ? "Keep" :
134 (PostParams->MemConfig.EnableMemClr == TRUE) ? "Clear" :
135 "unknown"
136 );
Marc Jones1587dc82017-05-15 18:55:11 -0600137
Martin Rothbc5c3e72017-12-09 10:40:45 -0700138 timestamp_add_now(TS_AGESA_INIT_POST_START);
Marc Jones1587dc82017-05-15 18:55:11 -0600139 status = AmdInitPost (PostParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700140 timestamp_add_now(TS_AGESA_INIT_POST_DONE);
Marc Jones1587dc82017-05-15 18:55:11 -0600141
142 /* If UMA is enabled we currently have it below TOP_MEM as well.
143 * UMA may or may not be cacheable, so Sub4GCacheTop could be
144 * higher than UmaBase. With UMA_NONE we see UmaBase==0. */
145 if (PostParams->MemConfig.UmaBase)
146 backup_top_of_low_cacheable(PostParams->MemConfig.UmaBase << 16);
147 else
148 backup_top_of_low_cacheable(PostParams->MemConfig.Sub4GCacheTop);
149
150
151 printk(
152 BIOS_SPEW,
153 "setup_uma_memory: umamode %s\n",
154 (PostParams->MemConfig.UmaMode == UMA_AUTO) ? "UMA_AUTO" :
155 (PostParams->MemConfig.UmaMode == UMA_SPECIFIED) ? "UMA_SPECIFIED" :
156 (PostParams->MemConfig.UmaMode == UMA_NONE) ? "UMA_NONE" :
157 "unknown"
158 );
159 printk(
160 BIOS_SPEW,
161 "setup_uma_memory: syslimit 0x%08llX, bottomio 0x%08lx\n",
162 (unsigned long long)(PostParams->MemConfig.SysLimit) << 16,
163 (unsigned long)(PostParams->MemConfig.BottomIo) << 16
164 );
165 printk(
166 BIOS_SPEW,
167 "setup_uma_memory: uma size %luMB, uma start 0x%08lx\n",
168 (unsigned long)(PostParams->MemConfig.UmaSize) >> (20 - 16),
169 (unsigned long)(PostParams->MemConfig.UmaBase) << 16
170 );
171
172 if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(PostParams->StdHeader.HeapStatus);
173 AmdReleaseStruct (&AmdParamStruct);
Marc Jones1587dc82017-05-15 18:55:11 -0600174
175 return status;
176}
177
178AGESA_STATUS agesawrapper_amdinitenv(void)
179{
180 AGESA_STATUS status;
181 AMD_INTERFACE_PARAMS AmdParamStruct;
182 AMD_ENV_PARAMS *EnvParam;
183
Aaron Durbine3f7d442017-11-03 11:44:10 -0600184 memset(&AmdParamStruct, 0, sizeof(AmdParamStruct));
Marc Jones1587dc82017-05-15 18:55:11 -0600185
186 AmdParamStruct.AgesaFunctionName = AMD_INIT_ENV;
187 AmdParamStruct.AllocationMethod = PostMemDram;
188 AmdParamStruct.StdHeader.AltImageBasePtr = 0;
189 AmdParamStruct.StdHeader.CalloutPtr = &GetBiosCallout;
190 AmdParamStruct.StdHeader.Func = 0;
191 AmdParamStruct.StdHeader.ImageBasePtr = 0;
192 status = AmdCreateStruct (&AmdParamStruct);
193 EnvParam = (AMD_ENV_PARAMS *)AmdParamStruct.NewStructPtr;
194
195 EnvParam->FchInterface.AzaliaController = AzEnable;
196 EnvParam->FchInterface.SataClass = CONFIG_STONEYRIDGE_SATA_MODE;
197 EnvParam->FchInterface.SataEnable = !((CONFIG_STONEYRIDGE_SATA_MODE == 0) || (CONFIG_STONEYRIDGE_SATA_MODE == 3));
198 EnvParam->FchInterface.IdeEnable = (CONFIG_STONEYRIDGE_SATA_MODE == 0) || (CONFIG_STONEYRIDGE_SATA_MODE == 3);
199 EnvParam->FchInterface.SataIdeMode = (CONFIG_STONEYRIDGE_SATA_MODE == 3);
200 EnvParam->GnbEnvConfiguration.IommuSupport = FALSE;
201
Martin Rothbc5c3e72017-12-09 10:40:45 -0700202 timestamp_add_now(TS_AGESA_INIT_ENV_START);
Marc Jones1587dc82017-05-15 18:55:11 -0600203 status = AmdInitEnv (EnvParam);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700204 timestamp_add_now(TS_AGESA_INIT_ENV_DONE);
205
Marc Jones1587dc82017-05-15 18:55:11 -0600206 if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(EnvParam->StdHeader.HeapStatus);
207 /* Initialize Subordinate Bus Number and Secondary Bus Number
208 * In platform BIOS this address is allocated by PCI enumeration code
209 Modify D1F0x18
210 */
211
212 return status;
213}
214
215#ifndef __PRE_RAM__
216VOID* agesawrapper_getlateinitptr (int pick)
217{
218 switch (pick) {
219 case PICK_DMI:
220 return DmiTable;
221 case PICK_PSTATE:
222 return AcpiPstate;
223 case PICK_SRAT:
224 return AcpiSrat;
225 case PICK_SLIT:
226 return AcpiSlit;
227 case PICK_WHEA_MCE:
228 return AcpiWheaMce;
229 case PICK_WHEA_CMC:
230 return AcpiWheaCmc;
231 case PICK_ALIB:
232 return AcpiAlib;
233 case PICK_IVRS:
234 return AcpiIvrs;
235 case PICK_CRAT:
236 return AcpiCrat;
237 default:
238 return NULL;
239 }
240}
241#endif /* #ifndef __PRE_RAM__ */
242
243AGESA_STATUS agesawrapper_amdinitmid(void)
244{
245 AGESA_STATUS status;
246 AMD_INTERFACE_PARAMS AmdParamStruct;
247 AMD_MID_PARAMS *MidParam;
248
249 /* Enable MMIO on AMD CPU Address Map Controller */
250 amd_initcpuio ();
251
Aaron Durbine3f7d442017-11-03 11:44:10 -0600252 memset(&AmdParamStruct, 0, sizeof(AmdParamStruct));
Marc Jones1587dc82017-05-15 18:55:11 -0600253
254 AmdParamStruct.AgesaFunctionName = AMD_INIT_MID;
255 AmdParamStruct.AllocationMethod = PostMemDram;
256 AmdParamStruct.StdHeader.AltImageBasePtr = 0;
257 AmdParamStruct.StdHeader.CalloutPtr = &GetBiosCallout;
258 AmdParamStruct.StdHeader.Func = 0;
259 AmdParamStruct.StdHeader.ImageBasePtr = 0;
260
261 AmdCreateStruct (&AmdParamStruct);
262 MidParam = (AMD_MID_PARAMS *)AmdParamStruct.NewStructPtr;
263
264 MidParam->GnbMidConfiguration.iGpuVgaMode = 0;/* 0 iGpuVgaAdapter, 1 iGpuVgaNonAdapter; */
265 MidParam->GnbMidConfiguration.GnbIoapicAddress = 0xFEC20000;
266
267 MidParam->FchInterface.AzaliaController = AzEnable;
268 MidParam->FchInterface.SataClass = CONFIG_STONEYRIDGE_SATA_MODE;
269 MidParam->FchInterface.SataEnable = !((CONFIG_STONEYRIDGE_SATA_MODE == 0) || (CONFIG_STONEYRIDGE_SATA_MODE == 3));
270 MidParam->FchInterface.IdeEnable = (CONFIG_STONEYRIDGE_SATA_MODE == 0) || (CONFIG_STONEYRIDGE_SATA_MODE == 3);
271 MidParam->FchInterface.SataIdeMode = (CONFIG_STONEYRIDGE_SATA_MODE == 3);
272
Martin Rothbc5c3e72017-12-09 10:40:45 -0700273 timestamp_add_now(TS_AGESA_INIT_MID_START);
Marc Jones1587dc82017-05-15 18:55:11 -0600274 status = AmdInitMid ((AMD_MID_PARAMS *)AmdParamStruct.NewStructPtr);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700275 timestamp_add_now(TS_AGESA_INIT_MID_DONE);
276
Marc Jones1587dc82017-05-15 18:55:11 -0600277 if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(AmdParamStruct.StdHeader.HeapStatus);
278 AmdReleaseStruct (&AmdParamStruct);
279
280 return status;
281}
282
283#ifndef __PRE_RAM__
284AGESA_STATUS agesawrapper_amdinitlate(void)
285{
286 AGESA_STATUS Status;
287 AMD_INTERFACE_PARAMS AmdParamStruct;
288 AMD_LATE_PARAMS *AmdLateParams;
289
Aaron Durbine3f7d442017-11-03 11:44:10 -0600290 memset(&AmdParamStruct, 0, sizeof(AmdParamStruct));
Marc Jones1587dc82017-05-15 18:55:11 -0600291
292 AmdParamStruct.AgesaFunctionName = AMD_INIT_LATE;
293 AmdParamStruct.AllocationMethod = PostMemDram;
294 AmdParamStruct.StdHeader.AltImageBasePtr = 0;
295 AmdParamStruct.StdHeader.CalloutPtr = &GetBiosCallout;
296 AmdParamStruct.StdHeader.HeapStatus = HEAP_SYSTEM_MEM;
297 AmdParamStruct.StdHeader.Func = 0;
298 AmdParamStruct.StdHeader.ImageBasePtr = 0;
299
300 /* NOTE: if not call amdcreatestruct, the initializer(AmdInitLateInitializer) would not be called */
301 AmdCreateStruct(&AmdParamStruct);
302 AmdLateParams = (AMD_LATE_PARAMS *)AmdParamStruct.NewStructPtr;
Martin Rothbc5c3e72017-12-09 10:40:45 -0700303
304 timestamp_add_now(TS_AGESA_INIT_LATE_START);
Marc Jones1587dc82017-05-15 18:55:11 -0600305 Status = AmdInitLate(AmdLateParams);
Martin Rothbc5c3e72017-12-09 10:40:45 -0700306 timestamp_add_now(TS_AGESA_INIT_LATE_DONE);
307
Marc Jones1587dc82017-05-15 18:55:11 -0600308 if (Status != AGESA_SUCCESS) {
309 agesawrapper_amdreadeventlog(AmdLateParams->StdHeader.HeapStatus);
310 ASSERT(Status == AGESA_SUCCESS);
311 }
312
313 DmiTable = AmdLateParams->DmiTable;
314 AcpiPstate = AmdLateParams->AcpiPState;
315
316 AcpiWheaMce = AmdLateParams->AcpiWheaMce;
317 AcpiWheaCmc = AmdLateParams->AcpiWheaCmc;
318 AcpiAlib = AmdLateParams->AcpiAlib;
319 AcpiIvrs = AmdLateParams->AcpiIvrs;
320 AcpiCrat = AmdLateParams->AcpiCrat;
321
322 printk(BIOS_DEBUG, "DmiTable:%x, AcpiPstatein: %x, AcpiSrat:%x,"
323 "AcpiSlit:%x, Mce:%x, Cmc:%x,"
324 "Alib:%x, AcpiIvrs:%x in %s\n",
325 (unsigned int)DmiTable, (unsigned int)AcpiPstate, (unsigned int)AcpiSrat,
326 (unsigned int)AcpiSlit, (unsigned int)AcpiWheaMce, (unsigned int)AcpiWheaCmc,
327 (unsigned int)AcpiAlib, (unsigned int)AcpiIvrs, __func__);
328
329 /* AmdReleaseStruct (&AmdParamStruct); */
330 return Status;
331}
332#endif /* #ifndef __PRE_RAM__ */
333
334AGESA_STATUS agesawrapper_amdlaterunaptask (
335 UINT32 Func,
Stefan Reinauer8d29dd12017-06-26 14:30:39 -0700336 UINTN Data,
Marc Jones1587dc82017-05-15 18:55:11 -0600337 VOID *ConfigPtr
338 )
339{
340 AGESA_STATUS Status;
341 AP_EXE_PARAMS ApExeParams;
342
Aaron Durbine3f7d442017-11-03 11:44:10 -0600343 memset(&ApExeParams, 0, sizeof(ApExeParams));
Marc Jones1587dc82017-05-15 18:55:11 -0600344
345 ApExeParams.StdHeader.AltImageBasePtr = 0;
346 ApExeParams.StdHeader.CalloutPtr = &GetBiosCallout;
347 ApExeParams.StdHeader.Func = 0;
348 ApExeParams.StdHeader.ImageBasePtr = 0;
349 ApExeParams.FunctionNumber = Func;
350 ApExeParams.RelatedDataBlock = ConfigPtr;
351
352 Status = AmdLateRunApTask (&ApExeParams);
353 if (Status != AGESA_SUCCESS) {
354 /* agesawrapper_amdreadeventlog(); */
355 ASSERT(Status == AGESA_SUCCESS);
356 }
357
358 return Status;
359}
360
361AGESA_STATUS agesawrapper_amdreadeventlog (UINT8 HeapStatus)
362{
363 AGESA_STATUS Status;
364 EVENT_PARAMS AmdEventParams;
365
Aaron Durbine3f7d442017-11-03 11:44:10 -0600366 memset(&AmdEventParams, 0, sizeof(AmdEventParams));
Marc Jones1587dc82017-05-15 18:55:11 -0600367
368 AmdEventParams.StdHeader.AltImageBasePtr = 0;
369 AmdEventParams.StdHeader.CalloutPtr = &GetBiosCallout;
370 AmdEventParams.StdHeader.Func = 0;
371 AmdEventParams.StdHeader.ImageBasePtr = 0;
372 AmdEventParams.StdHeader.HeapStatus = HeapStatus;
373 Status = AmdReadEventLog (&AmdEventParams);
374 while (AmdEventParams.EventClass != 0) {
375 printk(BIOS_DEBUG,"\nEventLog: EventClass = %x, EventInfo = %x.\n", (unsigned int)AmdEventParams.EventClass,(unsigned int)AmdEventParams.EventInfo);
376 printk(BIOS_DEBUG," Param1 = %x, Param2 = %x.\n",(unsigned int)AmdEventParams.DataParam1, (unsigned int)AmdEventParams.DataParam2);
377 printk(BIOS_DEBUG," Param3 = %x, Param4 = %x.\n",(unsigned int)AmdEventParams.DataParam3, (unsigned int)AmdEventParams.DataParam4);
378 Status = AmdReadEventLog (&AmdEventParams);
379 }
380
381 return Status;
382}
383
384const void *agesawrapper_locate_module (const CHAR8 name[8])
385{
386 const void* agesa;
387 const AMD_IMAGE_HEADER* image;
388 const AMD_MODULE_HEADER* module;
389 size_t file_size;
390
Marshall Dawson3191e0f2017-10-12 15:57:19 -0600391 agesa = cbfs_boot_map_with_leak((const char *)CONFIG_AGESA_CBFS_NAME,
392 CBFS_TYPE_RAW, &file_size);
Marc Jones1587dc82017-05-15 18:55:11 -0600393
394 if (!agesa)
395 return NULL;
396 image = LibAmdLocateImage(agesa, agesa + file_size - 1, 4096, name);
397 module = (AMD_MODULE_HEADER*)image->ModuleInfoOffset;
398
399 return module;
400}
Aaron Durbina78319b2017-12-08 15:38:59 -0700401
402static MODULE_ENTRY agesa_dispatcher CAR_GLOBAL;
403
404MODULE_ENTRY agesa_get_dispatcher(void)
405{
406 const AMD_MODULE_HEADER *module;
407 static const CHAR8 id[8] = AGESA_ID;
408 MODULE_ENTRY val = car_get_var(agesa_dispatcher);
409
410 if (val != NULL)
411 return val;
412
413 module = agesawrapper_locate_module(id);
414 if (!module)
415 return NULL;
416
417 val = module->ModuleDispatcher;
418 car_set_var(agesa_dispatcher, val);
419
420 return val;
421}