mirror of
https://github.com/reactos/reactos.git
synced 2025-01-13 01:22:03 +00:00
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:
parent
1849ba7261
commit
7e8e7b9634
4 changed files with 1164 additions and 39 deletions
|
@ -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:
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.extern PpcInit
|
||||
_start:
|
||||
b PpcInit
|
||||
b PpcInit+4
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
661
reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
Normal file
661
reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue