[BOOTMGFW]:

- Start implementing the page allocator. Right now, we are able to obtain & dump the UEFI memory map.

svn path=/trunk/; revision=69045
This commit is contained in:
Alex Ionescu 2015-09-06 04:53:49 +00:00
parent 110b26a50d
commit 6713972af8
5 changed files with 651 additions and 8 deletions

View file

@ -52,6 +52,13 @@ EarlyPrint(_In_ PWCHAR Format, ...);
#define BL_CONTEXT_PAGING_ON 1
#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_LIBRARY_FLAG_REINITIALIZE 0x02
#define BL_LIBRARY_FLAG_REINITIALIZE_ALL 0x04
#define BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED 0x20
/* ENUMERATIONS **************************************************************/
typedef enum _BL_TRANSLATION_TYPE
@ -152,6 +159,19 @@ typedef enum _BL_MEMORY_TYPE
BlPalMemory = 0xF000000C,
} BL_MEMORY_TYPE;
typedef enum _BL_MEMORY_ATTR
{
BlMemoryUncached = 1,
BlMemoryWriteCombined = 2,
BlMemoryWriteThrough = 4,
BlMemoryWriteBack = 8,
BlMemoryUncachedExported = 0x10,
BlMemoryWriteProtected = 0x100,
BlMemoryReadProtected = 0x200,
BlMemoryExecuteProtected = 0x400,
BlMemoryRuntime = 0x1000000
} BL_MEMORY_ATTR;
/* DATA STRUCTURES ***********************************************************/
typedef struct _BL_LIBRARY_PARAMETERS
@ -358,6 +378,14 @@ typedef struct _BL_ARCH_CONTEXT
ULONG ContextFlags;
} BL_ARCH_CONTEXT, *PBL_ARCH_CONTEXT;
typedef struct _BL_MEMORY_DESCRIPTOR_LIST
{
LIST_ENTRY ListHead;
PLIST_ENTRY First;
PLIST_ENTRY This;
ULONG Type;
} BL_MEMORY_DESCRIPTOR_LIST, *PBL_MEMORY_DESCRIPTOR_LIST;
/* INLINE ROUTINES ***********************************************************/
FORCEINLINE
@ -382,6 +410,18 @@ BlSetupDefaultParameters (
RtlCopyMemory(LibraryParameters, &DefaultParameters, sizeof(*LibraryParameters));
}
FORCEINLINE
VOID
MmMdInitializeListHead (
_In_ PBL_MEMORY_DESCRIPTOR_LIST List
)
{
/* Initialize the list */
InitializeListHead(&List->ListHead);
List->First = &List->ListHead;
List->This = NULL;
}
/* INITIALIZATION ROUTINES ***************************************************/
NTSTATUS
@ -461,12 +501,24 @@ MmHaInitialize (
_In_ ULONG HeapAttributes
);
NTSTATUS
VOID
MmMdInitialize (
_In_ ULONG Phase,
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
);
NTSTATUS
MmFwGetMemoryMap (
_Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap,
_In_ ULONG Flags
);
VOID
MmMdFreeList(
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
);
extern ULONG MmDescriptorCallTreeCount;
extern ULONG BlpApplicationFlags;
extern BL_LIBRARY_PARAMETERS BlpLibraryParameters;
extern BL_TRANSLATION_TYPE MmTranslationType;

View file

