⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 virtmem.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//

#include "kernel.h"

#define LOG(x)  NKDbgPrintfW(L"%s == %8.8lx\n", TEXT(#x), x)

int FirstFreeSection = RESERVED_SECTIONS+1;

MEMBLOCK *PmbDecommitting;
extern CRITICAL_SECTION VAcs;
extern HANDLE GwesOOMEvent;
extern long GwesCriticalThreshold;
extern PFREEINFO GetRegionFromAddr(PHYSICAL_ADDRESS addr);
extern LPVOID PhysPageToZero (PHYSICAL_ADDRESS paPFN);
extern void ZeroAndLinkPhysPage (LPVOID pPage);

const DWORD AllocationType[MB_FLAG_PAGER_TYPE+1] = {MEM_PRIVATE, MEM_IMAGE, MEM_MAPPED};

BOOL (* pfnOEMSetMemoryAttributes) (LPVOID pVirtualAddr, LPVOID pPhysAddr, DWORD cbSize, DWORD dwAttributes);


static BOOL FakedOEMIsROM (LPVOID pvAddr, DWORD cbSize)
{
    return FALSE;
}

BOOL (*pfnOEMIsRom) (LPVOID pvAddr, DWORD cbSize) = FakedOEMIsROM;


static LPVOID EntryToKVA (DWORD dwEntry)
{
    LPVOID pRet = NULL;
    if (dwEntry & PG_VALID_MASK) {
    
    // check for VirtualCopy'd entries on MIPS and SHx seperately
#ifdef MIPS
        if ((dwEntry & ~PG_PERMISSION_MASK) >= (DWORD)(0x20000000 >> PFN_SHIFT)) {
            return NULL;
        }
#elif defined (SHx)
        if (dwEntry >= 0x20000000) {
            return NULL;
        }
#endif
        pRet = Phys2Virt (PFNfromEntry (dwEntry));

        if (pRet && ((dwEntry & PG_CACHE_MASK) == PG_NOCACHE))
            pRet = (LPVOID) ((DWORD) pRet | 0x20000000);
    }

    return pRet;
}


PVOID VerifyAccess (LPVOID pvAddr, DWORD dwFlags, ACCESSKEY aky)
{
    DWORD dwAddr = (DWORD) pvAddr;
    extern LPVOID MDValidateKVA (DWORD);

    if (!(dwFlags & VERIFY_KERNEL_OK)                       // "kernel ok" flag not set
        && (GetThreadMode(pCurThread) != KERNEL_MODE)       // not in kernel mode
        && ((dwAddr & 0x80000000)                           // kmode only address
//#if defined (x86) || defined (ARM)
            || (IsInSharedSection (dwAddr) && (dwFlags & VERIFY_WRITE_FLAG))    // write to shared section
//#endif
        )) {

        return NULL;
    }

    if (IsKernelVa (dwAddr)) {
        pvAddr = MDValidateKVA (dwAddr);
    } else {
        PSECTION pscn = (dwAddr & 0x80000000)? &NKSection : SectionTable[dwAddr>>VA_SECTION];
        MEMBLOCK *pmb;
        ulong entry;

        if (pscn
            && (pmb = (*pscn)[(dwAddr>>VA_BLOCK)&BLOCK_MASK])
            && (pmb != RESERVED_BLOCK)
            && (pmb->alk & aky)
            && ((entry = pmb->aPages[(dwAddr>>VA_PAGE)&PAGE_MASK]) & PG_VALID_MASK)
            && (!(dwFlags & VERIFY_WRITE_FLAG) || IsPageWritable (entry))) {

            if (!(pvAddr = EntryToKVA (entry))) {
                // a VirtualCopy'd address that doesn't have a statically mapped kernel
                // address equivalent. Just return the user mode VA.
                //DEBUGMSG (1, (L"VerifyAccess (%8.8lx %8.8lx %8.8lx) return %8.8lx (entry = %8.8lx)\r\n", dwAddr, dwFlags, aky, dwAddr, entry));
                return (LPVOID) dwAddr;
            }
            pvAddr = (LPVOID) ((DWORD)pvAddr | (dwAddr & (PAGE_SIZE-1)));
        } else {
            return NULL;
        }
    }

    // DEBUGMSG (1, (L"VerifyAccess (%8.8lx %8.8lx %8.8lx) return %8.8lx\r\n", dwAddr, dwFlags, aky, pvAddr));
    return pvAddr;
}

