Big merge: thanks alex and greatlord. Not a complete merge but most
[reactos.git] / reactos / boot / freeldr / freeldr / arch / powerpc / mach.c
index 0f33944..1c1d010 100644 (file)
 #include "freeldr.h"
 #include "machine.h"
 #include "of.h"
+#include "mmu.h"
 
-extern void BootMain( char * );
-extern char *GetFreeLoaderVersionString();
+#define TOTAL_HEAP_NEEDED (32 * 1024 * 1024) /* 32 megs */
+
+extern void BootMain( LPSTR CmdLine );
+extern PCHAR GetFreeLoaderVersionString();
+extern ULONG CacheSizeLimit;
 of_proxy ofproxy;
-void *PageDirectoryStart, *PageDirectoryEnd;
+void *PageDirectoryStart, *PageDirectoryEnd, *mem_base = 0;
 static int chosen_package, stdin_handle, part_handle = -1;
 BOOLEAN AcpiPresent = FALSE;
 char BootPath[0x100] = { 0 }, BootPart[0x100] = { 0 }, CmdLine[0x100] = { 0 };
 jmp_buf jmp;
+volatile char *video_mem = 0;
 
-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), 
+void le_swap( void *start_addr_v, 
+              void *end_addr_v, 
+              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), 
         *target_addr = (long *)ROUND_DOWN((long)target_addr_v,8);
     long tmp;
@@ -45,90 +51,6 @@ void le_swap( const void *start_addr_v,
     }
 }
 
-int ofw_finddevice( const char *name ) {
-    int ret, len;
-
-    len = strlen(name);
-    le_swap( name, name + len, name );
-    ret = ofproxy( 0, (char *)name, NULL, NULL, NULL );
-    le_swap( name, name + len, name );
-    return ret;
-}
-
-int ofw_getprop( int package, const char *name, void *buffer, int buflen ) {
-    int ret, len = strlen(name);
-    le_swap( name, name + len, name );
-    le_swap( buffer, (char *)buffer + buflen, buffer );
-    ret = ofproxy
-        ( 4, (void *)package, (char *)name, buffer, (void *)buflen );
-    le_swap( buffer, (char *)buffer + buflen, buffer );
-    le_swap( name, name + len, name );
-    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 );
-    ret = ofproxy
-        ( 8, (void *)handle, (char *)data, (void *)len, NULL );
-    le_swap( data, data + len, data );
-    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;
-}
-
-void ofw_exit() {
-    ofproxy( 16, NULL, NULL, NULL, NULL );
-}
-
-void ofw_dumpregs() {
-    ofproxy( 20, NULL, NULL, NULL, NULL );
-}
-
-void ofw_print_string( const char *str ) {
-    int len = strlen(str);
-    le_swap( (char *)str, str + len, (char *)str );
-    ofproxy( 24, (void *)str, NULL, NULL, NULL );
-    le_swap( (char *)str, str + len, (char *)str );
-}
-
-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; } 
@@ -176,7 +98,7 @@ int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
 }
 
 BOOLEAN PpcConsKbHit() {
-    return TRUE;
+    return FALSE;
 }
 
 int PpcConsGetCh() {
@@ -189,26 +111,29 @@ void PpcVideoClearScreen( UCHAR Attr ) {
     ofw_print_string("ClearScreen\n");
 }
 
-VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init ) {
-    printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
-    return VideoGraphicsMode;
-}
-
-/* FIXME: Query */
 VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
-    ofw_print_string("GetDisplaySize\n");
-    *Width = 640;
-    *Height = 480;
-    *Depth = 8;
+    //ofw_print_string("GetDisplaySize\n");
+    *Width = 80;
+    *Height = 25;
+    *Depth = 16;
+    //printf("GetDisplaySize(%d,%d,%d)\n", *Width, *Height, *Depth);
 }
 
 ULONG PpcVideoGetBufferSize() {
     ULONG Width, Height, Depth;
-    ofw_print_string("PpcVideoGetBufferSize\n");
+    //ofw_print_string("PpcVideoGetBufferSize\n");
     PpcVideoGetDisplaySize( &Width, &Height, &Depth );
     return Width * Height * Depth / 8;
 }
 
+VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init ) {
+    //printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
+    if( Init && !video_mem ) {
+       video_mem = MmAllocateMemory( PpcVideoGetBufferSize() );
+    }
+    return VideoTextMode;
+}
+
 VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
     printf("SetTextCursorPosition(%d,%d)\n", X,Y);
 }
