Author: ion Date: Mon Feb 6 19:07:17 2017 New Revision: 73729 URL: http://svn.reactos.org/svn/reactos?rev=73729&view=rev Log: [BOOTLIB]: Implement MmPaReserveSelfMapPages, MmPaReleaseSelfMapPages [BOOTLIB]: Stub MmDefMoveVirtualAddressRange, MmDefZeroVirtualAddressRange, MmDefRelocateSelfMap, MmDefpDestroySelfMap, MmDefpUnmapVirtualAddress, MmDefpRemapVirtualAddress, MmDefpMapPhysicalAddress, MmDefpTranslateVirtualAddress, [BOOTLIB]: Implement MmDefpFlushTlbEntry, MmDefpFlushTlb [BOOTLIB]: Implement MmPaReleaseSelfMapPages, MmPaReserveSelfMapPages. [BOOTLIB]: Implement Archx86IsCpuidSupported, BlArchIsCpuIdFunctionSupported, BlArchCpuId, BlArchGetPerformanceCounter. [BOOTLIB]: Implement MmArchInitialize. [BOOTLIB]: Implement most of MmDefInitializeTranslation. Almost ready to turn on paging.
Modified: trunk/reactos/boot/environ/include/bl.h trunk/reactos/boot/environ/lib/mm/descriptor.c trunk/reactos/boot/environ/lib/mm/i386/mmx86.c trunk/reactos/boot/environ/lib/mm/mm.c trunk/reactos/boot/environ/lib/mm/pagealloc.c Modified: trunk/reactos/boot/environ/include/bl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?rev=73729&r1=73728&r2=73729&view=diff ============================================================================== --- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Mon Feb 6 19:07:17 2017 @@ -223,6 +223,7 @@ { BlMdPhysical, BlMdVirtual, + BlMdTracker } BL_MEMORY_DESCRIPTOR_TYPE; typedef enum _BL_TRANSLATION_TYPE @@ -2114,6 +2115,17 @@ _In_ ULONG RangeType ); +NTSTATUS +MmPaReleaseSelfMapPages ( + _In_ PHYSICAL_ADDRESS Address + ); + +NTSTATUS +MmPaReserveSelfMapPages ( + _Inout_ PPHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Alignment, + _In_ ULONG PageCount + ); NTSTATUS BlMmFreePhysicalPages ( _In_ PHYSICAL_ADDRESS Address Modified: trunk/reactos/boot/environ/lib/mm/descriptor.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/descriptor.c?rev=73729&r1=73728&r2=73729&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/mm/descriptor.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/descriptor.c [iso-8859-1] Mon Feb 6 19:07:17 2017 @@ -680,7 +680,6 @@ FoundPageCount = Descriptor->PageCount; FoundEndPage = FoundBasePage + FoundPageCount; EndPage = PageCount + BasePage; - //EarlyPrint(L"Looking for Region 0x%08I64X-0x%08I64X in 0x%08I64X-0x%08I64X\r\n", BasePage, EndPage, FoundBasePage, FoundEndPage); /* Make a copy of the original descriptor */ RtlCopyMemory(&NewDescriptor, NextEntry, sizeof(NewDescriptor)); @@ -694,19 +693,21 @@ /* Check if the found region starts after the region or ends before the region */ if ((FoundBasePage >= BasePage) || (EndPage >= FoundEndPage)) { - /* This descriptor doesn't cover any part of the range */ - //EarlyPrint(L"No part of this descriptor contains the region\r\n"); + /* This descriptor doesn't cover any part of the range -- nothing to do */ + NOTHING; } else { - /* This descriptor covers the head of the allocation */ - //EarlyPrint(L"Descriptor covers the head of the region\r\n"); + /* This descriptor covers the head of the allocation @TODO: FIXME */ + EfiPrintf(L"FIXME: Descriptor covers the head of the region\r\n"); + EfiStall(1000000); } } else { - /* This descriptor contains the entire allocation */ - //EarlyPrint(L"Descriptor contains the entire region\r\n"); + /* This descriptor contains the entire allocation @TODO: FIXME */ + EfiPrintf(L"FIXME: Descriptor contains the entire region\r\n"); + EfiStall(1000000); } /* Keep going */ @@ -747,7 +748,6 @@ if (!Descriptor->PageCount) { /* Remove it */ - //EarlyPrint(L"Entire descriptor consumed\r\n"); MmMdRemoveDescriptorFromList(MdList, Descriptor); MmMdFreeDescriptor(Descriptor); Modified: trunk/reactos/boot/environ/lib/mm/i386/mmx86.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/i386/mmx86.c?rev=73729&r1=73728&r2=73729&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/mm/i386/mmx86.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/i386/mmx86.c [iso-8859-1] Mon Feb 6 19:07:17 2017 @@ -17,7 +17,12 @@ ULONG MmArchLargePageSize; BL_ADDRESS_RANGE MmArchKsegAddressRange; ULONG_PTR MmArchTopOfApplicationAddressSpace; -ULONG_PTR Mmx86SelfMapBase; +PHYSICAL_ADDRESS Mmx86SelfMapBase; +ULONG MmDeferredMappingCount; +PVOID MmPdpt; +PVOID MmArchReferencePage; +PVOID MmPteBase; +ULONG MmArchReferencePageSize; typedef VOID (*PBL_MM_FLUSH_TLB) ( @@ -29,10 +34,79 @@ VOID ); +typedef NTSTATUS +(*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE) ( + _In_ PVOID DestinationAddress, + _In_ PVOID SourceAddress, + _In_ ULONGLONG Size + ); + +typedef NTSTATUS +(*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE) ( + _In_ PVOID DestinationAddress, + _In_ ULONGLONG Size + ); + +typedef VOID +(*PBL_MM_DESTROY_SELF_MAP) ( + VOID + ); + +typedef VOID +(*PBL_MM_FLUSH_TLB_ENTRY) ( + _In_ PVOID VirtualAddress + ); + +typedef VOID +(*PBL_MM_FLUSH_TLB) ( + VOID + ); + +typedef NTSTATUS +(*PBL_MM_UNMAP_VIRTUAL_ADDRESS) ( + _In_ PVOID VirtualAddress, + _In_ ULONG Size + ); + +typedef NTSTATUS +(*PBL_MM_REMAP_VIRTUAL_ADDRESS) ( + _In_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_ PVOID VirtualAddress, + _In_ ULONG Size, + _In_ ULONG CacheAttributes + ); + +typedef NTSTATUS +(*PBL_MM_MAP_PHYSICAL_ADDRESS) ( + _In_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_ PVOID VirtualAddress, + _In_ ULONG Size, + _In_ ULONG CacheAttributes + ); + +typedef BOOLEAN +(*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS) ( + _In_ PVOID VirtualAddress, + _Out_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_opt_ PULONG CacheAttributes + ); + +PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress; +PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress; +PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress; +PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress; +PBL_MM_FLUSH_TLB Mmx86FlushTlb; +PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry; +PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap; + PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap; PBL_MM_FLUSH_TLB BlMmFlushTlb; - -ULONG MmDeferredMappingCount; +PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange; +PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange; + +PBL_MM_FLUSH_TLB Mmx86FlushTlb; + +#define PTE_BASE (PVOID)0xC0000000 /* FUNCTIONS *****************************************************************/ @@ -43,6 +117,38 @@ { /* Nothing to do */ return; +} + +VOID +MmDefRelocateSelfMap ( + VOID + ) +{ + if (MmPteBase != PTE_BASE) + { + EfiPrintf(L"Supposed to relocate CR3\r\n"); + } +} + +NTSTATUS +MmDefMoveVirtualAddressRange ( + _In_ PVOID DestinationAddress, + _In_ PVOID SourceAddress, + _In_ ULONGLONG Size + ) +{ + EfiPrintf(L"Supposed to move shit\r\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +MmDefZeroVirtualAddressRange ( + _In_ PVOID DestinationAddress, + _In_ ULONGLONG Size + ) +{ + EfiPrintf(L"Supposed to zero shit\r\n"); + return STATUS_NOT_IMPLEMENTED; } NTSTATUS @@ -79,17 +185,6 @@ } BOOLEAN -Mmx86TranslateVirtualAddress ( - _In_ PVOID VirtualAddress, - _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress, - _Out_opt_ PULONG CachingFlags - ) -{ - EfiPrintf(L"paging TODO\r\n"); - return FALSE; -} - -BOOLEAN MmArchTranslateVirtualAddress ( _In_ PVOID VirtualAddress, _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress, @@ -131,6 +226,293 @@ return Descriptor != NULL; } +BOOLEAN +Archx86IsCpuidSupported ( + VOID + ) +{ + ULONG CallerFlags, Flags; + + /* Read the original flags, and add the CPUID bit */ + CallerFlags = __getcallerseflags() ^ 0x200000; + __writeeflags(CallerFlags); + + /* Read our flags now */ + Flags = __readeflags(); + + /* Check if the bit stuck */ + return (((CallerFlags ^ Flags) >> 21) & 1) ^ 1; +} + +BOOLEAN +BlArchIsCpuIdFunctionSupported ( + _In_ ULONG Function + ) +{ + BOOLEAN Supported; + INT CpuInfo[4]; + + /* Check if the CPU supports this instruction */ + Supported = Archx86IsCpuidSupported(); + if (!Supported) + { + return FALSE; + } + + /* Check if it's the extended function */ + if (Function >= 0x80000000) + { + /* Check if extended functions are supported */ + __cpuid(CpuInfo, 0x80000000); + if ((CpuInfo[0] & 0xFFFFFF00) != 0x80000000) + { + /* Nope */ + return FALSE; + } + } + else + { + /* It's a regular function, get the maximum one supported */ + __cpuid(CpuInfo, 0); + } + + /* Check if our function is within bounds */ + if (Function <= CpuInfo[0]) + { + return TRUE; + } + + /* Nope */ + return FALSE; +} + +VOID +BlArchCpuId ( + _In_ ULONG Function, + _In_ ULONG SubFunction, + _Out_ INT* Result + ) +{ + /* Use the intrinsic */ + __cpuidex(Result, Function, SubFunction); +} + +ULONGLONG +BlArchGetPerformanceCounter ( + VOID + ) +{ + INT CpuInfo[4]; + + /* Serialize with CPUID, if it exists */ + if (Archx86IsCpuidSupported()) + { + BlArchCpuId(0, 0, CpuInfo); + } + + /* Read the TSC */ + return __rdtsc(); +} + +VOID +MmDefpDestroySelfMap ( + VOID + ) +{ + EfiPrintf(L"No destroy\r\n"); +} + +VOID +MmDefpFlushTlbEntry ( + _In_ PVOID VirtualAddress + ) +{ + /* Flush the TLB */ + __invlpg(VirtualAddress); +} + +VOID +MmDefpFlushTlb ( + VOID + ) +{ + /* Flush the TLB */ + __writecr3(__readcr3()); +} + +NTSTATUS +MmDefpUnmapVirtualAddress ( + _In_ PVOID VirtualAddress, + _In_ ULONG Size + ) +{ + EfiPrintf(L"No unmap\r\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +MmDefpRemapVirtualAddress ( + _In_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_ PVOID VirtualAddress, + _In_ ULONG Size, + _In_ ULONG CacheAttributes + ) +{ + EfiPrintf(L"No remap\r\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +MmDefpMapPhysicalAddress ( + _In_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_ PVOID VirtualAddress, + _In_ ULONG Size, + _In_ ULONG CacheAttributes + ) +{ + EfiPrintf(L"No map\r\n"); + return STATUS_NOT_IMPLEMENTED; +} + +BOOLEAN +MmDefpTranslateVirtualAddress ( + _In_ PVOID VirtualAddress, + _Out_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_opt_ PULONG CacheAttributes + ) +{ + EfiPrintf(L"No translate\r\n"); + return FALSE; +} + +NTSTATUS +MmDefInitializeTranslation ( + _In_ PBL_MEMORY_DATA MemoryData, + _In_ BL_TRANSLATION_TYPE TranslationType + ) +{ + NTSTATUS Status; + PHYSICAL_ADDRESS PhysicalAddress; + + /* Set the global function pointers for memory translation */ + Mmx86TranslateVirtualAddress = MmDefpTranslateVirtualAddress; + Mmx86MapPhysicalAddress = MmDefpMapPhysicalAddress; + Mmx86UnmapVirtualAddress = MmDefpUnmapVirtualAddress; + Mmx86RemapVirtualAddress = MmDefpRemapVirtualAddress; + Mmx86FlushTlb = MmDefpFlushTlb; + Mmx86FlushTlbEntry = MmDefpFlushTlbEntry; + Mmx86DestroySelfMap = MmDefpDestroySelfMap; + + /* Check what mode we're currently in */ + if (TranslationType == BlVirtual) + { + EfiPrintf(L"Virtual->Virtual not yet supported\r\n"); + return STATUS_NOT_IMPLEMENTED; + } + else if (TranslationType != BlNone) + { + /* Not even Windows supports PAE->Virtual downgrade */ + return STATUS_NOT_IMPLEMENTED; + } + + /* The None->Virtual case */ + MmPdpt = NULL; + Mmx86SelfMapBase.QuadPart = 0; + MmArchReferencePage = NULL; + + /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */ + EfiPrintf(L"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n"); + //Status = MmPaTruncateMemory(0x100000); + Status = STATUS_SUCCESS; + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Allocate a page directory */ + Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress, + BlLoaderPageDirectory, + 1, + 0, + 0, + &MmMdlUnmappedAllocated, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Zero out the page directory */ + MmPdpt = (PVOID)PhysicalAddress.LowPart; + RtlZeroMemory(MmPdpt, PAGE_SIZE); + + /* Set the page size */ + MmArchReferencePageSize = PAGE_SIZE; + + /* Allocate the self-map page */ + Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress, + BlLoaderReferencePage, + 1, + 0, + 0, + &MmMdlUnmappedAllocated, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Set the reference page */ + MmArchReferencePage = (PVOID)PhysicalAddress.LowPart; + + /* Zero it out */ + RtlZeroMemory(MmArchReferencePage, MmArchReferencePageSize); + + /* Allocate 4MB worth of self-map pages */ + Status = MmPaReserveSelfMapPages(&Mmx86SelfMapBase, + (4 * 1024 * 1024) >> PAGE_SHIFT, + (4 * 1024 * 1024) >> PAGE_SHIFT); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Zero them out */ + RtlZeroMemory((PVOID)Mmx86SelfMapBase.LowPart, 4 * 1024 * 1024); + + EfiPrintf(L"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n", + MmPdpt, MmArchReferencePage, Mmx86SelfMapBase.LowPart); + Status = STATUS_NOT_IMPLEMENTED; + + //MmPteBase = Mmx86SelfMapBase.LowPart & 0xFFC00000; + +Quickie: + /* Free reference page if we allocated it */ + if (MmArchReferencePage) + { + PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage; + BlMmFreePhysicalPages(PhysicalAddress); + } + + /* Free page directory if we allocated it */ + if (MmPdpt) + { + PhysicalAddress.QuadPart = (ULONG_PTR)MmPdpt; + BlMmFreePhysicalPages(PhysicalAddress); + } + + /* Free the self map if we allocated it */ + if (Mmx86SelfMapBase.QuadPart) + { + MmPaReleaseSelfMapPages(Mmx86SelfMapBase); + } + + /* All done */ + return Status; +} + NTSTATUS MmArchInitialize ( _In_ ULONG Phase, @@ -140,6 +522,8 @@ ) { NTSTATUS Status; + ULONGLONG IncreaseUserVa, PerfCounter, CpuRandom; + INT CpuInfo[4]; /* For phase 2, just map deferred regions */ if (Phase != 1) @@ -160,7 +544,7 @@ MmArchKsegAddressRange.Minimum = 0; MmArchKsegAddressRange.Maximum = (ULONGLONG)~0; MmArchTopOfApplicationAddressSpace = 0; - Mmx86SelfMapBase = 0; + Mmx86SelfMapBase.QuadPart = 0; /* Set stub functions */ BlMmRelocateSelfMap = MmArchNullFunction; @@ -172,7 +556,70 @@ case BlVirtual: - Status = STATUS_NOT_IMPLEMENTED; + /* Set the large page size to 1024 pages (4MB) */ + MmArchLargePageSize = (4 * 1024 * 1024) / PAGE_SIZE; + + /* Check if /USERVA option was used */ + Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, + BcdOSLoaderInteger_IncreaseUserVa, + &IncreaseUserVa); + if (NT_SUCCESS(Status) && (IncreaseUserVa)) + { + /* Yes -- load the kernel at 0xE0000000 instead */ + MmArchKsegBase = 0xE0000000; + } + else + { + /* Nope, load at the standard 2GB split */ + MmArchKsegBase = 0x80000000; + } + + /* Check if CPUID 01h is supported */ + CpuRandom = 0; + if (BlArchIsCpuIdFunctionSupported(1)) + { + /* Call it */ + BlArchCpuId(1, 0, CpuInfo); + + /* Check if RDRAND is supported */ + if (CpuInfo[2] & 0x40000000) + { + EfiPrintf(L"Your CPU can do RDRAND! Good for you!\r\n"); + CpuRandom = 0; + } + } + + /* Read the TSC */ + PerfCounter = BlArchGetPerformanceCounter(); + PerfCounter >>= 4; + _rotl16(PerfCounter, 5); + + /* Set the address range */ + MmArchKsegAddressRange.Minimum = 0; + MmArchKsegAddressRange.Maximum = (ULONGLONG)~0; + + /* Set the KASLR bias */ + MmArchKsegBias = ((PerfCounter ^ CpuRandom) & 0xFFF) << 12; + MmArchKsegBias = 0; + MmArchKsegBase += MmArchKsegBias; + + /* Set the kernel range */ + MmArchKsegAddressRange.Minimum = MmArchKsegBase; + MmArchKsegAddressRange.Maximum = (ULONGLONG)~0; + + /* Set the boot application top maximum */ + MmArchTopOfApplicationAddressSpace = 0x70000000; + + /* Initialize virtual address space translation */ + Status = MmDefInitializeTranslation(MemoryData, TranslationType); + if (NT_SUCCESS(Status)) + { + /* Set stub functions */ + BlMmRelocateSelfMap = MmDefRelocateSelfMap; + BlMmFlushTlb = Mmx86FlushTlb; + BlMmMoveVirtualAddressRange = MmDefMoveVirtualAddressRange; + BlMmZeroVirtualAddressRange = MmDefZeroVirtualAddressRange; + } break; case BlPae: Modified: trunk/reactos/boot/environ/lib/mm/mm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/mm.c?rev=73729&r1=73728&r2=73729&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/mm/mm.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/mm.c [iso-8859-1] Mon Feb 6 19:07:17 2017 @@ -13,7 +13,9 @@ /* DATA VARIABLES ************************************************************/ -BL_TRANSLATION_TYPE MmTranslationType, MmOriginalTranslationType; +/* This is a bug in Windows, but is required for MmTrInitialize to load */ +BL_TRANSLATION_TYPE MmTranslationType = BlMax; +BL_TRANSLATION_TYPE MmOriginalTranslationType; ULONG MmDescriptorCallTreeCount; /* FUNCTIONS *****************************************************************/ @@ -23,15 +25,70 @@ VOID ) { + PBL_MEMORY_DESCRIPTOR Descriptor; + NTSTATUS Status; + PLIST_ENTRY NextEntry; + /* Nothing to track if we're using physical memory */ if (MmTranslationType == BlNone) { return STATUS_SUCCESS; } - /* TODO */ - EfiPrintf(L"Required for protected mode\r\n"); - return STATUS_NOT_IMPLEMENTED; + /* Initialize all the virtual lists */ + MmMdInitializeListHead(&MmMdlMappingTrackers); + MmMdlMappingTrackers.Type = BlMdTracker; + MmMdInitializeListHead(&MmMdlFreeVirtual); + MmMdlFreeVirtual.Type = BlMdVirtual; + + /* Initialize a 4GB free descriptor */ + Descriptor = MmMdInitByteGranularDescriptor(0, + BlConventionalMemory, + 0, + 0, + ((ULONGLONG)4 * 1024 * 1024 * 1024) >> + PAGE_SHIFT); + if (!Descriptor) + { + Status = STATUS_NO_MEMORY; + goto Quickie; + } + + /* Add this 4GB region to the free virtual address space list */ + Status = MmMdAddDescriptorToList(&MmMdlFreeVirtual, + Descriptor, + BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG); + if (!NT_SUCCESS(Status)) + { + RtlZeroMemory(Descriptor, sizeof(*Descriptor)); + goto Quickie; + } + + /* Remove any reserved regions of virtual address space */ + NextEntry = MmMdlReservedAllocated.First->Flink; + while (NextEntry != MmMdlReservedAllocated.First) + { + /* Grab the descriptor and see if it's mapped */ + Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry); + if (Descriptor->VirtualPage) + { + EfiPrintf(L"Need to handle reserved allocation: %llx %llx\r\n", + Descriptor->VirtualPage, Descriptor->PageCount); + EfiStall(100000); + Status = STATUS_NOT_IMPLEMENTED; + goto Quickie; + } + + /* Next entry */ + NextEntry = NextEntry->Flink; + } + + /* Set success if we made it */ + Status = STATUS_SUCCESS; + +Quickie: + /* Return back to caller */ + return Status; } NTSTATUS Modified: trunk/reactos/boot/environ/lib/mm/pagealloc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/pagealloc.c?rev=73729&r1=73728&r2=73729&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/mm/pagealloc.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/pagealloc.c [iso-8859-1] Mon Feb 6 19:07:17 2017 @@ -628,7 +628,7 @@ DontFree = FALSE; HasPageData = FALSE; - /* Only page-aligned addresses a re accepted */ + /* Only page-aligned addresses are accepted */ if (Address.QuadPart & (PAGE_SIZE - 1)) { EfiPrintf(L"free mem fail 1\r\n"); @@ -1096,3 +1096,124 @@ MmMdFreeList(&FirmwareMdList); return Status; } + +NTSTATUS +MmPaReleaseSelfMapPages ( + _In_ PHYSICAL_ADDRESS Address + ) +{ + PBL_MEMORY_DESCRIPTOR Descriptor; + ULONGLONG BasePage; + NTSTATUS Status; + + /* Only page-aligned addresses are accepted */ + if (Address.QuadPart & (PAGE_SIZE - 1)) + { + EfiPrintf(L"free mem fail 1\r\n"); + return STATUS_INVALID_PARAMETER; + } + + /* Get the base page, and find a descriptor that matches */ + BasePage = Address.QuadPart >> PAGE_SHIFT; + Descriptor = MmMdFindDescriptor(BL_MM_INCLUDE_UNMAPPED_UNALLOCATED, + BL_MM_REMOVE_PHYSICAL_REGION_FLAG, + BasePage); + if (!(Descriptor) || (Descriptor->BasePage != BasePage)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Free the physical pages */ + Status = MmFwFreePages(BasePage, Descriptor->PageCount); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Remove the firmware flags */ + Descriptor->Flags &= ~(BlMemoryNonFirmware | + BlMemoryFirmware | + BlMemoryPersistent); + + /* Set it as free memory */ + Descriptor->Type = BlConventionalMemory; + + /* Create a new descriptor that's free memory, covering the old range */ + Descriptor = MmMdInitByteGranularDescriptor(0, + BlConventionalMemory, + BasePage, + 0, + Descriptor->PageCount); + if (!Descriptor) + { + return STATUS_NO_MEMORY; + } + + /* Insert it into the virtual free list */ + return MmMdAddDescriptorToList(&MmMdlFreeVirtual, + Descriptor, + BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG | + BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG); +} + +NTSTATUS +MmPaReserveSelfMapPages ( + _Inout_ PPHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Alignment, + _In_ ULONG PageCount + ) +{ + NTSTATUS Status; + BL_PA_REQUEST Request; + BL_MEMORY_DESCRIPTOR Descriptor; + + /* Increment descriptor usage count */ + ++MmDescriptorCallTreeCount; + + /* Bail if we don't have an address */ + if (!PhysicalAddress) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Make a request for the required number of self-map pages */ + Request.BaseRange.Minimum = PapMinimumPhysicalPage; + Request.BaseRange.Maximum = 0xFFFFFFFF >> PAGE_SHIFT; + Request.VirtualRange.Minimum = 0; + Request.VirtualRange.Maximum = 0; + Request.Pages = PageCount; + Request.Alignment = Alignment; + Request.Type = BL_MM_REQUEST_DEFAULT_TYPE; + Request.Flags = 0;; + Status = MmPaAllocatePages(&MmMdlUnmappedUnallocated, + &Descriptor, + &MmMdlUnmappedUnallocated, + &Request, + BlLoaderSelfMap); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Remove this region from free virtual memory */ + Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual, + BL_MM_REMOVE_VIRTUAL_REGION_FLAG, + Descriptor.BasePage, + Descriptor.PageCount, + 0); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Return the physical address */ + PhysicalAddress->QuadPart = Descriptor.BasePage << PAGE_SHIFT; + +Quickie: + /* Free global descriptors and reduce the count by one */ + MmMdFreeGlobalDescriptors(); + --MmDescriptorCallTreeCount; + return Status; +} +