📄 loader.c
字号:
/*
* 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 + -