[BOOTMGFW]:

- Cleanup some bugs/issues in the memory map parsing code.
- Implement creation of BL/NT-compatible memory descriptors based on UEFI descriptors.
- Implement other remaining parts of the page allocator initialization routine.
- Last part missing is to implement routines for removing from a memory list, and for handling the boot manager's own descriptor.

svn path=/trunk/; revision=69047
This commit is contained in:
Alex Ionescu 2015-09-06 06:15:08 +00:00
parent e25a440db4
commit 4ea30042a6
6 changed files with 511 additions and 10 deletions

View file

@ -930,10 +930,10 @@ EfiInitCreateInputParametersEx (
EfiInitScratch.MemoryDataOffset;
EfiInitScratch.BootMemoryData.DescriptorSize = sizeof(BL_MEMORY_DESCRIPTOR);
EfiInitScratch.BootMemoryData.DescriptorCount = 1;
EfiInitScratch.BootMemoryData.Unknown = 8;
EfiInitScratch.BootMemoryData.DescriptorOffset = FIELD_OFFSET(BL_MEMORY_DESCRIPTOR, BasePage);
/* Build the memory entry descriptor for this image itself */
EfiInitScratch.MemEntry.Flags = 8;
EfiInitScratch.MemEntry.Flags = BlMemoryWriteBack;
EfiInitScratch.MemEntry.Type = BlLoaderMemory;
EfiInitScratch.MemEntry.BasePage = EfiInitScratch.ImageBase >> PAGE_SHIFT;
EfiInitScratch.MemEntry.PageCount = ALIGN_UP_BY(EfiInitScratch.ImageSize, PAGE_SIZE) >> PAGE_SHIFT;

View file

@ -53,12 +53,23 @@ EarlyPrint(_In_ PWCHAR Format, ...);
#define BL_CONTEXT_INTERRUPTS_ON 2
#define BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS 0x01
#define BL_MM_FLAG_UNKNOWN 0x02
#define BL_MM_FLAG_REQUEST_COALESCING 0x02
#define BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG 0x01
#define BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG 0x02
#define BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG 0x10
#define BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG 0x20
#define BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG 0x2000
#define BL_MM_DESCRIPTOR_REQUIRES_COALESCING_FLAG 0x2000000
#define BL_MM_DESCRIPTOR_REQUIRES_UPDATING_FLAG 0x4000000
#define BL_LIBRARY_FLAG_REINITIALIZE 0x02
#define BL_LIBRARY_FLAG_REINITIALIZE_ALL 0x04
#define BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED 0x20
#define BL_MEMORY_CLASS_SHIFT 28
/* ENUMERATIONS **************************************************************/
typedef enum _BL_TRANSLATION_TYPE
@ -222,7 +233,7 @@ typedef struct _BL_MEMORY_DATA
ULONG MdListOffset;
ULONG DescriptorCount;
ULONG DescriptorSize;
ULONG Unknown;
ULONG DescriptorOffset;
} BL_MEMORY_DATA, *PBL_MEMORY_DATA;
typedef struct _BL_FIRMWARE_DESCRIPTOR
@ -518,10 +529,27 @@ MmMdFreeList(
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
);
PBL_MEMORY_DESCRIPTOR
MmMdInitByteGranularDescriptor (
_In_ ULONG Flags,
_In_ BL_MEMORY_TYPE Type,
_In_ ULONGLONG BasePage,
_In_ ULONGLONG VirtualPage,
_In_ ULONGLONG PageCount
);
NTSTATUS
MmMdAddDescriptorToList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
_In_ ULONG Flags
);
extern ULONG MmDescriptorCallTreeCount;
extern ULONG BlpApplicationFlags;
extern BL_LIBRARY_PARAMETERS BlpLibraryParameters;
extern BL_TRANSLATION_TYPE MmTranslationType;
extern PBL_ARCH_CONTEXT CurrentExecutionContext;
extern PBL_DEVICE_DESCRIPTOR BlpBootDevice;
#endif

View file

