]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c
OvmfPkg: Increase default RELEASE build image size to 2MB
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Pei / PlatformInit / MrcWrapper.c
CommitLineData
b303605e
MK
1/** @file\r
2Framework PEIM to initialize memory on a Quark Memory Controller.\r
3\r
4Copyright (c) 2013 Intel Corporation.\r
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "CommonHeader.h"\r
17#include "MrcWrapper.h"\r
18#include <Ioh.h>\r
19#include "Platform.h"\r
20\r
21#include <Library/PlatformHelperLib.h>\r
22\r
23//\r
24// ------------------------ TSEG Base\r
25//\r
26// ------------------------ RESERVED_CPU_S3_SAVE_OFFSET\r
27// CPU S3 data\r
28// ------------------------ RESERVED_ACPI_S3_RANGE_OFFSET\r
29// S3 Memory base structure\r
30// ------------------------ TSEG + 1 page\r
31\r
32#define RESERVED_CPU_S3_SAVE_OFFSET (RESERVED_ACPI_S3_RANGE_OFFSET - sizeof (SMM_S3_RESUME_STATE))\r
33\r
34// Strap configuration register specifying DDR setup\r
35#define QUARK_SCSS_REG_STPDDRCFG 0x00\r
36\r
37// Macro counting array elements\r
38#define COUNT(a) (sizeof(a)/sizeof(*a))\r
39\r
40\r
41EFI_MEMORY_TYPE_INFORMATION mDefaultQncMemoryTypeInformation[] = {\r
42 { EfiReservedMemoryType, EDKII_RESERVED_SIZE_PAGES }, // BIOS Reserved\r
43 { EfiACPIMemoryNVS, ACPI_NVS_SIZE_PAGES }, // S3, SMM, etc\r
44 { EfiRuntimeServicesData, RUNTIME_SERVICES_DATA_SIZE_PAGES },\r
45 { EfiRuntimeServicesCode, RUNTIME_SERVICES_CODE_SIZE_PAGES },\r
46 { EfiACPIReclaimMemory, ACPI_RECLAIM_SIZE_PAGES }, // ACPI ASL\r
47 { EfiMaxMemoryType, 0 }\r
48};\r
49\r
50/**\r
51 Configure Uart mmio base for MRC serial log purpose\r
52\r
53 @param MrcData - MRC configuration data updated\r
54\r
55**/\r
56VOID\r
57MrcUartConfig(\r
58 MRC_PARAMS *MrcData\r
59 )\r
60{\r
61 UINT8 UartIdx;\r
62 UINT32 RegData32;\r
63 UINT8 IohUartBus;\r
64 UINT8 IohUartDev;\r
65\r
66 UartIdx = PcdGet8(PcdIohUartFunctionNumber);\r
67 IohUartBus = PcdGet8(PcdIohUartBusNumber);\r
68 IohUartDev = PcdGet8(PcdIohUartDevNumber);\r
69\r
70 RegData32 = PciRead32 (PCI_LIB_ADDRESS(IohUartBus, IohUartDev, UartIdx, PCI_BASE_ADDRESSREG_OFFSET));\r
71 MrcData->uart_mmio_base = RegData32 & 0xFFFFFFF0;\r
72}\r
73\r
74/**\r
75 Configure MRC from memory controller fuse settings.\r
76\r
77 @param MrcData - MRC configuration data to be updated.\r
78\r
79 @return EFI_SUCCESS MRC Config parameters updated from platform data.\r
80**/\r
81EFI_STATUS\r
82MrcConfigureFromMcFuses (\r
83 OUT MRC_PARAMS *MrcData\r
84 )\r
85{\r
86 UINT32 McFuseStat;\r
87\r
88 McFuseStat = QNCPortRead (\r
89 QUARK_NC_MEMORY_CONTROLLER_SB_PORT_ID,\r
90 QUARK_NC_MEMORY_CONTROLLER_REG_DFUSESTAT\r
91 );\r
92\r
93 DEBUG ((EFI_D_INFO, "MRC McFuseStat 0x%08x\n", McFuseStat));\r
94\r
95 if ((McFuseStat & B_DFUSESTAT_ECC_DIS) != 0) {\r
96 DEBUG ((EFI_D_INFO, "MRC Fuse : fus_dun_ecc_dis.\n"));\r
97 MrcData->ecc_enables = 0;\r
98 } else {\r
99 MrcData->ecc_enables = 1;\r
100 }\r
101 return EFI_SUCCESS;\r
102}\r
103\r
104/**\r
105 Configure MRC from platform info hob.\r
106\r
107 @param MrcData - MRC configuration data to be updated.\r
108\r
109 @return EFI_SUCCESS MRC Config parameters updated from hob.\r
110 @return EFI_NOT_FOUND Platform Info or MRC Config parameters not found.\r
111 @return EFI_INVALID_PARAMETER Wrong params in hob.\r
112**/\r
113EFI_STATUS\r
114MrcConfigureFromInfoHob (\r
115 OUT MRC_PARAMS *MrcData\r
116 )\r
117{\r
118 PDAT_MRC_ITEM *ItemData;\r
119\r
120 ItemData = (PDAT_MRC_ITEM *)PcdGetPtr (PcdMrcParameters);\r
121\r
122 MrcData->channel_enables = ItemData->ChanMask;\r
123 MrcData->channel_width = ItemData->ChanWidth;\r
124 MrcData->address_mode = ItemData->AddrMode;\r
125 // Enable scrambling if requested.\r
126 MrcData->scrambling_enables = (ItemData->Flags & PDAT_MRC_FLAG_SCRAMBLE_EN) != 0;\r
127 MrcData->ddr_type = ItemData->DramType;\r
128 MrcData->dram_width = ItemData->DramWidth;\r
129 MrcData->ddr_speed = ItemData->DramSpeed;\r
130 // Enable ECC if requested.\r
131 MrcData->rank_enables = ItemData->RankMask;\r
132 MrcData->params.DENSITY = ItemData->DramDensity;\r
133 MrcData->params.tCL = ItemData->tCL;\r
134 MrcData->params.tRAS = ItemData->tRAS;\r
135 MrcData->params.tWTR = ItemData->tWTR;\r
136 MrcData->params.tRRD = ItemData->tRRD;\r
137 MrcData->params.tFAW = ItemData->tFAW;\r
138\r
139 MrcData->refresh_rate = ItemData->SrInt;\r
140 MrcData->sr_temp_range = ItemData->SrTemp;\r
141 MrcData->ron_value = ItemData->DramRonVal;\r
142 MrcData->rtt_nom_value = ItemData->DramRttNomVal;\r
143 MrcData->rd_odt_value = ItemData->SocRdOdtVal;\r
144\r
145 DEBUG ((EFI_D_INFO, "MRC dram_width %d\n", MrcData->dram_width));\r
146 DEBUG ((EFI_D_INFO, "MRC rank_enables %d\n",MrcData->rank_enables));\r
147 DEBUG ((EFI_D_INFO, "MRC ddr_speed %d\n", MrcData->ddr_speed));\r
148 DEBUG ((EFI_D_INFO, "MRC flags: %s\n",\r
149 (MrcData->scrambling_enables) ? L"SCRAMBLE_EN" : L""\r
150 ));\r
151\r
152 DEBUG ((EFI_D_INFO, "MRC density=%d tCL=%d tRAS=%d tWTR=%d tRRD=%d tFAW=%d\n",\r
153 MrcData->params.DENSITY,\r
154 MrcData->params.tCL,\r
155 MrcData->params.tRAS,\r
156 MrcData->params.tWTR,\r
157 MrcData->params.tRRD,\r
158 MrcData->params.tFAW\r
159 ));\r
160\r
161 return EFI_SUCCESS;\r
162}\r
163\r
164/**\r
165\r
166 Configure ECC scrub\r
167\r
168 @param MrcData - MRC configuration\r
169\r
170**/\r
171VOID\r
172EccScrubSetup(\r
173 const MRC_PARAMS *MrcData\r
174 )\r
175{\r
176 UINT32 BgnAdr = 0;\r
177 UINT32 EndAdr = MrcData->mem_size;\r
178 UINT32 BlkSize = PcdGet8(PcdEccScrubBlkSize) & SCRUB_CFG_BLOCKSIZE_MASK;\r
179 UINT32 Interval = PcdGet8(PcdEccScrubInterval) & SCRUB_CFG_INTERVAL_MASK;\r
180\r
181 if( MrcData->ecc_enables == 0 || MrcData->boot_mode == bmS3 || Interval == 0) {\r
182 // No scrub configuration needed if ECC not enabled\r
183 // On S3 resume reconfiguration is done as part of resume\r
184 // script, see SNCS3Save.c ==> SaveRuntimeScriptTable()\r
185 // Also if PCD disables scrub, then we do nothing.\r
186 return;\r
187 }\r
188\r
189 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, EndAdr);\r
190 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG, BgnAdr);\r
191 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG, BgnAdr);\r
192 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,\r
193 Interval << SCRUB_CFG_INTERVAL_SHIFT |\r
194 BlkSize << SCRUB_CFG_BLOCKSIZE_SHIFT);\r
195\r
196 McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = SCRUB_RESUME_MSG();\r
197}\r
198\r
199/** Post InstallS3Memory / InstallEfiMemory tasks given MrcData context.\r
200\r
201 @param[in] MrcData MRC configuration.\r
202 @param[in] IsS3 TRUE if after InstallS3Memory.\r
203\r
204**/\r
205VOID\r
206PostInstallMemory (\r
207 IN MRC_PARAMS *MrcData,\r
208 IN BOOLEAN IsS3\r
209 )\r
210{\r
211 UINT32 RmuMainDestBaseAddress;\r
212 UINT32 *RmuMainSrcBaseAddress;\r
213 UINTN RmuMainSize;\r
214 EFI_STATUS Status;\r
215\r
216 //\r
217 // Setup ECC policy (All boot modes).\r
218 //\r
219 QNCPolicyDblEccBitErr (V_WDT_CONTROL_DBL_ECC_BIT_ERR_WARM);\r
220\r
221 //\r
222 // Find the 64KB of memory for Rmu Main at the top of available memory.\r
223 //\r
224 InfoPostInstallMemory (&RmuMainDestBaseAddress, NULL, NULL);\r
225 DEBUG ((EFI_D_INFO, "RmuMain Base Address : 0x%x\n", RmuMainDestBaseAddress));\r
226\r
227 //\r
228 // Relocate RmuMain.\r
229 //\r
230 if (IsS3) {\r
231 QNCSendOpcodeDramReady (RmuMainDestBaseAddress);\r
232 } else {\r
233 Status = PlatformFindFvFileRawDataSection (NULL, PcdGetPtr(PcdQuarkMicrocodeFile), (VOID **) &RmuMainSrcBaseAddress, &RmuMainSize);\r
234 ASSERT_EFI_ERROR (Status);\r
235 if (!EFI_ERROR (Status)) {\r
236 DEBUG ((EFI_D_INFO, "Found Microcode ADDR:SIZE 0x%08x:0x%04x\n", (UINTN) RmuMainSrcBaseAddress, RmuMainSize));\r
237 }\r
238\r
239 RmuMainRelocation (RmuMainDestBaseAddress, (UINT32) RmuMainSrcBaseAddress, RmuMainSize);\r
240 QNCSendOpcodeDramReady (RmuMainDestBaseAddress);\r
241 EccScrubSetup (MrcData);\r
242 }\r
243}\r
244\r
245/**\r
246\r
247 Do memory initialisation for QNC DDR3 SDRAM Controller\r
248\r
249 @param FfsHeader Not used.\r
250 @param PeiServices General purpose services available to every PEIM.\r
251\r
252 @return EFI_SUCCESS Memory initialisation completed successfully.\r
253 All other error conditions encountered result in an ASSERT.\r
254\r
255**/\r
256EFI_STATUS\r
257MemoryInit (\r
258 IN EFI_PEI_SERVICES **PeiServices\r
259 )\r
260{\r
261 MRC_PARAMS MrcData;\r
262 EFI_BOOT_MODE BootMode;\r
263 EFI_STATUS Status;\r
264 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;\r
265 EFI_STATUS_CODE_VALUE ErrorCodeValue;\r
266 PEI_QNC_MEMORY_INIT_PPI *QncMemoryInitPpi;\r
267 UINT16 PmswAdr;\r
268\r
269 ErrorCodeValue = 0;\r
270\r
271 //\r
272 // It is critical that both of these data structures are initialized to 0.\r
273 // This PEIM knows the number of DIMMs in the system and works with that\r
274 // information. The MCH PEIM that consumes these data structures does not\r
275 // know the number of DIMMs so it expects the entire structure to be\r
276 // properly initialized. By initializing these to zero, all flags indicating\r
277 // that the SPD is present or the row should be configured are set to false.\r
278 //\r
279 ZeroMem (&MrcData, sizeof(MrcData));\r
280\r
281 //\r
282 // Get necessary PPI\r
283 //\r
284 Status = PeiServicesLocatePpi (\r
285 &gEfiPeiReadOnlyVariable2PpiGuid, // GUID\r
286 0, // INSTANCE\r
287 NULL, // EFI_PEI_PPI_DESCRIPTOR\r
288 (VOID **)&VariableServices // PPI\r
289 );\r
290 ASSERT_EFI_ERROR (Status);\r
291\r
292 //\r
293 // Determine boot mode\r
294 //\r
295 Status = PeiServicesGetBootMode (&BootMode);\r
296 ASSERT_EFI_ERROR (Status);\r
297\r
298 //\r
299 // Initialize Error type for reporting status code\r
300 //\r
301 switch (BootMode) {\r
302 case BOOT_ON_FLASH_UPDATE:\r
303 ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_EC_UPDATE_FAIL;\r
304 break;\r
305 case BOOT_ON_S3_RESUME:\r
306 ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_EC_S3_RESUME_FAIL;\r
307 break;\r
308 default:\r
309 ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY;\r
310 break;\r
311 }\r
312\r
313 //\r
314 // Specify MRC boot mode\r
315 //\r
316 switch (BootMode) {\r
317 case BOOT_ON_S3_RESUME:\r
318 case BOOT_ON_FLASH_UPDATE:\r
319 MrcData.boot_mode = bmS3;\r
320 break;\r
321 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:\r
322 MrcData.boot_mode = bmFast;\r
323 break;\r
324 default:\r
325 MrcData.boot_mode = bmCold;\r
326 break;\r
327 }\r
328\r
329 //\r
330 // Configure MRC input parameters.\r
331 //\r
332 Status = MrcConfigureFromMcFuses (&MrcData);\r
333 ASSERT_EFI_ERROR (Status);\r
334 Status = MrcConfigureFromInfoHob (&MrcData);\r
335 ASSERT_EFI_ERROR (Status);\r
336 MrcUartConfig(&MrcData);\r
337\r
338 if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
339 //\r
340 // Always do bmCold on recovery.\r
341 //\r
342 DEBUG ((DEBUG_INFO, "MemoryInit:Force bmCold on Recovery\n"));\r
343 MrcData.boot_mode = bmCold;\r
344 } else {\r
345\r
346 //\r
347 // Load Memory configuration data saved in previous boot from variable\r
348 //\r
349 Status = LoadConfig (\r
350 PeiServices,\r
351 VariableServices,\r
352 &MrcData\r
353 );\r
354\r
355 if (EFI_ERROR (Status)) {\r
356\r
357 switch (BootMode) {\r
358 case BOOT_ON_S3_RESUME:\r
359 case BOOT_ON_FLASH_UPDATE:\r
360 REPORT_STATUS_CODE (\r
361 EFI_ERROR_CODE + EFI_ERROR_UNRECOVERED,\r
362 ErrorCodeValue\r
363 );\r
364 PeiServicesResetSystem ();\r
365 break;\r
366\r
367 default:\r
368 MrcData.boot_mode = bmCold;\r
369 break;\r
370 }\r
371 }\r
372 }\r
373\r
374 //\r
375 // Locate Memory Reference Code PPI\r
376 //\r
377 Status = PeiServicesLocatePpi (\r
378 &gQNCMemoryInitPpiGuid, // GUID\r
379 0, // INSTANCE\r
380 NULL, // EFI_PEI_PPI_DESCRIPTOR\r
381 (VOID **)&QncMemoryInitPpi // PPI\r
382 );\r
383 ASSERT_EFI_ERROR (Status);\r
384\r
385 PmswAdr = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMSW;\r
386 if( IoRead32 (PmswAdr) & B_QNC_GPE0BLK_PMSW_DRAM_INIT) {\r
387 // MRC did not complete last execution, force cold boot path\r
388 MrcData.boot_mode = bmCold;\r
389 }\r
390\r
391 // Mark MRC pending\r
392 IoOr32 (PmswAdr, (UINT32)B_QNC_GPE0BLK_PMSW_DRAM_INIT);\r
393\r
394 //\r
395 // Call Memory Reference Code's Routines\r
396 //\r
397 QncMemoryInitPpi->MrcStart (&MrcData);\r
398\r
399 // Mark MRC completed\r
400 IoAnd32 (PmswAdr, ~(UINT32)B_QNC_GPE0BLK_PMSW_DRAM_INIT);\r
401\r
402\r
403 //\r
404 // Note emulation platform has to read actual memory size\r
405 // MrcData.mem_size from PcdGet32 (PcdMemorySize);\r
406\r
407 if (BootMode == BOOT_ON_S3_RESUME) {\r
408\r
409 DEBUG ((EFI_D_INFO, "Following BOOT_ON_S3_RESUME boot path.\n"));\r
410\r
411 Status = InstallS3Memory (PeiServices, VariableServices, MrcData.mem_size);\r
412 if (EFI_ERROR (Status)) {\r
413 REPORT_STATUS_CODE (\r
414 EFI_ERROR_CODE + EFI_ERROR_UNRECOVERED,\r
415 ErrorCodeValue\r
416 );\r
417 PeiServicesResetSystem ();\r
418 }\r
419 PostInstallMemory (&MrcData, TRUE);\r
420 return EFI_SUCCESS;\r
421 }\r
422\r
423 //\r
424 // Assign physical memory to PEI and DXE\r
425 //\r
426 DEBUG ((EFI_D_INFO, "InstallEfiMemory.\n"));\r
427\r
428 Status = InstallEfiMemory (\r
429 PeiServices,\r
430 VariableServices,\r
431 BootMode,\r
432 MrcData.mem_size\r
433 );\r
434 ASSERT_EFI_ERROR (Status);\r
435\r
436 PostInstallMemory (&MrcData, FALSE);\r
437\r
438 //\r
439 // Save current configuration into Hob and will save into Variable later in DXE\r
440 //\r
441 DEBUG ((EFI_D_INFO, "SaveConfig.\n"));\r
442 Status = SaveConfig (\r
443 &MrcData\r
444 );\r
445 ASSERT_EFI_ERROR (Status);\r
446\r
447 DEBUG ((EFI_D_INFO, "MemoryInit Complete.\n"));\r
448\r
449 return EFI_SUCCESS;\r
450}\r
451\r
452/**\r
453\r
454 This function saves a config to a HOB.\r
455\r
456 @param RowInfo The MCH row configuration information.\r
457 @param TimingData Timing data to be saved.\r
458 @param RowConfArray Row configuration information for each row in the system.\r
459 @param SpdData SPD info read for each DIMM slot in the system.\r
460\r
461 @return EFI_SUCCESS: The function completed successfully.\r
462\r
463**/\r
464EFI_STATUS\r
465SaveConfig (\r
466 IN MRC_PARAMS *MrcData\r
467 )\r
468{\r
469 //\r
470 // Build HOB data for Memory Config\r
471 // HOB data size (stored in variable) is required to be multiple of 8 bytes\r
472 //\r
473 BuildGuidDataHob (\r
474 &gEfiMemoryConfigDataGuid,\r
475 (VOID *) &MrcData->timings,\r
476 ((sizeof (MrcData->timings) + 0x7) & (~0x7))\r
477 );\r
478\r
479 DEBUG ((EFI_D_INFO, "IIO IoApicBase = %x IoApicLimit=%x\n", IOAPIC_BASE, (IOAPIC_BASE + IOAPIC_SIZE - 1)));\r
480 DEBUG ((EFI_D_INFO, "IIO RcbaAddress = %x\n", (UINT32)PcdGet64 (PcdRcbaMmioBaseAddress)));\r
481\r
482 return EFI_SUCCESS;\r
483}\r
484\r
485/**\r
486\r
487 Load a configuration stored in a variable.\r
488\r
489 @param TimingData Timing data to be loaded from NVRAM.\r
490 @param RowConfArray Row configuration information for each row in the system.\r
491\r
492 @return EFI_SUCCESS The function completed successfully.\r
493 Other Could not read variable.\r
494\r
495**/\r
496EFI_STATUS\r
497LoadConfig (\r
498 IN EFI_PEI_SERVICES **PeiServices,\r
499 IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,\r
500 IN OUT MRC_PARAMS *MrcData\r
501 )\r
502{\r
503 EFI_STATUS Status;\r
504 UINTN BufferSize;\r
505 PLATFORM_VARIABLE_MEMORY_CONFIG_DATA VarData;\r
506\r
507 BufferSize = ((sizeof (VarData.timings) + 0x7) & (~0x7)); // HOB data size (stored in variable) is required to be multiple of 8bytes\r
508\r
509 Status = VariableServices->GetVariable (\r
510 VariableServices,\r
511 EFI_MEMORY_CONFIG_DATA_NAME,\r
512 &gEfiMemoryConfigDataGuid,\r
513 NULL,\r
514 &BufferSize,\r
515 &VarData.timings\r
516 );\r
517 if (!EFI_ERROR (Status)) {\r
518 CopyMem (&MrcData->timings, &VarData.timings, sizeof(MrcData->timings));\r
519 }\r
520 return Status;\r
521}\r
522\r
523/**\r
524\r
525 This function installs memory.\r
526\r
527 @param PeiServices PEI Services table.\r
528 @param BootMode The specific boot path that is being followed\r
529 @param Mch Pointer to the DualChannelDdrMemoryInit PPI\r
530 @param RowConfArray Row configuration information for each row in the system.\r
531\r
532 @return EFI_SUCCESS The function completed successfully.\r
533 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
534 EFI_ABORTED An error occurred.\r
535\r
536**/\r
537EFI_STATUS\r
538InstallEfiMemory (\r
539 IN EFI_PEI_SERVICES **PeiServices,\r
540 IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,\r
541 IN EFI_BOOT_MODE BootMode,\r
542 IN UINT32 TotalMemorySize\r
543 )\r
544{\r
545 EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress;\r
546 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;\r
547 EFI_STATUS Status;\r
548 EFI_PEI_HOB_POINTERS Hob;\r
549 PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];\r
550 UINT8 Index;\r
551 UINT8 NumRanges;\r
552 UINT8 SmramIndex;\r
553 UINT8 SmramRanges;\r
554 UINT64 PeiMemoryLength;\r
555 UINTN BufferSize;\r
556 UINTN PeiMemoryIndex;\r
557 UINTN RequiredMemSize;\r
558 EFI_RESOURCE_ATTRIBUTE_TYPE Attribute;\r
559 EFI_PHYSICAL_ADDRESS BadMemoryAddress;\r
560 EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;\r
561 VOID *CapsuleBuffer;\r
562 UINTN CapsuleBufferLength;\r
563 PEI_CAPSULE_PPI *Capsule;\r
564 VOID *LargeMemRangeBuf;\r
565 UINTN LargeMemRangeBufLen;\r
566\r
567 //\r
568 // Test the memory from 1M->TOM\r
569 //\r
570 if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
571 Status = BaseMemoryTest (\r
572 PeiServices,\r
573 0x100000,\r
574 (TotalMemorySize - 0x100000),\r
575 Quick,\r
576 &BadMemoryAddress\r
577 );\r
578 ASSERT_EFI_ERROR (Status);\r
579 }\r
580\r
581\r
582 //\r
583 // Get the Memory Map\r
584 //\r
585 NumRanges = MAX_RANGES;\r
586\r
587 ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);\r
588\r
589 Status = GetMemoryMap (\r
590 PeiServices,\r
591 TotalMemorySize,\r
592 (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *) MemoryMap,\r
593 &NumRanges\r
594 );\r
595 ASSERT_EFI_ERROR (Status);\r
596\r
597 //\r
598 // Find the highest memory range in processor native address space to give to\r
599 // PEI. Then take the top.\r
600 //\r
601 PeiMemoryBaseAddress = 0;\r
602\r
603 //\r
604 // Query the platform for the minimum memory size\r
605 //\r
606\r
607 Status = GetPlatformMemorySize (\r
608 PeiServices,\r
609 BootMode,\r
610 &PeiMemoryLength\r
611 );\r
612 ASSERT_EFI_ERROR (Status);\r
613\r
614 //\r
615 // Get required memory size for ACPI use. This helps to put ACPI memory on the topest\r
616 //\r
617 RequiredMemSize = 0;\r
618 RetriveRequiredMemorySize (PeiServices, &RequiredMemSize);\r
619\r
620 PeiMemoryIndex = 0;\r
621\r
622 for (Index = 0; Index < NumRanges; Index++)\r
623 {\r
624 DEBUG ((EFI_D_INFO, "Found 0x%x bytes at ", MemoryMap[Index].RangeLength));\r
625 DEBUG ((EFI_D_INFO, "0x%x.\n", MemoryMap[Index].PhysicalAddress));\r
626\r
627 if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&\r
628 (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS) &&\r
629 (MemoryMap[Index].PhysicalAddress >= PeiMemoryBaseAddress) &&\r
630 (MemoryMap[Index].RangeLength >= PeiMemoryLength)) {\r
631 PeiMemoryBaseAddress = MemoryMap[Index].PhysicalAddress +\r
632 MemoryMap[Index].RangeLength -\r
633 PeiMemoryLength;\r
634 PeiMemoryIndex = Index;\r
635 }\r
636 }\r
637\r
638 //\r
639 // Find the largest memory range excluding that given to PEI.\r
640 //\r
641 LargeMemRangeBuf = NULL;\r
642 LargeMemRangeBufLen = 0;\r
643 for (Index = 0; Index < NumRanges; Index++) {\r
644 if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&\r
645 (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS)) {\r
646 if (Index != PeiMemoryIndex) {\r
647 if (MemoryMap[Index].RangeLength > LargeMemRangeBufLen) {\r
648 LargeMemRangeBuf = (VOID *) ((UINTN) MemoryMap[Index].PhysicalAddress);\r
649 LargeMemRangeBufLen = (UINTN) MemoryMap[Index].RangeLength;\r
650 }\r
651 } else {\r
652 if ((MemoryMap[Index].RangeLength - PeiMemoryLength) >= LargeMemRangeBufLen) {\r
653 LargeMemRangeBuf = (VOID *) ((UINTN) MemoryMap[Index].PhysicalAddress);\r
654 LargeMemRangeBufLen = (UINTN) (MemoryMap[Index].RangeLength - PeiMemoryLength);\r
655 }\r
656 }\r
657 }\r
658 }\r
659\r
660 Capsule = NULL;\r
661 CapsuleBuffer = NULL;\r
662 CapsuleBufferLength = 0;\r
663 if (BootMode == BOOT_ON_FLASH_UPDATE) {\r
664 Status = PeiServicesLocatePpi (\r
665 &gPeiCapsulePpiGuid, // GUID\r
666 0, // INSTANCE\r
667 NULL, // EFI_PEI_PPI_DESCRIPTOR\r
668 (VOID **)&Capsule // PPI\r
669 );\r
670 ASSERT_EFI_ERROR (Status);\r
671\r
672 if (Status == EFI_SUCCESS) {\r
673 CapsuleBuffer = LargeMemRangeBuf;\r
674 CapsuleBufferLength = LargeMemRangeBufLen;\r
675\r
676 //\r
677 // Call the Capsule PPI Coalesce function to coalesce the capsule data.\r
678 //\r
679 Status = Capsule->Coalesce (\r
680 PeiServices,\r
681 &CapsuleBuffer,\r
682 &CapsuleBufferLength\r
683 );\r
684 //\r
685 // If it failed, then NULL out our capsule PPI pointer so that the capsule\r
686 // HOB does not get created below.\r
687 //\r
688 if (Status != EFI_SUCCESS) {\r
689 Capsule = NULL;\r
690 }\r
691 }\r
692 }\r
693\r
694 //\r
695 // Set up the IMR policy required for this platform\r
696 //\r
697 Status = SetPlatformImrPolicy (\r
698 PeiMemoryBaseAddress,\r
699 PeiMemoryLength,\r
700 RequiredMemSize\r
701 );\r
702 ASSERT_EFI_ERROR (Status);\r
703\r
704 //\r
705 // Carve out the top memory reserved for ACPI\r
706 //\r
707 Status = PeiServicesInstallPeiMemory (PeiMemoryBaseAddress, (PeiMemoryLength - RequiredMemSize));\r
708 ASSERT_EFI_ERROR (Status);\r
709\r
710 BuildResourceDescriptorHob (\r
711 EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,\r
712 (\r
713 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
714 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
715 EFI_RESOURCE_ATTRIBUTE_TESTED |\r
716 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
717 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
718 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
719 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
720 ),\r
721 PeiMemoryBaseAddress, // MemoryBegin\r
722 PeiMemoryLength // MemoryLength\r
723 );\r
724\r
725 //\r
726 // Install physical memory descriptor hobs for each memory range.\r
727 //\r
728 SmramRanges = 0;\r
729 for (Index = 0; Index < NumRanges; Index++) {\r
730 Attribute = 0;\r
731 if (MemoryMap[Index].Type == DualChannelDdrMainMemory)\r
732 {\r
733 if (Index == PeiMemoryIndex) {\r
734 //\r
735 // This is a partially tested Main Memory range, give it to EFI\r
736 //\r
737 BuildResourceDescriptorHob (\r
738 EFI_RESOURCE_SYSTEM_MEMORY,\r
739 (\r
740 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
741 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
742 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
743 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
744 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
745 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
746 ),\r
747 MemoryMap[Index].PhysicalAddress,\r
748 MemoryMap[Index].RangeLength - PeiMemoryLength\r
749 );\r
750 } else {\r
751 //\r
752 // This is an untested Main Memory range, give it to EFI\r
753 //\r
754 BuildResourceDescriptorHob (\r
755 EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,\r
756 (\r
757 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
758 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
759 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
760 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
761 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
762 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
763 ),\r
764 MemoryMap[Index].PhysicalAddress, // MemoryBegin\r
765 MemoryMap[Index].RangeLength // MemoryLength\r
766 );\r
767 }\r
768 } else {\r
769 if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||\r
770 (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)) {\r
771 SmramRanges++;\r
772 }\r
773 if ((MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable) ||\r
774 (MemoryMap[Index].Type == DualChannelDdrGraphicsMemoryNonCacheable)) {\r
775 Attribute |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;\r
776 }\r
777 if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||\r
778 (MemoryMap[Index].Type == DualChannelDdrGraphicsMemoryCacheable)) {\r
779 //\r
780 // TSEG and HSEG can be used with a write-back(WB) cache policy; however,\r
781 // the specification requires that the TSEG and HSEG space be cached only\r
782 // inside of the SMI handler. when using HSEG or TSEG an IA-32 processor\r
783 // does not automatically write back and invalidate its cache before entering\r
784 // SMM or before existing SMM therefore any MTRR defined for the active TSEG\r
785 // or HSEG must be set to un-cacheable(UC) outside of SMM.\r
786 //\r
787 Attribute |= EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;\r
788 }\r
789 if (MemoryMap[Index].Type == DualChannelDdrReservedMemory) {\r
790 Attribute |= EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |\r
791 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;\r
792 }\r
793 //\r
794 // Make sure non-system memory is marked as reserved\r
795 //\r
796 BuildResourceDescriptorHob (\r
797 EFI_RESOURCE_MEMORY_RESERVED, // MemoryType,\r
798 Attribute, // MemoryAttribute\r
799 MemoryMap[Index].PhysicalAddress, // MemoryBegin\r
800 MemoryMap[Index].RangeLength // MemoryLength\r
801 );\r
802 }\r
803 }\r
804\r
805 //\r
806 // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer\r
807 // to the SMM Services Table that is required on the S3 resume path\r
808 //\r
809 ASSERT (SmramRanges > 0);\r
810 BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);\r
811 BufferSize += ((SmramRanges - 1) * sizeof (EFI_SMRAM_DESCRIPTOR));\r
812\r
813 Hob.Raw = BuildGuidHob (\r
814 &gEfiSmmPeiSmramMemoryReserveGuid,\r
815 BufferSize\r
816 );\r
817 ASSERT (Hob.Raw);\r
818\r
819 SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *) (Hob.Raw);\r
820 SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;\r
821\r
822 SmramIndex = 0;\r
823 for (Index = 0; Index < NumRanges; Index++) {\r
824 if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||\r
825 (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)\r
826 ) {\r
827 //\r
828 // This is an SMRAM range, create an SMRAM descriptor\r
829 //\r
830 SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress;\r
831 SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress;\r
832 SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength;\r
833 if (MemoryMap[Index].Type == DualChannelDdrSmramCacheable) {\r
834 SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;\r
835 } else {\r
836 SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED;\r
837 }\r
838\r
839 SmramIndex++;\r
840 }\r
841 }\r
842\r
843 //\r
844 // Build a HOB with the location of the reserved memory range.\r
845 //\r
846 CopyMem(&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[SmramRanges-1], sizeof(EFI_SMRAM_DESCRIPTOR));\r
847 DescriptorAcpiVariable.CpuStart += RESERVED_CPU_S3_SAVE_OFFSET;\r
848 BuildGuidDataHob (\r
849 &gEfiAcpiVariableGuid,\r
850 &DescriptorAcpiVariable,\r
851 sizeof (EFI_SMRAM_DESCRIPTOR)\r
852 );\r
853\r
854 //\r
855 // If we found the capsule PPI (and we didn't have errors), then\r
856 // call the capsule PEIM to allocate memory for the capsule.\r
857 //\r
858 if (Capsule != NULL) {\r
859 Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength);\r
860 }\r
861\r
862 return EFI_SUCCESS;\r
863}\r
864\r
865/**\r
866\r
867 Find memory that is reserved so PEI has some to use.\r
868\r
869 @param PeiServices PEI Services table.\r
870 @param VariableSevices Variable PPI instance.\r
871\r
872 @return EFI_SUCCESS The function completed successfully.\r
873 Error value from LocatePpi()\r
874 Error Value from VariableServices->GetVariable()\r
875\r
876**/\r
877EFI_STATUS\r
878InstallS3Memory (\r
879 IN EFI_PEI_SERVICES **PeiServices,\r
880 IN EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices,\r
881 IN UINT32 TotalMemorySize\r
882 )\r
883{\r
884 EFI_STATUS Status;\r
885 UINTN S3MemoryBase;\r
886 UINTN S3MemorySize;\r
887 UINT8 SmramRanges;\r
888 UINT8 NumRanges;\r
889 UINT8 Index;\r
890 UINT8 SmramIndex;\r
891 UINTN BufferSize;\r
892 EFI_PEI_HOB_POINTERS Hob;\r
893 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;\r
894 PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];\r
895 RESERVED_ACPI_S3_RANGE *S3MemoryRangeData;\r
896 EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;\r
897\r
898 //\r
899 // Get the Memory Map\r
900 //\r
901 NumRanges = MAX_RANGES;\r
902\r
903 ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);\r
904\r
905 Status = GetMemoryMap (\r
906 PeiServices,\r
907 TotalMemorySize,\r
908 (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *) MemoryMap,\r
909 &NumRanges\r
910 );\r
911 ASSERT_EFI_ERROR (Status);\r
912\r
913 //\r
914 // Install physical memory descriptor hobs for each memory range.\r
915 //\r
916 SmramRanges = 0;\r
917 for (Index = 0; Index < NumRanges; Index++) {\r
918 if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||\r
919 (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)) {\r
920 SmramRanges++;\r
921 }\r
922 }\r
923\r
924 ASSERT (SmramRanges > 0);\r
925\r
926 //\r
927 // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer\r
928 // to the SMM Services Table that is required on the S3 resume path\r
929 //\r
930 BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);\r
931 if (SmramRanges > 0) {\r
932 BufferSize += ((SmramRanges - 1) * sizeof (EFI_SMRAM_DESCRIPTOR));\r
933 }\r
934\r
935 Hob.Raw = BuildGuidHob (\r
936 &gEfiSmmPeiSmramMemoryReserveGuid,\r
937 BufferSize\r
938 );\r
939 ASSERT (Hob.Raw);\r
940\r
941 SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *) (Hob.Raw);\r
942 SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;\r
943\r
944 SmramIndex = 0;\r
945 for (Index = 0; Index < NumRanges; Index++) {\r
946 if ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||\r
947 (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)\r
948 ) {\r
949 //\r
950 // This is an SMRAM range, create an SMRAM descriptor\r
951 //\r
952 SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress;\r
953 SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress;\r
954 SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength;\r
955 if (MemoryMap[Index].Type == DualChannelDdrSmramCacheable) {\r
956 SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;\r
957 } else {\r
958 SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED;\r
959 }\r
960\r
961 SmramIndex++;\r
962 }\r
963 }\r
964\r
965 //\r
966 // Build a HOB with the location of the reserved memory range.\r
967 //\r
968 CopyMem(&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[SmramRanges-1], sizeof(EFI_SMRAM_DESCRIPTOR));\r
969 DescriptorAcpiVariable.CpuStart += RESERVED_CPU_S3_SAVE_OFFSET;\r
970 BuildGuidDataHob (\r
971 &gEfiAcpiVariableGuid,\r
972 &DescriptorAcpiVariable,\r
973 sizeof (EFI_SMRAM_DESCRIPTOR)\r
974 );\r
975\r
976 //\r
977 // Get the location and size of the S3 memory range in the reserved page and\r
978 // install it as PEI Memory.\r
979 //\r
980\r
981 DEBUG ((EFI_D_INFO, "TSEG Base = 0x%08x\n", SmramHobDescriptorBlock->Descriptor[SmramRanges-1].PhysicalStart));\r
982 S3MemoryRangeData = (RESERVED_ACPI_S3_RANGE*)(UINTN)\r
983 (SmramHobDescriptorBlock->Descriptor[SmramRanges-1].PhysicalStart + RESERVED_ACPI_S3_RANGE_OFFSET);\r
984\r
985 S3MemoryBase = (UINTN) (S3MemoryRangeData->AcpiReservedMemoryBase);\r
986 DEBUG ((EFI_D_INFO, "S3MemoryBase = 0x%08x\n", S3MemoryBase));\r
987 S3MemorySize = (UINTN) (S3MemoryRangeData->AcpiReservedMemorySize);\r
988 DEBUG ((EFI_D_INFO, "S3MemorySize = 0x%08x\n", S3MemorySize));\r
989\r
990 Status = PeiServicesInstallPeiMemory (S3MemoryBase, S3MemorySize);\r
991 ASSERT_EFI_ERROR (Status);\r
992\r
993 //\r
994 // Retrieve the system memory length and build memory hob for the system\r
995 // memory above 1MB. So Memory Callback can set cache for the system memory\r
996 // correctly on S3 boot path, just like it does on Normal boot path.\r
997 //\r
998 ASSERT_EFI_ERROR ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0);\r
999 BuildResourceDescriptorHob (\r
1000 EFI_RESOURCE_SYSTEM_MEMORY,\r
1001 (\r
1002 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
1003 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
1004 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
1005 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
1006 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
1007 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
1008 ),\r
1009 0x100000,\r
1010 S3MemoryRangeData->SystemMemoryLength - 0x100000\r
1011 );\r
1012\r
1013 for (Index = 0; Index < NumRanges; Index++) {\r
1014 if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&\r
1015 (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < 0x100000)) {\r
1016 BuildResourceDescriptorHob (\r
1017 EFI_RESOURCE_SYSTEM_MEMORY,\r
1018 (\r
1019 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
1020 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
1021 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
1022 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
1023 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
1024 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
1025 ),\r
1026 MemoryMap[Index].PhysicalAddress,\r
1027 MemoryMap[Index].RangeLength\r
1028 );\r
1029 DEBUG ((EFI_D_INFO, "Build resource HOB for Legacy Region on S3 patch :"));\r
1030 DEBUG ((EFI_D_INFO, " Memory Base:0x%lX Length:0x%lX\n", MemoryMap[Index].PhysicalAddress, MemoryMap[Index].RangeLength));\r
1031 }\r
1032 }\r
1033\r
1034 return EFI_SUCCESS;\r
1035}\r
1036\r
1037/**\r
1038\r
1039 This function returns the size, in bytes, required for the DXE phase.\r
1040\r
1041 @param PeiServices PEI Services table.\r
1042 @param Size Pointer to the size, in bytes, required for the DXE phase.\r
1043\r
1044 @return None\r
1045\r
1046**/\r
1047VOID\r
1048RetriveRequiredMemorySize (\r
1049 IN EFI_PEI_SERVICES **PeiServices,\r
1050 OUT UINTN *Size\r
1051 )\r
1052{\r
1053 EFI_STATUS Status;\r
1054 EFI_PEI_HOB_POINTERS Hob;\r
1055 EFI_MEMORY_TYPE_INFORMATION *MemoryData;\r
1056 UINT8 Index;\r
1057 UINTN TempPageNum;\r
1058\r
1059 MemoryData = NULL;\r
1060 TempPageNum = 0;\r
1061 Index = 0;\r
1062\r
1063 Status = PeiServicesGetHobList ((VOID **)&Hob.Raw);\r
1064 while (!END_OF_HOB_LIST (Hob)) {\r
1065 if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&\r
1066 CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)\r
1067 ) {\r
1068 MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));\r
1069 break;\r
1070 }\r
1071\r
1072 Hob.Raw = GET_NEXT_HOB (Hob);\r
1073 }\r
1074 //\r
1075 // Platform PEIM should supply such a information. Generic PEIM doesn't assume any default value\r
1076 //\r
1077 if (!MemoryData) {\r
1078 return ;\r
1079 }\r
1080\r
1081 while (MemoryData[Index].Type != EfiMaxMemoryType) {\r
1082 //\r
1083 // Accumulate default memory size requirements\r
1084 //\r
1085 TempPageNum += MemoryData[Index].NumberOfPages;\r
1086 Index++;\r
1087 }\r
1088\r
1089 if (TempPageNum == 0) {\r
1090 return ;\r
1091 }\r
1092\r
1093 //\r
1094 // Add additional pages used by DXE memory manager\r
1095 //\r
1096 (*Size) = (TempPageNum + EDKII_DXE_MEM_SIZE_PAGES) * EFI_PAGE_SIZE;\r
1097\r
1098 return ;\r
1099}\r
1100\r
1101/**\r
1102\r
1103 This function returns the memory ranges to be enabled, along with information\r
1104 describing how the range should be used.\r
1105\r
1106 @param PeiServices PEI Services Table.\r
1107 @param TimingData Detected DDR timing parameters for installed memory.\r
1108 @param RowConfArray Pointer to an array of EFI_DUAL_CHANNEL_DDR_ROW_CONFIG structures. The number\r
1109 of items in the array must match MaxRows returned by the McGetRowInfo() function.\r
1110 @param MemoryMap Buffer to record details of the memory ranges tobe enabled.\r
1111 @param NumRanges On input, this contains the maximum number of memory ranges that can be described\r
1112 in the MemoryMap buffer.\r
1113\r
1114 @return MemoryMap The buffer will be filled in\r
1115 NumRanges will contain the actual number of memory ranges that are to be anabled.\r
1116 EFI_SUCCESS The function completed successfully.\r
1117\r
1118**/\r
1119EFI_STATUS\r
1120GetMemoryMap (\r
1121 IN EFI_PEI_SERVICES **PeiServices,\r
1122 IN UINT32 TotalMemorySize,\r
1123 IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,\r
1124 IN OUT UINT8 *NumRanges\r
1125 )\r
1126{\r
1127 EFI_PHYSICAL_ADDRESS MemorySize;\r
1128 EFI_PHYSICAL_ADDRESS RowLength;\r
1129 EFI_STATUS Status;\r
1130 PEI_MEMORY_RANGE_PCI_MEMORY PciMemoryMask;\r
1131 PEI_MEMORY_RANGE_OPTION_ROM OptionRomMask;\r
1132 PEI_MEMORY_RANGE_SMRAM SmramMask;\r
1133 PEI_MEMORY_RANGE_SMRAM TsegMask;\r
1134 UINT32 BlockNum;\r
1135 UINT8 EsmramcRegister;\r
1136 UINT8 ExtendedMemoryIndex;\r
1137 UINT32 Register;\r
1138\r
1139 if ((*NumRanges) < MAX_RANGES) {\r
1140 return EFI_BUFFER_TOO_SMALL;\r
1141 }\r
1142\r
1143 *NumRanges = 0;\r
1144\r
1145 //\r
1146 // Find out which memory ranges to reserve on this platform\r
1147 //\r
1148 Status = ChooseRanges (\r
1149 &OptionRomMask,\r
1150 &SmramMask,\r
1151 &PciMemoryMask\r
1152 );\r
1153 ASSERT_EFI_ERROR (Status);\r
1154\r
1155 //\r
1156 // Generate Memory ranges for the memory map.\r
1157 //\r
1158 EsmramcRegister = 0;\r
1159 MemorySize = 0;\r
1160\r
1161 RowLength = TotalMemorySize;\r
1162\r
1163 //\r
1164 // Add memory below 640KB to the memory map. Make sure memory between\r
1165 // 640KB and 1MB are reserved, even if not used for SMRAM\r
1166 //\r
1167 MemoryMap[*NumRanges].PhysicalAddress = MemorySize;\r
1168 MemoryMap[*NumRanges].CpuAddress = MemorySize;\r
1169 MemoryMap[*NumRanges].RangeLength = 0xA0000;\r
1170 MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;\r
1171 (*NumRanges)++;\r
1172\r
1173 //\r
1174 // Just mark this range reserved\r
1175 //\r
1176 MemoryMap[*NumRanges].PhysicalAddress = 0xA0000;\r
1177 MemoryMap[*NumRanges].CpuAddress = 0xA0000;\r
1178 MemoryMap[*NumRanges].RangeLength = 0x60000;\r
1179 MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;\r
1180 (*NumRanges)++;\r
1181\r
1182 RowLength -= (0x100000 - MemorySize);\r
1183 MemorySize = 0x100000;\r
1184\r
1185 //\r
1186 // Add remaining memory to the memory map\r
1187 //\r
1188 MemoryMap[*NumRanges].PhysicalAddress = MemorySize;\r
1189 MemoryMap[*NumRanges].CpuAddress = MemorySize;\r
1190 MemoryMap[*NumRanges].RangeLength = RowLength;\r
1191 MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;\r
1192 (*NumRanges)++;\r
1193 MemorySize += RowLength;\r
1194\r
1195 ExtendedMemoryIndex = (UINT8) (*NumRanges - 1);\r
1196\r
1197 // See if we need to trim TSEG out of the highest memory range\r
1198 //\r
1199 if (SmramMask & PEI_MR_SMRAM_TSEG_MASK) {//pcd\r
1200 //\r
1201 // Create the new range for TSEG and remove that range from the previous SdrDdrMainMemory range\r
1202 //\r
1203 TsegMask = (SmramMask & PEI_MR_SMRAM_SIZE_MASK);\r
1204\r
1205 BlockNum = 1;\r
1206 while (TsegMask) {\r
1207 TsegMask >>= 1;\r
1208 BlockNum <<= 1;\r
1209 }\r
1210\r
1211 BlockNum >>= 1;\r
1212\r
1213 if (BlockNum) {\r
1214\r
1215 MemoryMap[*NumRanges].RangeLength = (BlockNum * 128 * 1024);\r
1216 Register = (UINT32)((MemorySize - 1) & SMM_END_MASK);\r
1217 MemorySize -= MemoryMap[*NumRanges].RangeLength;\r
1218 MemoryMap[*NumRanges].PhysicalAddress = MemorySize;\r
1219 MemoryMap[*NumRanges].CpuAddress = MemorySize;\r
1220 MemoryMap[ExtendedMemoryIndex].RangeLength -= MemoryMap[*NumRanges].RangeLength;\r
1221\r
1222 //\r
1223 // Update QuarkNcSoc HSMMCTL register\r
1224 //\r
1225 Register |= (UINT32)(((RShiftU64(MemorySize, 16)) & SMM_START_MASK) + (SMM_WRITE_OPEN | SMM_READ_OPEN | SMM_CODE_RD_OPEN));\r
1226 QncHsmmcWrite (Register);\r
1227 }\r
1228\r
1229 //\r
1230 // Chipset only supports cacheable SMRAM\r
1231 //\r
1232 MemoryMap[*NumRanges].Type = DualChannelDdrSmramCacheable;\r
1233\r
1234 (*NumRanges)++;\r
1235 }\r
1236\r
1237 //\r
1238 // trim 64K memory from highest memory range for Rmu Main binary shadow\r
1239 //\r
1240 MemoryMap[*NumRanges].RangeLength = 0x10000;\r
1241 MemorySize -= MemoryMap[*NumRanges].RangeLength;\r
1242 MemoryMap[*NumRanges].PhysicalAddress = MemorySize;\r
1243 MemoryMap[*NumRanges].CpuAddress = MemorySize;\r
1244 MemoryMap[ExtendedMemoryIndex].RangeLength -= MemoryMap[*NumRanges].RangeLength;\r
1245 MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;\r
1246 (*NumRanges)++;\r
1247\r
1248 return EFI_SUCCESS;\r
1249}\r
1250\r
1251/**\r
1252\r
1253Routine Description:\r
1254\r
1255 Fill in bit masks to specify reserved memory ranges on the Lakeport platform\r
1256\r
1257Arguments:\r
1258\r
1259Returns:\r
1260\r
1261 OptionRomMask - Bit mask specifying memory regions reserved for Legacy option\r
1262 ROM use (if any)\r
1263\r
1264 SmramMask - Bit mask specifying memory regions reserved for SMM use (if any)\r
1265\r
1266**/\r
1267EFI_STATUS\r
1268ChooseRanges (\r
1269 IN OUT PEI_MEMORY_RANGE_OPTION_ROM *OptionRomMask,\r
1270 IN OUT PEI_MEMORY_RANGE_SMRAM *SmramMask,\r
1271 IN OUT PEI_MEMORY_RANGE_PCI_MEMORY *PciMemoryMask\r
1272 )\r
1273{\r
1274\r
1275 //\r
1276 // Choose regions to reserve for Option ROM use\r
1277 //\r
1278 *OptionRomMask = PEI_MR_OPTION_ROM_NONE;\r
1279\r
1280 //\r
1281 // Choose regions to reserve for SMM use (AB/H SEG and TSEG). Size is in 128K blocks\r
1282 //\r
1283 *SmramMask = PEI_MR_SMRAM_CACHEABLE_MASK | PEI_MR_SMRAM_TSEG_MASK | ((PcdGet32(PcdTSegSize)) >> 17);\r
1284\r
1285 *PciMemoryMask = 0;\r
1286\r
1287 return EFI_SUCCESS;\r
1288}\r
1289\r
1290EFI_STATUS\r
1291GetPlatformMemorySize (\r
1292 IN EFI_PEI_SERVICES **PeiServices,\r
1293 IN EFI_BOOT_MODE BootMode,\r
1294 IN OUT UINT64 *MemorySize\r
1295 )\r
1296{\r
1297 EFI_STATUS Status;\r
1298 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;\r
1299 UINTN DataSize;\r
1300 EFI_MEMORY_TYPE_INFORMATION MemoryData [EfiMaxMemoryType + 1];\r
1301 UINTN Index;\r
1302\r
1303 DataSize = sizeof (MemoryData);\r
1304\r
1305 if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
1306\r
1307 //\r
1308 // // Treat recovery as if variable not found (eg 1st boot).\r
1309 //\r
1310 Status = EFI_NOT_FOUND;\r
1311\r
1312 } else {\r
1313 Status = PeiServicesLocatePpi (\r
1314 &gEfiPeiReadOnlyVariable2PpiGuid,\r
1315 0,\r
1316 NULL,\r
1317 (VOID **)&Variable\r
1318 );\r
1319\r
1320 ASSERT_EFI_ERROR (Status);\r
1321\r
1322 DataSize = sizeof (MemoryData);\r
1323 Status = Variable->GetVariable (\r
1324 Variable,\r
1325 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
1326 &gEfiMemoryTypeInformationGuid,\r
1327 NULL,\r
1328 &DataSize,\r
1329 &MemoryData\r
1330 );\r
1331 }\r
1332\r
1333 //\r
1334 // Accumulate maximum amount of memory needed\r
1335 //\r
1336 if (EFI_ERROR (Status)) {\r
1337 //\r
1338 // Start with minimum memory\r
1339 //\r
1340 *MemorySize = PEI_MIN_MEMORY_SIZE;\r
1341\r
1342 for (Index = 0; Index < sizeof(mDefaultQncMemoryTypeInformation) / sizeof (EFI_MEMORY_TYPE_INFORMATION); Index++) {\r
1343 *MemorySize += mDefaultQncMemoryTypeInformation[Index].NumberOfPages * EFI_PAGE_SIZE;\r
1344 }\r
1345\r
1346 //\r
1347 // Build the GUID'd HOB for DXE\r
1348 //\r
1349 BuildGuidDataHob (\r
1350 &gEfiMemoryTypeInformationGuid,\r
1351 mDefaultQncMemoryTypeInformation,\r
1352 sizeof(mDefaultQncMemoryTypeInformation)\r
1353 );\r
1354 } else {\r
1355 //\r
1356 // Start with at least PEI_MIN_MEMORY_SIZE pages of memory for the DXE Core and the DXE Stack\r
1357 //\r
1358\r
1359 *MemorySize = PEI_MIN_MEMORY_SIZE;\r
1360 for (Index = 0; Index < DataSize / sizeof (EFI_MEMORY_TYPE_INFORMATION); Index++) {\r
1361 DEBUG ((EFI_D_INFO, "Index %d, Page: %d\n", Index, MemoryData[Index].NumberOfPages));\r
1362 *MemorySize += MemoryData[Index].NumberOfPages * EFI_PAGE_SIZE;\r
1363 }\r
1364\r
1365 //\r
1366 // Build the GUID'd HOB for DXE\r
1367 //\r
1368 BuildGuidDataHob (\r
1369 &gEfiMemoryTypeInformationGuid,\r
1370 MemoryData,\r
1371 DataSize\r
1372 );\r
1373\r
1374 }\r
1375\r
1376 return EFI_SUCCESS;\r
1377}\r
1378\r
1379\r
1380EFI_STATUS\r
1381BaseMemoryTest (\r
1382 IN EFI_PEI_SERVICES **PeiServices,\r
1383 IN EFI_PHYSICAL_ADDRESS BeginAddress,\r
1384 IN UINT64 MemoryLength,\r
1385 IN PEI_MEMORY_TEST_OP Operation,\r
1386 OUT EFI_PHYSICAL_ADDRESS *ErrorAddress\r
1387 )\r
1388{\r
1389 UINT32 TestPattern;\r
1390 EFI_PHYSICAL_ADDRESS TempAddress;\r
1391 UINT32 SpanSize;\r
1392\r
1393 TestPattern = 0x5A5A5A5A;\r
1394 SpanSize = 0;\r
1395\r
1396 //\r
1397 // Make sure we don't try and test anything above the max physical address range\r
1398 //\r
1399 ASSERT (BeginAddress + MemoryLength < MAX_ADDRESS);\r
1400\r
1401 switch (Operation) {\r
1402 case Extensive:\r
1403 SpanSize = 0x4;\r
1404 break;\r
1405\r
1406 case Sparse:\r
1407 case Quick:\r
1408 SpanSize = 0x40000;\r
1409 break;\r
1410\r
1411 case Ignore:\r
1412 goto Done;\r
1413 break;\r
1414 }\r
1415 //\r
1416 // Write the test pattern into memory range\r
1417 //\r
1418 TempAddress = BeginAddress;\r
1419 while (TempAddress < BeginAddress + MemoryLength) {\r
1420 (*(UINT32 *) (UINTN) TempAddress) = TestPattern;\r
1421 TempAddress += SpanSize;\r
1422 }\r
1423 //\r
1424 // Read pattern from memory and compare it\r
1425 //\r
1426 TempAddress = BeginAddress;\r
1427 while (TempAddress < BeginAddress + MemoryLength) {\r
1428 if ((*(UINT32 *) (UINTN) TempAddress) != TestPattern) {\r
1429 *ErrorAddress = TempAddress;\r
1430 DEBUG ((EFI_D_ERROR, "Memory test failed at 0x%x.\n", TempAddress));\r
1431 return EFI_DEVICE_ERROR;\r
1432 }\r
1433\r
1434 TempAddress += SpanSize;\r
1435 }\r
1436\r
1437Done:\r
1438 return EFI_SUCCESS;\r
1439}\r
1440\r
1441/**\r
1442\r
1443 This function sets up the platform specific IMR protection for the various\r
1444 memory regions.\r
1445\r
1446 @param PeiMemoryBaseAddress Base address of memory allocated for PEI.\r
1447 @param PeiMemoryLength Length in bytes of the PEI memory (includes ACPI memory).\r
1448 @param RequiredMemSize Size in bytes of the ACPI/Runtime memory\r
1449\r
1450 @return EFI_SUCCESS The function completed successfully.\r
1451 EFI_ACCESS_DENIED Access to IMRs failed.\r
1452\r
1453**/\r
1454EFI_STATUS\r
1455SetPlatformImrPolicy (\r
1456 IN EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress,\r
1457 IN UINT64 PeiMemoryLength,\r
1458 IN UINTN RequiredMemSize\r
1459 )\r
1460{\r
1461 UINT8 Index;\r
1462 UINT32 Register;\r
1463 UINT16 DeviceId;\r
1464\r
1465 //\r
1466 // Check what Soc we are running on (read Host bridge DeviceId)\r
1467 //\r
1468 DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);\r
1469\r
1470 //\r
1471 // If any IMR register is locked then we cannot proceed\r
1472 //\r
1473 for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <=(QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index=Index+4)\r
1474 {\r
1475 Register = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index);\r
1476 if (Register & IMR_LOCK) {\r
1477 return EFI_ACCESS_DENIED;\r
1478 }\r
1479 }\r
1480\r
1481 //\r
1482 // Add IMR0 protection for the 'PeiMemory'\r
1483 //\r
1484 QncImrWrite (\r
1485 QUARK_NC_MEMORY_MANAGER_IMR0,\r
1486 (UINT32)(((RShiftU64(PeiMemoryBaseAddress, 8)) & IMRL_MASK) | IMR_EN),\r
1487 (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-RequiredMemSize + EFI_PAGES_TO_SIZE(EDKII_DXE_MEM_SIZE_PAGES-1) - 1), 8)) & IMRL_MASK),\r
1488 (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
1489 (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
1490 );\r
1491\r
1492 //\r
1493 // Add IMR2 protection for shadowed RMU binary.\r
1494 //\r
1495 QncImrWrite (\r
1496 QUARK_NC_MEMORY_MANAGER_IMR2,\r
1497 (UINT32)(((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength), 8)) & IMRH_MASK) | IMR_EN),\r
1498 (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength+PcdGet32(PcdFlashQNCMicrocodeSize)-1), 8)) & IMRH_MASK),\r
1499 (UINT32)(CPU_SNOOP + RMU + CPU0_NON_SMM),\r
1500 (UINT32)(CPU_SNOOP + RMU + CPU0_NON_SMM)\r
1501 );\r
1502\r
1503 //\r
1504 // Add IMR3 protection for the default SMRAM.\r
1505 //\r
1506 QncImrWrite (\r
1507 QUARK_NC_MEMORY_MANAGER_IMR3,\r
1508 (UINT32)(((RShiftU64((SMM_DEFAULT_SMBASE), 8)) & IMRL_MASK) | IMR_EN),\r
1509 (UINT32)((RShiftU64((SMM_DEFAULT_SMBASE+SMM_DEFAULT_SMBASE_SIZE_BYTES-1), 8)) & IMRH_MASK),\r
1510 (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
1511 (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
1512 );\r
1513\r
1514 //\r
1515 // Add IMR5 protection for the legacy S3 and AP Startup Vector region (below 1MB).\r
1516 //\r
1517 QncImrWrite (\r
1518 QUARK_NC_MEMORY_MANAGER_IMR5,\r
1519 (UINT32)(((RShiftU64(AP_STARTUP_VECTOR, 8)) & IMRL_MASK) | IMR_EN),\r
1520 (UINT32)((RShiftU64((AP_STARTUP_VECTOR + EFI_PAGE_SIZE - 1), 8)) & IMRH_MASK),\r
1521 (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
1522 (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
1523 );\r
1524\r
1525 //\r
1526 // Add IMR6 protection for the ACPI Reclaim/ACPI/Runtime Services.\r
1527 //\r
1528 QncImrWrite (\r
1529 QUARK_NC_MEMORY_MANAGER_IMR6,\r
1530 (UINT32)(((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-RequiredMemSize+EFI_PAGES_TO_SIZE(EDKII_DXE_MEM_SIZE_PAGES-1)), 8)) & IMRL_MASK) | IMR_EN),\r
1531 (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-EFI_PAGE_SIZE-1), 8)) & IMRH_MASK),\r
1532 (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
1533 (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
1534 );\r
1535\r
1536 //\r
1537 // Enable IMR4 protection of eSRAM.\r
1538 //\r
1539 QncImrWrite (\r
1540 QUARK_NC_MEMORY_MANAGER_IMR4,\r
1541 (UINT32)(((RShiftU64((UINTN)PcdGet32 (PcdEsramStage1Base), 8)) & IMRL_MASK) | IMR_EN),\r
1542 (UINT32)((RShiftU64(((UINTN)PcdGet32 (PcdEsramStage1Base) + (UINTN)PcdGet32 (PcdESramMemorySize) - 1), 8)) & IMRH_MASK),\r
1543 (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
1544 (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
1545 );\r
1546\r
1547 //\r
1548 // Enable Interrupt on IMR/SMM Violation\r
1549 //\r
1550 QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BIMRVCTL, (UINT32)(EnableIMRInt));\r
1551 if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
1552 QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BSMMVCTL, (UINT32)(EnableSMMInt));\r
1553 }\r
1554\r
1555 //\r
1556 // Disable IMR7 memory protection (eSRAM + DDR3 memory) since our policies\r
1557 // are now setup.\r
1558 //\r
1559 QncImrWrite (\r
1560 QUARK_NC_MEMORY_MANAGER_IMR7,\r
1561 (UINT32)(IMRL_RESET & ~IMR_EN),\r
1562 (UINT32)IMRH_RESET,\r
1563 (UINT32)IMRX_ALL_ACCESS,\r
1564 (UINT32)IMRX_ALL_ACCESS\r
1565 );\r
1566\r
1567 return EFI_SUCCESS;\r
1568}\r
1569\r
1570/** Return info derived from Installing Memory by MemoryInit.\r
1571\r
1572 @param[out] RmuMainBaseAddressPtr Return RmuMainBaseAddress to this location.\r
1573 @param[out] SmramDescriptorPtr Return start of Smram descriptor list to this location.\r
1574 @param[out] NumSmramRegionsPtr Return numbers of Smram regions to this location.\r
1575\r
1576 @return Address of RMU shadow region at the top of available memory.\r
1577 @return List of Smram descriptors for each Smram region.\r
1578 @return Numbers of Smram regions.\r
1579**/\r
1580VOID\r
1581EFIAPI\r
1582InfoPostInstallMemory (\r
1583 OUT UINT32 *RmuMainBaseAddressPtr OPTIONAL,\r
1584 OUT EFI_SMRAM_DESCRIPTOR **SmramDescriptorPtr OPTIONAL,\r
1585 OUT UINTN *NumSmramRegionsPtr OPTIONAL\r
1586 )\r
1587{\r
1588 EFI_STATUS Status;\r
1589 EFI_PEI_HOB_POINTERS Hob;\r
1590 UINT64 CalcLength;\r
1591 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;\r
1592\r
1593 if ((RmuMainBaseAddressPtr == NULL) && (SmramDescriptorPtr == NULL) && (NumSmramRegionsPtr == NULL)) {\r
1594 return;\r
1595 }\r
1596\r
1597 SmramHobDescriptorBlock = NULL;\r
1598 if (SmramDescriptorPtr != NULL) {\r
1599 *SmramDescriptorPtr = NULL;\r
1600 }\r
1601 if (NumSmramRegionsPtr != NULL) {\r
1602 *NumSmramRegionsPtr = 0;\r
1603 }\r
1604\r
1605 //\r
1606 // Calculate RMU shadow region base address.\r
1607 // Set to 1 MB. Since 1MB cacheability will always be set\r
1608 // until override by CSM.\r
1609 //\r
1610 CalcLength = 0x100000;\r
1611\r
1612 Status = PeiServicesGetHobList ((VOID **) &Hob.Raw);\r
1613 ASSERT_EFI_ERROR (Status);\r
1614 while (!END_OF_HOB_LIST (Hob)) {\r
1615 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
1616 if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
1617 //\r
1618 // Skip the memory region below 1MB\r
1619 //\r
1620 if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {\r
1621 CalcLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);\r
1622 }\r
1623 }\r
1624 } else if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {\r
1625 if (CompareGuid (&(Hob.Guid->Name), &gEfiSmmPeiSmramMemoryReserveGuid)) {\r
1626 SmramHobDescriptorBlock = (VOID*) (Hob.Raw + sizeof (EFI_HOB_GUID_TYPE));\r
1627 if (SmramDescriptorPtr != NULL) {\r
1628 *SmramDescriptorPtr = SmramHobDescriptorBlock->Descriptor;\r
1629 }\r
1630 if (NumSmramRegionsPtr != NULL) {\r
1631 *NumSmramRegionsPtr = SmramHobDescriptorBlock->NumberOfSmmReservedRegions;\r
1632 }\r
1633 }\r
1634 }\r
1635 Hob.Raw = GET_NEXT_HOB (Hob);\r
1636 }\r
1637\r
1638 if (RmuMainBaseAddressPtr != NULL) {\r
1639 *RmuMainBaseAddressPtr = (UINT32) CalcLength;\r
1640 }\r
1641}\r