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

📄 loader.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  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

/* Base Addres of Kernel in Physical Memory */
#define KERNEL_BASE_PHYS 0x200000

/* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
#define PFN_SHIFT 12

/* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
#define PDE_SHIFT 22
#define PDE_SHIFT_PAE 18


/* Converts a Relative Address read from the Kernel into a Physical Address */
#define RaToPa(p) \
    (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)

/* Converts a Physical Address Pointer into a Page Frame Number */
#define PaPtrToPfn(p) \
    (((ULONG_PTR)&p) >> PFN_SHIFT)

/* Converts a Physical Address into a Page Frame Number */
#define PaToPfn(p) \
    ((p) >> PFN_SHIFT)

#define STARTUP_BASE                0xC0000000
#define HYPERSPACE_BASE             0xC0400000
#define HYPERSPACE_PAE_BASE         0xC0800000
#define APIC_BASE                   0xFEC00000
#define KPCR_BASE                   0xFF000000

#define LowMemPageTableIndex        0
#define StartupPageTableIndex       (STARTUP_BASE >> 22)
#define HyperspacePageTableIndex    (HYPERSPACE_BASE >> 22)
#define KpcrPageTableIndex          (KPCR_BASE >> 22)
#define ApicPageTableIndex          (APIC_BASE >> 22)

#define LowMemPageTableIndexPae     0
#define StartupPageTableIndexPae    (STARTUP_BASE >> 21)
#define HyperspacePageTableIndexPae (HYPERSPACE_PAE_BASE >> 21)
#define KpcrPageTableIndexPae       (KPCR_BASE >> 21)
#define ApicPageTableIndexPae       (APIC_BASE >> 21)


#define KernelEntryPoint            (KernelEntry - KERNEL_BASE_PHYS) + KernelBase

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

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

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

/* Whether PAE is to be used or not */
BOOLEAN PaeModeEnabled;

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

typedef struct _HARDWARE_PTE_X64 {
    ULONG Valid             : 1;
    ULONG Write             : 1;
    ULONG Owner             : 1;
    ULONG WriteThrough      : 1;
    ULONG CacheDisable      : 1;
    ULONG Accessed          : 1;
    ULONG Dirty             : 1;
    ULONG LargePage         : 1;
    ULONG Global            : 1;
    ULONG CopyOnWrite       : 1;
    ULONG Prototype         : 1;
    ULONG reserved          : 1;
    ULONG PageFrameNumber   : 20;
    ULONG reserved2         : 31;
    ULONG NoExecute         : 1;
} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64;

typedef struct _PAGE_DIRECTORY_X86 {
    HARDWARE_PTE Pde[1024];
} PAGE_DIRECTORY_X86, *PPAGE_DIRECTORY_X86;

typedef struct _PAGE_DIRECTORY_X64 {
    HARDWARE_PTE_X64 Pde[2048];
} PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64;

typedef struct _PAGE_DIRECTORY_TABLE_X64 {
    HARDWARE_PTE_X64 Pde[4];
} PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64;

/* 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 ULONG_PTR hyperspace_pagetable;
extern ULONG_PTR _pae_pagedirtable;
extern PAGE_DIRECTORY_X86 apic_pagetable;
extern PAGE_DIRECTORY_X86 kpcr_pagetable;

/* Page Directory and Tables for PAE Systems */
extern PAGE_DIRECTORY_TABLE_X64 startup_pagedirectorytable_pae;
extern PAGE_DIRECTORY_X64 startup_pagedirectory_pae;
extern PAGE_DIRECTORY_X64 lowmem_pagetable_pae;
extern PAGE_DIRECTORY_X64 kernel_pagetable_pae;
extern ULONG_PTR hyperspace_pagetable_pae;
extern ULONG_PTR pagedirtable_pae;
extern PAGE_DIRECTORY_X64 apic_pagetable_pae;
extern PAGE_DIRECTORY_X64 kpcr_pagetable_pae;

BOOLEAN
NTAPI
FrLdrLoadImage(IN PCHAR szFileName,
               IN INT nPos);

/* 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();

    /* Get the PAE Mode */
    FrLdrGetPaeMode();

    /* 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;

    if (PaeModeEnabled)
    {
        PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectorytable_pae;

        /* Enable PAE */
        __writecr4(__readcr4() | X86_CR4_PAE);
    }

    /* 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);
}

/*++
 * FrLdrGetKernelBase
 * INTERNAL
 *
 *     Gets the Kernel Base to use.
 *
 * Params:
 *
 * Returns:
 *     None.
 *
 * Remarks:
 *     Sets both the FreeLdr internal variable as well as the one which
 *     will be used by the Kernel.
 *
 *--*/
static VOID
FASTCALL
FrLdrGetKernelBase(VOID)
{
    PCHAR p;

    /* Set KernelBase */
    LoaderBlock.KernelBase = KernelBase;

    /* Read Command Line */
    p = (PCHAR)LoaderBlock.CommandLine;
    while ((p = strchr(p, '/')) != NULL) {

        /* Find "/3GB" */
        if (!_strnicmp(p + 1, "3GB", 3)) {

            /* Make sure there's nothing following it */
            if (p[4] == ' ' || p[4] == 0) {

                /* Use 3GB */
                KernelBase = 0xE0000000;
                LoaderBlock.KernelBase = 0xC0000000;
            }
        }

        p++;
    }
}

/*++
 * FrLdrGetPaeMode
 * INTERNAL
 *
 *     Determines whether PAE mode should be enabled or not.
 *
 * Params:
 *     None.
 *
 * Returns:
 *     None.
 *
 * Remarks:
 *     None.
 *
 *--*/
VOID
FASTCALL
FrLdrGetPaeMode(VOID)
{
    BOOLEAN PaeModeSupported;

    PaeModeSupported = FALSE;
    PaeModeEnabled = FALSE;

    if (CpuidSupported() & 1)
    {
       ULONG eax, ebx, ecx, FeatureBits;
       GetCpuid(1, &eax, &ebx, &ecx, &FeatureBits);
       if (FeatureBits & X86_FEATURE_PAE)
       {
          PaeModeSupported = TRUE;
       }
    }

    if (PaeModeSupported)
    {
       PCHAR p;

       /* Read Command Line */
       p = (PCHAR)LoaderBlock.CommandLine;
       while ((p = strchr(p, '/')) != NULL) {

          p++;
          /* Find "PAE" */
          if (!_strnicmp(p, "PAE", 3)) {

              /* Make sure there's nothing following it */
              if (p[3] == ' ' || p[3] == 0) {

                  /* Use Pae */
                  PaeModeEnabled = TRUE;
                  break;
              }
          }
       }
    }
}

/*++
 * 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;
    PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae;
    PPAGE_DIRECTORY_X64 PageDirPae;
    ULONG KernelPageTableIndex;
    ULONG i;

    if (PaeModeEnabled) {

        /* Get the Kernel Table Index */
        KernelPageTableIndex = (KernelBase >> 21);

        /* Get the Startup Page Directory Table */
        PageDirTablePae = (PPAGE_DIRECTORY_TABLE_X64)&startup_pagedirectorytable_pae;

        /* Get the Startup Page Directory */
        PageDirPae = (PPAGE_DIRECTORY_X64)&startup_pagedirectory_pae;

        /* Set the Startup page directory table */
        for (i = 0; i < 4; i++)
        {
            PageDirTablePae->Pde[i].Valid = 1;
            PageDirTablePae->Pde[i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i;

⌨️ 快捷键说明

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