static BOOL IsROMNoCS (LPVOID pvAddr, DWORD cbSize)
{
    PSECTION pscn;
    MEMBLOCK *pmb;
    DWORD dwAddr = (DWORD) pvAddr;
    DWORD ixBlock, ixPage, cPages;

    // kernel address: just pass it to OEM
    if (IsKernelVa (pvAddr))
        return pfnOEMIsRom (pvAddr, cbSize);

    // consider kpageblock ROM
    if (ZeroPtr (pvAddr) < 0x10000)
        return TRUE;

    // virtual address, figure out from VM structure
    pscn = (dwAddr & 0x80000000)? &NKSection : SectionTable[dwAddr>>VA_SECTION];
    ixBlock = (dwAddr >> VA_BLOCK) & BLOCK_MASK;
    ixPage = (dwAddr >> VA_PAGE) & PAGE_MASK;
    cPages = ((dwAddr + cbSize + PAGE_SIZE-1) / PAGE_SIZE) - (dwAddr / PAGE_SIZE);

    while (cPages) {
        if ((pmb = (*pscn)[ixBlock ++]) == NULL_BLOCK)
            // not reserved, cannot be written to -- consider it ROM
            return TRUE;
            
        if (RESERVED_BLOCK == pmb) {
            // reseved, but not commited, cannot be ROM
            if ((int) (cPages -= (PAGES_PER_BLOCK - ixPage)) <= 0)
                return FALSE;
        } else {
            // examine all pages in the memblock
            for ( ; cPages && (ixPage < PAGES_PER_BLOCK); cPages --, ixPage ++ ) {
                DWORD dwEntry = pmb->aPages[ixPage];
                if (BAD_PAGE == dwEntry)
                    return TRUE;
                if ((pvAddr = EntryToKVA(dwEntry))
                    && pfnOEMIsRom (pvAddr, 1))
                    return TRUE;
            }
        }
        ixPage = 0;
    }

    return FALSE;
}

BOOL IsROM (LPVOID pvAddr, DWORD cbSize)
{
    BOOL fRet;
    EnterCriticalSection (&VAcs);
    fRet = IsROMNoCS (pvAddr, cbSize);
    LeaveCriticalSection (&VAcs);
    return fRet;
}