@ -165,11 +165,11 @@ BlInitializeLibrary(
NTSTATUS Status;
/* Are we re-initializing the library? */
if (LibraryParameters->LibraryFlags & 2)
if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE)
{
/* From scratch? */
BlpLibraryParameters = *LibraryParameters;
if (LibraryParameters->LibraryFlags & 4)
if (LibraryParameters->LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
{
#if 0
/* Initialize all the core modules again */

View file

@ -151,6 +151,437 @@ EfiSetWatchdogTimer (
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiGetMemoryMap (
_Out_ UINTN* MemoryMapSize,
_Inout_ EFI_MEMORY_DESCRIPTOR *MemoryMap,
_Out_ UINTN* MapKey,
_Out_ UINTN* DescriptorSize,
_Out_ UINTN* DescriptorVersion
)
{
BL_ARCH_MODE OldMode;
EFI_STATUS EfiStatus;
/* Are we in protected mode? */
OldMode = CurrentExecutionContext->Mode;
if (OldMode != BlRealMode)
{
/* FIXME: Not yet implemented */
return STATUS_NOT_IMPLEMENTED;
}
/* Make the EFI call */
EfiStatus = EfiBS->GetMemoryMap(MemoryMapSize,
MemoryMap,
MapKey,
DescriptorSize,
DescriptorVersion);
/* Switch back to protected mode if we came from there */
if (OldMode != BlRealMode)
{
BlpArchSwitchContext(OldMode);
}
/* Convert the error to an NTSTATUS */
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiFreePages (
_In_ ULONG Pages,
_In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
)
{
BL_ARCH_MODE OldMode;
EFI_STATUS EfiStatus;
/* Are we in protected mode? */
OldMode = CurrentExecutionContext->Mode;
if (OldMode != BlRealMode)
{
/* FIXME: Not yet implemented */
return STATUS_NOT_IMPLEMENTED;
}
/* Make the EFI call */
EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages);
/* Switch back to protected mode if we came from there */
if (OldMode != BlRealMode)
{
BlpArchSwitchContext(OldMode);
}
/* Convert the error to an NTSTATUS */
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiAllocatePages (
_In_ ULONG Type,
_In_ ULONG Pages,
_Inout_ EFI_PHYSICAL_ADDRESS* Memory
)
{
BL_ARCH_MODE OldMode;
EFI_STATUS EfiStatus;
/* Are we in protected mode? */
OldMode = CurrentExecutionContext->Mode;
if (OldMode != BlRealMode)
{
/* FIXME: Not yet implemented */
return STATUS_NOT_IMPLEMENTED;
}
/* Make the EFI call */
EfiStatus = EfiBS->AllocatePages(Type, EfiLoaderData, Pages, Memory);
/* Switch back to protected mode if we came from there */
if (OldMode != BlRealMode)
{
BlpArchSwitchContext(OldMode);
}
/* Convert the error to an NTSTATUS */
return EfiGetNtStatusCode(EfiStatus);
}
BL_MEMORY_ATTR
MmFwpGetOsAttributeType (
_In_ ULONGLONG Attribute
)
{
BL_MEMORY_ATTR OsAttribute = 0;
if (Attribute & EFI_MEMORY_UC)
{
OsAttribute = BlMemoryUncached;
}
if (Attribute & EFI_MEMORY_WC)
{
OsAttribute |= BlMemoryWriteCombined;
}
if (Attribute & EFI_MEMORY_WT)
{
OsAttribute |= BlMemoryWriteThrough;
}
if (Attribute & EFI_MEMORY_WB)
{
OsAttribute |= BlMemoryWriteBack;
}
if (Attribute & EFI_MEMORY_UCE)
{
OsAttribute |= BlMemoryUncachedExported;
}
if (Attribute & EFI_MEMORY_WP)
{
OsAttribute |= BlMemoryWriteProtected;
}
if (Attribute & EFI_MEMORY_RP)
{
OsAttribute |= BlMemoryReadProtected;
}
if (Attribute & EFI_MEMORY_XP)
{
OsAttribute |= BlMemoryExecuteProtected;
}
if (Attribute & EFI_MEMORY_RUNTIME)
{
OsAttribute |= BlMemoryRuntime;
}
return OsAttribute;
}
BL_MEMORY_TYPE
MmFwpGetOsMemoryType (
_In_ EFI_MEMORY_TYPE MemoryType
)
{
BL_MEMORY_TYPE OsType;
switch (MemoryType)
{
case EfiLoaderCode:
case EfiLoaderData:
OsType = BlLoaderMemory;
break;
case EfiBootServicesCode:
case EfiBootServicesData:
OsType = BlEfiBootMemory;
break;
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
OsType = BlEfiRuntimeMemory;
break;
case EfiConventionalMemory:
OsType = BlConventionalMemory;
break;
case EfiUnusableMemory:
OsType = BlUnusableMemory;
break;
case EfiACPIReclaimMemory:
OsType = BlAcpiReclaimMemory;
break;
case EfiACPIMemoryNVS:
OsType = BlAcpiNvsMemory;
break;
case EfiMemoryMappedIO:
OsType = BlDeviceIoMemory;
break;
case EfiMemoryMappedIOPortSpace:
OsType = BlDevicePortMemory;
break;
case EfiPalCode:
OsType = BlPalMemory;
break;
default:
OsType = BlReservedMemory;
break;
}
return OsType;
}
NTSTATUS
MmFwGetMemoryMap (
_Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap,
_In_ ULONG Flags
)
{
BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
BOOLEAN UseEfiBuffer;
NTSTATUS Status;
ULONGLONG Pages, StartPage, EndPage;
UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
EFI_PHYSICAL_ADDRESS EfiBuffer;
EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
EFI_STATUS EfiStatus;
BL_ARCH_MODE OldMode;
EFI_MEMORY_DESCRIPTOR EfiDescriptor;
BL_MEMORY_TYPE MemoryType;
/* Increment the nesting depth */
MmDescriptorCallTreeCount++;
/* Determine if we should use EFI or our own allocator at this point */
UseEfiBuffer = Flags & BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS;
if (!(LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED))
{
UseEfiBuffer = TRUE;
}
/* Bail out if we don't have a list to use */
if (MemoryMap == NULL)
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* Free the current descriptor list */
MmMdFreeList(MemoryMap);
/* Call into EFI to get the size of the memory map */
Status = EfiGetMemoryMap(&EfiMemoryMapSize,
NULL,
&MapKey,
&DescriptorSize,
&DescriptorVersion);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
/* This should've failed because our buffer was too small, nothing else */
EarlyPrint(L"Got strange EFI status for memory map: %lx\n", Status);
if (NT_SUCCESS(Status))
{
Status = STATUS_UNSUCCESSFUL;
}
goto Quickie;
}
/* Add 4 more descriptors just in case things changed */
EfiMemoryMapSize += (4 * DescriptorSize);
Pages = BYTES_TO_PAGES(EfiMemoryMapSize);
EarlyPrint(L"Memory map size: %lx bytes, %d pages\n", EfiMemoryMapSize, Pages);
/* Should we use EFI to grab memory? */
if (UseEfiBuffer)
{
/* Yes -- request one more page to align up correctly */
Pages++;
/* Grab the required pages */
Status = EfiAllocatePages(AllocateAnyPages,
Pages,
&EfiBuffer);
if (!NT_SUCCESS(Status))
{
EarlyPrint(L"EFI allocation failed: %lx\n", Status);
goto Quickie;
}
/* Free the pages for now */
Status = EfiFreePages(Pages, EfiBuffer);
if (!NT_SUCCESS(Status))
{
EfiBuffer = 0;
goto Quickie;
}
/* Now round to the actual buffer size, removing the extra page */
EfiBuffer = ROUND_TO_PAGES(EfiBuffer);
Pages--;
Status = EfiAllocatePages(AllocateAddress,
Pages,
&EfiBuffer);
if (!NT_SUCCESS(Status))
{
EfiBuffer = 0;
goto Quickie;
}
/* Get the final aligned size and proper buffer */
EfiMemoryMapSize = EFI_PAGES_TO_SIZE(Pages);
EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)(ULONG_PTR)EfiBuffer;
/* Switch to real mode if not already in it */
OldMode = CurrentExecutionContext->Mode;
if (OldMode != BlRealMode)
{
BlpArchSwitchContext(BlRealMode);
}
/* Call EFI to get the memory map */
EfiStatus = EfiBS->GetMemoryMap(&EfiMemoryMapSize,
EfiMemoryMap,
&MapKey,
&DescriptorSize,
&DescriptorVersion);
/* Switch back into the previous mode */
if (OldMode != BlRealMode)
{
BlpArchSwitchContext(OldMode);
}
/* Convert the result code */
Status = EfiGetNtStatusCode(EfiStatus);
}
else
{
/* We don't support this path yet */
Status = STATUS_NOT_IMPLEMENTED;
}
/* So far so good? */
if (!NT_SUCCESS(Status))
{
EarlyPrint(L"Failed to get EFI memory map: %lx\n", Status);
goto Quickie;
}
/* Did we get correct data from firmware? */
if (((EfiMemoryMapSize % DescriptorSize)) ||
(DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR)))
{
EarlyPrint(L"Incorrect descriptor size\n");
Status = STATUS_UNSUCCESSFUL;
goto Quickie;
}
/* Loop the EFI memory map */
EarlyPrint(L"UEFI MEMORY MAP\n\n");
EarlyPrint(L"TYPE START END ATTRIBUTES\n");
EarlyPrint(L"===============================================================\n");
while (EfiMemoryMapSize != 0)
{
/* Check if this is an EFI buffer, but we're not in real mode */
if ((UseEfiBuffer) && (OldMode != BlRealMode))
{
BlpArchSwitchContext(BlRealMode);
}
/* Capture it so we can go back to protected mode (if possible) */
EfiDescriptor = *EfiMemoryMap;
/* Go back to protected mode, if we had switched */
if ((UseEfiBuffer) && (OldMode != BlRealMode))
{
BlpArchSwitchContext(OldMode);
}
/* Convert to OS memory type */
MemoryType = MmFwpGetOsMemoryType(EfiDescriptor.Type);
/* Round up or round down depending on where the memory is coming from */
if (MemoryType == BlConventionalMemory)
{
StartPage = BYTES_TO_PAGES(EfiDescriptor.PhysicalStart);
}
else
{
StartPage = EfiDescriptor.PhysicalStart >> PAGE_SHIFT;
}
/* Calculate the ending page */
EndPage = StartPage + EfiDescriptor.NumberOfPages;
/* If after rounding, we ended up with 0 pages, skip this */
if (StartPage == EndPage)
{
goto LoopAgain;
}
EarlyPrint(L"%08X 0x%016I64X-0x%016I64X 0x%X\n",
MemoryType,
StartPage << PAGE_SHIFT,
EndPage << PAGE_SHIFT,
EfiDescriptor.Attribute);
/* Consume this descriptor, and move to the next one */
LoopAgain:
EfiMemoryMapSize -= DescriptorSize;
EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize);
}
Quickie:
/* Free the EFI buffer, if we had one */
if (EfiBuffer != 0)
{
EfiFreePages(Pages, EfiBuffer);
}
/* On failure, free the memory map if one was passed in */
if (!NT_SUCCESS(Status) && (MemoryMap != NULL))
{
MmMdFreeList(MemoryMap);
}
/* Decrement the nesting depth and return */
MmDescriptorCallTreeCount--;
return Status;
}
NTSTATUS
BlpFwInitialize (
_In_ ULONG Phase,

View file

@ -12,15 +12,128 @@
/* DATA VARIABLES ************************************************************/
BL_MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[512];
ULONG MmGlobalMemoryDescriptorCount;
PBL_MEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
BOOLEAN MmGlobalMemoryDescriptorsUsed;
PBL_MEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
ULONG MmDynamicMemoryDescriptorCount;
/* FUNCTIONS *****************************************************************/
VOID
MmMdpSwitchToDynamicDescriptors (
_In_ ULONG Count
)
{
EarlyPrint(L"NOT SUPPORTED!!!\n");
while (1);
}
NTSTATUS
MmMdFreeDescriptor (
_In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
)
{
NTSTATUS Status;
/* Check if this is a valid static descriptor */
if (((MmDynamicMemoryDescriptors) &&
(MemoryDescriptor >= MmDynamicMemoryDescriptors) &&
(MemoryDescriptor < (MmDynamicMemoryDescriptors + MmDynamicMemoryDescriptorCount))) ||
((MemoryDescriptor >= MmStaticMemoryDescriptors) && (MemoryDescriptor < &MmStaticMemoryDescriptors[511])))
{
/* It's a global/static descriptor, so just zero it */
RtlZeroMemory(MemoryDescriptor, sizeof(BL_MEMORY_DESCRIPTOR));
Status = STATUS_SUCCESS;
}
else
{
/* It's a dynamic descriptor, so free it */
EarlyPrint(L"Dynamic descriptors not yet supported\n");
Status = STATUS_NOT_IMPLEMENTED;
}
/* Done */
return Status;
}
VOID
MmMdpSaveCurrentListPointer (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ PLIST_ENTRY Current
)
{
/* Make sure that this is not a global descriptor and not the first one */
if (((Current < &MmGlobalMemoryDescriptors->ListEntry) ||
(Current >= &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorCount].ListEntry)) &&
(Current != MdList->First))
{
/* Save this as the current pointer */
MdList->This = Current;
}
}
VOID
MmMdRemoveDescriptorFromList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ PBL_MEMORY_DESCRIPTOR Entry
)
{
/* Remove the entry */
RemoveEntryList(&Entry->ListEntry);
/* Check if this was the current link */
if (MdList->This == &Entry->ListEntry)
{
/* Remove the current link and set the next one */
MdList->This = NULL;
MmMdpSaveCurrentListPointer(MdList, Entry->ListEntry.Blink);
}
}
VOID
MmMdFreeList(
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
)
{
PLIST_ENTRY FirstEntry, NextEntry;
PBL_MEMORY_DESCRIPTOR Entry;
/* Go over every descriptor from the top */
FirstEntry = MdList->First;
NextEntry = FirstEntry->Flink;
while (NextEntry != FirstEntry)
{
/* Remove and free each one */
Entry = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
NextEntry = NextEntry->Flink;
MmMdRemoveDescriptorFromList(MdList, Entry);
MmMdFreeDescriptor(Entry);
}
}
VOID
MmMdInitialize (
_In_ ULONG Phase,
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
)
{
EarlyPrint(L"Md init\n");
return STATUS_NOT_IMPLEMENTED;
/* Are we in phase 1? */
if (Phase != 0)
{
/* Switch to dynamic descriptors if we have too many */
if (LibraryParameters->DescriptorCount > RTL_NUMBER_OF(MmStaticMemoryDescriptors))
{
MmMdpSwitchToDynamicDescriptors(LibraryParameters->DescriptorCount);
}
}
else
{
/* In phase 0, start with a pool of 512 static descriptors */
MmGlobalMemoryDescriptorCount = RTL_NUMBER_OF(MmStaticMemoryDescriptors);
MmGlobalMemoryDescriptors = MmStaticMemoryDescriptors;
RtlZeroMemory(MmStaticMemoryDescriptors, sizeof(MmStaticMemoryDescriptors));
MmGlobalMemoryDescriptorsUsed = FALSE;
}
}

