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.
24 #define TOTAL_HEAP_NEEDED (16 * 1024 * 1024) /* 16 megs */
26 extern void BootMain( char * );
27 extern char *GetFreeLoaderVersionString();
29 void *PageDirectoryStart
, *PageDirectoryEnd
, *mem_base
= 0;
30 static int chosen_package
, stdin_handle
, part_handle
= -1;
31 BOOLEAN AcpiPresent
= FALSE
;
32 char BootPath
[0x100] = { 0 }, BootPart
[0x100] = { 0 }, CmdLine
[0x100] = { 0 };
34 volatile char *video_mem
= 0;
36 void le_swap( void *start_addr_v
,
38 void *target_addr_v
) {
40 *start_addr
= (long *)ROUND_DOWN((long)start_addr_v
,8),
41 *end_addr
= (long *)ROUND_UP((long)end_addr_v
,8),
42 *target_addr
= (long *)ROUND_DOWN((long)target_addr_v
,8);
44 while( start_addr
<= end_addr
) {
46 target_addr
[0] = REV(start_addr
[1]);
47 target_addr
[1] = REV(tmp
);
53 void PpcPutChar( int ch
) {
55 if( ch
== 0x0a ) { buf
[0] = 0x0d; buf
[1] = 0x0a; }
56 else { buf
[0] = ch
; buf
[1] = 0; }
58 ofw_print_string( buf
);
61 int PpcFindDevice( int depth
, int parent
, char *devname
, int *nth
) {
68 next
= ofw_child( parent
);
70 //printf( "next = %x\n", next );
72 gotname
= ofw_getprop(parent
, "name", buf
, 256);
74 //printf( "gotname = %d\n", gotname );
76 match
= !strncmp(buf
, devname
, strlen(devname
));
78 if( !nth
&& match
) return parent
;
80 for( i
= 0; i
< depth
; i
++ ) PpcPutChar( ' ' );
84 printf( "%c Name: %s\n", match
? '*' : ' ', buf
);
86 printf( "- No name attribute for %x\n", parent
);
90 while( !match
&& next
) {
91 i
= PpcFindDevice( depth
+1, next
, devname
, nth
);
93 next
= ofw_peer( next
);
99 BOOLEAN
PpcConsKbHit() {
105 ofw_read( stdin_handle
, &buf
, 1 );
109 void PpcVideoClearScreen( UCHAR Attr
) {
110 ofw_print_string("ClearScreen\n");
113 VOID
PpcVideoGetDisplaySize( PULONG Width
, PULONG Height
, PULONG Depth
) {
114 //ofw_print_string("GetDisplaySize\n");
118 //printf("GetDisplaySize(%d,%d,%d)\n", *Width, *Height, *Depth);
121 ULONG
PpcVideoGetBufferSize() {
122 ULONG Width
, Height
, Depth
;
123 //ofw_print_string("PpcVideoGetBufferSize\n");
124 PpcVideoGetDisplaySize( &Width
, &Height
, &Depth
);
125 return Width
* Height
* Depth
/ 8;
128 VIDEODISPLAYMODE
PpcVideoSetDisplayMode( char *DisplayMode
, BOOLEAN Init
) {
129 //printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
130 if( Init
&& !video_mem
) {
131 video_mem
= MmAllocateMemory( PpcVideoGetBufferSize() );
133 return VideoTextMode
;
136 VOID
PpcVideoSetTextCursorPosition( ULONG X
, ULONG Y
) {
137 printf("SetTextCursorPosition(%d,%d)\n", X
,Y
);
140 VOID
PpcVideoHideShowTextCursor( BOOLEAN Show
) {
141 printf("HideShowTextCursor(%s)\n", Show
? "true" : "false");
144 VOID
PpcVideoPutChar( int Ch
, UCHAR Attr
, unsigned X
, unsigned Y
) {
145 printf( "\033[%d;%dH%c", Y
, X
, Ch
);
148 VOID
PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer
) {
151 PCHAR ChBuf
= Buffer
;
154 PpcVideoGetDisplaySize( &w
, &h
, &d
);
156 for( i
= 0; i
< h
; i
++ ) {
157 for( j
= 0; j
< w
; j
++ ) {
158 offset
= (j
* 2) + (i
* w
* 2);
159 if( ChBuf
[offset
] != video_mem
[offset
] ) {
160 video_mem
[offset
] = ChBuf
[offset
];
161 PpcVideoPutChar(ChBuf
[offset
],0,j
+1,i
+1);
167 BOOLEAN
PpcVideoIsPaletteFixed() {
171 VOID
PpcVideoSetPaletteColor( UCHAR Color
,
172 UCHAR Red
, UCHAR Green
, UCHAR Blue
) {
173 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color
, Red
, Green
, Blue
);
176 VOID
PpcVideoGetPaletteColor( UCHAR Color
,
177 UCHAR
*Red
, UCHAR
*Green
, UCHAR
*Blue
) {
178 printf( "GetPaletteColor(%x)\n", Color
);
181 VOID
PpcVideoSync() {
185 VOID
PpcVideoPrepareForReactOS() {
186 printf( "PrepareForReactOS\n");
189 * Get memory the proper openfirmware way
191 ULONG
PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap
,
192 ULONG MaxMemoryMapSize
) {
193 int i
, memhandle
, mmuhandle
, returned
, total
= 0, num_mem
= 0;
196 printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize
);
199 BiosMemoryMap
[0].Type
= MEMTYPE_USABLE
;
200 BiosMemoryMap
[0].BaseAddress
= (ULONG
)mem_base
;
201 BiosMemoryMap
[0].Length
= TOTAL_HEAP_NEEDED
;
202 printf("[cached] returning 1 element\n");
206 ofw_getprop(chosen_package
, "memory",
207 (char *)&memhandle
, sizeof(memhandle
));
208 ofw_getprop(chosen_package
, "mmu",
209 (char *)&mmuhandle
, sizeof(mmuhandle
));
211 returned
= ofw_getprop(memhandle
, "available",
212 (char *)memdata
, sizeof(memdata
));
214 /* We need to leave some for open firmware. Let's claim up to 16 megs
217 for( i
= 0; i
< returned
/ sizeof(int) && !num_mem
; i
+= 2 ) {
218 BiosMemoryMap
[num_mem
].Type
= MEMTYPE_USABLE
;
219 BiosMemoryMap
[num_mem
].BaseAddress
= memdata
[i
];
220 mem_base
= (void *)memdata
[i
];
221 BiosMemoryMap
[num_mem
].Length
= memdata
[i
+1];
222 if( BiosMemoryMap
[num_mem
].Length
>= TOTAL_HEAP_NEEDED
&&
223 total
< TOTAL_HEAP_NEEDED
) {
224 BiosMemoryMap
[num_mem
].Length
= TOTAL_HEAP_NEEDED
;
225 ofw_claim(BiosMemoryMap
[num_mem
].BaseAddress
,
226 BiosMemoryMap
[num_mem
].Length
, 0x1000); /* claim it */
227 total
+= BiosMemoryMap
[0].Length
;
232 printf( "Returning memory map (%dk total)\n", total
/ 1024 );
239 * For now, it'll be easy enough to use the boot command line as our boot path.
240 * Treat it as the path of a disk partition. We might even be able to get
241 * away with grabbing a partition image by tftp in this scenario.
244 BOOLEAN
PpcDiskGetBootVolume( PULONG DriveNumber
, PULONGLONG StartSector
, PULONGLONG SectorCount
, int *FsType
) {
252 BOOLEAN
PpcDiskGetSystemVolume( char *SystemPath
,
256 PULONGLONG StartSector
,
257 PULONGLONG SectorCount
,
259 char *remain
= strchr(SystemPath
, '\\');
261 strcpy( RemainingPath
, remain
+1 );
263 RemainingPath
[0] = 0;
266 return PpcDiskGetBootVolume(DriveNumber
, StartSector
, SectorCount
, FsType
);
269 BOOLEAN
PpcDiskGetBootPath( char *OutBootPath
, unsigned Size
) {
270 strncpy( OutBootPath
, BootPath
, Size
);
274 VOID
PpcDiskGetBootDevice( PULONG BootDevice
) {
275 BootDevice
[0] = BootDevice
[1] = 0;
278 BOOLEAN
PpcDiskBootingFromFloppy(VOID
) {
282 BOOLEAN
PpcDiskReadLogicalSectors( ULONG DriveNumber
, ULONGLONG SectorNumber
,
283 ULONG SectorCount
, PVOID Buffer
) {
286 if( part_handle
== -1 ) {
287 part_handle
= ofw_open( BootPart
);
289 if( part_handle
== -1 ) {
290 printf("Could not open any disk devices we know about\n");
295 if( part_handle
== -1 ) {
296 printf("Got partition handle %x\n", part_handle
);
300 if( ofw_seek( part_handle
,
301 (ULONG
)(SectorNumber
>> 25),
302 (ULONG
)((SectorNumber
* 512) & 0xffffffff) ) ) {
303 printf("Seek to %x failed\n", (ULONG
)(SectorNumber
* 512));
306 rlen
= ofw_read( part_handle
, Buffer
, (ULONG
)(SectorCount
* 512) );
310 BOOLEAN
PpcDiskGetPartitionEntry( ULONG DriveNumber
, ULONG PartitionNumber
,
311 PPARTITION_TABLE_ENTRY PartitionTableEntry
) {
312 printf("GetPartitionEntry(%d,%d)\n", DriveNumber
, PartitionNumber
);
316 BOOLEAN
PpcDiskGetDriveGeometry( ULONG DriveNumber
, PGEOMETRY DriveGeometry
) {
317 printf("GetGeometry(%d)\n", DriveNumber
);
318 DriveGeometry
->BytesPerSector
= 512;
319 DriveGeometry
->Heads
= 16;
320 DriveGeometry
->Sectors
= 63;
324 ULONG
PpcDiskGetCacheableBlockCount( ULONG DriveNumber
) {
325 printf("GetCacheableBlockCount\n");
329 VOID
PpcRTCGetCurrentDateTime( PULONG Hear
, PULONG Month
, PULONG Day
,
330 PULONG Hour
, PULONG Minute
, PULONG Second
) {
331 //printf("RTCGeturrentDateTime\n");
335 printf("PpcHwDetect\n");
338 BOOLEAN
PpcDiskNormalizeSystemPath(char *SystemPath
, unsigned Size
) {
340 ULONG PartitionNumber
;
342 PARTITION_TABLE_ENTRY PartEntry
;
345 if (!DissectArcPath(SystemPath
, BootPath
, &DriveNumber
, &PartitionNumber
))
350 if (0 != PartitionNumber
)
355 if (! DiskGetActivePartitionEntry(DriveNumber
,
358 PartitionNumber
< 1 || 9 < PartitionNumber
)
364 while ('\0' != *p
&& 0 != _strnicmp(p
, "partition(", 10)) {
368 if (NULL
== p
|| '0' != *(p
- 1)) {
371 *(p
- 1) = '0' + PartitionNumber
;
376 typedef unsigned int uint32_t;
378 void PpcInit( of_proxy the_ofproxy
) {
379 int len
, stdin_handle_chosen
;
380 ofproxy
= the_ofproxy
;
382 ofw_print_string("Freeldr PowerPC Init\n");
384 chosen_package
= ofw_finddevice( "/chosen" );
386 ofw_print_string("Freeldr: chosen_package is ");
387 ofw_print_number(chosen_package
);
388 ofw_print_string("\n");
390 ofw_getprop( chosen_package
, "stdin",
391 (char *)&stdin_handle_chosen
, sizeof(stdin_handle_chosen
) );
393 ofw_print_string("Freeldr: stdin_handle is ");
394 ofw_print_number(stdin_handle_chosen
);
395 ofw_print_string("\n");
397 stdin_handle
= stdin_handle_chosen
;
399 /* stdin_handle = REV(stdin_handle); */
401 MachVtbl
.ConsPutChar
= PpcPutChar
;
402 MachVtbl
.ConsKbHit
= PpcConsKbHit
;
403 MachVtbl
.ConsGetCh
= PpcConsGetCh
;
405 printf( "stdin_handle is %x\n", stdin_handle
);
406 printf("virt2phys (0xe00000,D) -> %x\n", PpcVirt2phys(0xe00000,0));
407 printf("virt2phys (0xe01000,D) -> %x\n", PpcVirt2phys(0xe01000,0));
409 MachVtbl
.VideoClearScreen
= PpcVideoClearScreen
;
410 MachVtbl
.VideoSetDisplayMode
= PpcVideoSetDisplayMode
;
411 MachVtbl
.VideoGetDisplaySize
= PpcVideoGetDisplaySize
;
412 MachVtbl
.VideoGetBufferSize
= PpcVideoGetBufferSize
;
413 MachVtbl
.VideoSetTextCursorPosition
= PpcVideoSetTextCursorPosition
;
414 MachVtbl
.VideoHideShowTextCursor
= PpcVideoHideShowTextCursor
;
415 MachVtbl
.VideoPutChar
= PpcVideoPutChar
;
416 MachVtbl
.VideoCopyOffScreenBufferToVRAM
=
417 PpcVideoCopyOffScreenBufferToVRAM
;
418 MachVtbl
.VideoIsPaletteFixed
= PpcVideoIsPaletteFixed
;
419 MachVtbl
.VideoSetPaletteColor
= PpcVideoSetPaletteColor
;
420 MachVtbl
.VideoGetPaletteColor
= PpcVideoGetPaletteColor
;
421 MachVtbl
.VideoSync
= PpcVideoSync
;
422 MachVtbl
.VideoPrepareForReactOS
= PpcVideoPrepareForReactOS
;
424 MachVtbl
.GetMemoryMap
= PpcGetMemoryMap
;
426 MachVtbl
.DiskNormalizeSystemPath
= PpcDiskNormalizeSystemPath
;
427 MachVtbl
.DiskGetBootVolume
= PpcDiskGetBootVolume
;
428 MachVtbl
.DiskGetSystemVolume
= PpcDiskGetSystemVolume
;
429 MachVtbl
.DiskGetBootPath
= PpcDiskGetBootPath
;
430 MachVtbl
.DiskGetBootDevice
= PpcDiskGetBootDevice
;
431 MachVtbl
.DiskBootingFromFloppy
= PpcDiskBootingFromFloppy
;
432 MachVtbl
.DiskReadLogicalSectors
= PpcDiskReadLogicalSectors
;
433 MachVtbl
.DiskGetPartitionEntry
= PpcDiskGetPartitionEntry
;
434 MachVtbl
.DiskGetDriveGeometry
= PpcDiskGetDriveGeometry
;
435 MachVtbl
.DiskGetCacheableBlockCount
= PpcDiskGetCacheableBlockCount
;
437 MachVtbl
.RTCGetCurrentDateTime
= PpcRTCGetCurrentDateTime
;
439 MachVtbl
.HwDetect
= PpcHwDetect
;
441 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
443 len
= ofw_getprop(chosen_package
, "bootargs",
444 CmdLine
, sizeof(CmdLine
));
446 if( len
< 0 ) len
= 0;
452 void MachInit(const char *CmdLine
) {
459 printf( "Determining boot device: [%s]\n", CmdLine
);
461 printf( "Boot Args: %s\n", CmdLine
);
463 for( i
= 0; i
< strlen(CmdLine
); i
++ ) {
464 if( strncmp(CmdLine
+ i
, "boot=", 5) == 0) {
465 strcpy(BootPart
, CmdLine
+ i
+ 5);
466 sep
= strchr(BootPart
, ' ');
473 if( strlen(BootPart
) == 0 ) {
474 len
= ofw_getprop(chosen_package
, "bootpath",
475 BootPath
, sizeof(BootPath
));
477 if( len
< 0 ) len
= 0;
479 printf( "Boot Path: %s\n", BootPath
);
481 sep
= strrchr(BootPath
, ',');
483 strcpy(BootPart
, BootPath
);
485 BootPart
[sep
- BootPath
] = 0;
489 printf( "FreeLDR starting (boot partition: %s)\n", BootPart
);
492 /* Compatibility functions that don't do much */
496 UCHAR NTAPI
READ_PORT_UCHAR(PUCHAR Address
) {
500 void WRITE_PORT_UCHAR(PUCHAR Address
, UCHAR Value
) {
503 void DiskStopFloppyMotor() {
506 void BootOldLinuxKernel( unsigned long size
) {
510 void BootNewLinuxKernel() {
514 void ChainLoadBiosBootSectorCode() {