[BOOT:MM] Finish MmMdRemoveRegionFromMdlEx()
This commit is contained in:
parent
3aae765c9c
commit
65e33fdad5
@ -611,7 +611,7 @@ Return Value:
|
||||
//
|
||||
// Remove the current descriptor.
|
||||
//
|
||||
Status = MmMdRemoveRegionFromMdlEx(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL, 0);
|
||||
Status = MmMdRemoveRegionFromMdlEx(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL, NULL);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
|
@ -515,7 +515,7 @@ Return Value:
|
||||
NTSTATUS
|
||||
MmMdRemoveRegionFromMdlEx (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONGLONG FirstPage,
|
||||
IN ULONGLONG RemoveStart,
|
||||
IN ULONGLONG PageCount,
|
||||
IN ULONG Flags,
|
||||
OUT PMEMORY_DESCRIPTOR_LIST Unused
|
||||
@ -531,46 +531,153 @@ Arguments:
|
||||
|
||||
Mdl - MDL to remove the region from.
|
||||
|
||||
FirstPage - The first page in the region.
|
||||
RemoveStart - The first page in the region.
|
||||
|
||||
PageCount - The number of pages in the region.
|
||||
|
||||
Flags - MDL_OPERATION_FLAGS_*.
|
||||
MDL_OPERATION_FLAGS_PHYSICAL if the region is physical.
|
||||
MDL_OPERATION_FLAGS_VIRTUAL if the region is virtual.
|
||||
|
||||
Unused - Unused.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if Flags value is invalid.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONGLONG RemoveEnd, DescriptorEnd;
|
||||
PLIST_ENTRY Entry;
|
||||
PMEMORY_DESCRIPTOR Descriptor;
|
||||
MEMORY_DESCRIPTOR RemovedDescriptor;
|
||||
NTSTATUS Status;
|
||||
ULONG Offset;
|
||||
BOOLEAN Mapped;
|
||||
ULONGLONG RemoveEnd;
|
||||
PLIST_ENTRY ListEntry;
|
||||
ULONGLONG DescriptorStart, DescriptorEnd;
|
||||
PMEMORY_DESCRIPTOR Descriptor, NewDescriptor;
|
||||
|
||||
(VOID)Flags;
|
||||
(VOID)Unused;
|
||||
|
||||
RemoveEnd = FirstPage + PageCount;
|
||||
Entry = Mdl->Head->Flink;
|
||||
while (Entry != Mdl->Head) {
|
||||
Descriptor = (PMEMORY_DESCRIPTOR)Entry;
|
||||
DescriptorEnd = Descriptor->FirstPage + Descriptor->PageCount;
|
||||
|
||||
RtlCopyMemory(&RemovedDescriptor, Descriptor, sizeof(MEMORY_DESCRIPTOR));
|
||||
|
||||
// if (FirstPage <= Descriptor->FirstPage && Descriptor->FirstPage < RemoveEnd) {
|
||||
// }
|
||||
Mapped = FALSE;
|
||||
if (Flags & MDL_OPERATION_FLAGS_VIRTUAL) {
|
||||
if (Mdl->Type == MDL_TYPE_PHYSICAL) {
|
||||
Mapped = TRUE;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// If the MDL is virtual, the
|
||||
// virtual flag must be set.
|
||||
//
|
||||
if (Mdl->Type == MDL_TYPE_VIRTUAL) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Implement the rest of this routine.
|
||||
//
|
||||
RemoveEnd = RemoveStart + PageCount;
|
||||
ListEntry = Mdl->Head->Flink;
|
||||
while (ListEntry != Mdl->Head) {
|
||||
Descriptor = (PMEMORY_DESCRIPTOR)ListEntry;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
if (Mapped) {
|
||||
DescriptorStart = Descriptor->MappedFirstPage;
|
||||
} else {
|
||||
DescriptorStart = Descriptor->FirstPage;
|
||||
}
|
||||
DescriptorEnd = DescriptorStart + Descriptor->PageCount;
|
||||
|
||||
//
|
||||
// Check if the region to be removed
|
||||
// is inside the current descriptor.
|
||||
//
|
||||
if (RemoveStart <= DescriptorStart && RemoveEnd > DescriptorStart) {
|
||||
//
|
||||
// The region is around the start of the descriptor, or
|
||||
// they have identical locations and sizes.
|
||||
// | RemoveStart | DescriptorStart | RemoveEnd | DescriptorEnd |
|
||||
// | Lower address ............................ Higher address |
|
||||
//
|
||||
|
||||
if (RemoveEnd < DescriptorEnd) {
|
||||
Offset = RemoveEnd - DescriptorStart;
|
||||
} else {
|
||||
Offset = DescriptorEnd - DescriptorStart;
|
||||
}
|
||||
|
||||
//
|
||||
// Shrink the descriptor.
|
||||
//
|
||||
Descriptor->FirstPage += Offset;
|
||||
Descriptor->PageCount -= Offset;
|
||||
if (Descriptor->MappedFirstPage) {
|
||||
Descriptor->MappedFirstPage += Offset;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove descriptor if now empty.
|
||||
//
|
||||
if (Descriptor->PageCount == 0) {
|
||||
MmMdRemoveDescriptorFromList(Mdl, Descriptor);
|
||||
MmMdFreeDescriptor(Descriptor);
|
||||
}
|
||||
} else if (RemoveStart < DescriptorEnd && RemoveEnd >= DescriptorEnd) {
|
||||
//
|
||||
// The region is around the end of the descriptor.
|
||||
// | DescriptorStart | RemoveStart | DescriptorEnd | RemoveEnd |
|
||||
// | Lower address ............................ Higher address |
|
||||
//
|
||||
|
||||
//
|
||||
// Simply shrink the descriptor.
|
||||
//
|
||||
Descriptor->PageCount -= DescriptorEnd - RemoveStart;
|
||||
} else if (RemoveStart > DescriptorStart && RemoveEnd < DescriptorEnd) {
|
||||
//
|
||||
// The region is completely inside the descriptor.
|
||||
// In this case, the descriptor must be split in two.
|
||||
// | DescriptorStart | RemoveStart | RemoveEnd | DescriptorEnd |
|
||||
// | Lower address ............................ Higher address |
|
||||
//
|
||||
|
||||
//
|
||||
// Create a new descriptor before the removed region.
|
||||
//
|
||||
NewDescriptor = MmMdInitDescriptor(
|
||||
Descriptor->FirstPage,
|
||||
Descriptor->MappedFirstPage,
|
||||
RemoveStart - DescriptorStart,
|
||||
Descriptor->Attributes,
|
||||
Descriptor->Type
|
||||
);
|
||||
|
||||
//
|
||||
// Shrink and move the current descriptor.
|
||||
//
|
||||
Offset = NewDescriptor->PageCount + PageCount;
|
||||
Descriptor->FirstPage += Offset;
|
||||
Descriptor->PageCount -= Offset;
|
||||
if (Descriptor->MappedFirstPage) {
|
||||
Descriptor->MappedFirstPage += Offset;
|
||||
}
|
||||
|
||||
//
|
||||
// Now check if MmMdInitDescriptor() actually worked.
|
||||
//
|
||||
if (NewDescriptor == NULL) {
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NewDescriptor);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
Loading…
Reference in New Issue
Block a user