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

📄 loader.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  FreeLoader
 *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 *  Copyright (C) 2005       Alex Ionescu  <alex@relsoft.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#define _NTSYSTEM_
#include <freeldr.h>

#define NDEBUG
#include <debug.h>
#undef DbgPrint

/* Load Address of Next Module */
ULONG_PTR NextModuleBase = KERNEL_BASE_PHYS;

/* Currently Opened Module */
PLOADER_MODULE CurrentModule = NULL;

/* Unrelocated Kernel Base in Virtual Memory */
ULONG_PTR KernelBase;

/* Kernel Entrypoint in Physical Memory */
ULONG_PTR KernelEntry;

/* Page Directory and Tables for non-PAE Systems */
extern PAGE_DIRECTORY_X86 startup_pagedirectory;
extern PAGE_DIRECTORY_X86 lowmem_pagetable;
extern PAGE_DIRECTORY_X86 kernel_pagetable;
extern PAGE_DIRECTORY_X86 hyperspace_pagetable;
extern PAGE_DIRECTORY_X86 apic_pagetable;
extern PAGE_DIRECTORY_X86 kpcr_pagetable;
extern PAGE_DIRECTORY_X86 kuser_pagetable;

PVOID
NTAPI
LdrPEGetExportByName(PVOID BaseAddress,
                     PUCHAR SymbolName,
                     USHORT Hint);

/* FUNCTIONS *****************************************************************/

/*++
 * FrLdrStartup
 * INTERNAL
 *
 *     Prepares the system for loading the Kernel.
 *
 * Params:
 *     Magic - Multiboot Magic
 *
 * Returns:
 *     None.
 *
 * Remarks:
 *     None.
 *
 *--*/
VOID
NTAPI
FrLdrStartup(ULONG Magic)
{
    /* Disable Interrupts */
    _disable();

    /* Re-initalize EFLAGS */
    Ke386EraseFlags();

    /* Initialize the page directory */
    FrLdrSetupPageDirectory();

    /* Initialize Paging, Write-Protection and Load NTOSKRNL */
    FrLdrSetupPae(Magic);
}

/*++
 * FrLdrSetupPae
 * INTERNAL
 *
 *     Configures PAE on a MP System, and sets the PDBR if it's supported, or if
 *     the system is UP.
 *
 * Params:
 *     Magic - Multiboot Magic
 *
 * Returns:
 *     None.
 *
 * Remarks:
 *     None.
 *
 *--*/
VOID
FASTCALL
FrLdrSetupPae(ULONG Magic)
{
    ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory;
    ASMCODE PagedJump;

    /* Set the PDBR */
    __writecr3(PageDirectoryBaseAddress);

    /* Enable Paging and Write Protect*/
    __writecr0(__readcr0() | X86_CR0_PG | X86_CR0_WP);

    /* Jump to Kernel */
    PagedJump = (ASMCODE)(PVOID)(KernelEntryPoint);
    PagedJump(Magic, &LoaderBlock);
}

/*++
 * FrLdrSetupPageDirectory
 * INTERNAL
 *
 *     Sets up the ReactOS Startup Page Directory.
 *
 * Params:
 *     None.
 *
 * Returns:
 *     None.
 *
 * Remarks:
 *     We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
 *     As such, please note that PageFrameNumber == PageEntryNumber.
 *
 *--*/
VOID
FASTCALL
FrLdrSetupPageDirectory(VOID)
{
    PPAGE_DIRECTORY_X86 PageDir;
    ULONG KernelPageTableIndex;
    ULONG i;

    /* Get the Kernel Table Index */
    KernelPageTableIndex = KernelBase >> PDE_SHIFT;

    /* Get the Startup Page Directory */
    PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;

    /* Set up the Low Memory PDE */
    PageDir->Pde[LowMemPageTableIndex].Valid = 1;
    PageDir->Pde[LowMemPageTableIndex].Write = 1;
    PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);

    /* Set up the Kernel PDEs */
    PageDir->Pde[KernelPageTableIndex].Valid = 1;
    PageDir->Pde[KernelPageTableIndex].Write = 1;
    PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
    PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
    PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
    PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);

    /* Set up the Startup PDE */
    PageDir->Pde[StartupPageTableIndex].Valid = 1;
    PageDir->Pde[StartupPageTableIndex].Write = 1;
    PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);

    /* Set up the Hyperspace PDE */
    PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
    PageDir->Pde[HyperspacePageTableIndex].Write = 1;
    PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);

    /* Set up the Apic PDE */
    PageDir->Pde[ApicPageTableIndex].Valid = 1;
    PageDir->Pde[ApicPageTableIndex].Write = 1;
    PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);

    /* Set up the KPCR PDE */
    PageDir->Pde[KpcrPageTableIndex].Valid = 1;
    PageDir->Pde[KpcrPageTableIndex].Write = 1;
    PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable);

    /* Set up the KUSER PDE */
    PageDir->Pde[KuserPageTableIndex].Valid = 1;
    PageDir->Pde[KuserPageTableIndex].Write = 1;
    PageDir->Pde[KuserPageTableIndex].PageFrameNumber = PaPtrToPfn(kuser_pagetable);

    /* Set up Low Memory PTEs */
    PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
    for (i=0; i<1024; i++)
    {
        PageDir->Pde[i].Valid = 1;
        PageDir->Pde[i].Write = 1;
        PageDir->Pde[i].Owner = 1;
        PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
    }

    /* Set up Kernel PTEs */
    PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
    for (i=0; i<1536; i++)
    {
        PageDir->Pde[i].Valid = 1;
        PageDir->Pde[i].Write = 1;
        PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
    }

    /* Set up APIC PTEs */
    PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
    PageDir->Pde[0].Valid = 1;
    PageDir->Pde[0].Write = 1;
    PageDir->Pde[0].CacheDisable = 1;
    PageDir->Pde[0].WriteThrough = 1;
    PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
    PageDir->Pde[0x200].Valid = 1;
    PageDir->Pde[0x200].Write = 1;
    PageDir->Pde[0x200].CacheDisable = 1;
    PageDir->Pde[0x200].WriteThrough = 1;
    PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);

    /* Set up KPCR PTEs */
    PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable;
    PageDir->Pde[0].Valid = 1;
    PageDir->Pde[0].Write = 1;
    PageDir->Pde[0].PageFrameNumber = 1;

    /* Setup KUSER PTEs */
    PageDir = (PPAGE_DIRECTORY_X86)&kuser_pagetable;
    for (i = 0; i < 1024; i++)
    {
        /* SEetup each entry */
        PageDir->Pde[i].Valid = 1;
        PageDir->Pde[i].Write = 1;
        PageDir->Pde[i].Owner = 1;
        PageDir->Pde[i].PageFrameNumber = PaToPfn(KI_USER_SHARED_DATA + i * PAGE_SIZE);
    }
}

