diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index d140b2e7a58..70649dbd541 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -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; diff --git a/reactos/boot/environ/lib/misc/image.c b/reactos/boot/environ/lib/misc/image.c index 5af7931bd61..be901085ffd 100644 --- a/reactos/boot/environ/lib/misc/image.c +++ b/reactos/boot/environ/lib/misc/image.c @@ -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; } diff --git a/reactos/boot/environ/lib/mm/descriptor.c b/reactos/boot/environ/lib/mm/descriptor.c index d5e0e7e56a8..2c7d8595c0f 100644 --- a/reactos/boot/environ/lib/mm/descriptor.c +++ b/reactos/boot/environ/lib/mm/descriptor.c @@ -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; } } diff --git a/reactos/boot/environ/lib/mm/pagealloc.c b/reactos/boot/environ/lib/mm/pagealloc.c index 2b682a1d8b1..886532dfb0e 100644 --- a/reactos/boot/environ/lib/mm/pagealloc.c +++ b/reactos/boot/environ/lib/mm/pagealloc.c @@ -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; +}