PowerPC support drop in freeldr, from my branch.

Some stuff not working, but disk IO now implemented.
Get boot partition either from boot-device env var or from cmd line.
Needs some work to build with the new tools.

svn path=/trunk/; revision=19857
This commit is contained in:
Art Yerkes 2005-12-04 12:13:48 +00:00
parent 1849ba7261
commit 7e8e7b9634
4 changed files with 1164 additions and 39 deletions

View file

@ -61,9 +61,10 @@ _begin:
li %r9,0x12 /* BATL(0, BAT_M, BAT_PP_RW) */
mtibatl 0,%r9
mtdbatl 0,%r9
li %r9,0x1ffe /* BATU(0, BAT_BL_256M, BAT_Vs) */
mtibatu 0,%r9
mtdbatu 0,%r9
li %r10,0x1ffe /* BATU(0, BAT_BL_256M, BAT_Vs) */
mtibatu 0,%r10
mtdbatu 0,%r10
isync
li %r8,0x3030
@ -93,6 +94,8 @@ _begin:
bl ofw_print_eol
bl setup_exc
/* Zero CTR */
mtcr %r31
@ -630,6 +633,53 @@ ofw_finddevice:
/* Return */
blr
ofw_open:
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,32
/* Store r8, r9, lr */
stw %r8,20(%r1)
stw %r9,24(%r1)
mflr %r8
stw %r8,28(%r1)
/* Get open name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_open_name - _start
stw %r9,0(%r1)
/* 1 Argument and 1 return */
li %r9,1
stw %r9,4(%r1)
stw %r9,8(%r1)
stw %r3,12(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
lwz %r3,16(%r1)
/* Restore registers */
lwz %r8,28(%r1)
mtlr %r8
lwz %r9,24(%r1)
lwz %r8,20(%r1)
addi %r1,%r1,32
/* Return */
blr
ofw_getprop_hook:
/* Reserve stack space:
* 32 bytes for the ofw call
@ -889,7 +939,224 @@ ofw_exit_loop:
/* Fire */
blrl
/* No return from exit */
ofw_child:
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,32
/* Store r8, r9, lr */
stw %r8,20(%r1)
stw %r9,24(%r1)
mflr %r8
stw %r8,28(%r1)
/* Get child name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_child_name - _start
stw %r9,0(%r1)
/* 1 Argument and 1 return */
li %r9,1
stw %r9,4(%r1)
stw %r9,8(%r1)
stw %r3,12(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
lwz %r3,16(%r1)
/* Restore registers */
lwz %r8,28(%r1)
mtlr %r8
lwz %r9,24(%r1)
lwz %r8,20(%r1)
addi %r1,%r1,32
/* Return */
blr
ofw_peer:
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,32
/* Store r8, r9, lr */
stw %r8,20(%r1)
stw %r9,24(%r1)
mflr %r8
stw %r8,28(%r1)
/* Get peer name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_peer_name - _start
stw %r9,0(%r1)
/* 1 Argument and 1 return */
li %r9,1
stw %r9,4(%r1)
stw %r9,8(%r1)
stw %r3,12(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
lwz %r3,16(%r1)
/* Restore registers */
lwz %r8,28(%r1)
mtlr %r8
lwz %r9,24(%r1)
lwz %r8,20(%r1)
addi %r1,%r1,32
/* Return */
blr
ofw_seek:
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,32
/* Store r8, r9, lr */
stw %r8,20(%r1)
stw %r9,24(%r1)
mflr %r8
stw %r8,28(%r1)
/* Get peer name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_seek_name - _start
stw %r9,0(%r1)
/* 3 Arguments and 1 return */
li %r9,3
stw %r9,4(%r1)
li %r9,1
stw %r9,8(%r1)
stw %r3,12(%r1)
stw %r4,16(%r1)
stw %r5,20(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
lwz %r3,16(%r1)
/* Restore registers */
lwz %r8,28(%r1)
mtlr %r8
lwz %r9,24(%r1)
lwz %r8,20(%r1)
addi %r1,%r1,32
/* Return */
blr
setup_exc:
subi %r1,%r1,32
stw %r3,0(%r1)
mflr %r3
stw %r3,4(%r1)
stw %r8,8(%r1)
stw %r9,12(%r1)
stw %r10,16(%r1)
stw %r12,20(%r1)
lis %r8,0xe00000@ha
xor %r12,%r12,%r12
addi %r12,%r12,0x300
addi %r9,%r8,dsi_exc - _start
addi %r10,%r8,dsi_end - _start
copy_loop:
cmp 0,0,%r9,%r10
beq ret_setup_exc
mr %r3,%r12
bl ofw_print_number
bl ofw_print_space
lwz %r3,0(%r9)
stw %r3,0(%r12)
bl ofw_print_number
bl ofw_print_eol
addi %r12,%r12,4
addi %r9,%r9,4
b copy_loop
ret_setup_exc:
mfmsr %r12
andi. %r12,%r12,0xffbf
mtmsr %r12
lwz %r12,20(%r1)
lwz %r10,16(%r1)
lwz %r9,12(%r1)
lwz %r8,8(%r1)
lwz %r3,4(%r1)
mtlr %r3
lwz %r3,0(%r1)
blr
dsi_exc:
subi %r1,%r1,16
stw %r0,0(%r1)
stw %r3,4(%r1)
mfsrr0 %r3
addi %r3,%r3,4
mtsrr0 %r3
/* mfsrr1 %r3 */
/* ori %r3,%r3,2 */
/* mtsrr1 %r3 */
lwz %r3,4(%r1)
lwz %r0,0(%r1)
addi %r1,%r1,16
rfi
dsi_end:
.org 0x1000
freeldr_banner:
.ascii "ReactOS OpenFirmware Boot Program\r\n\0"
@ -899,7 +1166,6 @@ freeldr_halt:
freeldr_reg_init:
.ascii "r\0"
freeldr_reg_lr:
.ascii "lr \0"
freeldr_reg_cr:
@ -933,6 +1199,18 @@ ofw_read_name:
ofw_exit_name:
.ascii "exit\0"
ofw_open_name:
.ascii "open\0"
ofw_child_name:
.ascii "child\0"
ofw_peer_name:
.ascii "peer\0"
ofw_seek_name:
.ascii "seek\0"
ofw_chosen_name:
.ascii "/chosen\0"
@ -954,6 +1232,10 @@ ofw_functions:
.long ofw_print_regs
.long ofw_print_string
.long ofw_print_number
.long ofw_open
.long ofw_child
.long ofw_peer
.long ofw_seek
.org 0x2000
stack:

View file

@ -1,3 +1,3 @@
.extern PpcInit
_start:
b PpcInit
b PpcInit+4

View file

@ -22,20 +22,18 @@
extern void BootMain( char * );
extern char *GetFreeLoaderVersionString();
ULONG BootPartition = 0;
ULONG BootDrive = 0;
of_proxy ofproxy;
void *PageDirectoryStart, *PageDirectoryEnd;
static int chosen_package, stdin_handle;
static int chosen_package, stdin_handle, part_handle = -1;
BOOLEAN AcpiPresent = FALSE;
char BootPath[0x100];
char BootPath[0x100] = { 0 }, BootPart[0x100] = { 0 }, CmdLine[0x100] = { 0 };
jmp_buf jmp;
void le_swap( const void *start_addr_v,
const void *end_addr_v,
void le_swap( const void *start_addr_v,
const void *end_addr_v,
const void *target_addr_v ) {
long *start_addr = (long *)ROUND_DOWN((long)start_addr_v,8),
*end_addr = (long *)ROUND_UP((long)end_addr_v,8),
long *start_addr = (long *)ROUND_DOWN((long)start_addr_v,8),
*end_addr = (long *)ROUND_UP((long)end_addr_v,8),
*target_addr = (long *)ROUND_DOWN((long)target_addr_v,8);
long tmp;
while( start_addr <= end_addr ) {
@ -68,6 +66,7 @@ int ofw_getprop( int package, const char *name, void *buffer, int buflen ) {
return ret;
}
/* Since this is from external storage, it doesn't need swapping */
int ofw_write( int handle, const char *data, int len ) {
int ret;
le_swap( data, data + len, data );
@ -77,12 +76,15 @@ int ofw_write( int handle, const char *data, int len ) {
return ret;
}
/* Since this is from external storage, it doesn't need swapping */
int ofw_read( int handle, const char *data, int len ) {
int ret;
le_swap( data, data + len, data );
ret = ofproxy
( 12, (void *)handle, (char *)data, (void *)len, NULL );
le_swap( data, data + len, data );
return ret;
}
@ -105,14 +107,75 @@ void ofw_print_number( int num ) {
ofproxy( 28, (void *)num, NULL, NULL, NULL );
}
int ofw_open( const char *name ) {
int ret, len;
len = strlen(name);
le_swap( name, name + len, name );
ret = ofproxy( 32, (char *)name, NULL, NULL, NULL );
le_swap( name, name + len, name );
return ret;
}
int ofw_child( int package ) {
return ofproxy( 36, (void *)package, NULL, NULL, NULL );
}
int ofw_peer( int package ) {
return ofproxy( 40, (void *)package, NULL, NULL, NULL );
}
int ofw_seek( int handle, long long location ) {
return ofproxy( 44, (void *)handle, (void *)(int)(location >> 32), (void *)(int)location, NULL );
}
void PpcPutChar( int ch ) {
char buf[3];
if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; }
if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; }
else { buf[0] = ch; buf[1] = 0; }
buf[2] = 0;
ofw_print_string( buf );
}
int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
static char buf[256];
int next = 0;
int gotname = 0;
int match = 0;
int i;
next = ofw_child( parent );
//printf( "next = %x\n", next );
gotname = ofw_getprop(parent, "name", buf, 256);
//printf( "gotname = %d\n", gotname );
match = !strncmp(buf, devname, strlen(devname));
if( !nth && match ) return parent;
else if( match ) *nth--;
for( i = 0; i < depth; i++ ) PpcPutChar( ' ' );
if( depth == 1 ) {
if( gotname > 0 ) {
printf( "%c Name: %s\n", match ? '*' : ' ', buf );
} else {
printf( "- No name attribute for %x\n", parent );
}
}
while( !match && next ) {
i = PpcFindDevice( depth+1, next, devname, nth );
if( i ) return i;
next = ofw_peer( next );
}
return 0;
}
BOOL PpcConsKbHit() {
return TRUE;
}
@ -167,12 +230,12 @@ BOOL PpcVideoIsPaletteFixed() {
return FALSE;
}
VOID PpcVideoSetPaletteColor( UCHAR Color,
VOID PpcVideoSetPaletteColor( UCHAR Color,
UCHAR Red, UCHAR Green, UCHAR Blue ) {
printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color, Red, Green, Blue );
}
VOID PpcVideoGetPaletteColor( UCHAR Color,
VOID PpcVideoGetPaletteColor( UCHAR Color,
UCHAR *Red, UCHAR *Green, UCHAR *Blue ) {
printf( "GetPaletteColor(%x)\n", Color);
}
@ -198,16 +261,74 @@ ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
BiosMemoryMap[0].BaseAddress = 0;
BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
printf( "Returning memory map (%dk total)\n",
printf( "Returning memory map (%dk total)\n",
(int)BiosMemoryMap[0].Length / 1024 );
return 1;
}
/* Strategy:
*
* For now, it'll be easy enough to use the boot command line as our boot path.
* Treat it as the path of a disk partition. We might even be able to get
* away with grabbing a partition image by tftp in this scenario.
*/
BOOL PpcDiskGetBootVolume( PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType ) {
*DriveNumber = 0;
*StartSector = 0;
*SectorCount = 0;
*FsType = FS_FAT;
return TRUE;
}
BOOL PpcDiskGetSystemVolume( char *SystemPath,
char *RemainingPath,
PULONG Device,
PULONG DriveNumber,
PULONGLONG StartSector,
PULONGLONG SectorCount,
int *FsType ) {
return FALSE;
}
BOOL PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
strncpy( OutBootPath, BootPath, Size );
return TRUE;
}
VOID PpcDiskGetBootDevice( PULONG BootDevice ) {
BootDevice[0] = BootDevice[1] = 0;
}
BOOL PpcDiskBootingFromFloppy(VOID) {
return FALSE;
}
BOOL PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
ULONG SectorCount, PVOID Buffer ) {
printf("DiskReadLogicalSectors\n");
return FALSE;
int rlen = 0;
if( part_handle == -1 ) {
part_handle = ofw_open( BootPart );
if( part_handle == -1 ) {
printf("Could not open any disk devices we know about\n");
return FALSE;
}
}
if( part_handle == -1 ) {
printf("Got partition handle %x\n", part_handle);
return FALSE;
}
if( ofw_seek( part_handle, SectorNumber * 512 ) ) {
printf("Seek to %x failed\n", SectorNumber * 512);
return FALSE;
}
rlen = ofw_read( part_handle, Buffer, SectorCount * 512 );
return rlen > 0;
}
BOOL PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
@ -218,24 +339,32 @@ BOOL PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
BOOL PpcDiskGetDriveGeometry( ULONG DriveNumber, PGEOMETRY DriveGeometry ) {
printf("GetGeometry(%d)\n", DriveNumber);
return FALSE;
DriveGeometry->BytesPerSector = 512;
DriveGeometry->Heads = 16;
DriveGeometry->Sectors = 63;
return TRUE;
}
ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
printf("GetCacheableBlockCount\n");
return 0;
return 1;
}
VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
PULONG Hour, PULONG Minute, PULONG Second ) {
printf("RTCGeturrentDateTime\n");
}
VOID PpcHwDetect() {
printf("PpcHwDetect\n");
}
typedef unsigned int uint32_t;
void PpcInit( of_proxy the_ofproxy ) {
int len;
ofproxy = the_ofproxy;
chosen_package = ofw_finddevice( "/chosen" );
ofw_getprop( chosen_package, "stdin",
@ -246,8 +375,8 @@ void PpcInit( of_proxy the_ofproxy ) {
MachVtbl.ConsPutChar = PpcPutChar;
MachVtbl.ConsKbHit = PpcConsKbHit;
MachVtbl.ConsGetCh = PpcConsGetCh;
printf("chosen_package = %x\n", chosen_package);
printf( "stdin_handle is %x\n", stdin_handle );
MachVtbl.VideoClearScreen = PpcVideoClearScreen;
MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
@ -256,7 +385,7 @@ void PpcInit( of_proxy the_ofproxy ) {
MachVtbl.VideoSetTextCursorPosition = PpcVideoSetTextCursorPosition;
MachVtbl.VideoHideShowTextCursor = PpcVideoHideShowTextCursor;
MachVtbl.VideoPutChar = PpcVideoPutChar;
MachVtbl.VideoCopyOffScreenBufferToVRAM =
MachVtbl.VideoCopyOffScreenBufferToVRAM =
PpcVideoCopyOffScreenBufferToVRAM;
MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
@ -266,6 +395,11 @@ void PpcInit( of_proxy the_ofproxy ) {
MachVtbl.GetMemoryMap = PpcGetMemoryMap;
MachVtbl.DiskGetBootVolume = PpcDiskGetBootVolume;
MachVtbl.DiskGetSystemVolume = PpcDiskGetSystemVolume;
MachVtbl.DiskGetBootPath = PpcDiskGetBootPath;
MachVtbl.DiskGetBootDevice = PpcDiskGetBootDevice;
MachVtbl.DiskBootingFromFloppy = PpcDiskBootingFromFloppy;
MachVtbl.DiskReadLogicalSectors = PpcDiskReadLogicalSectors;
MachVtbl.DiskGetPartitionEntry = PpcDiskGetPartitionEntry;
MachVtbl.DiskGetDriveGeometry = PpcDiskGetDriveGeometry;
@ -276,24 +410,57 @@ void PpcInit( of_proxy the_ofproxy ) {
MachVtbl.HwDetect = PpcHwDetect;
printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
BootMain("freeldr-ppc");
len = ofw_getprop(chosen_package, "bootargs",
CmdLine, sizeof(CmdLine));
if( len < 0 ) len = 0;
CmdLine[len] = 0;
BootMain( CmdLine );
}
void MachInit(const char *CmdLine) {
int len;
printf( "Determining boot device:\n" );
len = ofw_getprop(chosen_package, "bootpath",
BootPath, sizeof(BootPath));
printf( "Got %d bytes of path\n", len );
BootPath[len] = 0;
printf( "Boot Path: %s\n", BootPath );
void MachInit(char *CmdLine) {
int len, i;
char *sep;
printf( "FreeLDR starting\n" );
}
void FrLdrSetupPageDirectory() {
BootPart[0] = 0;
BootPath[0] = 0;
printf( "Determining boot device: [%s]\n", CmdLine );
printf( "Boot Args: %s\n", CmdLine );
sep = NULL;
for( i = 0; i < strlen(CmdLine); i++ ) {
if( strncmp(CmdLine + i, "boot=", 5) == 0) {
strcpy(BootPart, CmdLine + i + 5);
sep = strchr(BootPart, ' ');
if( sep )
*sep = 0;
break;
}
}
if( strlen(BootPart) == 0 ) {
len = ofw_getprop(chosen_package, "bootpath",
BootPath, sizeof(BootPath));
if( len < 0 ) len = 0;
BootPath[len] = 0;
printf( "Boot Path: %s\n", BootPath );
sep = strrchr(BootPath, ',');
strcpy(BootPart, BootPath);
if( sep ) {
BootPart[sep - BootPath] = 0;
}
}
printf( "FreeLDR starting (boot partition: %s)\n", BootPart );
}
/* Compatibility functions that don't do much */
void beep() {
}
@ -303,3 +470,18 @@ UCHAR STDCALL READ_PORT_UCHAR(PUCHAR Address) {
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
}
void DiskStopFloppyMotor() {
}
void BootOldLinuxKernel( unsigned long size ) {
ofw_exit();
}
void BootNewLinuxKernel() {
ofw_exit();
}
void ChainLoadBiosBootSectorCode() {
ofw_exit();
}

View file

@ -0,0 +1,661 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: Freeloader
* FILE: boot/freeldr/freeldr/multiboot.c
* PURPOSE: ReactOS Loader
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Hartmut Birr - SMP/PAE Code
*/
#include <freeldr.h>
#include <internal/powerpc/ke.h>
#define NDEBUG
#include <debug.h>
/* 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 20
#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 Phsyical Address Pointer into a Page Frame Number */
#define PaPtrToPfn(p) \
(((ULONG_PTR)&p) >> PFN_SHIFT)
/* Converts a Phsyical Address into a Page Frame Number */
#define PaToPfn(p) \
((p) >> PFN_SHIFT)
#define STARTUP_BASE 0xF0000000
#define HYPERSPACE_BASE 0xF0800000
#define APIC_BASE 0xFEC00000
#define KPCR_BASE 0xFF000000
#define LowMemPageTableIndex 0
#define StartupPageTableIndex (STARTUP_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
#define HyperspacePageTableIndex (HYPERSPACE_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
#define KpcrPageTableIndex (KPCR_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
#define ApicPageTableIndex (APIC_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
#define LowMemPageTableIndexPae 0
#define StartupPageTableIndexPae (STARTUP_BASE >> 21)
#define HyperspacePageTableIndexPae (HYPERSPACE_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 */
PFRLDR_MODULE CurrentModule = NULL;
/* Unrelocated Kernel Base in Virtual Memory */
ULONG_PTR KernelBase;
/* Wether PAE is to be used or not */
BOOLEAN PaeModeEnabled;
/* Kernel Entrypoint in Physical Memory */
ULONG_PTR KernelEntry;
/* FUNCTIONS *****************************************************************/
/*++
* FrLdrStartup
* INTERNAL
*
* Prepares the system for loading the Kernel.
*
* Params:
* Magic - Multiboot Magic
*
* Returns:
* None.
*
* Remarks:
* None.
*
*--*/
VOID
STDCALL
FrLdrStartup(ULONG Magic)
{
#if 0
/* Disable Interrupts */
KeArchDisableInterrupts();
/* Re-initalize EFLAGS */
KeArchEraseFlags();
/* Initialize the page directory */
FrLdrSetupPageDirectory();
#endif
}
/*++
* 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.
*
*--*/
VOID
FASTCALL
FrLdrGetKernelBase(VOID)
{
PCHAR p;
/* 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 = 0xC0000000;
}
}
p++;
}
/* Set KernelBase */
LoaderBlock.KernelBase = KernelBase;
}
/*++
* 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)
{
#if 0
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;
}
/* Set up the Low Memory PDE */
for (i = 0; i < 2; i++)
{
PageDirPae->Pde[LowMemPageTableIndexPae + i].Valid = 1;
PageDirPae->Pde[LowMemPageTableIndexPae + i].Write = 1;
PageDirPae->Pde[LowMemPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(lowmem_pagetable_pae) + i;
}
/* Set up the Kernel PDEs */
for (i = 0; i < 3; i++)
{
PageDirPae->Pde[KernelPageTableIndex + i].Valid = 1;
PageDirPae->Pde[KernelPageTableIndex + i].Write = 1;
PageDirPae->Pde[KernelPageTableIndex + i].PageFrameNumber = PaPtrToPfn(kernel_pagetable_pae) + i;
}
/* Set up the Startup PDE */
for (i = 0; i < 4; i++)
{
PageDirPae->Pde[StartupPageTableIndexPae + i].Valid = 1;
PageDirPae->Pde[StartupPageTableIndexPae + i].Write = 1;
PageDirPae->Pde[StartupPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i;
}
/* Set up the Hyperspace PDE */
for (i = 0; i < 2; i++)
{
PageDirPae->Pde[HyperspacePageTableIndexPae + i].Valid = 1;
PageDirPae->Pde[HyperspacePageTableIndexPae + i].Write = 1;
PageDirPae->Pde[HyperspacePageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable_pae) + i;
}
/* Set up the Apic PDE */
for (i = 0; i < 2; i++)
{
PageDirPae->Pde[ApicPageTableIndexPae + i].Valid = 1;
PageDirPae->Pde[ApicPageTableIndexPae + i].Write = 1;
PageDirPae->Pde[ApicPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(apic_pagetable_pae) + i;
}
/* Set up the KPCR PDE */
PageDirPae->Pde[KpcrPageTableIndexPae].Valid = 1;
PageDirPae->Pde[KpcrPageTableIndexPae].Write = 1;
PageDirPae->Pde[KpcrPageTableIndexPae].PageFrameNumber = PaPtrToPfn(kpcr_pagetable_pae);
/* Set up Low Memory PTEs */
PageDirPae = (PPAGE_DIRECTORY_X64)&lowmem_pagetable_pae;
for (i=0; i<1024; i++) {
PageDirPae->Pde[i].Valid = 1;
PageDirPae->Pde[i].Write = 1;
PageDirPae->Pde[i].Owner = 1;
PageDirPae->Pde[i].PageFrameNumber = i;
}
/* Set up Kernel PTEs */
PageDirPae = (PPAGE_DIRECTORY_X64)&kernel_pagetable_pae;
for (i=0; i<1536; i++) {
PageDirPae->Pde[i].Valid = 1;
PageDirPae->Pde[i].Write = 1;
PageDirPae->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS) + i;
}
/* Set up APIC PTEs */
PageDirPae = (PPAGE_DIRECTORY_X64)&apic_pagetable_pae;
PageDirPae->Pde[0].Valid = 1;
PageDirPae->Pde[0].Write = 1;
PageDirPae->Pde[0].CacheDisable = 1;
PageDirPae->Pde[0].WriteThrough = 1;
PageDirPae->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
PageDirPae->Pde[0x200].Valid = 1;
PageDirPae->Pde[0x200].Write = 1;
PageDirPae->Pde[0x200].CacheDisable = 1;
PageDirPae->Pde[0x200].WriteThrough = 1;
PageDirPae->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
/* Set up KPCR PTEs */
PageDirPae = (PPAGE_DIRECTORY_X64)&kpcr_pagetable_pae;
PageDirPae->Pde[0].Valid = 1;
PageDirPae->Pde[0].Write = 1;
PageDirPae->Pde[0].PageFrameNumber = 1;
} else {
/* Get the Kernel Table Index */
KernelPageTableIndex = (KernelBase >> PDE_SHIFT) / sizeof(HARDWARE_PTE_X86);
/* 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 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;
}
return;
#endif
}
/*++
* FrLdrMapKernel
* INTERNAL
*
* Maps the Kernel into memory, does PE Section Mapping, initalizes the
* uninitialized data sections, and relocates the image.
*
* Params:
* KernelImage - FILE Structure representing the ntoskrnl image file.
*
* Returns:
* TRUE if the Kernel was mapped.
*
* Remarks:
* None.
*
*--*/
BOOL
STDCALL
FrLdrMapKernel(FILE *KernelImage)
{
#if 0
PIMAGE_DOS_HEADER ImageHeader;
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_SECTION_HEADER Section;
ULONG SectionCount;
ULONG ImageSize;
ULONG_PTR SourceSection;
ULONG_PTR TargetSection;
ULONG SectionSize;
LONG i;
PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
ULONG Count;
ULONG_PTR Address, MaxAddress;
PUSHORT TypeOffset;
ULONG_PTR Delta;
PUSHORT ShortPtr;
PULONG LongPtr;
/* Allocate 1024 bytes for PE Header */
ImageHeader = (PIMAGE_DOS_HEADER)MmAllocateMemory(1024);
/* Make sure it was succesful */
if (ImageHeader == NULL) {
return FALSE;
}
/* Load the first 1024 bytes of the kernel image so we can read the PE header */
if (!FsReadFile(KernelImage, 1024, NULL, ImageHeader)) {
/* Fail if we couldn't read */
MmFreeMemory(ImageHeader);
return FALSE;
}
/* Now read the MZ header to get the offset to the PE Header */
NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ImageHeader + ImageHeader->e_lfanew);
/* Get Kernel Base */
KernelBase = NtHeader->OptionalHeader.ImageBase;
FrLdrGetKernelBase();
/* Save Entrypoint */
KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
/* Save the Image Size */
ImageSize = NtHeader->OptionalHeader.SizeOfImage;
/* Free the Header */
MmFreeMemory(ImageHeader);
/* Set the file pointer to zero */
FsSetFilePointer(KernelImage, 0);
/* Load the file image */
FsReadFile(KernelImage, ImageSize, NULL, (PVOID)KERNEL_BASE_PHYS);
/* Reload the NT Header */
NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)KERNEL_BASE_PHYS + ImageHeader->e_lfanew);
/* Load the first section */
Section = IMAGE_FIRST_SECTION(NtHeader);
SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
/* Now go to the last section */
Section += SectionCount;
/* Walk each section backwards */
for (i=SectionCount; i >= 0; i--, Section--) {
/* Get the disk location and the memory location, and the size */
SourceSection = RaToPa(Section->PointerToRawData);
TargetSection = RaToPa(Section->VirtualAddress);
SectionSize = Section->SizeOfRawData;
/* If the section is already mapped correctly, go to the next */
if (SourceSection == TargetSection) continue;
/* Load it into memory */
memmove((PVOID)TargetSection, (PVOID)SourceSection, SectionSize);
/* Check for unitilizated data */
if (Section->SizeOfRawData < Section->Misc.VirtualSize) {
/* Zero it out */
memset((PVOID)RaToPa(Section->VirtualAddress + Section->SizeOfRawData),
0,
Section->Misc.VirtualSize - Section->SizeOfRawData);
}
}
/* Get the Relocation Data Directory */
RelocationDDir = &NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
/* Get the Relocation Section Start and End*/
RelocationDir = (PIMAGE_BASE_RELOCATION)(KERNEL_BASE_PHYS + RelocationDDir->VirtualAddress);
RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
/* Calculate Difference between Real Base and Compiled Base*/
Delta = KernelBase - NtHeader->OptionalHeader.ImageBase;;
/* Determine how far we shoudl relocate */
MaxAddress = KERNEL_BASE_PHYS + ImageSize;
/* Relocate until we've processed all the blocks */
while (RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0) {
/* See how many Relocation Blocks we have */
Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
/* Calculate the Address of this Directory */
Address = KERNEL_BASE_PHYS + RelocationDir->VirtualAddress;
/* Calculate the Offset of the Type */
TypeOffset = (PUSHORT)(RelocationDir + 1);
for (i = 0; i < Count; i++) {
ShortPtr = (PUSHORT)(Address + (*TypeOffset & 0xFFF));
/* Don't relocate after the end of the loaded driver */
if ((ULONG_PTR)ShortPtr >= MaxAddress) break;
switch (*TypeOffset >> 12) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
*ShortPtr += HIWORD(Delta);
break;
case IMAGE_REL_BASED_LOW:
*ShortPtr += LOWORD(Delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
LongPtr = (PULONG)ShortPtr;
*LongPtr += Delta;
break;
}
TypeOffset++;
}
/* Move to the next Relocation Table */
RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
}
/* Increase the next Load Base */
NextModuleBase = ROUND_UP(KERNEL_BASE_PHYS + ImageSize, PAGE_SIZE);
/* Return Success */
#endif
return TRUE;
}
ULONG_PTR
STDCALL
FrLdrLoadModule(FILE *ModuleImage,
LPSTR ModuleName,
PULONG ModuleSize)
{
#if 0
ULONG LocalModuleSize;
PFRLDR_MODULE ModuleData;
LPSTR NameBuffer;
LPSTR TempName;
/* Get current module data structure and module name string array */
ModuleData = &multiboot_modules[LoaderBlock.ModsCount];
/* Get only the Module Name */
do {
TempName = strchr(ModuleName, '\\');
if(TempName) {
ModuleName = TempName + 1;
}
} while(TempName);
NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount];
/* Get Module Size */
LocalModuleSize = FsGetFileSize(ModuleImage);
/* Fill out Module Data Structure */
ModuleData->ModuleStart = NextModuleBase;
ModuleData->ModuleEnd = NextModuleBase + LocalModuleSize;
/* Save name */
strcpy(NameBuffer, ModuleName);
ModuleData->ModuleName = NameBuffer;
/* Load the file image */
FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
/* Move to next memory block and increase Module Count */
NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE);
LoaderBlock.ModsCount++;
/* Return Module Size if required */
if (ModuleSize != NULL) {
*ModuleSize = LocalModuleSize;
}
return(ModuleData->ModuleStart);
#else
return 0;
#endif
}
ULONG_PTR
STDCALL
FrLdrCreateModule(LPSTR ModuleName)
{
#if 0
PFRLDR_MODULE ModuleData;
LPSTR NameBuffer;
/* Get current module data structure and module name string array */
ModuleData = &multiboot_modules[LoaderBlock.ModsCount];
NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount];
/* Set up the structure */
ModuleData->ModuleStart = NextModuleBase;
ModuleData->ModuleEnd = -1;
/* Copy the name */
strcpy(NameBuffer, ModuleName);
ModuleData->ModuleName = NameBuffer;
/* Set the current Module */
CurrentModule = ModuleData;
/* Return Module Base Address */
return(ModuleData->ModuleStart);
#else
return 0;
#endif
}
BOOL
STDCALL
FrLdrCloseModule(ULONG_PTR ModuleBase,
ULONG ModuleSize)
{
#if 0
PFRLDR_MODULE ModuleData = CurrentModule;
/* Make sure a module is opened */
if (ModuleData) {
/* Make sure this is the right module and that it hasn't been closed */
if ((ModuleBase == ModuleData->ModuleStart) && (ModuleData->ModuleEnd == -1)) {
/* Close the Module */
ModuleData->ModuleEnd = ModuleData->ModuleStart + ModuleSize;
/* Set the next Module Base and increase the number of modules */
NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE);
LoaderBlock.ModsCount++;
/* Close the currently opened module */
CurrentModule = NULL;
/* Success */
return(TRUE);
}
}
/* Failure path */
#endif
return(FALSE);
}