PLOADER_MODULE
NTAPI
LdrGetModuleObject(PCHAR ModuleName)
{
    ULONG i;

    for (i = 0; i < LoaderBlock.ModsCount; i++)
    {
        if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName)))
        {
            return &reactos_modules[i];
        }
    }

    return NULL;
}

PVOID
NTAPI
LdrPEFixupForward(IN PCHAR ForwardName)
{
    CHAR NameBuffer[128];
    PCHAR p;
    PLOADER_MODULE ModuleObject;

    strcpy(NameBuffer, ForwardName);
    p = strchr(NameBuffer, '.');
    if (p == NULL) return NULL;
    *p = 0;

    ModuleObject = LdrGetModuleObject(NameBuffer);
    if (!ModuleObject)
    {
        DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
        return NULL;
    }

    return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff);
}

PVOID
NTAPI
LdrPEGetExportByName(PVOID BaseAddress,
                     PUCHAR SymbolName,
                     USHORT Hint)
{
    PIMAGE_EXPORT_DIRECTORY ExportDir;
    PULONG * ExFunctions;
    PULONG * ExNames;
    USHORT * ExOrdinals;
    PVOID ExName;
    ULONG Ordinal;
    PVOID Function;
    LONG minn, maxn, mid, res;
    ULONG ExportDirSize;

    /* HAL and NTOS use a virtual address, switch it to physical mode */
    if ((ULONG_PTR)BaseAddress & 0x80000000)
    {
        BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - KSEG0_BASE + 0x200000);
    }

    ExportDir = (PIMAGE_EXPORT_DIRECTORY)
        RtlImageDirectoryEntryToData(BaseAddress,
                                     TRUE,
                                     IMAGE_DIRECTORY_ENTRY_EXPORT,
                                     &ExportDirSize);
    if (!ExportDir)
    {
        DbgPrint("LdrPEGetExportByName(): no export directory!\n");
        return NULL;
    }

    /* The symbol names may be missing entirely */
    if (!ExportDir->AddressOfNames)
    {
        DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
        return NULL;
    }

    /*
    * Get header pointers
    */
    ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
    ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
    ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);

    /*
    * Check the hint first
    */
    if (Hint < ExportDir->NumberOfNames)
    {
        ExName = RVA(BaseAddress, ExNames[Hint]);
        if (strcmp(ExName, (PCHAR)SymbolName) == 0)
        {
            Ordinal = ExOrdinals[Hint];
            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
            {
                Function = LdrPEFixupForward((PCHAR)Function);
                if (Function == NULL)
                {
                    DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
                }
                return Function;
            }

            if (Function != NULL) return Function;
        }
    }

    /*
    * Binary search
    */
    minn = 0;
    maxn = ExportDir->NumberOfNames - 1;
    while (minn <= maxn)
    {
        mid = (minn + maxn) / 2;

        ExName = RVA(BaseAddress, ExNames[mid]);
        res = strcmp(ExName, (PCHAR)SymbolName);
        if (res == 0)
        {
            Ordinal = ExOrdinals[mid];
            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
            {
                Function = LdrPEFixupForward((PCHAR)Function);
                if (Function == NULL)
                {
                    DbgPrint("1: failed to find %s\n", Function);
                }
                return Function;
            }
            if (Function != NULL)
            {
                return Function;

⌨️ 快捷键说明

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