PowerPC support drop in freeldr, from my branch.
authorArt Yerkes <art.yerkes@gmail.com>
Sun, 4 Dec 2005 12:13:48 +0000 (12:13 +0000)
committerArt Yerkes <art.yerkes@gmail.com>
Sun, 4 Dec 2005 12:13:48 +0000 (12:13 +0000)
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

reactos/boot/freeldr/bootsect/ofwboot.s
reactos/boot/freeldr/freeldr/arch/powerpc/boot.s
reactos/boot/freeldr/freeldr/arch/powerpc/mach.c
reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c [new file with mode: 0644]

index 36e0434..0ec81eb 100644 (file)
@@ -61,9 +61,10 @@ _begin:
        li      %r9,0x12             /* BATL(0, BAT_M, BAT_PP_RW) */
        mtibatl 0,%r9           
        mtdbatl 0,%r9           
        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
        isync                   
 
        li      %r8,0x3030
@@ -93,6 +94,8 @@ _begin:
 
        bl      ofw_print_eol
 
 
        bl      ofw_print_eol
 
+       bl      setup_exc
+
        /* Zero CTR */
        mtcr    %r31
        
        /* Zero CTR */
        mtcr    %r31
        
@@ -630,6 +633,53 @@ ofw_finddevice:
        /* Return */
        blr
 
        /* 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
 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 */
        /* 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"
        .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_init:
        .ascii  "r\0"
-
 freeldr_reg_lr:        
        .ascii  "lr \0"
 freeldr_reg_cr:        
 freeldr_reg_lr:        
        .ascii  "lr \0"
 freeldr_reg_cr:        
@@ -933,6 +1199,18 @@ ofw_read_name:
 ofw_exit_name:
        .ascii  "exit\0"
 
 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"
 
 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_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:
        
        .org    0x2000
 stack:
index 30c1f1c..a507daa 100644 (file)
@@ -1,3 +1,3 @@
        .extern PpcInit
 _start:
        .extern PpcInit
 _start:
-       b       PpcInit
+       b       PpcInit+4
index efd6add..401f060 100644 (file)
 
 extern void BootMain( char * );
 extern char *GetFreeLoaderVersionString();
 
 extern void BootMain( char * );
 extern char *GetFreeLoaderVersionString();
-ULONG BootPartition = 0;
-ULONG BootDrive = 0;
-
 of_proxy ofproxy;
 void *PageDirectoryStart, *PageDirectoryEnd;
 of_proxy ofproxy;
 void *PageDirectoryStart, *PageDirectoryEnd;
-static int chosen_package, stdin_handle;
+static int chosen_package, stdin_handle, part_handle = -1;
 BOOLEAN AcpiPresent = FALSE;
 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 ) {
               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 ) {
         *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;
 }
 
     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 );
 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;
 }
 
     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;
 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 );
     le_swap( data, data + len, data );
     ret = ofproxy
         ( 12, (void *)handle, (char *)data, (void *)len, NULL );
     le_swap( data, data + len, data );
+
     return ret;
 }
 
     return ret;
 }
 
@@ -105,14 +107,75 @@ void ofw_print_number( int num ) {
     ofproxy( 28, (void *)num, NULL, NULL, NULL );
 }
 
     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];
 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 );
 }
 
     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;
 }
 BOOL PpcConsKbHit() {
     return TRUE;
 }
@@ -167,12 +230,12 @@ BOOL PpcVideoIsPaletteFixed() {
     return FALSE;
 }
 
     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 );
 }
 
                               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);
 }
                               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 */
 
     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;
 }
 
             (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 ) {
 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,
 }
 
 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);
 
 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");
 }
 
 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() {
                                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 ) {
 void PpcInit( of_proxy the_ofproxy ) {
+    int len;
     ofproxy = the_ofproxy;
     ofproxy = the_ofproxy;
+
     chosen_package = ofw_finddevice( "/chosen" );
 
     ofw_getprop( chosen_package, "stdin",
     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;
     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;
 
     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.VideoSetTextCursorPosition = PpcVideoSetTextCursorPosition;
     MachVtbl.VideoHideShowTextCursor = PpcVideoHideShowTextCursor;
     MachVtbl.VideoPutChar = PpcVideoPutChar;
-    MachVtbl.VideoCopyOffScreenBufferToVRAM =
+    MachVtbl.VideoCopyOffScreenBufferToVRAM = 
         PpcVideoCopyOffScreenBufferToVRAM;
     MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
     MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
         PpcVideoCopyOffScreenBufferToVRAM;
     MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
     MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
@@ -266,6 +395,11 @@ void PpcInit( of_proxy the_ofproxy ) {
 
     MachVtbl.GetMemoryMap = PpcGetMemoryMap;
 
 
     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;
     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() );
     MachVtbl.HwDetect = PpcHwDetect;
 
     printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
-    BootMain("freeldr-ppc");
-}
 
 
-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 );
+    len = ofw_getprop(chosen_package, "bootargs",
+                     CmdLine, sizeof(CmdLine));
+
+    if( len < 0 ) len = 0;
+    CmdLine[len] = 0;
 
 
-    printf( "FreeLDR starting\n" );
+    BootMain( CmdLine );
 }
 
 }
 
-void FrLdrSetupPageDirectory() {
+void MachInit(char *CmdLine) {
+    int len, i;
+    char *sep;
+
+    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() {
 }
 
 void beep() {
 }
 
@@ -303,3 +470,18 @@ UCHAR STDCALL READ_PORT_UCHAR(PUCHAR Address) {
 
 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
 }
 
 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();
+}
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c b/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
new file mode 100644 (file)
index 0000000..550a4c7
--- /dev/null
@@ -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);
+}