blob: 577ff148524ae081e0da5b47b227039c828f4157 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * AMD Hob Transfer functions.
6 *
7 * Contains code that copy Heap to temp memory or main memory.
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: CPU
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 */
15/*
16 ******************************************************************************
17 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080018 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
19 * All rights reserved.
zbao7d94cf92012-07-02 14:19:14 +080020 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080021 * 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.
zbao7d94cf92012-07-02 14:19:14 +080031 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080032 * 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.
zbao7d94cf92012-07-02 14:19:14 +080042 ******************************************************************************
43 */
44
45/*----------------------------------------------------------------------------------------
46 * M O D U L E S U S E D
47 *----------------------------------------------------------------------------------------
48 */
49
50#include "AGESA.h"
51#include "amdlib.h"
52#include "Ids.h"
53#include "cpuRegisters.h"
54#include "GeneralServices.h"
55#include "cpuServices.h"
56#include "cpuCacheInit.h"
57#include "cpuFamilyTranslation.h"
58#include "heapManager.h"
59#include "cpuLateInit.h"
60#include "Filecode.h"
61CODE_GROUP (G1_PEICC)
62RDATA_GROUP (G1_PEICC)
63
64#define FILECODE LEGACY_PROC_HOBTRANSFER_FILECODE
65/*----------------------------------------------------------------------------------------
66 * D E F I N I T I O N S A N D M A C R O S
67 *----------------------------------------------------------------------------------------
68 */
69
70/*----------------------------------------------------------------------------------------
71 * T Y P E D E F S A N D S T R U C T U R E S
72 *----------------------------------------------------------------------------------------
73 */
74
75
76/*----------------------------------------------------------------------------------------
77 * 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
78 *----------------------------------------------------------------------------------------
79 */
80
81/*----------------------------------------------------------------------------------------
82 * P U B L I C F U N C T I O N S
83 *----------------------------------------------------------------------------------------
84 */
85
86/*----------------------------------------------------------------------------------------
87 * E X P O R T E D F U N C T I O N S
88 *----------------------------------------------------------------------------------------
89 */
90extern BUILD_OPT_CFG UserOptions;
91
92/* -----------------------------------------------------------------------------*/
93/**
94 *
95 * CopyHeapToTempRamAtPost
96 *
97 * This function copies BSP heap content to RAM
98 *
99 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
100 *
101 * @retval AGESA_STATUS
102 *
103 */
104AGESA_STATUS
105CopyHeapToTempRamAtPost (
106 IN OUT AMD_CONFIG_PARAMS *StdHeader
107 )
108{
109 UINT8 *BaseAddressInCache;
110 UINT8 *BaseAddressInTempMem;
111 UINT8 *Source;
112 UINT8 *Destination;
113 UINT8 AlignTo16ByteInCache;
114 UINT8 AlignTo16ByteInTempMem;
115 UINT8 Ignored;
116 UINT32 SizeOfNodeData;
117 UINT32 TotalSize;
118 UINT32 HeapRamFixMtrr;
119 UINT32 HeapRamVariableMtrr;
120 UINT32 HeapInCacheOffset;
121 UINT64 MsrData;
122 UINT64 VariableMtrrBase;
123 UINT64 VariableMtrrMask;
124 UINTN AmdHeapRamAddress;
125 AGESA_STATUS IgnoredStatus;
126 BUFFER_NODE *HeapInCache;
127 BUFFER_NODE *HeapInTempMem;
128 HEAP_MANAGER *HeapManagerInCache;
129 HEAP_MANAGER *HeapManagerInTempMem;
130 CACHE_INFO *CacheInfoPtr;
131 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
132
133 AmdHeapRamAddress = (UINTN) UserOptions.CfgHeapDramAddress;
134 //
135 //If the user define address above 1M, Mem Init has already set
136 //whole available memory as WB cacheable.
137 //
138 if (AmdHeapRamAddress < 0x100000) {
139 // Region below 1MB
Paul Menzel2e0d9442014-01-25 15:59:31 +0100140 // Fixed MTRR region
zbao7d94cf92012-07-02 14:19:14 +0800141 // turn on modification bit
142 LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
143 MsrData |= 0x80000;
144 LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
145
146 if (AmdHeapRamAddress >= 0xC0000) {
147 //
148 // 0xC0000 ~ 0xFFFFF
149 //
Stefan Reinauerd91ddc82015-07-30 11:17:40 -0700150 HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX4k_C0000 + ((((UINTN)AmdHeapRamAddress >> 16) & 0x3) * 2));
zbao7d94cf92012-07-02 14:19:14 +0800151 MsrData = AMD_MTRR_FIX4K_UC_DRAM;
152 LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader);
153 LibAmdMsrWrite ((HeapRamFixMtrr + 1), &MsrData, StdHeader);
154 } else if (AmdHeapRamAddress >= 0x80000) {
155 //
156 // 0x80000~0xBFFFF
157 //
Stefan Reinauerd91ddc82015-07-30 11:17:40 -0700158 HeapRamFixMtrr = (UINT32) (AMD_MTRR_FIX16k_80000 + (((UINTN)AmdHeapRamAddress >> 17) & 0x1));
zbao7d94cf92012-07-02 14:19:14 +0800159 MsrData = AMD_MTRR_FIX16K_UC_DRAM;
160 LibAmdMsrWrite (HeapRamFixMtrr, &MsrData, StdHeader);
161 } else {
162 //
163 // 0x0 ~ 0x7FFFF
164 //
165 LibAmdMsrRead (AMD_MTRR_FIX64k_00000, &MsrData, StdHeader);
166 MsrData = MsrData & (~(0xFF << (8 * ((AmdHeapRamAddress >> 16) & 0x7))));
Stefan Reinauerd91ddc82015-07-30 11:17:40 -0700167 MsrData = MsrData | (AMD_MTRR_FIX64K_UC_DRAM << (8 * (((UINTN)AmdHeapRamAddress >> 16) & 0x7)));
zbao7d94cf92012-07-02 14:19:14 +0800168 LibAmdMsrWrite (AMD_MTRR_FIX64k_00000, &MsrData, StdHeader);
169 }
170
Paul Menzel2e0d9442014-01-25 15:59:31 +0100171 // Turn on MTRR enable bit and turn off modification bit
zbao7d94cf92012-07-02 14:19:14 +0800172 LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
173 MsrData |= 0x40000;
174 MsrData &= 0xFFFFFFFFFFF7FFFF;
175 LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
176 } else {
177 // Region above 1MB
Paul Menzel2e0d9442014-01-25 15:59:31 +0100178 // Variable MTRR region
zbao7d94cf92012-07-02 14:19:14 +0800179 // Get family specific cache Info
180 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
181 FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader);
182
183 // Find an empty MTRRphysBase/MTRRphysMask
184 for (HeapRamVariableMtrr = AMD_MTRR_VARIABLE_HEAP_BASE;
185 HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0;
186 HeapRamVariableMtrr--) {
187 LibAmdMsrRead (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
188 LibAmdMsrRead ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
189 if ((VariableMtrrBase == 0) && (VariableMtrrMask == 0)) {
190 break;
191 }
192 }
193 if (HeapRamVariableMtrr < AMD_MTRR_VARIABLE_BASE0) {
194 // All variable MTRR is used.
195 ASSERT (FALSE);
196 }
197
198 // Set variable MTRR base and mask
199 // If the address ranges of two or more MTRRs overlap
200 // and if at least one of the memory types is UC, the UC memory type is used.
201 VariableMtrrBase = (UINT64) (AmdHeapRamAddress & CacheInfoPtr->HeapBaseMask);
202 VariableMtrrMask = CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK;
203 LibAmdMsrWrite (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
204 LibAmdMsrWrite ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
205 }
206 // Copying Heap content
207 if (IsBsp (StdHeader, &IgnoredStatus)) {
208 TotalSize = sizeof (HEAP_MANAGER);
209 SizeOfNodeData = 0;
210 AlignTo16ByteInTempMem = 0;
Stefan Reinauerd91ddc82015-07-30 11:17:40 -0700211 BaseAddressInCache = (UINT8 *) (UINTN)StdHeader->HeapBasePtr;
zbao7d94cf92012-07-02 14:19:14 +0800212 HeapManagerInCache = (HEAP_MANAGER *) BaseAddressInCache;
213 HeapInCacheOffset = HeapManagerInCache->FirstActiveBufferOffset;
214 HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset);
215
216 BaseAddressInTempMem = (UINT8 *) (UINTN) UserOptions.CfgHeapDramAddress;
217 HeapManagerInTempMem = (HEAP_MANAGER *) BaseAddressInTempMem;
218 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
219
220 // copy heap from cache to temp memory.
221 // only heap with persist great than HEAP_LOCAL_CACHE will be copied.
222 // Note: Only copy heap with persist greater than HEAP_LOCAL_CACHE.
223 while (HeapInCacheOffset != AMD_HEAP_INVALID_HEAP_OFFSET) {
224 if (HeapInCache->Persist > HEAP_LOCAL_CACHE) {
225 AlignTo16ByteInCache = HeapInCache->PadSize;
226 AlignTo16ByteInTempMem = (UINT8) ((0x10 - (((UINTN) (VOID *) HeapInTempMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF);
227 SizeOfNodeData = HeapInCache->BufferSize - AlignTo16ByteInCache;
228 TotalSize = (UINT32) (TotalSize + sizeof (BUFFER_NODE) + SizeOfNodeData + AlignTo16ByteInTempMem);
229 Source = (UINT8 *) HeapInCache + sizeof (BUFFER_NODE) + AlignTo16ByteInCache;
230 Destination = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE) + AlignTo16ByteInTempMem;
231 LibAmdMemCopy (HeapInTempMem, HeapInCache, sizeof (BUFFER_NODE), StdHeader);
232 LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader);
233 HeapInTempMem->OffsetOfNextNode = TotalSize;
234 HeapInTempMem->BufferSize = SizeOfNodeData + AlignTo16ByteInTempMem;
235 HeapInTempMem->PadSize = AlignTo16ByteInTempMem;
236 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
237 }
238 HeapInCacheOffset = HeapInCache->OffsetOfNextNode;
239 HeapInCache = (BUFFER_NODE *) (BaseAddressInCache + HeapInCacheOffset);
240 }
241 // initialize heap manager
242 if (TotalSize == sizeof (HEAP_MANAGER)) {
243 // heap is empty
244 HeapManagerInTempMem->UsedSize = sizeof (HEAP_MANAGER);
245 HeapManagerInTempMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
246 HeapManagerInTempMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
247 } else {
248 // heap is NOT empty
249 HeapManagerInTempMem->UsedSize = TotalSize;
250 HeapManagerInTempMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER);
251 HeapManagerInTempMem->FirstFreeSpaceOffset = TotalSize;
252 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize - SizeOfNodeData - AlignTo16ByteInTempMem - sizeof (BUFFER_NODE));
253 HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
254 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + TotalSize);
255 }
256 // heap signature
257 HeapManagerInCache->Signature = 0x00000000;
258 HeapManagerInTempMem->Signature = HEAP_SIGNATURE_VALID;
259 // Free space node
260 HeapInTempMem->BufferSize = (UINT32) (AMD_HEAP_SIZE_PER_CORE - TotalSize);
261 HeapInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
262 }
263 return AGESA_SUCCESS;
264}
265
266
267/* -----------------------------------------------------------------------------*/
268/**
269 *
270 * CopyHeapToMainRamAtPost
271 *
272 * This function copies Temp Ram heap content to Main Ram
273 *
274 * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
275 *
276 * @retval AGESA_STATUS
277 *
278 */
279AGESA_STATUS
280CopyHeapToMainRamAtPost (
281 IN OUT AMD_CONFIG_PARAMS *StdHeader
282 )
283{
284 UINT8 *BaseAddressInTempMem;
285 UINT8 *BaseAddressInMainMem;
286 UINT8 *Source;
287 UINT8 *Destination;
288 UINT8 AlignTo16ByteInTempMem;
289 UINT8 AlignTo16ByteInMainMem;
290 UINT8 Ignored;
291 UINT32 SizeOfNodeData;
292 UINT32 TotalSize;
293 UINT32 HeapInTempMemOffset;
294 UINT32 HeapRamVariableMtrr;
295 UINT64 VariableMtrrBase;
296 UINT64 VariableMtrrMask;
297 AGESA_STATUS IgnoredStatus;
298 BUFFER_NODE *HeapInTempMem;
299 BUFFER_NODE *HeapInMainMem;
300 HEAP_MANAGER *HeapManagerInTempMem;
301 HEAP_MANAGER *HeapManagerInMainMem;
302 AGESA_BUFFER_PARAMS AgesaBuffer;
303 CACHE_INFO *CacheInfoPtr;
304 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
305
306 if (IsBsp (StdHeader, &IgnoredStatus)) {
307 TotalSize = sizeof (HEAP_MANAGER);
308 SizeOfNodeData = 0;
309 AlignTo16ByteInMainMem = 0;
Stefan Reinauerd91ddc82015-07-30 11:17:40 -0700310 BaseAddressInTempMem = (UINT8 *)(UINTN) StdHeader->HeapBasePtr;
311 HeapManagerInTempMem = (HEAP_MANAGER *)(UINTN) StdHeader->HeapBasePtr;
zbao7d94cf92012-07-02 14:19:14 +0800312 HeapInTempMemOffset = HeapManagerInTempMem->FirstActiveBufferOffset;
313 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset);
314
315 AgesaBuffer.StdHeader = *StdHeader;
316 AgesaBuffer.BufferHandle = AMD_HEAP_IN_MAIN_MEMORY_HANDLE;
317 AgesaBuffer.BufferLength = AMD_HEAP_SIZE_PER_CORE;
318 if (AgesaAllocateBuffer (0, &AgesaBuffer) != AGESA_SUCCESS) {
319 return AGESA_ERROR;
320 }
321 BaseAddressInMainMem = (UINT8 *) AgesaBuffer.BufferPointer;
322 HeapManagerInMainMem = (HEAP_MANAGER *) BaseAddressInMainMem;
323 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize);
324 LibAmdMemFill (BaseAddressInMainMem, 0x00, AMD_HEAP_SIZE_PER_CORE, StdHeader);
325 // copy heap from temp memory to main memory.
326 // only heap with persist great than HEAP_TEMP_MEM will be copied.
327 // Note: Only copy heap buffers with persist greater than HEAP_TEMP_MEM.
328 while (HeapInTempMemOffset != AMD_HEAP_INVALID_HEAP_OFFSET) {
329 if (HeapInTempMem->Persist > HEAP_TEMP_MEM) {
330 AlignTo16ByteInTempMem = HeapInTempMem->PadSize;
331 AlignTo16ByteInMainMem = (UINT8) ((0x10 - (((UINTN) (VOID *) HeapInMainMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF);
332 SizeOfNodeData = HeapInTempMem->BufferSize - AlignTo16ByteInTempMem;
333 TotalSize = (UINT32) (TotalSize + sizeof (BUFFER_NODE) + SizeOfNodeData + AlignTo16ByteInMainMem);
334 Source = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE) + AlignTo16ByteInTempMem;
335 Destination = (UINT8 *) HeapInMainMem + sizeof (BUFFER_NODE) + AlignTo16ByteInMainMem;
336 LibAmdMemCopy (HeapInMainMem, HeapInTempMem, sizeof (BUFFER_NODE), StdHeader);
337 LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader);
338 HeapInMainMem->OffsetOfNextNode = TotalSize;
339 HeapInMainMem->BufferSize = SizeOfNodeData + AlignTo16ByteInMainMem;
340 HeapInMainMem->PadSize = AlignTo16ByteInMainMem;
341 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize);
342 }
343 HeapInTempMemOffset = HeapInTempMem->OffsetOfNextNode;
344 HeapInTempMem = (BUFFER_NODE *) (BaseAddressInTempMem + HeapInTempMemOffset);
345 }
346 // initialize heap manager
347 if (TotalSize == sizeof (HEAP_MANAGER)) {
348 // heap is empty
349 HeapManagerInMainMem->UsedSize = sizeof (HEAP_MANAGER);
350 HeapManagerInMainMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
351 HeapManagerInMainMem->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
352 } else {
353 // heap is NOT empty
354 HeapManagerInMainMem->UsedSize = TotalSize;
355 HeapManagerInMainMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER);
356 HeapManagerInMainMem->FirstFreeSpaceOffset = TotalSize;
357 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize - SizeOfNodeData - AlignTo16ByteInMainMem - sizeof (BUFFER_NODE));
358 HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
359 HeapInMainMem = (BUFFER_NODE *) (BaseAddressInMainMem + TotalSize);
360 }
361 // heap signature
362 HeapManagerInTempMem->Signature = 0x00000000;
363 HeapManagerInMainMem->Signature = HEAP_SIGNATURE_VALID;
364 // Free space node
365 HeapInMainMem->BufferSize = AMD_HEAP_SIZE_PER_CORE - TotalSize;
366 HeapInMainMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
367 }
368 // if address of heap in temp memory is above 1M, then we must used one variable MTRR.
369 if ( (UINTN) StdHeader->HeapBasePtr >= 0x100000) {
370 // Find out which variable MTRR was used in CopyHeapToTempRamAtPost.
371 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
372 FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader);
373 for (HeapRamVariableMtrr = AMD_MTRR_VARIABLE_HEAP_BASE;
374 HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0;
375 HeapRamVariableMtrr--) {
376 LibAmdMsrRead (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
377 LibAmdMsrRead ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
378 if ((VariableMtrrBase == (UINT64) (UINTN) (StdHeader->HeapBasePtr & CacheInfoPtr->HeapBaseMask)) &&
379 (VariableMtrrMask == (UINT64) (CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK))) {
380 break;
381 }
382 }
383 if (HeapRamVariableMtrr >= AMD_MTRR_VARIABLE_BASE0) {
384 // Clear variable MTRR which set in CopyHeapToTempRamAtPost.
385 VariableMtrrBase = 0;
386 VariableMtrrMask = 0;
387 LibAmdMsrWrite (HeapRamVariableMtrr, &VariableMtrrBase, StdHeader);
388 LibAmdMsrWrite ((HeapRamVariableMtrr + 1), &VariableMtrrMask, StdHeader);
389 }
390 }
391 return AGESA_SUCCESS;
392}