2 * FreeLoader PowerPC Part
3 * Copyright (C) 2005 Art Yerkes
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 extern void BootMain( char * );
24 extern char *GetFreeLoaderVersionString();
26 void *PageDirectoryStart
, *PageDirectoryEnd
;
27 static int chosen_package
, stdin_handle
, part_handle
= -1;
28 BOOLEAN AcpiPresent
= FALSE
;
29 char BootPath
[0x100] = { 0 }, BootPart
[0x100] = { 0 }, CmdLine
[0x100] = { 0 };
32 void le_swap( const void *start_addr_v
,
33 const void *end_addr_v
,
34 const void *target_addr_v
) {
35 long *start_addr
= (long *)ROUND_DOWN((long)start_addr_v
,8),
36 *end_addr
= (long *)ROUND_UP((long)end_addr_v
,8),
37 *target_addr
= (long *)ROUND_DOWN((long)target_addr_v
,8);
39 while( start_addr
<= end_addr
) {
41 target_addr
[0] = REV(start_addr
[1]);
42 target_addr
[1] = REV(tmp
);
48 int ofw_finddevice( const char *name
) {
52 le_swap( name
, name
+ len
, name
);
53 ret
= ofproxy( 0, (char *)name
, NULL
, NULL
, NULL
);
54 le_swap( name
, name
+ len
, name
);
58 int ofw_getprop( int package
, const char *name
, void *buffer
, int buflen
) {
59 int ret
, len
= strlen(name
);
60 le_swap( name
, name
+ len
, name
);
61 le_swap( buffer
, buffer
+ buflen
, buffer
);
63 ( 4, (void *)package
, (char *)name
, buffer
, (void *)buflen
);
64 le_swap( buffer
, buffer
+ buflen
, buffer
);
65 le_swap( name
, name
+ len
, name
);
69 /* Since this is from external storage, it doesn't need swapping */
70 int ofw_write( int handle
, const char *data
, int len
) {
72 le_swap( data
, data
+ len
, data
);
74 ( 8, (void *)handle
, (char *)data
, (void *)len
, NULL
);
75 le_swap( data
, data
+ len
, data
);
79 /* Since this is from external storage, it doesn't need swapping */
80 int ofw_read( int handle
, const char *data
, int len
) {
83 le_swap( data
, data
+ len
, data
);
85 ( 12, (void *)handle
, (char *)data
, (void *)len
, NULL
);
86 le_swap( data
, data
+ len
, data
);
92 ofproxy( 16, NULL
, NULL
, NULL
, NULL
);
96 ofproxy( 20, NULL
, NULL
, NULL
, NULL
);
99 void ofw_print_string( const char *str
) {
100 int len
= strlen(str
);
101 le_swap( (char *)str
, str
+ len
, (char *)str
);
102 ofproxy( 24, (void *)str
, NULL
, NULL
, NULL
);
103 le_swap( (char *)str
, str
+ len
, (char *)str
);
106 void ofw_print_number( int num
) {
107 ofproxy( 28, (void *)num
, NULL
, NULL
, NULL
);
110 int ofw_open( const char *name
) {
114 le_swap( name
, name
+ len
, name
);
115 ret
= ofproxy( 32, (char *)name
, NULL
, NULL
, NULL
);
116 le_swap( name
, name
+ len
, name
);
120 int ofw_child( int package
) {
121 return ofproxy( 36, (void *)package
, NULL
, NULL
, NULL
);
124 int ofw_peer( int package
) {
125 return ofproxy( 40, (void *)package
, NULL
, NULL
, NULL
);
128 int ofw_seek( int handle
, long long location
) {
129 return ofproxy( 44, (void *)handle
, (void *)(int)(location
>> 32), (void *)(int)location
, NULL
);
132 void PpcPutChar( int ch
) {
134 if( ch
== 0x0a ) { buf
[0] = 0x0d; buf
[1] = 0x0a; }
135 else { buf
[0] = ch
; buf
[1] = 0; }
137 ofw_print_string( buf
);
140 int PpcFindDevice( int depth
, int parent
, char *devname
, int *nth
) {
141 static char buf
[256];
147 next
= ofw_child( parent
);
149 //printf( "next = %x\n", next );
151 gotname
= ofw_getprop(parent
, "name", buf
, 256);
153 //printf( "gotname = %d\n", gotname );
155 match
= !strncmp(buf
, devname
, strlen(devname
));
157 if( !nth
&& match
) return parent
;
158 else if( match
) *nth
--;
160 for( i
= 0; i
< depth
; i
++ ) PpcPutChar( ' ' );
164 printf( "%c Name: %s\n", match
? '*' : ' ', buf
);
166 printf( "- No name attribute for %x\n", parent
);
170 while( !match
&& next
) {
171 i
= PpcFindDevice( depth
+1, next
, devname
, nth
);
173 next
= ofw_peer( next
);
179 BOOL
PpcConsKbHit() {
185 ofw_read( stdin_handle
, &buf
, 1 );
189 void PpcVideoClearScreen( UCHAR Attr
) {
190 ofw_print_string("ClearScreen\n");
193 VIDEODISPLAYMODE
PpcVideoSetDisplayMode( char *DisplayMode
, BOOL Init
) {
194 printf( "DisplayMode: %s %s\n", DisplayMode
, Init
? "true" : "false" );
195 return VideoGraphicsMode
;
199 VOID
PpcVideoGetDisplaySize( PULONG Width
, PULONG Height
, PULONG Depth
) {
200 ofw_print_string("GetDisplaySize\n");
206 ULONG
PpcVideoGetBufferSize() {
207 ULONG Width
, Height
, Depth
;
208 ofw_print_string("PpcVideoGetBufferSize\n");
209 PpcVideoGetDisplaySize( &Width
, &Height
, &Depth
);
210 return Width
* Height
* Depth
/ 8;
213 VOID
PpcVideoSetTextCursorPosition( ULONG X
, ULONG Y
) {
214 printf("SetTextCursorPosition(%d,%d)\n", X
,Y
);
217 VOID
PpcVideoHideShowTextCursor( BOOL Show
) {
218 printf("HideShowTextCursor(%s)\n", Show
? "true" : "false");
221 VOID
PpcVideoPutChar( int Ch
, UCHAR Attr
, unsigned X
, unsigned Y
) {
222 printf( "\033[%d;%dH%c", Y
, X
, Ch
);
225 VOID
PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer
) {
226 printf( "CopyOffScreenBufferToVRAM(%x)\n", Buffer
);
229 BOOL
PpcVideoIsPaletteFixed() {
233 VOID
PpcVideoSetPaletteColor( UCHAR Color
,
234 UCHAR Red
, UCHAR Green
, UCHAR Blue
) {
235 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color
, Red
, Green
, Blue
);
238 VOID
PpcVideoGetPaletteColor( UCHAR Color
,
239 UCHAR
*Red
, UCHAR
*Green
, UCHAR
*Blue
) {
240 printf( "GetPaletteColor(%x)\n", Color
);
243 VOID
PpcVideoSync() {
247 VOID
PpcVideoPrepareForReactOS() {
248 printf( "PrepareForReactOS\n");
251 * According to the linux people (this is backed up by my own experience),
252 * the memory object in older ofw does not do getprop right.
254 * The "right" way is to probe the pci bridge. *sigh*
256 ULONG
PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap
,
257 ULONG MaxMemoryMapSize
) {
258 printf("GetMemoryMap(chosen=%x)\n", chosen_package
);
260 BiosMemoryMap
[0].Type
= MEMTYPE_USABLE
;
261 BiosMemoryMap
[0].BaseAddress
= 0;
262 BiosMemoryMap
[0].Length
= 32 * 1024 * 1024; /* Assume 32 meg for now */
264 printf( "Returning memory map (%dk total)\n",
265 (int)BiosMemoryMap
[0].Length
/ 1024 );
272 * For now, it'll be easy enough to use the boot command line as our boot path.
273 * Treat it as the path of a disk partition. We might even be able to get
274 * away with grabbing a partition image by tftp in this scenario.
277 BOOL
PpcDiskGetBootVolume( PULONG DriveNumber
, PULONGLONG StartSector
, PULONGLONG SectorCount
, int *FsType
) {
285 BOOL
PpcDiskGetSystemVolume( char *SystemPath
,
289 PULONGLONG StartSector
,
290 PULONGLONG SectorCount
,
295 BOOL
PpcDiskGetBootPath( char *OutBootPath
, unsigned Size
) {
296 strncpy( OutBootPath
, BootPath
, Size
);
300 VOID
PpcDiskGetBootDevice( PULONG BootDevice
) {
301 BootDevice
[0] = BootDevice
[1] = 0;
304 BOOL
PpcDiskBootingFromFloppy(VOID
) {
308 BOOL
PpcDiskReadLogicalSectors( ULONG DriveNumber
, ULONGLONG SectorNumber
,
309 ULONG SectorCount
, PVOID Buffer
) {
312 if( part_handle
== -1 ) {
313 part_handle
= ofw_open( BootPart
);
315 if( part_handle
== -1 ) {
316 printf("Could not open any disk devices we know about\n");
321 if( part_handle
== -1 ) {
322 printf("Got partition handle %x\n", part_handle
);
326 if( ofw_seek( part_handle
, SectorNumber
* 512 ) ) {
327 printf("Seek to %x failed\n", SectorNumber
* 512);
330 rlen
= ofw_read( part_handle
, Buffer
, SectorCount
* 512 );
334 BOOL
PpcDiskGetPartitionEntry( ULONG DriveNumber
, ULONG PartitionNumber
,
335 PPARTITION_TABLE_ENTRY PartitionTableEntry
) {
336 printf("GetPartitionEntry(%d,%d)\n", DriveNumber
, PartitionNumber
);
340 BOOL
PpcDiskGetDriveGeometry( ULONG DriveNumber
, PGEOMETRY DriveGeometry
) {
341 printf("GetGeometry(%d)\n", DriveNumber
);
342 DriveGeometry
->BytesPerSector
= 512;
343 DriveGeometry
->Heads
= 16;
344 DriveGeometry
->Sectors
= 63;
348 ULONG
PpcDiskGetCacheableBlockCount( ULONG DriveNumber
) {
349 printf("GetCacheableBlockCount\n");
353 VOID
PpcRTCGetCurrentDateTime( PULONG Hear
, PULONG Month
, PULONG Day
,
354 PULONG Hour
, PULONG Minute
, PULONG Second
) {
355 printf("RTCGeturrentDateTime\n");
359 printf("PpcHwDetect\n");
362 typedef unsigned int uint32_t;
364 void PpcInit( of_proxy the_ofproxy
) {
366 ofproxy
= the_ofproxy
;
368 chosen_package
= ofw_finddevice( "/chosen" );
370 ofw_getprop( chosen_package
, "stdin",
371 &stdin_handle
, sizeof(stdin_handle
) );
373 stdin_handle
= REV(stdin_handle
);
375 MachVtbl
.ConsPutChar
= PpcPutChar
;
376 MachVtbl
.ConsKbHit
= PpcConsKbHit
;
377 MachVtbl
.ConsGetCh
= PpcConsGetCh
;
379 printf( "stdin_handle is %x\n", stdin_handle
);
381 MachVtbl
.VideoClearScreen
= PpcVideoClearScreen
;
382 MachVtbl
.VideoSetDisplayMode
= PpcVideoSetDisplayMode
;
383 MachVtbl
.VideoGetDisplaySize
= PpcVideoGetDisplaySize
;
384 MachVtbl
.VideoGetBufferSize
= PpcVideoGetBufferSize
;
385 MachVtbl
.VideoSetTextCursorPosition
= PpcVideoSetTextCursorPosition
;
386 MachVtbl
.VideoHideShowTextCursor
= PpcVideoHideShowTextCursor
;
387 MachVtbl
.VideoPutChar
= PpcVideoPutChar
;
388 MachVtbl
.VideoCopyOffScreenBufferToVRAM
=
389 PpcVideoCopyOffScreenBufferToVRAM
;
390 MachVtbl
.VideoIsPaletteFixed
= PpcVideoIsPaletteFixed
;
391 MachVtbl
.VideoSetPaletteColor
= PpcVideoSetPaletteColor
;
392 MachVtbl
.VideoGetPaletteColor
= PpcVideoGetPaletteColor
;
393 MachVtbl
.VideoSync
= PpcVideoSync
;
394 MachVtbl
.VideoPrepareForReactOS
= PpcVideoPrepareForReactOS
;
396 MachVtbl
.GetMemoryMap
= PpcGetMemoryMap
;
398 MachVtbl
.DiskGetBootVolume
= PpcDiskGetBootVolume
;
399 MachVtbl
.DiskGetSystemVolume
= PpcDiskGetSystemVolume
;
400 MachVtbl
.DiskGetBootPath
= PpcDiskGetBootPath
;
401 MachVtbl
.DiskGetBootDevice
= PpcDiskGetBootDevice
;
402 MachVtbl
.DiskBootingFromFloppy
= PpcDiskBootingFromFloppy
;
403 MachVtbl
.DiskReadLogicalSectors
= PpcDiskReadLogicalSectors
;
404 MachVtbl
.DiskGetPartitionEntry
= PpcDiskGetPartitionEntry
;
405 MachVtbl
.DiskGetDriveGeometry
= PpcDiskGetDriveGeometry
;
406 MachVtbl
.DiskGetCacheableBlockCount
= PpcDiskGetCacheableBlockCount
;
408 MachVtbl
.RTCGetCurrentDateTime
= PpcRTCGetCurrentDateTime
;
410 MachVtbl
.HwDetect
= PpcHwDetect
;
412 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
414 len
= ofw_getprop(chosen_package
, "bootargs",
415 CmdLine
, sizeof(CmdLine
));
417 if( len
< 0 ) len
= 0;
423 void MachInit(char *CmdLine
) {
430 printf( "Determining boot device: [%s]\n", CmdLine
);
432 printf( "Boot Args: %s\n", CmdLine
);
434 for( i
= 0; i
< strlen(CmdLine
); i
++ ) {
435 if( strncmp(CmdLine
+ i
, "boot=", 5) == 0) {
436 strcpy(BootPart
, CmdLine
+ i
+ 5);
437 sep
= strchr(BootPart
, ' ');
444 if( strlen(BootPart
) == 0 ) {
445 len
= ofw_getprop(chosen_package
, "bootpath",
446 BootPath
, sizeof(BootPath
));
448 if( len
< 0 ) len
= 0;
450 printf( "Boot Path: %s\n", BootPath
);
452 sep
= strrchr(BootPath
, ',');
454 strcpy(BootPart
, BootPath
);
456 BootPart
[sep
- BootPath
] = 0;
460 printf( "FreeLDR starting (boot partition: %s)\n", BootPart
);
463 /* Compatibility functions that don't do much */
467 UCHAR STDCALL
READ_PORT_UCHAR(PUCHAR Address
) {
471 void WRITE_PORT_UCHAR(PUCHAR Address
, UCHAR Value
) {
474 void DiskStopFloppyMotor() {
477 void BootOldLinuxKernel( unsigned long size
) {
481 void BootNewLinuxKernel() {
485 void ChainLoadBiosBootSectorCode() {