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.
26 extern void BootMain( LPSTR CmdLine
);
27 extern PCHAR
GetFreeLoaderVersionString();
28 extern ULONG CacheSizeLimit
;
30 void *PageDirectoryStart
, *PageDirectoryEnd
;
31 static int chosen_package
, stdin_handle
, part_handle
= -1, kernel_mem
= 0;
32 int mmu_handle
= 0, FixedMemory
= 0;
33 BOOLEAN AcpiPresent
= FALSE
;
34 char BootPath
[0x100] = { 0 }, BootPart
[0x100] = { 0 }, CmdLine
[0x100] = { 0 };
36 volatile char *video_mem
= 0;
37 boot_infos_t BootInfo
;
39 void le_swap( void *start_addr_v
,
41 void *target_addr_v
) {
43 *start_addr
= (long *)ROUND_DOWN((long)start_addr_v
,8),
44 *end_addr
= (long *)ROUND_UP((long)end_addr_v
,8),
45 *target_addr
= (long *)ROUND_DOWN((long)target_addr_v
,8);
47 while( start_addr
<= end_addr
) {
49 target_addr
[0] = REV(start_addr
[1]);
50 target_addr
[1] = REV(tmp
);
56 void PpcPutChar( int ch
) {
58 if( ch
== 0x0a ) { buf
[0] = 0x0d; buf
[1] = 0x0a; }
59 else { buf
[0] = ch
; buf
[1] = 0; }
61 ofw_print_string( buf
);
64 int PpcFindDevice( int depth
, int parent
, char *devname
, int *nth
) {
71 next
= ofw_child( parent
);
73 //printf( "next = %x\n", next );
75 gotname
= ofw_getprop(parent
, "name", buf
, 256);
77 //printf( "gotname = %d\n", gotname );
79 match
= !strncmp(buf
, devname
, strlen(devname
));
81 if( !nth
&& match
) return parent
;
83 for( i
= 0; i
< depth
; i
++ ) PpcPutChar( ' ' );
87 printf( "%c Name: %s\n", match
? '*' : ' ', buf
);
89 printf( "- No name attribute for %x\n", parent
);
93 while( !match
&& next
) {
94 i
= PpcFindDevice( depth
+1, next
, devname
, nth
);
96 next
= ofw_peer( next
);
102 BOOLEAN
PpcConsKbHit() {
108 ofw_read( stdin_handle
, &buf
, 1 );
112 void PpcVideoClearScreen( UCHAR Attr
) {
113 ofw_print_string("ClearScreen\n");
116 VOID
PpcVideoGetDisplaySize( PULONG Width
, PULONG Height
, PULONG Depth
) {
117 //ofw_print_string("GetDisplaySize\n");
121 //printf("GetDisplaySize(%d,%d,%d)\n", *Width, *Height, *Depth);
124 ULONG
PpcVideoGetBufferSize() {
125 ULONG Width
, Height
, Depth
;
126 //ofw_print_string("PpcVideoGetBufferSize\n");
127 PpcVideoGetDisplaySize( &Width
, &Height
, &Depth
);
128 return Width
* Height
* Depth
/ 8;
131 VIDEODISPLAYMODE
PpcVideoSetDisplayMode( char *DisplayMode
, BOOLEAN Init
) {
132 //printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
133 if( Init
&& !video_mem
) {
134 video_mem
= MmAllocateMemory( PpcVideoGetBufferSize() );
136 return VideoTextMode
;
139 VOID
PpcVideoSetTextCursorPosition( ULONG X
, ULONG Y
) {
140 printf("SetTextCursorPosition(%d,%d)\n", X
,Y
);
143 VOID
PpcVideoHideShowTextCursor( BOOLEAN Show
) {
144 printf("HideShowTextCursor(%s)\n", Show
? "true" : "false");
147 VOID
PpcVideoPutChar( int Ch
, UCHAR Attr
, unsigned X
, unsigned Y
) {
148 printf( "\033[%d;%dH%c", Y
, X
, Ch
);
151 VOID
PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer
) {
154 PCHAR ChBuf
= Buffer
;
157 PpcVideoGetDisplaySize( &w
, &h
, &d
);
159 for( i
= 0; i
< h
; i
++ ) {
160 for( j
= 0; j
< w
; j
++ ) {
161 offset
= (j
* 2) + (i
* w
* 2);
162 if( ChBuf
[offset
] != video_mem
[offset
] ) {
163 video_mem
[offset
] = ChBuf
[offset
];
164 PpcVideoPutChar(ChBuf
[offset
],0,j
+1,i
+1);
170 BOOLEAN
PpcVideoIsPaletteFixed() {
174 VOID
PpcVideoSetPaletteColor( UCHAR Color
,
175 UCHAR Red
, UCHAR Green
, UCHAR Blue
) {
176 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color
, Red
, Green
, Blue
);
179 VOID
PpcVideoGetPaletteColor( UCHAR Color
,
180 UCHAR
*Red
, UCHAR
*Green
, UCHAR
*Blue
) {
181 printf( "GetPaletteColor(%x)\n", Color
);
184 VOID
PpcVideoSync() {
188 static int prom_next_node(int *nodep
)
192 if ((node
= *nodep
) != 0
193 && (*nodep
= ofw_child(node
)) != 0)
195 if ((*nodep
= ofw_peer(node
)) != 0)
198 if ((node
= ofw_parent(node
)) == 0)
200 if ((*nodep
= ofw_peer(node
)) != 0)
205 /* Appropriated from linux' btext.c
207 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
209 VOID
PpcVideoPrepareForReactOS() {
210 int i
, j
, k
, /* display_handle, */ display_package
, display_size
= 0;
213 //pci_reg_property display_regs[8];
214 char type
[256], path
[256], name
[256];
227 int logo_x
= 10, logo_y
= 10;
228 int logo_scale_x
= 8, logo_scale_y
= 8;
231 for( node
= ofw_finddevice("/"); prom_next_node(&node
); ) {
232 memset(type
, 0, sizeof(type
));
233 memset(path
, 0, sizeof(path
));
235 ret
= ofw_getprop(node
, "name", name
, sizeof(name
));
237 if(ofw_getprop(node
, "device_type", type
, sizeof(type
)) <= 0) {
238 printf("Could not get type for node %x\n", node
);
242 printf("Node %x ret %d name %s type %s\n", node
, ret
, name
, type
);
244 if(strcmp(type
, "display") == 0) break;
249 if(ofw_package_to_path(node
, path
, sizeof(path
)) < 0) {
250 printf("could not get path for display package %x\n", node
);
254 printf("Opening display package: %s\n", path
);
255 display_package
= ofw_finddevice(path
);
256 printf("display package %x\n", display_package
);
258 BootInfo
.dispDeviceRect
[0] = BootInfo
.dispDeviceRect
[1] = 0;
260 ofw_getprop(display_package
, "width",
261 (void *)&BootInfo
.dispDeviceRect
[2], sizeof(int));
262 ofw_getprop(display_package
, "height",
263 (void *)&BootInfo
.dispDeviceRect
[3], sizeof(int));
264 ofw_getprop(display_package
, "depth",
265 (void *)&BootInfo
.dispDeviceDepth
, sizeof(int));
266 ofw_getprop(display_package
, "linebytes",
267 (void *)&BootInfo
.dispDeviceRowBytes
, sizeof(int));
269 BootInfo
.dispDeviceRect
[2] = REV(BootInfo
.dispDeviceRect
[2]);
270 BootInfo
.dispDeviceRect
[3] = REV(BootInfo
.dispDeviceRect
[3]);
271 BootInfo
.dispDeviceDepth
= REV(BootInfo
.dispDeviceDepth
);
272 BootInfo
.dispDeviceRowBytes
= REV(BootInfo
.dispDeviceRowBytes
);
277 (void *)&device_address
,
278 sizeof(device_address
)) < 1) {
279 printf("Could not get device base\n");
283 BootInfo
.dispDeviceBase
= (PVOID
)(REV(device_address
));
285 display_size
= BootInfo
.dispDeviceRowBytes
* BootInfo
.dispDeviceRect
[3];
287 printf("Display size is %x bytes (%x per row times %x rows)\n",
289 BootInfo
.dispDeviceRowBytes
,
290 BootInfo
.dispDeviceRect
[3]);
292 printf("display is at %x\n", BootInfo
.dispDeviceBase
);
294 for( i
= 0; i
< logo_y
* logo_scale_y
; i
++ ) {
295 for( j
= 0; j
< logo_x
* logo_scale_x
; j
++ ) {
296 elts
= (j
/logo_scale_x
) + ((i
/logo_scale_y
) * logo_x
);
298 for( k
= 0; k
< BootInfo
.dispDeviceDepth
/8; k
++ ) {
299 SetPhysByte(((ULONG_PTR
)BootInfo
.dispDeviceBase
)+
301 ((j
* (BootInfo
.dispDeviceDepth
/8)) +
302 (i
* (BootInfo
.dispDeviceRowBytes
))),
303 logo
[elts
] == ' ' ? 0 : 255);
310 * Get memory the proper openfirmware way
312 ULONG
PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap
,
313 ULONG MaxMemoryMapSize
) {
314 int i
, memhandle
, returned
, total
= 0, slots
= 0;
317 printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize
);
319 memhandle
= ofw_finddevice("/memory");
321 returned
= ofw_getprop(memhandle
, "available",
322 (char *)memdata
, sizeof(memdata
));
324 printf("Returned data: %d\n", returned
);
325 if( returned
== -1 ) {
326 printf("getprop /memory[@reg] failed\n");
330 for( i
= 0; i
< returned
; i
++ ) {
331 printf("%x ", memdata
[i
]);
335 for( i
= 0; i
< returned
/ 2; i
++ ) {
336 BiosMemoryMap
[slots
].Type
= 1/*MEMTYPE_USABLE*/;
337 BiosMemoryMap
[slots
].BaseAddress
= REV(memdata
[i
*2]);
338 BiosMemoryMap
[slots
].Length
= REV(memdata
[i
*2+1]);
339 printf("MemoryMap[%d] = (%x:%x)\n",
341 (int)BiosMemoryMap
[slots
].BaseAddress
,
342 (int)BiosMemoryMap
[slots
].Length
);
344 /* Hack for pearpc */
346 BiosMemoryMap
[slots
].Length
= kernel_mem
* 1024;
348 ofw_claim((int)BiosMemoryMap
[slots
].BaseAddress
,
349 (int)BiosMemoryMap
[slots
].Length
,
351 FixedMemory
= BiosMemoryMap
[slots
].BaseAddress
;
353 total
+= BiosMemoryMap
[slots
].Length
;
357 } else if( BiosMemoryMap
[slots
].Length
&&
358 ofw_claim((int)BiosMemoryMap
[slots
].BaseAddress
,
359 (int)BiosMemoryMap
[slots
].Length
,
361 total
+= BiosMemoryMap
[slots
].Length
;
366 printf( "Returning memory map (%dk total)\n", total
/ 1024 );
373 * For now, it'll be easy enough to use the boot command line as our boot path.
374 * Treat it as the path of a disk partition. We might even be able to get
375 * away with grabbing a partition image by tftp in this scenario.
378 BOOLEAN
PpcDiskGetBootVolume( PULONG DriveNumber
, PULONGLONG StartSector
, PULONGLONG SectorCount
, int *FsType
) {
386 BOOLEAN
PpcDiskGetSystemVolume( char *SystemPath
,
390 PULONGLONG StartSector
,
391 PULONGLONG SectorCount
,
393 char *remain
= strchr(SystemPath
, '\\');
395 strcpy( RemainingPath
, remain
+1 );
397 RemainingPath
[0] = 0;
400 return PpcDiskGetBootVolume(DriveNumber
, StartSector
, SectorCount
, FsType
);
403 BOOLEAN
PpcDiskGetBootPath( char *OutBootPath
, unsigned Size
) {
404 strncpy( OutBootPath
, BootPath
, Size
);
408 VOID
PpcDiskGetBootDevice( PULONG BootDevice
) {
409 BootDevice
[0] = BootDevice
[1] = 0;
412 BOOLEAN
PpcDiskBootingFromFloppy(VOID
) {
416 BOOLEAN
PpcDiskReadLogicalSectors( ULONG DriveNumber
, ULONGLONG SectorNumber
,
417 ULONG SectorCount
, PVOID Buffer
) {
420 if( part_handle
== -1 ) {
421 part_handle
= ofw_open( BootPart
);
423 if( part_handle
== -1 ) {
424 printf("Could not open any disk devices we know about\n");
429 if( part_handle
== -1 ) {
430 printf("Got partition handle %x\n", part_handle
);
434 if( ofw_seek( part_handle
,
435 (ULONG
)(SectorNumber
>> 25),
436 (ULONG
)((SectorNumber
* 512) & 0xffffffff) ) ) {
437 printf("Seek to %x failed\n", (ULONG
)(SectorNumber
* 512));
441 rlen
= ofw_read( part_handle
, Buffer
, (ULONG
)(SectorCount
* 512) );
445 BOOLEAN
PpcDiskGetPartitionEntry( ULONG DriveNumber
, ULONG PartitionNumber
,
446 PPARTITION_TABLE_ENTRY PartitionTableEntry
) {
447 printf("GetPartitionEntry(%d,%d)\n", DriveNumber
, PartitionNumber
);
451 BOOLEAN
PpcDiskGetDriveGeometry( ULONG DriveNumber
, PGEOMETRY DriveGeometry
) {
452 printf("GetGeometry(%d)\n", DriveNumber
);
453 DriveGeometry
->BytesPerSector
= 512;
454 DriveGeometry
->Heads
= 16;
455 DriveGeometry
->Sectors
= 63;
459 ULONG
PpcDiskGetCacheableBlockCount( ULONG DriveNumber
) {
460 printf("GetCacheableBlockCount\n");
464 VOID
PpcRTCGetCurrentDateTime( PULONG Hear
, PULONG Month
, PULONG Day
,
465 PULONG Hour
, PULONG Minute
, PULONG Second
) {
466 //printf("RTCGeturrentDateTime\n");
470 printf("PpcHwDetect\n");
473 BOOLEAN
PpcDiskNormalizeSystemPath(char *SystemPath
, unsigned Size
) {
475 ULONG PartitionNumber
;
477 PARTITION_TABLE_ENTRY PartEntry
;
480 if (!DissectArcPath(SystemPath
, BootPath
, &DriveNumber
, &PartitionNumber
))
485 if (0 != PartitionNumber
)
490 if (! DiskGetActivePartitionEntry(DriveNumber
,
493 PartitionNumber
< 1 || 9 < PartitionNumber
)
499 while ('\0' != *p
&& 0 != _strnicmp(p
, "partition(", 10)) {
503 if (NULL
== p
|| '0' != *(p
- 1)) {
506 *(p
- 1) = '0' + PartitionNumber
;
512 typedef unsigned int uint32_t;
513 void PpcInit( of_proxy the_ofproxy
) {
514 int len
, stdin_handle_chosen
, mmu_handle_chosen
;
515 ofproxy
= the_ofproxy
;
517 //SetPhys(0x900, (19 << 26) | (50 << 1));
519 chosen_package
= ofw_finddevice( "/chosen" );
521 ofw_getprop( chosen_package
, "stdin",
522 (char *)&stdin_handle_chosen
, sizeof(stdin_handle_chosen
) );
523 ofw_getprop( chosen_package
, "mmu",
524 (char *)&mmu_handle_chosen
, sizeof(mmu_handle_chosen
) );
526 ofw_print_string("Found stdin ");
527 ofw_print_number(stdin_handle_chosen
);
528 ofw_print_string("\r\n");
530 stdin_handle
= REV(stdin_handle_chosen
);
531 mmu_handle
= REV(mmu_handle_chosen
);
533 MachVtbl
.ConsPutChar
= PpcPutChar
;
534 MachVtbl
.ConsKbHit
= PpcConsKbHit
;
535 MachVtbl
.ConsGetCh
= PpcConsGetCh
;
537 printf( "chosen_package %x, stdin_handle is %x\n",
538 chosen_package
, stdin_handle
);
539 printf("virt2phys (0xe00000,D) -> %x\n", PpcVirt2phys(0xe00000,0));
540 printf("virt2phys (0xe01000,D) -> %x\n", PpcVirt2phys(0xe01000,0));
542 MachVtbl
.VideoClearScreen
= PpcVideoClearScreen
;
543 MachVtbl
.VideoSetDisplayMode
= PpcVideoSetDisplayMode
;
544 MachVtbl
.VideoGetDisplaySize
= PpcVideoGetDisplaySize
;
545 MachVtbl
.VideoGetBufferSize
= PpcVideoGetBufferSize
;
546 MachVtbl
.VideoSetTextCursorPosition
= PpcVideoSetTextCursorPosition
;
547 MachVtbl
.VideoHideShowTextCursor
= PpcVideoHideShowTextCursor
;
548 MachVtbl
.VideoPutChar
= PpcVideoPutChar
;
549 MachVtbl
.VideoCopyOffScreenBufferToVRAM
=
550 PpcVideoCopyOffScreenBufferToVRAM
;
551 MachVtbl
.VideoIsPaletteFixed
= PpcVideoIsPaletteFixed
;
552 MachVtbl
.VideoSetPaletteColor
= PpcVideoSetPaletteColor
;
553 MachVtbl
.VideoGetPaletteColor
= PpcVideoGetPaletteColor
;
554 MachVtbl
.VideoSync
= PpcVideoSync
;
555 MachVtbl
.VideoPrepareForReactOS
= PpcVideoPrepareForReactOS
;
557 MachVtbl
.GetMemoryMap
= PpcGetMemoryMap
;
559 MachVtbl
.DiskNormalizeSystemPath
= PpcDiskNormalizeSystemPath
;
560 MachVtbl
.DiskGetBootVolume
= PpcDiskGetBootVolume
;
561 MachVtbl
.DiskGetSystemVolume
= PpcDiskGetSystemVolume
;
562 MachVtbl
.DiskGetBootPath
= PpcDiskGetBootPath
;
563 MachVtbl
.DiskGetBootDevice
= PpcDiskGetBootDevice
;
564 MachVtbl
.DiskBootingFromFloppy
= PpcDiskBootingFromFloppy
;
565 MachVtbl
.DiskReadLogicalSectors
= PpcDiskReadLogicalSectors
;
566 MachVtbl
.DiskGetPartitionEntry
= PpcDiskGetPartitionEntry
;
567 MachVtbl
.DiskGetDriveGeometry
= PpcDiskGetDriveGeometry
;
568 MachVtbl
.DiskGetCacheableBlockCount
= PpcDiskGetCacheableBlockCount
;
570 MachVtbl
.RTCGetCurrentDateTime
= PpcRTCGetCurrentDateTime
;
572 MachVtbl
.HwDetect
= PpcHwDetect
;
574 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
576 len
= ofw_getprop(chosen_package
, "bootargs",
577 CmdLine
, sizeof(CmdLine
));
579 if( len
< 0 ) len
= 0;
582 printf("bootargs: len %d [%s]\n", len
, CmdLine
);
587 void MachInit(const char *CmdLine
) {
594 printf( "Determining boot device: [%s]\n", CmdLine
);
597 for( i
= 0; i
< strlen(CmdLine
); i
++ ) {
598 if( strncmp(CmdLine
+ i
, "boot=", 5) == 0) {
599 strcpy(BootPart
, CmdLine
+ i
+ 5);
600 sep
= strchr(BootPart
, ',');
603 while(CmdLine
[i
] && CmdLine
[i
]!=',') i
++;
605 if( strncmp(CmdLine
+ i
, "mem=", 4) == 0) {
606 kernel_mem
= atoi(CmdLine
+i
+4);
607 printf("Allocate %dk kernel memory\n", kernel_mem
);
608 while(CmdLine
[i
] && CmdLine
[i
]!=',') i
++;
612 if( strlen(BootPart
) == 0 ) {
613 len
= ofw_getprop(chosen_package
, "bootpath",
614 BootPath
, sizeof(BootPath
));
616 if( len
< 0 ) len
= 0;
618 printf( "Boot Path: %s\n", BootPath
);
620 sep
= strrchr(BootPath
, ',');
622 strcpy(BootPart
, BootPath
);
624 BootPart
[sep
- BootPath
] = 0;
628 printf( "FreeLDR starting (boot partition: %s)\n", BootPart
);
631 /* Compatibility functions that don't do much */
635 UCHAR NTAPI
READ_PORT_UCHAR(PUCHAR Address
) {
639 void WRITE_PORT_UCHAR(PUCHAR Address
, UCHAR Value
) {
642 void DiskStopFloppyMotor() {
645 void BootOldLinuxKernel( unsigned long size
) {
649 void BootNewLinuxKernel() {
653 void ChainLoadBiosBootSectorCode() {
657 void DbgBreakPoint() {