PowerPC support drop in freeldr, from my branch.
[reactos.git] / reactos / boot / freeldr / freeldr / arch / powerpc / mach.c
1 /*
2 * FreeLoader PowerPC Part
3 * Copyright (C) 2005 Art Yerkes
4 *
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.
9 *
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.
14 *
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.
18 */
19 #include "freeldr.h"
20 #include "machine.h"
21 #include "of.h"
22
23 extern void BootMain( char * );
24 extern char *GetFreeLoaderVersionString();
25 of_proxy ofproxy;
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 };
30 jmp_buf jmp;
31
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);
38 long tmp;
39 while( start_addr <= end_addr ) {
40 tmp = start_addr[0];
41 target_addr[0] = REV(start_addr[1]);
42 target_addr[1] = REV(tmp);
43 start_addr += 2;
44 target_addr += 2;
45 }
46 }
47
48 int ofw_finddevice( const char *name ) {
49 int ret, len;
50
51 len = strlen(name);
52 le_swap( name, name + len, name );
53 ret = ofproxy( 0, (char *)name, NULL, NULL, NULL );
54 le_swap( name, name + len, name );
55 return ret;
56 }
57
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 );
62 ret = ofproxy
63 ( 4, (void *)package, (char *)name, buffer, (void *)buflen );
64 le_swap( buffer, buffer + buflen, buffer );
65 le_swap( name, name + len, name );
66 return ret;
67 }
68
69 /* Since this is from external storage, it doesn't need swapping */
70 int ofw_write( int handle, const char *data, int len ) {
71 int ret;
72 le_swap( data, data + len, data );
73 ret = ofproxy
74 ( 8, (void *)handle, (char *)data, (void *)len, NULL );
75 le_swap( data, data + len, data );
76 return ret;
77 }
78
79 /* Since this is from external storage, it doesn't need swapping */
80 int ofw_read( int handle, const char *data, int len ) {
81 int ret;
82
83 le_swap( data, data + len, data );
84 ret = ofproxy
85 ( 12, (void *)handle, (char *)data, (void *)len, NULL );
86 le_swap( data, data + len, data );
87
88 return ret;
89 }
90
91 void ofw_exit() {
92 ofproxy( 16, NULL, NULL, NULL, NULL );
93 }
94
95 void ofw_dumpregs() {
96 ofproxy( 20, NULL, NULL, NULL, NULL );
97 }
98
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 );
104 }
105
106 void ofw_print_number( int num ) {
107 ofproxy( 28, (void *)num, NULL, NULL, NULL );
108 }
109
110 int ofw_open( const char *name ) {
111 int ret, len;
112
113 len = strlen(name);
114 le_swap( name, name + len, name );
115 ret = ofproxy( 32, (char *)name, NULL, NULL, NULL );
116 le_swap( name, name + len, name );
117 return ret;
118 }
119
120 int ofw_child( int package ) {
121 return ofproxy( 36, (void *)package, NULL, NULL, NULL );
122 }
123
124 int ofw_peer( int package ) {
125 return ofproxy( 40, (void *)package, NULL, NULL, NULL );
126 }
127
128 int ofw_seek( int handle, long long location ) {
129 return ofproxy( 44, (void *)handle, (void *)(int)(location >> 32), (void *)(int)location, NULL );
130 }
131
132 void PpcPutChar( int ch ) {
133 char buf[3];
134 if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; }
135 else { buf[0] = ch; buf[1] = 0; }
136 buf[2] = 0;
137 ofw_print_string( buf );
138 }
139
140 int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
141 static char buf[256];
142 int next = 0;
143 int gotname = 0;
144 int match = 0;
145 int i;
146
147 next = ofw_child( parent );
148
149 //printf( "next = %x\n", next );
150
151 gotname = ofw_getprop(parent, "name", buf, 256);
152
153 //printf( "gotname = %d\n", gotname );
154
155 match = !strncmp(buf, devname, strlen(devname));
156
157 if( !nth && match ) return parent;
158 else if( match ) *nth--;
159
160 for( i = 0; i < depth; i++ ) PpcPutChar( ' ' );
161
162 if( depth == 1 ) {
163 if( gotname > 0 ) {
164 printf( "%c Name: %s\n", match ? '*' : ' ', buf );
165 } else {
166 printf( "- No name attribute for %x\n", parent );
167 }
168 }
169
170 while( !match && next ) {
171 i = PpcFindDevice( depth+1, next, devname, nth );
172 if( i ) return i;
173 next = ofw_peer( next );
174 }
175
176 return 0;
177 }
178
179 BOOL PpcConsKbHit() {
180 return TRUE;
181 }
182
183 int PpcConsGetCh() {
184 char buf;
185 ofw_read( stdin_handle, &buf, 1 );
186 return buf;
187 }
188
189 void PpcVideoClearScreen( UCHAR Attr ) {
190 ofw_print_string("ClearScreen\n");
191 }
192
193 VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOL Init ) {
194 printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
195 return VideoGraphicsMode;
196 }
197
198 /* FIXME: Query */
199 VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
200 ofw_print_string("GetDisplaySize\n");
201 *Width = 640;
202 *Height = 480;
203 *Depth = 8;
204 }
205
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;
211 }
212
213 VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
214 printf("SetTextCursorPosition(%d,%d)\n", X,Y);
215 }
216
217 VOID PpcVideoHideShowTextCursor( BOOL Show ) {
218 printf("HideShowTextCursor(%s)\n", Show ? "true" : "false");
219 }
220
221 VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
222 printf( "\033[%d;%dH%c", Y, X, Ch );
223 }
224
225 VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
226 printf( "CopyOffScreenBufferToVRAM(%x)\n", Buffer );
227 }
228
229 BOOL PpcVideoIsPaletteFixed() {
230 return FALSE;
231 }
232
233 VOID PpcVideoSetPaletteColor( UCHAR Color,
234 UCHAR Red, UCHAR Green, UCHAR Blue ) {
235 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color, Red, Green, Blue );
236 }
237
238 VOID PpcVideoGetPaletteColor( UCHAR Color,
239 UCHAR *Red, UCHAR *Green, UCHAR *Blue ) {
240 printf( "GetPaletteColor(%x)\n", Color);
241 }
242
243 VOID PpcVideoSync() {
244 printf( "Sync\n" );
245 }
246
247 VOID PpcVideoPrepareForReactOS() {
248 printf( "PrepareForReactOS\n");
249 }
250 /* XXX FIXME:
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.
253 *
254 * The "right" way is to probe the pci bridge. *sigh*
255 */
256 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
257 ULONG MaxMemoryMapSize ) {
258 printf("GetMemoryMap(chosen=%x)\n", chosen_package);
259
260 BiosMemoryMap[0].Type = MEMTYPE_USABLE;
261 BiosMemoryMap[0].BaseAddress = 0;
262 BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
263
264 printf( "Returning memory map (%dk total)\n",
265 (int)BiosMemoryMap[0].Length / 1024 );
266
267 return 1;
268 }
269
270 /* Strategy:
271 *
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.
275 */
276
277 BOOL PpcDiskGetBootVolume( PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType ) {
278 *DriveNumber = 0;
279 *StartSector = 0;
280 *SectorCount = 0;
281 *FsType = FS_FAT;
282 return TRUE;
283 }
284
285 BOOL PpcDiskGetSystemVolume( char *SystemPath,
286 char *RemainingPath,
287 PULONG Device,
288 PULONG DriveNumber,
289 PULONGLONG StartSector,
290 PULONGLONG SectorCount,
291 int *FsType ) {
292 return FALSE;
293 }
294
295 BOOL PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
296 strncpy( OutBootPath, BootPath, Size );
297 return TRUE;
298 }
299
300 VOID PpcDiskGetBootDevice( PULONG BootDevice ) {
301 BootDevice[0] = BootDevice[1] = 0;
302 }
303
304 BOOL PpcDiskBootingFromFloppy(VOID) {
305 return FALSE;
306 }
307
308 BOOL PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
309 ULONG SectorCount, PVOID Buffer ) {
310 int rlen = 0;
311
312 if( part_handle == -1 ) {
313 part_handle = ofw_open( BootPart );
314
315 if( part_handle == -1 ) {
316 printf("Could not open any disk devices we know about\n");
317 return FALSE;
318 }
319 }
320
321 if( part_handle == -1 ) {
322 printf("Got partition handle %x\n", part_handle);
323 return FALSE;
324 }
325
326 if( ofw_seek( part_handle, SectorNumber * 512 ) ) {
327 printf("Seek to %x failed\n", SectorNumber * 512);
328 return FALSE;
329 }
330 rlen = ofw_read( part_handle, Buffer, SectorCount * 512 );
331 return rlen > 0;
332 }
333
334 BOOL PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
335 PPARTITION_TABLE_ENTRY PartitionTableEntry ) {
336 printf("GetPartitionEntry(%d,%d)\n", DriveNumber, PartitionNumber);
337 return FALSE;
338 }
339
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;
345 return TRUE;
346 }
347
348 ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
349 printf("GetCacheableBlockCount\n");
350 return 1;
351 }
352
353 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
354 PULONG Hour, PULONG Minute, PULONG Second ) {
355 printf("RTCGeturrentDateTime\n");
356 }
357
358 VOID PpcHwDetect() {
359 printf("PpcHwDetect\n");
360 }
361
362 typedef unsigned int uint32_t;
363
364 void PpcInit( of_proxy the_ofproxy ) {
365 int len;
366 ofproxy = the_ofproxy;
367
368 chosen_package = ofw_finddevice( "/chosen" );
369
370 ofw_getprop( chosen_package, "stdin",
371 &stdin_handle, sizeof(stdin_handle) );
372
373 stdin_handle = REV(stdin_handle);
374
375 MachVtbl.ConsPutChar = PpcPutChar;
376 MachVtbl.ConsKbHit = PpcConsKbHit;
377 MachVtbl.ConsGetCh = PpcConsGetCh;
378
379 printf( "stdin_handle is %x\n", stdin_handle );
380
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;
395
396 MachVtbl.GetMemoryMap = PpcGetMemoryMap;
397
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;
407
408 MachVtbl.RTCGetCurrentDateTime = PpcRTCGetCurrentDateTime;
409
410 MachVtbl.HwDetect = PpcHwDetect;
411
412 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
413
414 len = ofw_getprop(chosen_package, "bootargs",
415 CmdLine, sizeof(CmdLine));
416
417 if( len < 0 ) len = 0;
418 CmdLine[len] = 0;
419
420 BootMain( CmdLine );
421 }
422
423 void MachInit(char *CmdLine) {
424 int len, i;
425 char *sep;
426
427 BootPart[0] = 0;
428 BootPath[0] = 0;
429
430 printf( "Determining boot device: [%s]\n", CmdLine );
431
432 printf( "Boot Args: %s\n", CmdLine );
433 sep = NULL;
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, ' ');
438 if( sep )
439 *sep = 0;
440 break;
441 }
442 }
443
444 if( strlen(BootPart) == 0 ) {
445 len = ofw_getprop(chosen_package, "bootpath",
446 BootPath, sizeof(BootPath));
447
448 if( len < 0 ) len = 0;
449 BootPath[len] = 0;
450 printf( "Boot Path: %s\n", BootPath );
451
452 sep = strrchr(BootPath, ',');
453
454 strcpy(BootPart, BootPath);
455 if( sep ) {
456 BootPart[sep - BootPath] = 0;
457 }
458 }
459
460 printf( "FreeLDR starting (boot partition: %s)\n", BootPart );
461 }
462
463 /* Compatibility functions that don't do much */
464 void beep() {
465 }
466
467 UCHAR STDCALL READ_PORT_UCHAR(PUCHAR Address) {
468 return 0xff;
469 }
470
471 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
472 }
473
474 void DiskStopFloppyMotor() {
475 }
476
477 void BootOldLinuxKernel( unsigned long size ) {
478 ofw_exit();
479 }
480
481 void BootNewLinuxKernel() {
482 ofw_exit();
483 }
484
485 void ChainLoadBiosBootSectorCode() {
486 ofw_exit();
487 }