diff --git a/BOOT/ENVIRON/INC/mm.h b/BOOT/ENVIRON/INC/mm.h index a175de7..1b77c9a 100644 --- a/BOOT/ENVIRON/INC/mm.h +++ b/BOOT/ENVIRON/INC/mm.h @@ -53,6 +53,13 @@ MmMdRemoveDescriptorFromList ( IN PMEMORY_DESCRIPTOR Descriptor ); +PMEMORY_DESCRIPTOR +MmMdFindDescriptorFromMdl ( + IN PMEMORY_DESCRIPTOR_LIST Mdl, + IN ULONGLONG Page, + IN ULONG Flags + ); + NTSTATUS MmMdRemoveRegionFromMdlEx ( IN PMEMORY_DESCRIPTOR_LIST Mdl, diff --git a/BOOT/ENVIRON/LIB/EFI/efimm.c b/BOOT/ENVIRON/LIB/EFI/efimm.c index b4e033d..3bec1aa 100644 --- a/BOOT/ENVIRON/LIB/EFI/efimm.c +++ b/BOOT/ENVIRON/LIB/EFI/efimm.c @@ -302,17 +302,18 @@ Return Value: { NTSTATUS Status; - UINTN EfiMapSize; - UINTN EfiMapKey; - UINTN EfiDescriptorSize; - UINT32 EfiDescriptorVersion; - UINTN PageCount, EfiPageCount; EFI_PHYSICAL_ADDRESS EfiBuffer; EFI_MEMORY_DESCRIPTOR *EfiMap; - BOOLEAN IsRamdisk; - MEMORY_TYPE MemoryType; + UINTN EfiMapKey; + UINTN EfiMapSize, EfiDescriptorSize; + UINT32 EfiDescriptorVersion; UINT64 EfiStartPage, EfiEndPage; + UINTN EfiPageCount; + ULONGLONG NtStartPage; + ULONG NtPageCount; + BOOLEAN IsRamdisk; UINT64 EfiRamdiskStartPage, EfiRamdiskEndPage; + MEMORY_TYPE MemoryType; PMEMORY_DESCRIPTOR NtDescriptor; (VOID)Flags; @@ -347,8 +348,8 @@ Return Value: } EfiMapSize += 4 * EfiDescriptorSize; - PageCount = (ALIGN_UP(EfiMapSize, PAGE_SIZE) >> PAGE_SHIFT) + 1; - EfiPageCount = EFI_PAGE(PageCount); + NtPageCount = (ALIGN_UP(EfiMapSize, PAGE_SIZE) >> PAGE_SHIFT) + 1; + EfiPageCount = EFI_PAGE(NtPageCount); Status = EfiAllocatePages(AllocateAnyPages, EfiLoaderData, EfiPageCount, &EfiBuffer); if (!NT_SUCCESS(Status)) { DebugPrint(L"MmFwGetMemoryMap(): EfiAllocatePages() failed\r\n"); @@ -572,9 +573,55 @@ Return Value: } // - // TODO: Account for possible MDL changes due to freeing EfiBuffer. + // The following code is to free the buffer and + // also mark the freed memory as free in the MDL. // + Status = EfiFreePages(EfiBuffer, EfiPageCount); + if (!NT_SUCCESS(Status)) { + Status = STATUS_SUCCESS; + goto exit; + } + EfiBuffer = 0; + + EfiStartPage = EfiBuffer >> EFI_PAGE_SHIFT; + EfiEndPage = ALIGN_UP(EfiStartPage + EfiPageCount, EFI_PAGE(1)); + NtStartPage = NT_PAGE(EfiStartPage); + NtPageCount = NT_PAGE(EfiEndPage) - NtStartPage; + + // + // Find the current descriptor. + // + NtDescriptor = MmMdFindDescriptorFromMdl(Mdl, NtStartPage, MDL_OPERATION_FLAGS_PHYSICAL); + if (NtDescriptor == NULL) { + Status = STATUS_UNSUCCESSFUL; + goto exit; + } + + // + // Create a new free descriptor, with the same + // attributes as the current one. + // + NtDescriptor = MmMdInitDescriptor(NtStartPage, 0, NtPageCount, NtDescriptor->Attributes, MEMORY_TYPE_FREE); + if (NtDescriptor == NULL) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + // + // Remove the current descriptor. + // + Status = MmMdRemoveRegionFromMdlEx(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL, 0); + if (!NT_SUCCESS(Status)) { + MmMdFreeDescriptor(NtDescriptor); + goto exit; + } + + // + // Add the new descriptor to the MDL. + // + Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, 0x01); + exit: if (EfiBuffer) { EfiFreePages(EfiBuffer, EfiPageCount); diff --git a/BOOT/ENVIRON/LIB/MM/mmmd.c b/BOOT/ENVIRON/LIB/MM/mmmd.c index ec8f037..ffdf89f 100644 --- a/BOOT/ENVIRON/LIB/MM/mmmd.c +++ b/BOOT/ENVIRON/LIB/MM/mmmd.c @@ -386,6 +386,45 @@ Return Value: } } +PMEMORY_DESCRIPTOR +MmMdFindDescriptorFromMdl ( + IN PMEMORY_DESCRIPTOR_LIST Mdl, + IN ULONGLONG Page, + IN ULONG Flags + ) + +/*++ + +Routine Description: + + Searches an MDL for the descriptor containing a page. + +Arguments: + + Mdl - The MDL to search. + + Page - The page to search for. + + Flags - MDL_OPERATION_FLAGS_* + MDL_OPERATION_FLAGS_PHYSICAL if Page is physical. + MDL_OPERATION_FLAGS_VIRTUAL if Page is virtual. + +Return Value: + + Pointer to the descriptor if successful. + NULL if an error occurs. + +--*/ + + +{ + // + // TODO: Implement this routine. + // + + return NULL; +} + NTSTATUS MmMdRemoveRegionFromMdlEx ( IN PMEMORY_DESCRIPTOR_LIST Mdl,