EFI_PEI_HOB_POINTERS Hob;\r
EFI_PLATFORM_CPU_INFO PlatformCpuInfo;\r
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *NewDescriptorBlock;\r
+ UINTN Index;\r
+ UINTN MaxIndex;\r
+ UINT64 Base;\r
UINT64 Size;\r
+ UINT64 NewSize;\r
\r
//\r
- // Make sure last SMRAM region is aligned\r
+ // Make sure base and size of the SMRAM region is aligned\r
//\r
Hob.Raw = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
if (Hob.Raw != NULL) {\r
DescriptorBlock = GET_GUID_HOB_DATA (Hob.Raw);\r
- Size = DescriptorBlock->Descriptor[DescriptorBlock->NumberOfSmmReservedRegions - 1].PhysicalSize;\r
- Size = LShiftU64 (1, HighBitSet64 (Size - 1) + 1);\r
- DescriptorBlock->Descriptor[DescriptorBlock->NumberOfSmmReservedRegions - 1].PhysicalSize = Size;\r
+ DEBUG ((DEBUG_INFO, "SMM PEI SMRAM Memory Reserved HOB\n"));\r
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+ DEBUG((DEBUG_INFO, " SMRAM Descriptor[%02x]: Start=%016lx Size=%016lx State=%02x\n",\r
+ Index,\r
+ DescriptorBlock->Descriptor[Index].PhysicalStart,\r
+ DescriptorBlock->Descriptor[Index].PhysicalSize,\r
+ DescriptorBlock->Descriptor[Index].RegionState\r
+ ));\r
+ }\r
+\r
+ //\r
+ // Find the largest usable range of SMRAM between 1MB and 4GB\r
+ //\r
+ for (Index = 0, MaxIndex = 0, Size = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+ //\r
+ // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization\r
+ //\r
+ if ((DescriptorBlock->Descriptor[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {\r
+ continue;\r
+ }\r
+ //\r
+ // Skip any SMRAM region below 1MB\r
+ //\r
+ if (DescriptorBlock->Descriptor[Index].CpuStart < BASE_1MB) {\r
+ continue;\r
+ }\r
+ //\r
+ // Skip any SMRAM region that is above 4GB or crosses the 4GB boundary\r
+ //\r
+ if ((DescriptorBlock->Descriptor[Index].CpuStart + DescriptorBlock->Descriptor[Index].PhysicalSize) >= BASE_4GB) {\r
+ continue;\r
+ }\r
+ //\r
+ // Cache the largest SMRAM region index\r
+ //\r
+ if (DescriptorBlock->Descriptor[Index].PhysicalSize >= DescriptorBlock->Descriptor[MaxIndex].PhysicalSize) {\r
+ MaxIndex = Index;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Find the extent of the contiguous SMRAM region that surrounds the largest usable SMRAM range\r
+ //\r
+ Base = DescriptorBlock->Descriptor[MaxIndex].CpuStart;\r
+ Size = DescriptorBlock->Descriptor[MaxIndex].PhysicalSize;\r
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+ if (DescriptorBlock->Descriptor[Index].CpuStart < Base &&\r
+ Base == (DescriptorBlock->Descriptor[Index].CpuStart + DescriptorBlock->Descriptor[Index].PhysicalSize)) {\r
+ Base = DescriptorBlock->Descriptor[Index].CpuStart;\r
+ Size += DescriptorBlock->Descriptor[Index].PhysicalSize;\r
+ } else if ((Base + Size) == DescriptorBlock->Descriptor[Index].CpuStart) {\r
+ Size += DescriptorBlock->Descriptor[Index].PhysicalSize;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Round SMRAM region up to nearest power of 2 that is at least 4KB\r
+ //\r
+ NewSize = MAX (LShiftU64 (1, HighBitSet64 (Size - 1) + 1), SIZE_4KB);\r
+ if ((Base & ~(NewSize - 1)) != Base) {\r
+ //\r
+ // SMRAM region Base Address has smaller alignment than SMRAM region Size\r
+ // This is not compatible with SMRR settings\r
+ //\r
+ DEBUG((DEBUG_ERROR, "ERROR: SMRAM Region Size has larger alignment than SMRAM Region Base\n"));\r
+ DEBUG((DEBUG_ERROR, " SMRAM Region Base=%016lx Size=%016lx\n", Base, NewSize));\r
+ ASSERT (FALSE);\r
+ } else if (Size != NewSize) {\r
+ //\r
+ // See if the size difference can be added to an adjacent descriptor that is already allocated\r
+ //\r
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+ if ((DescriptorBlock->Descriptor[Index].CpuStart + DescriptorBlock->Descriptor[Index].PhysicalSize) == (Base + Size)) {\r
+ if (((DescriptorBlock->Descriptor[Index].RegionState) & EFI_ALLOCATED) != 0) {\r
+ DescriptorBlock->Descriptor[Index].PhysicalSize += (NewSize - Size);\r
+ Size = NewSize;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Size != NewSize) {\r
+ //\r
+ // Add an allocated descriptor to the SMM PEI SMRAM Memory Reserved HOB to accomodate the larger size.\r
+ //\r
+ Index = DescriptorBlock->NumberOfSmmReservedRegions;\r
+ NewDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)BuildGuidHob (\r
+ &gEfiSmmPeiSmramMemoryReserveGuid,\r
+ sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + ((Index + 1) * sizeof (EFI_SMRAM_DESCRIPTOR))\r
+ );\r
+ ASSERT (NewDescriptorBlock != NULL);\r
+\r
+ //\r
+ // Copy old EFI_SMRAM_HOB_DESCRIPTOR_BLOCK to new allocated region\r
+ //\r
+ CopyMem (\r
+ NewDescriptorBlock,\r
+ DescriptorBlock,\r
+ sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + (Index * sizeof (EFI_SMRAM_DESCRIPTOR))\r
+ );\r
+\r
+ //\r
+ // Make sure last descriptor in NewDescriptorBlock contains last descriptor from DescriptorBlock\r
+ //\r
+ CopyMem (\r
+ &NewDescriptorBlock->Descriptor[Index],\r
+ &NewDescriptorBlock->Descriptor[Index - 1],\r
+ sizeof (EFI_SMRAM_DESCRIPTOR)\r
+ );\r
+\r
+ //\r
+ // Fill next to last descriptor with an allocated descriptor that aligns the total size of SMRAM\r
+ //\r
+ NewDescriptorBlock->Descriptor[Index - 1].CpuStart = Base + Size;\r
+ NewDescriptorBlock->Descriptor[Index - 1].PhysicalStart = Base + Size;\r
+ NewDescriptorBlock->Descriptor[Index - 1].PhysicalSize = NewSize - Size;\r
+ NewDescriptorBlock->Descriptor[Index - 1].RegionState = DescriptorBlock->Descriptor[MaxIndex].RegionState | EFI_ALLOCATED;\r
+ NewDescriptorBlock->NumberOfSmmReservedRegions++;\r
+\r
+ //\r
+ // Invalidate the original gEfiSmmPeiSmramMemoryReserveGuid HOB\r
+ //\r
+ ZeroMem (&Hob.Guid->Name, sizeof (&Hob.Guid->Name));\r
+ }\r
+\r
+ Hob.Raw = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
+ DescriptorBlock = GET_GUID_HOB_DATA (Hob.Raw);\r
+ DEBUG ((DEBUG_INFO, "SMM PEI SMRAM Memory Reserved HOB - Updated\n"));\r
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+ DEBUG((DEBUG_INFO, " SMRAM Descriptor[%02x]: Start=%016lx Size=%016lx State=%02x\n",\r
+ Index,\r
+ DescriptorBlock->Descriptor[Index].PhysicalStart,\r
+ DescriptorBlock->Descriptor[Index].PhysicalSize,\r
+ DescriptorBlock->Descriptor[Index].RegionState\r
+ ));\r
+ }\r
+ }\r
}\r
\r
//\r