@ -371,7 +371,7 @@ MmFwGetMemoryMap (
)
{
BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
BOOLEAN UseEfiBuffer;
BOOLEAN UseEfiBuffer, HaveRamDisk;
NTSTATUS Status;
ULONGLONG Pages, StartPage, EndPage;
UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
@ -381,6 +381,11 @@ MmFwGetMemoryMap (
BL_ARCH_MODE OldMode;
EFI_MEMORY_DESCRIPTOR EfiDescriptor;
BL_MEMORY_TYPE MemoryType;
PBL_MEMORY_DESCRIPTOR Descriptor;
BL_MEMORY_ATTR Attribute;
/* Initialize EFI memory map attributes */
EfiMemoryMapSize = MapKey = DescriptorSize = DescriptorVersion = 0;
/* Increment the nesting depth */
MmDescriptorCallTreeCount++;
@ -509,6 +514,21 @@ MmFwGetMemoryMap (
goto Quickie;
}
/* Did we boot from a RAM disk? */
if ((BlpBootDevice->DeviceType == LocalDevice) &&
(BlpBootDevice->Local.Type == RamDiskDevice))
{
/* We don't handle this yet */
EarlyPrint(L"RAM boot not supported\n");
Status = STATUS_NOT_IMPLEMENTED;
goto Quickie;
}
else
{
/* We didn't, so there won't be any need to find the memory descriptor */
HaveRamDisk = FALSE;
}
/* Loop the EFI memory map */
EarlyPrint(L"UEFI MEMORY MAP\n\n");
EarlyPrint(L"TYPE START END ATTRIBUTES\n");
@ -552,18 +572,137 @@ MmFwGetMemoryMap (
goto LoopAgain;
}
EarlyPrint(L"%08X 0x%016I64X-0x%016I64X 0x%X\n",
EarlyPrint(L"%08X 0x%016I64X-0x%016I64X 0x%I64X\n",
MemoryType,
StartPage << PAGE_SHIFT,
EndPage << PAGE_SHIFT,
EfiDescriptor.Attribute);
/* Consume this descriptor, and move to the next one */
/* Check for any range of memory below 1MB */
if (StartPage < 0x100)
{
/* Does this range actually contain NULL? */
if (StartPage == 0)
{
/* Manually create a reserved descriptof for this page */
Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
Descriptor = MmMdInitByteGranularDescriptor(Attribute,
BlReservedMemory,
0,
0,
1);
if (!Descriptor)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Add this descriptor into the list */
Status = MmMdAddDescriptorToList(MemoryMap,
Descriptor,
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
if (!NT_SUCCESS(Status))
{
EarlyPrint(L"Failed to add zero page descriptor: %lx\n", Status);
break;
}
/* Now handle the rest of the range, unless this was it */
StartPage = 1;
if (EndPage == 1)
{
goto LoopAgain;
}
}
/* Does the range go beyond 1MB? */
if (EndPage > 0x100)
{
/* Then create the descriptor for everything up until the megabyte */
Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
Descriptor = MmMdInitByteGranularDescriptor(Attribute,
MemoryType,
StartPage,
0,
0x100 - StartPage);
if (!Descriptor)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Check if this region is currently free RAM */
if (Descriptor->Type == BlConventionalMemory)
{
/* Set an unknown flag on the descriptor */
Descriptor->Flags |= 0x80000;
}
/* Add this descriptor into the list */
Status = MmMdAddDescriptorToList(MemoryMap,
Descriptor,
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
if (!NT_SUCCESS(Status))
{
EarlyPrint(L"Failed to add 1MB descriptor: %lx\n", Status);
break;
}
/* Now handle the rest of the range above 1MB */
StartPage = 0x100;
}
}
/* Check if we loaded from a RAM disk */
if (HaveRamDisk)
{
/* We don't handle this yet */
EarlyPrint(L"RAM boot not supported\n");
Status = STATUS_NOT_IMPLEMENTED;
goto Quickie;
}
/* Create a descriptor for the current range */
Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
Descriptor = MmMdInitByteGranularDescriptor(Attribute,
MemoryType,
StartPage,
0,
EndPage - StartPage);
if (!Descriptor)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Check if this region is currently free RAM below 1MB */
if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100))
{
/* Set an unknown flag on the descriptor */
Descriptor->Flags |= 0x80000;
}
/* Add the descriptor to the list, requesting coalescing as asked */
Status = MmMdAddDescriptorToList(MemoryMap,
Descriptor,
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG |
(Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0);
if (!NT_SUCCESS(Status))
{
EarlyPrint(L"Failed to add full descriptor: %lx\n", Status);
break;
}
LoopAgain:
/* Consume this descriptor, and move to the next one */
EfiMemoryMapSize -= DescriptorSize;
EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize);
}
/* FIXME: @TODO: Mark the EfiBuffer as free, since we're about to free it */
/* For now, just "leak" the 1-2 pages... */
Quickie:
/* Free the EFI buffer, if we had one */
if (EfiBuffer != 0)

View file

@ -19,8 +19,131 @@ BOOLEAN MmGlobalMemoryDescriptorsUsed;
PBL_MEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
ULONG MmDynamicMemoryDescriptorCount;
BL_MEMORY_TYPE MmPlatformMemoryTypePrecedence[] =
{
BlReservedMemory,
BlUnusableMemory,
BlDeviceIoMemory,
BlDevicePortMemory,
BlPalMemory,
BlEfiRuntimeMemory,
BlAcpiNvsMemory,
BlAcpiReclaimMemory,
BlEfiBootMemory
};
/* FUNCTIONS *****************************************************************/
/* The order is Conventional > Other > System > Loader > Application */
BOOLEAN
MmMdpHasPrecedence (
_In_ BL_MEMORY_TYPE Type1,
_In_ BL_MEMORY_TYPE Type2
)
{
BL_MEMORY_CLASS Class1, Class2;
ULONG i, j;
/* Descriptor is free RAM -- it preceeds */
if (Type1 == BlConventionalMemory)
{
return TRUE;
}
/* It isn't free RAM, but the comparator is -- it suceeds it */
if (Type2 == BlConventionalMemory)
{
return FALSE;
}
/* Descriptor is not system, application, or loader class -- it preceeds */
Class1 = Type1 >> BL_MEMORY_CLASS_SHIFT;
if ((Class1 != BlSystemClass) &&
(Class1 != BlApplicationClass) &&
(Class1 != BlLoaderClass))
{
return TRUE;
}
/* It isn't one of those classes, but the comparator it -- it suceeds it */
Class2 = Type2 >> BL_MEMORY_CLASS_SHIFT;
if ((Class2 != BlSystemClass) &&
(Class2 != BlApplicationClass) &&
(Class2 != BlLoaderClass))
{
return FALSE;
}
/* Descriptor is system class */
if (Class1 == BlSystemClass)
{
/* And so is the other guy... */
if (Class2 == BlSystemClass)
{
i = 0;
j = 0;
/* Scan for the descriptor's system precedence index */
do
{
if (MmPlatformMemoryTypePrecedence[j] == Type1)
{
break;
}
} while (++j < RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence));
/* Use an invalid index if one wasn't found */
if (j == RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence))
{
j = 0xFFFFFFFF;
}
/* Now scan for the comparator's system precedence index */
while (MmPlatformMemoryTypePrecedence[i] != Type2)
{
/* Use an invalid index if one wasn't found */
if (++i >= RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence))
{
i = 0xFFFFFFFF;
break;
}
}
/* Does the current have a valid index? */
if (j != 0xFFFFFFFF)
{
/* Yes, what about the comparator? */
if (i != 0xFFFFFFFF)
{
/* Let the indexes fight! */
return i >= j;
}
/* Succeed the comparator, its index is unknown */
return FALSE;
}
}
/* The comparator isn't system, so it preceeds it */
return TRUE;
}
/* Descriptor is not system class, but comparator is -- it suceeds it */
if (Class2 == BlSystemClass)
{
return FALSE;
}
/* Descriptor is loader class -- it preceeds */
if (Class1 == BlLoaderClass)
{
return TRUE;
}
/* It isn't loader class -- if the other guy is, suceed it */
return Class2 != BlLoaderClass;
}
VOID
MmMdpSwitchToDynamicDescriptors (
_In_ ULONG Count
@ -113,6 +236,157 @@ MmMdFreeList(
}
}
PBL_MEMORY_DESCRIPTOR
MmMdInitByteGranularDescriptor (
_In_ ULONG Flags,
_In_ BL_MEMORY_TYPE Type,
_In_ ULONGLONG BasePage,
_In_ ULONGLONG VirtualPage,
_In_ ULONGLONG PageCount
)
{
PBL_MEMORY_DESCRIPTOR MemoryDescriptor;
/* If we're out of descriptors, bail out */
if (MmGlobalMemoryDescriptorsUsed >= MmGlobalMemoryDescriptorCount)
{
EarlyPrint(L"Out of descriptors!\n");
return NULL;
}
/* Take one of the available descriptors and fill it out */
MemoryDescriptor = &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorsUsed];
MemoryDescriptor->BaseAddress = BasePage;
MemoryDescriptor->VirtualPage = VirtualPage;
MemoryDescriptor->PageCount = PageCount;
MemoryDescriptor->Flags = Flags;
MemoryDescriptor->Type = Type;
InitializeListHead(&MemoryDescriptor->ListEntry);
/* Increment the count and return the descriptor */
MmGlobalMemoryDescriptorsUsed++;
return MemoryDescriptor;
}
NTSTATUS
MmMdAddDescriptorToList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor,
_In_ ULONG Flags
)
{
PLIST_ENTRY ThisEntry, FirstEntry;
PBL_MEMORY_DESCRIPTOR ThisDescriptor;
/* Arguments must be present */
if (!(MdList) || !(MemoryDescriptor))
{
return STATUS_INVALID_PARAMETER;
}
/* Check if coalescing is forcefully disabled */
if (Flags & BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG)
{
/* Then we won't be coalescing */
Flags &= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
}
else
{
/* Coalesce if the descriptor requires it */
if (MemoryDescriptor->Flags & BL_MM_DESCRIPTOR_REQUIRES_COALESCING_FLAG)
{
Flags |= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
}
}
/* Check if truncation is forcefully disabled */
if (Flags & BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG)
{
Flags &= ~BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG;
}
/* Update the current list pointer if the descriptor requires it */
if (MemoryDescriptor->Flags & BL_MM_DESCRIPTOR_REQUIRES_UPDATING_FLAG)
{
Flags |= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG;
}
/* Get the current descriptor */
ThisEntry = MdList->This;
ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
/* Also get the first descriptor */
FirstEntry = MdList->First;
/* Check if there's no current pointer, or if it's higher than the new one */
if (!(ThisEntry) ||
(MemoryDescriptor->BaseAddress <= ThisDescriptor->BaseAddress))
{
/* Start at the first descriptor instead, since current is past us */
ThisEntry = FirstEntry->Flink;
ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
}
/* Loop until we find the right location to insert */
while (1)
{
/* Have we gotten back to the first entry? */
if (ThisEntry == FirstEntry)
{
/* Then we didn't find a good match, so insert it right here */
InsertTailList(FirstEntry, &MemoryDescriptor->ListEntry);
/* Do we have to truncate? */
if (Flags & BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG)
{
/* Do it and then exit */
#if 0
if (MmMdpTruncateDescriptor(MdList, Flags))
{
return STATUS_SUCCESS;
}
#endif
}
/* Do we have to coalesce? */
if (Flags & BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG)
{
/* Do it and then exit */
#if 0
if (MmMdpCoalesceDescriptor(MdList))
{
return STATUS_SUCCESS;
}
#endif
}
/* Do we have to update the current pointer? */
if (Flags & BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG)
{
/* Do it */
MmMdpSaveCurrentListPointer(MdList, &MemoryDescriptor->ListEntry);
}
/* We're done */
return STATUS_SUCCESS;
}
/* Is the new descriptor below this address, and has precedence over it? */
if ((MemoryDescriptor->BaseAddress < ThisDescriptor->BaseAddress) &&
(MmMdpHasPrecedence(MemoryDescriptor->Type, ThisDescriptor->Type)))
{
/* Then insert right here */
InsertTailList(ThisEntry, &MemoryDescriptor->ListEntry);
return STATUS_SUCCESS;
}
/* Try the next descriptor */
ThisEntry = ThisEntry->Flink;
ThisDescriptor = CONTAINING_RECORD(ThisEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
}
}
VOID
MmMdInitialize (
_In_ ULONG Phase,

View file

@ -31,7 +31,8 @@ BlMmRemoveBadMemory (
VOID
)
{
return STATUS_NOT_IMPLEMENTED;
/* FIXME: Read BCD option to see what bad memory to remove */
return STATUS_SUCCESS;
}
NTSTATUS

View file

@ -16,6 +16,8 @@ ULONGLONG PapMaximumPhysicalPage, PapMinimumPhysicalPage;
ULONG PapMinimumAllocationCount;
BOOLEAN PapInitializationStatus;
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedAllocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedUnallocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlFwAllocationTracker;
@ -31,6 +33,15 @@ BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers;
/* FUNCTIONS *****************************************************************/
NTSTATUS
BlpMmInitializeConstraints (
VOID
)
{
/* FIXME: Read BCD option 'avoidlowmemory' and 'truncatememory' */
return STATUS_SUCCESS;
}
NTSTATUS
MmPaInitialize (
__in PBL_MEMORY_DATA BootMemoryData,
@ -38,6 +49,8 @@ MmPaInitialize (
)
{
NTSTATUS Status;
ULONG ExistingDescriptors, FinalOffset;
PBL_MEMORY_DESCRIPTOR Descriptor;
/* Initialize physical allocator variables */
PapMaximumPhysicalPage = 0xFFFFFFFFFFFFF;
@ -59,10 +72,56 @@ MmPaInitialize (
/* Get the BIOS memory map */
Status = MmFwGetMemoryMap(&MmMdlUnmappedUnallocated,
BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS |
BL_MM_FLAG_UNKNOWN);
BL_MM_FLAG_REQUEST_COALESCING);
if (NT_SUCCESS(Status))
{
Status = STATUS_NOT_IMPLEMENTED;
PLIST_ENTRY listHead, nextEntry;
/* Loop the NT firmware memory list */
EarlyPrint(L"NT MEMORY MAP\n\n");
listHead = &MmMdlUnmappedUnallocated.ListHead;
nextEntry = listHead->Flink;
while (listHead != nextEntry)
{
Descriptor = CONTAINING_RECORD(nextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
EarlyPrint(L"Type: %lX Flags: %lX Start: 0x%I64X End: 0x%I64X\n",
Descriptor->Type,
Descriptor->Flags,
Descriptor->BasePage << PAGE_SHIFT,
(Descriptor->BasePage + Descriptor->PageCount) << PAGE_SHIFT);
nextEntry = nextEntry->Flink;
}
/*
* Because BL supports cross x86-x64 application launches and a LIST_ENTRY
* is of variable size, care must be taken here to ensure that we see a
* consistent view of descriptors. BL uses some offset magic to figure out
* where the data actually starts, since everything is ULONGLONG past the
* LIST_ENTRY itself
*/
FinalOffset = BootMemoryData->MdListOffset + BootMemoryData->DescriptorOffset;
Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)BootMemoryData + FinalOffset -
FIELD_OFFSET(BL_MEMORY_DESCRIPTOR, BasePage));
/* Scan all of them */
ExistingDescriptors = BootMemoryData->DescriptorCount;
while (ExistingDescriptors != 0)
{
EarlyPrint(L"Existing migration of memory not supported\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
/* We are done, so check for any RAM constraints which will make us truncate memory */
Status = BlpMmInitializeConstraints();
if (NT_SUCCESS(Status))
{
/* The Page Allocator has initialized */
PapInitializationStatus = TRUE;
Status = STATUS_SUCCESS;
}
}
/* Return status */