Cohen, Eugene
2015-06-04 19:02:25 UTC
I've been debugging an SMM IPL issue and have isolated it to an assumption in the SMRAM range reservation logic in SmmIplEntry. The logic checks to see if the reserved range resides within the SMRAM descriptor and if it does it reduces the size of the SMRAM range by the start address of the reservation. The purpose of this code is to find a large enough region to load the SMM Core.
This logic is flawed in that it assumes that the reserved range is only near the end of the SMRAM descriptor:
//
// This range has reserved area, calculate the left free size
//
gSmmCorePrivate->SmramRanges[Index].PhysicalSize = SmramResRegion->SmramReservedStart - gSmmCorePrivate->SmramRanges[Index].CpuStart;
Imagine the following scenario where we just reserve the first page of the SMRAM range:
SMRAM Descriptor:
Start: 0x80000000
Size: 0x02000000
Reserved Range:
Start: 0x80000000
Size: 0x00001000
In this case the adjustment to the SMRAM range size yields zero: ReservedStart - SMRAM Start is 0x80000000 - 0x80000000 = 0. So even though most of the range is still free the IPL code decides its unusable.
I don't know what the original intent was, but maybe if the math was changed to subtract the reserved size it would yield a more sensible result:
gSmmCorePrivate->SmramRanges[Index].PhysicalSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize - SmramResRegion->SmramReservedSize;
This logic only works if the reservation fits entirely within an SMRAM descriptor range. The PI SMM spec does not state that the reserved ranges (from SMM Configuration) must reside entirely within an SMRAM range (from SMM Access). If we want to keep the implementation this simple we should clarify this requirement in the spec.
Eugene
------------------------------------------------------------------------------
This logic is flawed in that it assumes that the reserved range is only near the end of the SMRAM descriptor:
//
// This range has reserved area, calculate the left free size
//
gSmmCorePrivate->SmramRanges[Index].PhysicalSize = SmramResRegion->SmramReservedStart - gSmmCorePrivate->SmramRanges[Index].CpuStart;
Imagine the following scenario where we just reserve the first page of the SMRAM range:
SMRAM Descriptor:
Start: 0x80000000
Size: 0x02000000
Reserved Range:
Start: 0x80000000
Size: 0x00001000
In this case the adjustment to the SMRAM range size yields zero: ReservedStart - SMRAM Start is 0x80000000 - 0x80000000 = 0. So even though most of the range is still free the IPL code decides its unusable.
I don't know what the original intent was, but maybe if the math was changed to subtract the reserved size it would yield a more sensible result:
gSmmCorePrivate->SmramRanges[Index].PhysicalSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize - SmramResRegion->SmramReservedSize;
This logic only works if the reservation fits entirely within an SMRAM descriptor range. The PI SMM spec does not state that the reserved ranges (from SMM Configuration) must reside entirely within an SMRAM range (from SMM Access). If we want to keep the implementation this simple we should clarify this requirement in the spec.
Eugene
------------------------------------------------------------------------------