BOOL IsStackVA (DWORD dwAddr, DWORD dwLen)
{
    DWORD dwStkEnd, dwStkBeg = KSTKBASE(pCurThread);

    if (pCurThread->tlsPtr != pCurThread->tlsNonSecure) {
        // non-trusted app
        dwStkEnd = dwStkBeg + CNP_STACK_SIZE;   // fix size for secure stack
    } else {
        dwStkEnd = dwStkBeg + (KCURFIBER(pCurThread)? KPROCSTKSIZE(pCurThread) : pCurThread->dwOrigStkSize);
    }
    if (!(dwAddr >> VA_SECTION)) {
        dwAddr |= pCurThread->pProc->dwVMBase;   // will return FALSE if dwAddr is VA of other process
    }
    if ((dwStkBeg < (dwAddr + dwLen)) && (dwStkEnd > dwAddr)) {
        NKDbgPrintfW (L"KPROCSTKSIZE = %8.8lx (tls = %8.8lx, tlsNonSec = %8.8lx)\n", KPROCSTKSIZE(pCurThread), pCurThread->tlsPtr, pCurThread->tlsNonSecure);
        NKDbgPrintfW (L"dwAddr = 0x%x, dwLen = 0x%x, dwStkBeg = 0x%x, dwStkEnd = 0x%x\n", dwAddr, dwLen, KSTKBASE(pCurThread), dwStkEnd);
        DEBUGCHK (0);
        return TRUE;
    }
    return FALSE;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ulong 
MakePagePerms( 
    DWORD fdwProtect, DWORD dwAddr
    ) 
{
    ulong ulMask;
    ulong uWriteProt = PG_PROT_WRITE;

    if (IsInSharedSection (dwAddr)
        && (PAGE_READWRITE != fdwProtect)) {
        // protection at shared section must be READWRITE
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        return 0;
    }
    
#ifdef ARM
    if ((dwAddr & 0x80000000)
        || ((dwAddr < (1 << VA_SECTION)) && (ProcArray == pCurProc))) {
        // secure section - kmode access only
        uWriteProt = PG_PROT_UNO_KRW;
    } else if (IsInSharedSection (dwAddr)) {
        // shared section - user R/O, kernel R/W
        uWriteProt = PG_PROT_URO_KRW;
    }
#endif
    
    switch (fdwProtect & ~(PAGE_GUARD | PAGE_NOCACHE
#ifdef ARM
            | PAGE_ARM_MINICACHE
#endif
#ifdef x86
            | PAGE_x86_WRITETHRU
#endif
            )) {
        case PAGE_READONLY:
            ulMask = PG_VALID_MASK | PG_PROT_READ;
            break;
        case PAGE_EXECUTE:
        case PAGE_EXECUTE_READ:
            ulMask = PG_VALID_MASK | PG_PROT_READ | PG_EXECUTE_MASK;
            break;
        case PAGE_EXECUTE_READWRITE:
            ulMask = PG_VALID_MASK | PG_DIRTY_MASK | PG_EXECUTE_MASK | uWriteProt;
            break;
        case PAGE_READWRITE:
            ulMask = PG_VALID_MASK | PG_DIRTY_MASK | uWriteProt;
            break;
        case PAGE_WRITECOPY:
        case PAGE_EXECUTE_WRITECOPY:
            KSetLastError(pCurThread, ERROR_NOT_SUPPORTED);
            return 0;
        case PAGE_NOACCESS:
            if (fdwProtect != PAGE_NOACCESS) {
                KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
                return 0;
            }
            ulMask = PG_GUARD;  /* dummy return value */
            break;
        default:
            KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
            return 0;
    }
    DEBUGCHK(ulMask);
    if (fdwProtect & PAGE_GUARD)
        ulMask = (ulMask & ~PG_VALID_MASK) | PG_GUARD;
#ifdef ARM
    ulMask |= (fdwProtect & PAGE_NOCACHE) ? PG_NOCACHE : (fdwProtect & PAGE_ARM_MINICACHE) ? PG_MINICACHE : PG_CACHE;
#elif defined(x86)
    ulMask |= (fdwProtect & PAGE_NOCACHE) ? PG_NOCACHE : (fdwProtect & PAGE_x86_WRITETHRU) ? PG_WRITE_THRU_MASK : PG_CACHE;
#else
    ulMask |= (fdwProtect & PAGE_NOCACHE) ? PG_NOCACHE : PG_CACHE;
#endif
    ulMask |= PG_SIZE_MASK;
    DEBUGMSG(ZONE_VIRTMEM, (TEXT("MakePagePerms: %8.8lx returns %8.8lx\r\n"), fdwProtect, ulMask));
    return ulMask;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DWORD 
ProtectFromPerms (ulong ulPage, DWORD dwAddr) 
{
    DWORD fdwProt;
    DWORD dwWriteProt = PAGE_READWRITE;

    if (IsInSharedSection (dwAddr) &&  !(pCurThread->tlsPtr[PRETLS_THRDINFO] & UTLS_INKMODE)) {
        dwWriteProt = PAGE_READONLY;
    }
    switch (ulPage & (PG_PROTECTION|PG_EXECUTE_MASK)) {
        case PG_PROT_READ:
            fdwProt = PAGE_READONLY;
            break;
        case PG_PROT_WRITE:
#ifdef ARM
        case PG_PROT_UNO_KRW:       // secure section
        case PG_PROT_URO_KRW:       // shared section
#endif
            fdwProt = dwWriteProt;
            break;
#if PG_EXECUTE_MASK
        case PG_EXECUTE_MASK|PG_PROT_READ:
            fdwProt = PAGE_EXECUTE_READ;
            break;
        case PG_EXECUTE_MASK|PG_PROT_READ|PG_PROT_WRITE:
            fdwProt = PAGE_EXECUTE_READWRITE;
            break;
#endif
        default: // invalid combinations get mapped to PAGE_NOACCESS
            return PAGE_NOACCESS;
    }
    if ((ulPage & (PG_VALID_MASK|PG_GUARD)) == PG_GUARD)
        fdwProt |= PAGE_GUARD;
    if ((ulPage & PG_CACHE_MASK) == PG_NOCACHE)
        fdwProt |= PAGE_NOCACHE;
    return fdwProt;
}

BOOL NKSetMemoryAttributes (LPVOID pVirtualAddr, LPVOID pShiftedPhysAddr, DWORD cbSize, DWORD dwAttributes)
{
    DWORD dwPhysAddr = (PHYSICAL_ADDRESS_UNKNOWN == pShiftedPhysAddr)? 0 : ((DWORD) pShiftedPhysAddr << 8);
    BOOL  fRet;
    // validate parameter
    if (!pfnOEMSetMemoryAttributes
        || !cbSize
        || !pVirtualAddr
        || ((DWORD) pVirtualAddr & (PAGE_SIZE-1))
        || (dwPhysAddr & (PAGE_SIZE-1))
        || (cbSize & (PAGE_SIZE-1))) {
        KSetLastError (pCurThread, pfnOEMSetMemoryAttributes? ERROR_NOT_SUPPORTED : ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    EnterCriticalSection (&VAcs);
    // call to OEM to set the memory attributes
    // NOTE: we intentionally not checking dwAttributes so we don't have to change kernel
    //       in case we support more attributes in the future.
    fRet = pfnOEMSetMemoryAttributes (pVirtualAddr, pShiftedPhysAddr, cbSize, dwAttributes);
    LeaveCriticalSection (&VAcs);

    if (!fRet) {
        KSetLastError (pCurThread, ERROR_NOT_SUPPORTED);
    }
    return fRet;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -