Index: ntoskrnl/mm/ARM3/section.c =================================================================== --- ntoskrnl/mm/ARM3/section.c (revision 68288) +++ ntoskrnl/mm/ARM3/section.c (working copy) @@ -3513,27 +3513,6 @@ } _SEH2_END; - /* Check for kernel-mode address */ - if (SafeBaseAddress > MM_HIGHEST_VAD_ADDRESS) - { - DPRINT1("Kernel base not allowed\n"); - return STATUS_INVALID_PARAMETER_3; - } - - /* Check for range entering kernel-mode */ - if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)SafeBaseAddress) < SafeViewSize) - { - DPRINT1("Overflowing into kernel base not allowed\n"); - return STATUS_INVALID_PARAMETER_3; - } - - /* Check for invalid zero bits */ - if (((ULONG_PTR)SafeBaseAddress + SafeViewSize) > (0xFFFFFFFF >> ZeroBits)) // arch? - { - DPRINT1("Invalid zero bits\n"); - return STATUS_INVALID_PARAMETER_4; - } - /* Reference the process */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_VM_OPERATION, @@ -3556,10 +3535,65 @@ return Status; } + /* Is this a request from a device driver to map its hardware? + * (note that we explicitly disallow umode access) + * ARM3 WARNING: Empirical tests displays this isn't exactly how + * Windows does it, but it's close enough for us. + */ + if ((Section->AllocationAttributes & SEC_PHYSICALMEMORY) && + PreviousMode == KernelMode) + { + PHYSICAL_ADDRESS PhysAddr; + MEMORY_CACHING_TYPE CacheType = (Protect & PAGE_NOCACHE) ? MmNonCached : MmHardwareCoherentCached; + PVOID pMem; + PhysAddr.QuadPart = SectionOffset->QuadPart; + + DPRINT1("NtMapViewOfSection, request for physical memory.\n"); + + pMem = MmMapIoSpace(PhysAddr, SafeViewSize, CacheType); + + DPRINT("MmMapIoSpace %s for 0x%I64x, Size: 0x%x\n", + pMem ? "worked" : "failed", + PhysAddr.QuadPart, SafeViewSize); + if (!pMem) + { + // For now, we might as well bugcheck. + // Returning from this error has displayed drivers don't care about + // success - allowing f.ex. filesystems to update _partially_, and + // then our caller crashes, making the filesystem unusable until + // chk + repair. + KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW, 0, 0, 0, 0); + } + *BaseAddress = pMem; + return STATUS_SUCCESS; + } + + /* WARNING: Chances are the following two checks are wrong. They don't + take (the optional) SectionOffset into account! */ + /* Check for kernel-mode address */ + if (SafeBaseAddress > MM_HIGHEST_VAD_ADDRESS) + { + DPRINT1("Kernel base not allowed\n"); + return STATUS_INVALID_PARAMETER_3; + } + + /* Check for range entering kernel-mode */ + if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)SafeBaseAddress) < SafeViewSize) + { + DPRINT1("Overflowing into kernel base not allowed\n"); + return STATUS_INVALID_PARAMETER_3; + } + + /* Check for invalid zero bits */ + if (((ULONG_PTR)SafeBaseAddress + SafeViewSize) > (0xFFFFFFFF >> ZeroBits)) // arch? + { + DPRINT1("Invalid zero bits\n"); + return STATUS_INVALID_PARAMETER_4; + } + /* Now do the actual mapping */ Status = MmMapViewOfSection(Section, - Process, - &SafeBaseAddress, + Process, &SafeBaseAddress, ZeroBits, CommitSize, &SafeSectionOffset,