/** @file\r
Framework PEIM to initialize memory on a Quark Memory Controller.\r
\r
-Copyright (c) 2013 Intel Corporation.\r
+Copyright (c) 2013 - 2016, Intel Corporation.\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
UINT64 PeiMemoryLength;\r
UINTN BufferSize;\r
UINTN PeiMemoryIndex;\r
- UINTN RequiredMemSize;\r
EFI_RESOURCE_ATTRIBUTE_TYPE Attribute;\r
EFI_PHYSICAL_ADDRESS BadMemoryAddress;\r
EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;\r
PEI_CAPSULE_PPI *Capsule;\r
VOID *LargeMemRangeBuf;\r
UINTN LargeMemRangeBufLen;\r
+ UINT8 MorControl;\r
+ UINTN DataSize;\r
\r
//\r
// Test the memory from 1M->TOM\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Get required memory size for ACPI use. This helps to put ACPI memory on the topest\r
+ // Detect MOR request by the OS.\r
//\r
- RequiredMemSize = 0;\r
- RetriveRequiredMemorySize (PeiServices, &RequiredMemSize);\r
+ MorControl = 0;\r
+ DataSize = sizeof (MorControl);\r
+ Status = VariableServices->GetVariable (\r
+ VariableServices,\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &MorControl\r
+ );\r
\r
PeiMemoryIndex = 0;\r
\r
DEBUG ((EFI_D_INFO, "Found 0x%x bytes at ", MemoryMap[Index].RangeLength));\r
DEBUG ((EFI_D_INFO, "0x%x.\n", MemoryMap[Index].PhysicalAddress));\r
\r
+ //\r
+ // If OS requested a memory overwrite perform it now. Only do it for memory\r
+ // used by the OS.\r
+ //\r
+ if (MOR_CLEAR_MEMORY_VALUE (MorControl) && MemoryMap[Index].Type == DualChannelDdrMainMemory) {\r
+ DEBUG ((EFI_D_INFO, "Clear memory per MOR request.\n"));\r
+ if ((UINTN)MemoryMap[Index].RangeLength > 0) {\r
+ if ((UINTN)MemoryMap[Index].PhysicalAddress == 0) {\r
+ //\r
+ // ZeroMem() generates an ASSERT() if Buffer parameter is NULL.\r
+ // Clear byte at 0 and start clear operation at address 1.\r
+ //\r
+ *(UINT8 *)(0) = 0;\r
+ ZeroMem ((VOID *)1, (UINTN)MemoryMap[Index].RangeLength - 1);\r
+ } else {\r
+ ZeroMem (\r
+ (VOID *)(UINTN)MemoryMap[Index].PhysicalAddress,\r
+ (UINTN)MemoryMap[Index].RangeLength\r
+ );\r
+ }\r
+ }\r
+ }\r
+\r
if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&\r
(MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS) &&\r
(MemoryMap[Index].PhysicalAddress >= PeiMemoryBaseAddress) &&\r
//\r
Status = SetPlatformImrPolicy (\r
PeiMemoryBaseAddress,\r
- PeiMemoryLength,\r
- RequiredMemSize\r
+ PeiMemoryLength\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
// Carve out the top memory reserved for ACPI\r
//\r
- Status = PeiServicesInstallPeiMemory (PeiMemoryBaseAddress, (PeiMemoryLength - RequiredMemSize));\r
+ Status = PeiServicesInstallPeiMemory (PeiMemoryBaseAddress, PeiMemoryLength);\r
ASSERT_EFI_ERROR (Status);\r
\r
BuildResourceDescriptorHob (\r
// memory above 1MB. So Memory Callback can set cache for the system memory\r
// correctly on S3 boot path, just like it does on Normal boot path.\r
//\r
- ASSERT_EFI_ERROR ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0);\r
+ ASSERT ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0);\r
BuildResourceDescriptorHob (\r
EFI_RESOURCE_SYSTEM_MEMORY,\r
(\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
-\r
- This function returns the size, in bytes, required for the DXE phase.\r
-\r
- @param PeiServices PEI Services table.\r
- @param Size Pointer to the size, in bytes, required for the DXE phase.\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-RetriveRequiredMemorySize (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- OUT UINTN *Size\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PEI_HOB_POINTERS Hob;\r
- EFI_MEMORY_TYPE_INFORMATION *MemoryData;\r
- UINT8 Index;\r
- UINTN TempPageNum;\r
-\r
- MemoryData = NULL;\r
- TempPageNum = 0;\r
- Index = 0;\r
-\r
- Status = PeiServicesGetHobList ((VOID **)&Hob.Raw);\r
- while (!END_OF_HOB_LIST (Hob)) {\r
- if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&\r
- CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)\r
- ) {\r
- MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));\r
- break;\r
- }\r
-\r
- Hob.Raw = GET_NEXT_HOB (Hob);\r
- }\r
- //\r
- // Platform PEIM should supply such a information. Generic PEIM doesn't assume any default value\r
- //\r
- if (!MemoryData) {\r
- return ;\r
- }\r
-\r
- while (MemoryData[Index].Type != EfiMaxMemoryType) {\r
- //\r
- // Accumulate default memory size requirements\r
- //\r
- TempPageNum += MemoryData[Index].NumberOfPages;\r
- Index++;\r
- }\r
-\r
- if (TempPageNum == 0) {\r
- return ;\r
- }\r
-\r
- //\r
- // Add additional pages used by DXE memory manager\r
- //\r
- (*Size) = (TempPageNum + EDKII_DXE_MEM_SIZE_PAGES) * EFI_PAGE_SIZE;\r
-\r
- return ;\r
-}\r
-\r
/**\r
\r
This function returns the memory ranges to be enabled, along with information\r
PEI_MEMORY_RANGE_SMRAM SmramMask;\r
PEI_MEMORY_RANGE_SMRAM TsegMask;\r
UINT32 BlockNum;\r
- UINT8 EsmramcRegister;\r
UINT8 ExtendedMemoryIndex;\r
UINT32 Register;\r
\r
//\r
// Generate Memory ranges for the memory map.\r
//\r
- EsmramcRegister = 0;\r
MemorySize = 0;\r
\r
RowLength = TotalMemorySize;\r
\r
@param PeiMemoryBaseAddress Base address of memory allocated for PEI.\r
@param PeiMemoryLength Length in bytes of the PEI memory (includes ACPI memory).\r
- @param RequiredMemSize Size in bytes of the ACPI/Runtime memory\r
\r
@return EFI_SUCCESS The function completed successfully.\r
EFI_ACCESS_DENIED Access to IMRs failed.\r
EFI_STATUS\r
SetPlatformImrPolicy (\r
IN EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress,\r
- IN UINT64 PeiMemoryLength,\r
- IN UINTN RequiredMemSize\r
+ IN UINT64 PeiMemoryLength\r
)\r
{\r
UINT8 Index;\r
}\r
}\r
\r
- //\r
- // Add IMR0 protection for the 'PeiMemory'\r
- //\r
- QncImrWrite (\r
- QUARK_NC_MEMORY_MANAGER_IMR0,\r
- (UINT32)(((RShiftU64(PeiMemoryBaseAddress, 8)) & IMRL_MASK) | IMR_EN),\r
- (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-RequiredMemSize + EFI_PAGES_TO_SIZE(EDKII_DXE_MEM_SIZE_PAGES-1) - 1), 8)) & IMRL_MASK),\r
- (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
- (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
- );\r
-\r
//\r
// Add IMR2 protection for shadowed RMU binary.\r
//\r
(UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
);\r
\r
- //\r
- // Add IMR5 protection for the legacy S3 and AP Startup Vector region (below 1MB).\r
- //\r
- QncImrWrite (\r
- QUARK_NC_MEMORY_MANAGER_IMR5,\r
- (UINT32)(((RShiftU64(AP_STARTUP_VECTOR, 8)) & IMRL_MASK) | IMR_EN),\r
- (UINT32)((RShiftU64((AP_STARTUP_VECTOR + EFI_PAGE_SIZE - 1), 8)) & IMRH_MASK),\r
- (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
- (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
- );\r
-\r
- //\r
- // Add IMR6 protection for the ACPI Reclaim/ACPI/Runtime Services.\r
- //\r
- QncImrWrite (\r
- QUARK_NC_MEMORY_MANAGER_IMR6,\r
- (UINT32)(((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-RequiredMemSize+EFI_PAGES_TO_SIZE(EDKII_DXE_MEM_SIZE_PAGES-1)), 8)) & IMRL_MASK) | IMR_EN),\r
- (UINT32)((RShiftU64((PeiMemoryBaseAddress+PeiMemoryLength-EFI_PAGE_SIZE-1), 8)) & IMRH_MASK),\r
- (UINT32)(CPU_SNOOP + CPU0_NON_SMM),\r
- (UINT32)(CPU_SNOOP + CPU0_NON_SMM)\r
- );\r
-\r
//\r
// Enable IMR4 protection of eSRAM.\r
//\r