[BOOTLIB]: Implement BlMmGetMemoryMap.

[BOOTLIB]: Implement MmMdCountList, MmMdInitializeList, MmMdCopyList
[BOOTLIB]: Bugfixes.

svn path=/trunk/; revision=73691
This commit is contained in:
Alex Ionescu 2017-02-05 01:54:52 +00:00
parent 3cd888817c
commit e3dca9d237
4 changed files with 491 additions and 17 deletions

View file

@ -91,6 +91,7 @@ DEFINE_GUID(BadMemoryGuid, 0x54B8275B, 0xD431, 0x473F, 0xAC, 0xFB, 0xE5, 0x36, 0
#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_ALLOCATE_FLAG 0x1000
#define BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG 0x2000
#define BL_MM_INCLUDE_MAPPED_ALLOCATED 0x01
@ -101,7 +102,22 @@ DEFINE_GUID(BadMemoryGuid, 0x54B8275B, 0xD431, 0x473F, 0xAC, 0xFB, 0xE5, 0x36, 0
#define BL_MM_INCLUDE_BAD_MEMORY 0x20
#define BL_MM_INCLUDE_FIRMWARE_MEMORY 0x40
#define BL_MM_INCLUDE_TRUNCATED_MEMORY 0x80
#define BL_MM_INCLUDE_PERSISTEND_MEMORY 0x100
#define BL_MM_INCLUDE_PERSISTENT_MEMORY 0x100
#define BL_MM_INCLUDE_FIRMWARE_MEMORY_2 0x200
#define BL_MM_INCLUDE_NO_FIRMWARE_MEMORY (BL_MM_INCLUDE_PERSISTENT_MEMORY | \
BL_MM_INCLUDE_TRUNCATED_MEMORY | \
BL_MM_INCLUDE_BAD_MEMORY | \
BL_MM_INCLUDE_RESERVED_ALLOCATED | \
BL_MM_INCLUDE_UNMAPPED_UNALLOCATED | \
BL_MM_INCLUDE_UNMAPPED_ALLOCATED | \
BL_MM_INCLUDE_MAPPED_UNALLOCATED | \
BL_MM_INCLUDE_MAPPED_ALLOCATED)
C_ASSERT(BL_MM_INCLUDE_NO_FIRMWARE_MEMORY == 0x1BF);
#define BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY (BL_MM_INCLUDE_FIRMWARE_MEMORY_2 | \
BL_MM_INCLUDE_FIRMWARE_MEMORY)
C_ASSERT(BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY == 0x240);
#define BL_MM_REQUEST_DEFAULT_TYPE 1
#define BL_MM_REQUEST_TOP_DOWN_TYPE 2
@ -1285,6 +1301,7 @@ MmMdInitializeListHead (
InitializeListHead(&List->ListHead);
List->First = &List->ListHead;
List->This = NULL;
List->Type = 0;
}
/* INITIALIZATION ROUTINES ***************************************************/
@ -1962,6 +1979,28 @@ Archx86TransferTo32BitApplicationAsm (
/* MEMORY DESCRIPTOR ROUTINES ************************************************/
VOID
MmMdInitializeList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST DescriptorList,
_In_ ULONG Type,
_In_ PLIST_ENTRY ListHead
);
NTSTATUS
MmMdCopyList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList,
_In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList,
_In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor,
_Out_ PULONG ActualCount,
_In_ ULONG Count,
_In_ ULONG Flags
);
ULONG
MmMdCountList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
);
VOID
MmMdFreeList(
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
@ -2076,6 +2115,14 @@ BlMmRemoveBadMemory (
VOID
);
NTSTATUS
BlMmGetMemoryMap (
_In_ PLIST_ENTRY MemoryMap,
_In_ PBL_IMAGE_PARAMETERS MemoryParameters,
_In_ ULONG WhichTypes,
_In_ ULONG Flags
);
/* VIRTUAL MEMORY ROUTINES ***************************************************/
NTSTATUS
@ -2558,7 +2605,18 @@ extern ULONG ConsoleGraphicalResolutionListSize;
extern PVOID DspRemoteInputConsole;
extern PVOID DspLocalInputConsole;
extern WCHAR BlScratchBuffer[8192];
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedAllocated;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedUnallocated;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlFwAllocationTracker;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedUnallocated;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlReservedAllocated;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlBadMemory;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlTruncatedMemory;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlPersistentMemory;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlCompleteBadMemory;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlFreeVirtual;
extern BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers;
extern ULONGLONG BlpTimePerformanceFrequency;
extern LIST_ENTRY RegisteredFileSystems;

View file

@ -1604,17 +1604,6 @@ BlpPdParseReturnArguments (
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
BlMmGetMemoryMap (
_In_ PLIST_ENTRY MemoryMap,
_In_ PBL_IMAGE_PARAMETERS ImageParameters,
_In_ ULONG WhichTypes,
_In_ ULONG Flags
)
{
return STATUS_SUCCESS;
}
NTSTATUS
ImgpInitializeBootApplicationParameters (
_In_ PBL_IMAGE_PARAMETERS ImageParameters,
@ -1628,17 +1617,18 @@ ImgpInitializeBootApplicationParameters (
BL_IMAGE_PARAMETERS MemoryParameters;
LIST_ENTRY MemoryList;
/* Get the image headers and validate it */
Status = RtlImageNtHeaderEx(0, ImageBase, ImageSize, &NtHeaders);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Get the size of the entire non-firmware, allocated, memory map */
MemoryParameters.BufferSize = 0;
Status = BlMmGetMemoryMap(&MemoryList,
&MemoryParameters,
BL_MM_INCLUDE_FIRMWARE_MEMORY |
BL_MM_INCLUDE_PERSISTENT_MEMORY |
BL_MM_INCLUDE_MAPPED_ALLOCATED |
BL_MM_INCLUDE_MAPPED_UNALLOCATED |
BL_MM_INCLUDE_UNMAPPED_ALLOCATED |
@ -1649,6 +1639,7 @@ ImgpInitializeBootApplicationParameters (
return Status;
}
EfiPrintf(L"Memory map needs %lx bytes\n", MemoryParameters.BufferSize);
return STATUS_SUCCESS;
}

View file

@ -15,7 +15,7 @@
BL_MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[512];
ULONG MmGlobalMemoryDescriptorCount;
PBL_MEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
BOOLEAN MmGlobalMemoryDescriptorsUsed;
ULONG MmGlobalMemoryDescriptorsUsed;
PBL_MEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
ULONG MmDynamicMemoryDescriptorCount;
@ -197,6 +197,152 @@ MmMdpSaveCurrentListPointer (
}
}
ULONG
MmMdCountList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
)
{
PLIST_ENTRY First, NextEntry;
ULONG Count;
/* Iterate the list */
for (Count = 0, First = MdList->First, NextEntry = First->Flink;
NextEntry != First;
NextEntry = NextEntry->Flink, Count++);
/* Return the count */
return Count;
}
VOID
MmMdInitializeList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ ULONG Type,
_In_ PLIST_ENTRY ListHead
)
{
/* Check if a list was specified */
if (ListHead)
{
/* Use it */
MdList->First = ListHead;
}
else
{
/* Otherwise, use the internal, built-in list */
InitializeListHead(&MdList->ListHead);
MdList->First = &MdList->ListHead;
}
/* Set the type */
MdList->Type = Type;
/* Initialize current iterator to nothing */
MdList->This = NULL;
}
NTSTATUS
MmMdCopyList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList,
_In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList,
_In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor,
_Out_ PULONG ActualCount,
_In_ ULONG Count,
_In_ ULONG Flags
)
{
NTSTATUS Status;
PULONG Used;
BOOLEAN Finished;
PLIST_ENTRY First, NextEntry;
PBL_MEMORY_DESCRIPTOR Descriptor;
/* Both parameters must be present */
if (!(DestinationList) || !(SourceList))
{
return STATUS_INVALID_PARAMETER;
}
/* Assume success */
Status = STATUS_SUCCESS;
/* Check if a descriptor is being used to store the list */
if (ListDescriptor)
{
/* See how big it is */
Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG;
Used = ActualCount;
}
else
{
/* We are using our internal descriptors instead */
Used = &MmGlobalMemoryDescriptorsUsed;
++MmDescriptorCallTreeCount;
/* Use as many as are available */
Count = MmGlobalMemoryDescriptorCount;
ListDescriptor = MmGlobalMemoryDescriptors;
}
/* Never truncate descriptors during a list copy */
Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG;
/* Iterate through the list */
First = SourceList->First;
NextEntry = First->Flink;
if (First->Flink != First)
{
/* As long as we have success */
while (NT_SUCCESS(Status))
{
/* Check if there's still space */
if (Count <= *Used)
{
Status = STATUS_NO_MEMORY;
break;
}
/* Get the current descriptor */
Descriptor = CONTAINING_RECORD(NextEntry,
BL_MEMORY_DESCRIPTOR,
ListEntry);
/* Copy it into one of the descriptors we have */
RtlCopyMemory(&ListDescriptor[*Used],
Descriptor,
sizeof(*Descriptor));
/* Add it to the list we have */
Status = MmMdAddDescriptorToList(DestinationList,
&ListDescriptor[*Used],
Flags);
++*Used;
/* Before moving on, check if we're done */
Finished = NextEntry->Flink == SourceList->First;
/* Move to the next entry */
NextEntry = NextEntry->Flink;
if (Finished)
{
break;
}
}
}
/* Check if the global descriptors were used */
if (ListDescriptor == MmGlobalMemoryDescriptors)
{
/* Unwind our usage */
MmMdFreeGlobalDescriptors();
--MmDescriptorCallTreeCount;
}
/* Return back to caller */
return Status;
}
VOID
MmMdRemoveDescriptorFromList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
@ -206,7 +352,7 @@ MmMdRemoveDescriptorFromList (
/* Remove the entry */
RemoveEntryList(&Entry->ListEntry);
/* Check if this was the current link */
/* Check if this was the current link */
if (MdList->This == &Entry->ListEntry)
{
/* Remove the current link and set the next one */
@ -838,6 +984,6 @@ MmMdInitialize (
MmGlobalMemoryDescriptorCount = RTL_NUMBER_OF(MmStaticMemoryDescriptors);
MmGlobalMemoryDescriptors = MmStaticMemoryDescriptors;
RtlZeroMemory(MmStaticMemoryDescriptors, sizeof(MmStaticMemoryDescriptors));
MmGlobalMemoryDescriptorsUsed = FALSE;
MmGlobalMemoryDescriptorsUsed = 0;
}
}

View file

@ -621,3 +621,282 @@ BlMmFreePhysicalPages (
return STATUS_SUCCESS;
//return MmPapFreePhysicalPages(4, 0, Address);
}
NTSTATUS
BlMmGetMemoryMap (
_In_ PLIST_ENTRY MemoryMap,
_In_ PBL_IMAGE_PARAMETERS MemoryParameters,
_In_ ULONG WhichTypes,
_In_ ULONG Flags
)
{
BL_MEMORY_DESCRIPTOR_LIST FirmwareMdList, FullMdList;
BOOLEAN DoFirmware, DoPersistent, DoTruncated, DoBad;
BOOLEAN DoReserved, DoUnmapUnalloc, DoUnmapAlloc;
BOOLEAN DoMapAlloc, DoMapUnalloc, DoFirmware2;
ULONG LoopCount, MdListCount, MdListSize, Used;
NTSTATUS Status;
/* Initialize the firmware list if we use it */
MmMdInitializeListHead(&FirmwareMdList);
/* Make sure we got our input parameters */
if (!(MemoryMap) || !(MemoryParameters))
{
return STATUS_INVALID_PARAMETER;
}
/* Either ask for firmware memory, or don't. Not neither */
if ((WhichTypes & ~BL_MM_INCLUDE_NO_FIRMWARE_MEMORY) &&
(WhichTypes & ~BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY))
{
return STATUS_INVALID_PARAMETER;
}
/* Either ask for firmware memory, or don't. Not both */
if ((WhichTypes & BL_MM_INCLUDE_NO_FIRMWARE_MEMORY) &&
(WhichTypes & BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY))
{
return STATUS_INVALID_PARAMETER;
}
/* Check which types of memory to dump */
DoFirmware = WhichTypes & BL_MM_INCLUDE_FIRMWARE_MEMORY;
DoPersistent = WhichTypes & BL_MM_INCLUDE_PERSISTENT_MEMORY;
DoTruncated = WhichTypes & BL_MM_INCLUDE_TRUNCATED_MEMORY;
DoBad = WhichTypes & BL_MM_INCLUDE_BAD_MEMORY;
DoReserved = WhichTypes & BL_MM_INCLUDE_RESERVED_ALLOCATED;
DoUnmapUnalloc = WhichTypes & BL_MM_INCLUDE_UNMAPPED_UNALLOCATED;
DoUnmapAlloc = WhichTypes & BL_MM_INCLUDE_UNMAPPED_ALLOCATED;
DoMapAlloc = WhichTypes & BL_MM_INCLUDE_MAPPED_ALLOCATED;
DoMapUnalloc = WhichTypes & BL_MM_INCLUDE_MAPPED_UNALLOCATED;
DoFirmware2 = WhichTypes & BL_MM_INCLUDE_FIRMWARE_MEMORY_2;
/* Begin the attempt loop */
LoopCount = 0;
while (TRUE)
{
/* Count how many entries we will need */
MdListCount = 0;
if (DoMapAlloc) MdListCount = MmMdCountList(&MmMdlMappedAllocated);
if (DoMapUnalloc) MdListCount += MmMdCountList(&MmMdlMappedUnallocated);
if (DoUnmapAlloc) MdListCount += MmMdCountList(&MmMdlUnmappedAllocated);
if (DoUnmapUnalloc) MdListCount += MmMdCountList(&MmMdlUnmappedUnallocated);
if (DoReserved) MdListCount += MmMdCountList(&MmMdlReservedAllocated);
if (DoBad) MdListCount += MmMdCountList(&MmMdlBadMemory);
if (DoTruncated) MdListCount += MmMdCountList(&MmMdlTruncatedMemory);
if (DoPersistent) MdListCount += MmMdCountList(&MmMdlPersistentMemory);
/* Plus firmware entries */
if (DoFirmware)
{
/* Free the previous entries, if any */
MmMdFreeList(&FirmwareMdList);
/* Get the firmware map */
Status = MmFwGetMemoryMap(&FirmwareMdList, 2);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* We overwrite, since this type is exclusive */
MdListCount = MmMdCountList(&FirmwareMdList);
}
/* Plus firmware entries-2 */
if (DoFirmware2)
{
/* Free the previous entries, if any */
MmMdFreeList(&FirmwareMdList);
/* Get the firmware map */
Status = MmFwGetMemoryMap(&FirmwareMdList, 0);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* We overwrite, since this type is exclusive */
MdListCount = MmMdCountList(&FirmwareMdList);
}
/* If there's no descriptors, we're done */
if (!MdListCount)
{
Status = STATUS_SUCCESS;
goto Quickie;
}
/* Check if the buffer we have is big enough */
if (MemoryParameters->BufferSize >=
(sizeof(BL_MEMORY_DESCRIPTOR) * MdListCount))
{
break;
}
/* It's not, allocate it, with a slack of 4 extra descriptors */
MdListSize = sizeof(BL_MEMORY_DESCRIPTOR) * (MdListCount + 4);
/* Except if we weren't asked to */
if (!(Flags & BL_MM_ADD_DESCRIPTOR_ALLOCATE_FLAG))
{
MemoryParameters->BufferSize = MdListSize;
Status = STATUS_BUFFER_TOO_SMALL;
goto Quickie;
}
/* Has it been less than 4 times we've tried this? */
if (++LoopCount <= 4)
{
/* Free the previous attempt, if any */
if (MemoryParameters->BufferSize)
{
BlMmFreeHeap(MemoryParameters->Buffer);
}
/* Allocate a new buffer */
MemoryParameters->BufferSize = MdListSize;
MemoryParameters->Buffer = BlMmAllocateHeap(MdListSize);
if (MemoryParameters->Buffer)
{
/* Try again */
continue;
}
}
/* If we got here, we're out of memory after 4 attempts */
Status = STATUS_NO_MEMORY;
goto Quickie;
}
/* We should have a buffer by now... */
if (MemoryParameters->Buffer)
{
/* Zero it out */
RtlZeroMemory(MemoryParameters->Buffer,
MdListCount * sizeof(BL_MEMORY_DESCRIPTOR));
}
/* Initialize our list of descriptors */
MmMdInitializeList(&FullMdList, 0, MemoryMap);
Used = 0;
/* Handle mapped, allocated */
if (DoMapAlloc)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlMappedAllocated,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle mapped, unallocated */
if (DoMapUnalloc)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlMappedUnallocated,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle unmapped, allocated */
if (DoUnmapAlloc)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlUnmappedAllocated,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle unmapped, unallocated */
if (DoUnmapUnalloc)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlUnmappedUnallocated,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle reserved, allocated */
if (DoReserved)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlReservedAllocated,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle bad */
if (DoBad)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlBadMemory,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle truncated */
if (DoTruncated)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlTruncatedMemory,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle persistent */
if (DoPersistent)
{
Status = MmMdCopyList(&FullMdList,
&MmMdlPersistentMemory,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle firmware */
if (DoFirmware)
{
Status = MmMdCopyList(&FullMdList,
&FirmwareMdList,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Handle firmware2 */
if (DoFirmware2)
{
Status = MmMdCopyList(&FullMdList,
&FirmwareMdList,
MemoryParameters->Buffer,
&Used,
MdListCount,
Flags);
}
/* Add up the final size */
Status = RtlULongLongToULong(Used * sizeof(BL_MEMORY_DESCRIPTOR),
&MemoryParameters->ActualSize);
Quickie:
MmMdFreeList(&FirmwareMdList);
return Status;
}