View file

@ -12,14 +12,61 @@
/* DATA VARIABLES ************************************************************/
ULONGLONG PapMaximumPhysicalPage, PapMinimumPhysicalPage;
ULONG PapMinimumAllocationCount;
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedAllocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedUnallocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlFwAllocationTracker;
BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedUnallocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlReservedAllocated;
BL_MEMORY_DESCRIPTOR_LIST MmMdlBadMemory;
BL_MEMORY_DESCRIPTOR_LIST MmMdlTruncatedMemory;
BL_MEMORY_DESCRIPTOR_LIST MmMdlPersistentMemory;
BL_MEMORY_DESCRIPTOR_LIST MmMdlCompleteBadMemory;
BL_MEMORY_DESCRIPTOR_LIST MmMdlFreeVirtual;
BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers;
/* FUNCTIONS *****************************************************************/
NTSTATUS
MmPaInitialize (
_In_ PBL_MEMORY_DATA MemoryData,
_In_ ULONG MinimumPages
__in PBL_MEMORY_DATA BootMemoryData,
__in ULONG MinimumAllocationCount
)
{
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
/* Initialize physical allocator variables */
PapMaximumPhysicalPage = 0xFFFFFFFFFFFFF;
PapMinimumAllocationCount = MinimumAllocationCount;
PapMinimumPhysicalPage = 0;
/* Initialize all the lists */
MmMdInitializeListHead(&MmMdlMappedAllocated);
MmMdInitializeListHead(&MmMdlMappedUnallocated);
MmMdInitializeListHead(&MmMdlFwAllocationTracker);
MmMdInitializeListHead(&MmMdlUnmappedAllocated);
MmMdInitializeListHead(&MmMdlReservedAllocated);
MmMdInitializeListHead(&MmMdlBadMemory);
MmMdInitializeListHead(&MmMdlTruncatedMemory);
MmMdInitializeListHead(&MmMdlPersistentMemory);
MmMdInitializeListHead(&MmMdlUnmappedUnallocated);
MmMdInitializeListHead(&MmMdlCompleteBadMemory);
/* Get the BIOS memory map */
Status = MmFwGetMemoryMap(&MmMdlUnmappedUnallocated,
BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS |
BL_MM_FLAG_UNKNOWN);
if (NT_SUCCESS(Status))
{
Status = STATUS_NOT_IMPLEMENTED;
}
/* Return status */
return Status;
}