@@ -222,7 +147,22 @@ VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
 }
 
 VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
-    printf( "CopyOffScreenBufferToVRAM(%x)\n", Buffer );
+    int i,j;
+    ULONG w,h,d;
+    PCHAR ChBuf = Buffer;
+    int offset = 0;
+
+    PpcVideoGetDisplaySize( &w, &h, &d );
+
+    for( i = 0; i < h; i++ ) {
+       for( j = 0; j < w; j++ ) {
+           offset = (j * 2) + (i * w * 2);
+           if( ChBuf[offset] != video_mem[offset] ) {
+               video_mem[offset] = ChBuf[offset];
+               PpcVideoPutChar(ChBuf[offset],0,j+1,i+1);
+           }
+       }
+    }
 }
 
 BOOLEAN PpcVideoIsPaletteFixed() {
@@ -246,24 +186,53 @@ VOID PpcVideoSync() {
 VOID PpcVideoPrepareForReactOS() {
     printf( "PrepareForReactOS\n");
 }
-/* XXX FIXME:
- * According to the linux people (this is backed up by my own experience),
- * the memory object in older ofw does not do getprop right.
- *
- * The "right" way is to probe the pci bridge. *sigh*
+/* 
+ * Get memory the proper openfirmware way
  */
 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
                        ULONG MaxMemoryMapSize ) {
-    printf("GetMemoryMap(chosen=%x)\n", chosen_package);
+    int i, memhandle, mmuhandle, returned, total = 0, num_mem = 0;
+    int memdata[256];
 
-    BiosMemoryMap[0].Type = MEMTYPE_USABLE;
-    BiosMemoryMap[0].BaseAddress = 0;
-    BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
+    printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize);
 
-    printf( "Returning memory map (%dk total)\n", 
-            (int)BiosMemoryMap[0].Length / 1024 );
+    if( mem_base ) {
+       BiosMemoryMap[0].Type = MEMTYPE_USABLE;
+       BiosMemoryMap[0].BaseAddress = (ULONG)mem_base;
+       BiosMemoryMap[0].Length = TOTAL_HEAP_NEEDED;
+       printf("[cached] returning 1 element\n");
+       return 1;
+    }
 
-    return 1;
+    ofw_getprop(chosen_package, "memory", 
+               (char *)&memhandle, sizeof(memhandle));
+    ofw_getprop(chosen_package, "mmu",
+               (char *)&mmuhandle, sizeof(mmuhandle));
+
+    returned = ofw_getprop(memhandle, "available", 
+                          (char *)memdata, sizeof(memdata));
+
+    /* We need to leave some for open firmware.  Let's claim up to 16 megs 
+     * for now */
+
+    for( i = 0; i < returned / sizeof(int) && !num_mem; i += 2 ) {
+       BiosMemoryMap[num_mem].Type = MEMTYPE_USABLE;
+       BiosMemoryMap[num_mem].BaseAddress = memdata[i];
+       mem_base = (void *)memdata[i];
+       BiosMemoryMap[num_mem].Length = memdata[i+1];
+       if( BiosMemoryMap[num_mem].Length >= TOTAL_HEAP_NEEDED && 
+           total < TOTAL_HEAP_NEEDED ) {
+           BiosMemoryMap[num_mem].Length = TOTAL_HEAP_NEEDED;       
+           ofw_claim(BiosMemoryMap[num_mem].BaseAddress, 
+                     BiosMemoryMap[num_mem].Length, 0x1000); /* claim it */
+           total += BiosMemoryMap[0].Length;
+           num_mem++;
+       }
+    }
+
+    printf( "Returning memory map (%dk total)\n", total / 1024 );
+
+    return num_mem;
 }
 
 /* Strategy:
@@ -288,7 +257,14 @@ BOOLEAN PpcDiskGetSystemVolume( char *SystemPath,
                              PULONGLONG StartSector, 
                              PULONGLONG SectorCount, 
                              int *FsType ) {
-    return FALSE;
+    char *remain = strchr(SystemPath, '\\');
+    if( remain ) {
+       strcpy( RemainingPath, remain+1 );
+    } else {
+       RemainingPath[0] = 0;
+    }
+    *Device = 0;
+    return PpcDiskGetBootVolume(DriveNumber, StartSector, SectorCount, FsType);
 }
 
 BOOLEAN PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
@@ -305,7 +281,7 @@ BOOLEAN PpcDiskBootingFromFloppy(VOID) {
 }
 
 BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
-                                ULONG SectorCount, PVOID Buffer ) {
+                                  ULONG SectorCount, PVOID Buffer ) {
     int rlen = 0;
 
     if( part_handle == -1 ) {
@@ -322,11 +298,13 @@ BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
        return FALSE;
     }
 
-    if( ofw_seek( part_handle, SectorNumber * 512 ) ) {
-       printf("Seek to %x failed\n", SectorNumber * 512);
+    if( ofw_seek( part_handle, 
+                  (ULONG)(SectorNumber >> 25), 
+                  (ULONG)((SectorNumber * 512) & 0xffffffff) ) ) {
+       printf("Seek to %x failed\n", (ULONG)(SectorNumber * 512));
        return FALSE;
     }
-    rlen = ofw_read( part_handle, Buffer, SectorCount * 512 );
+    rlen = ofw_read( part_handle, Buffer, (ULONG)(SectorCount * 512) );
     return rlen > 0;
 }
 
@@ -351,31 +329,83 @@ ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
 
 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day, 
                                PULONG Hour, PULONG Minute, PULONG Second ) {
-    printf("RTCGeturrentDateTime\n");
+    //printf("RTCGeturrentDateTime\n");
 }
 
 VOID PpcHwDetect() {
     printf("PpcHwDetect\n");
 }
 
+BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) {
+       CHAR BootPath[256];
+       ULONG PartitionNumber;
+       ULONG DriveNumber;
+       PARTITION_TABLE_ENTRY PartEntry;
+       char *p;
+
+       if (!DissectArcPath(SystemPath, BootPath, &DriveNumber, &PartitionNumber))
+       {
+               return FALSE;
+       }
+
+       if (0 != PartitionNumber)
+       {
+               return TRUE;
+       }
+
+       if (! DiskGetActivePartitionEntry(DriveNumber,
+                                         &PartEntry,
+                                         &PartitionNumber) ||
+           PartitionNumber < 1 || 9 < PartitionNumber)
+       {
+               return FALSE;
+       }
+
+       p = SystemPath;
+       while ('\0' != *p && 0 != _strnicmp(p, "partition(", 10)) {
+               p++;
+       }
+       p = strchr(p, ')');
+       if (NULL == p || '0' != *(p - 1)) {
+               return FALSE;
+       }
+       *(p - 1) = '0' + PartitionNumber;
+
+       return TRUE;
+}
+
 typedef unsigned int uint32_t;
 
 void PpcInit( of_proxy the_ofproxy ) {
-    int len;
+    int len, stdin_handle_chosen;
     ofproxy = the_ofproxy;
 
+    ofw_print_string("Freeldr PowerPC Init\n");
+
     chosen_package = ofw_finddevice( "/chosen" );
 
+    ofw_print_string("Freeldr: chosen_package is ");
+    ofw_print_number(chosen_package);
+    ofw_print_string("\n");
+
     ofw_getprop( chosen_package, "stdin",
-                 &stdin_handle, sizeof(stdin_handle) );
+                 (char *)&stdin_handle_chosen, sizeof(stdin_handle_chosen) );
 
-    stdin_handle = REV(stdin_handle);
+    ofw_print_string("Freeldr: stdin_handle is ");
+    ofw_print_number(stdin_handle_chosen);
+    ofw_print_string("\n");
+
+    stdin_handle = stdin_handle_chosen;
+
+    /* stdin_handle = REV(stdin_handle); */
 
     MachVtbl.ConsPutChar = PpcPutChar;
     MachVtbl.ConsKbHit   = PpcConsKbHit;
     MachVtbl.ConsGetCh   = PpcConsGetCh;
-    
+
     printf( "stdin_handle is %x\n", stdin_handle );
+    printf("virt2phys (0xe00000,D) -> %x\n", PpcVirt2phys(0xe00000,0));
+    printf("virt2phys (0xe01000,D) -> %x\n", PpcVirt2phys(0xe01000,0));
 
     MachVtbl.VideoClearScreen = PpcVideoClearScreen;
     MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
@@ -394,6 +424,7 @@ void PpcInit( of_proxy the_ofproxy ) {
 
     MachVtbl.GetMemoryMap = PpcGetMemoryMap;
 
+    MachVtbl.DiskNormalizeSystemPath = PpcDiskNormalizeSystemPath;
     MachVtbl.DiskGetBootVolume = PpcDiskGetBootVolume;
     MachVtbl.DiskGetSystemVolume = PpcDiskGetSystemVolume;
     MachVtbl.DiskGetBootPath = PpcDiskGetBootPath;