0f339440a27cbaa88140ff951d16c33b41e61616
[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, (char *)buffer + buflen, buffer );
62 ret = ofproxy
63 ( 4, (void *)package, (char *)name, buffer, (void *)buflen );
64 le_swap( buffer, (char *)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
159 for( i = 0; i < depth; i++ ) PpcPutChar( ' ' );
160
161 if( depth == 1 ) {
162 if( gotname > 0 ) {
163 printf( "%c Name: %s\n", match ? '*' : ' ', buf );
164 } else {
165 printf( "- No name attribute for %x\n", parent );
166 }
167 }
168
169 while( !match && next ) {
170 i = PpcFindDevice( depth+1, next, devname, nth );
171 if( i ) return i;
172 next = ofw_peer( next );
173 }
174
175 return 0;
176 }
177
178 BOOLEAN PpcConsKbHit() {
179 return TRUE;
180 }
181
182 int PpcConsGetCh() {
183 char buf;
184 ofw_read( stdin_handle, &buf, 1 );
185 return buf;
186 }
187
188 void PpcVideoClearScreen( UCHAR Attr ) {
189 ofw_print_string("ClearScreen\n");
190 }
191
192 VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init ) {
193 printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
194 return VideoGraphicsMode;
195 }
196
197 /* FIXME: Query */
198 VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
199 ofw_print_string("GetDisplaySize\n");
200 *Width = 640;
201 *Height = 480;
202 *Depth = 8;
203 }
204
205 ULONG PpcVideoGetBufferSize() {
206 ULONG Width, Height, Depth;
207 ofw_print_string("PpcVideoGetBufferSize\n");
208 PpcVideoGetDisplaySize( &Width, &Height, &Depth );
209 return Width * Height * Depth / 8;
210 }
211
212 VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
213 printf("SetTextCursorPosition(%d,%d)\n", X,Y);
214 }
215
216 VOID PpcVideoHideShowTextCursor( BOOLEAN Show ) {
217 printf("HideShowTextCursor(%s)\n", Show ? "true" : "false");
218 }
219
220 VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
221 printf( "\033[%d;%dH%c", Y, X, Ch );
222 }
223
224 VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
225 printf( "CopyOffScreenBufferToVRAM(%x)\n", Buffer );
226 }
227
228 BOOLEAN PpcVideoIsPaletteFixed() {
229 return FALSE;
230 }
231
232 VOID PpcVideoSetPaletteColor( UCHAR Color,
233 UCHAR Red, UCHAR Green, UCHAR Blue ) {
234 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color, Red, Green, Blue );
235 }
236
237 VOID PpcVideoGetPaletteColor( UCHAR Color,
238 UCHAR *Red, UCHAR *Green, UCHAR *Blue ) {
239 printf( "GetPaletteColor(%x)\n", Color);
240 }
241
242 VOID PpcVideoSync() {
243 printf( "Sync\n" );
244 }
245
246 VOID PpcVideoPrepareForReactOS() {
247 printf( "PrepareForReactOS\n");
248 }
249 /* XXX FIXME:
250 * According to the linux people (this is backed up by my own experience),
251 * the memory object in older ofw does not do getprop right.
252 *
253 * The "right" way is to probe the pci bridge. *sigh*
254 */
255 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
256 ULONG MaxMemoryMapSize ) {
257 printf("GetMemoryMap(chosen=%x)\n", chosen_package);
258
259 BiosMemoryMap[0].Type = MEMTYPE_USABLE;
260 BiosMemoryMap[0].BaseAddress = 0;
261 BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
262
263 printf( "Returning memory map (%dk total)\n",
264 (int)BiosMemoryMap[0].Length / 1024 );
265
266 return 1;
267 }
268
269 /* Strategy:
270 *
271 * For now, it'll be easy enough to use the boot command line as our boot path.
272 * Treat it as the path of a disk partition. We might even be able to get
273 * away with grabbing a partition image by tftp in this scenario.
274 */
275
276 BOOLEAN PpcDiskGetBootVolume( PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType ) {
277 *DriveNumber = 0;
278 *StartSector = 0;
279 *SectorCount = 0;
280 *FsType = FS_FAT;
281 return TRUE;
282 }
283
284 BOOLEAN PpcDiskGetSystemVolume( char *SystemPath,
285 char *RemainingPath,
286 PULONG Device,
287 PULONG DriveNumber,
288 PULONGLONG StartSector,
289 PULONGLONG SectorCount,
290 int *FsType ) {
291 return FALSE;
292 }
293
294 BOOLEAN PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
295 strncpy( OutBootPath, BootPath, Size );
296 return TRUE;
297 }
298
299 VOID PpcDiskGetBootDevice( PULONG BootDevice ) {
300 BootDevice[0] = BootDevice[1] = 0;
301 }
302
303 BOOLEAN PpcDiskBootingFromFloppy(VOID) {
304 return FALSE;
305 }
306
307 BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
308 ULONG SectorCount, PVOID Buffer ) {
309 int rlen = 0;
310
311 if( part_handle == -1 ) {
312 part_handle = ofw_open( BootPart );
313
314 if( part_handle == -1 ) {
315 printf("Could not open any disk devices we know about\n");
316 return FALSE;
317 }
318 }
319
320 if( part_handle == -1 ) {
321 printf("Got partition handle %x\n", part_handle);
322 return FALSE;
323 }
324
325 if( ofw_seek( part_handle, SectorNumber * 512 ) ) {
326 printf("Seek to %x failed\n", SectorNumber * 512);
327 return FALSE;
328 }
329 rlen = ofw_read( part_handle, Buffer, SectorCount * 512 );
330 return rlen > 0;
331 }
332
333 BOOLEAN PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
334 PPARTITION_TABLE_ENTRY PartitionTableEntry ) {
335 printf("GetPartitionEntry(%d,%d)\n", DriveNumber, PartitionNumber);
336 return FALSE;
337 }
338
339 BOOLEAN PpcDiskGetDriveGeometry( ULONG DriveNumber, PGEOMETRY DriveGeometry ) {
340 printf("GetGeometry(%d)\n", DriveNumber);
341 DriveGeometry->BytesPerSector = 512;
342 DriveGeometry->Heads = 16;
343 DriveGeometry->Sectors = 63;
344 return TRUE;
345 }
346
347 ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
348 printf("GetCacheableBlockCount\n");
349 return 1;
350 }
351
352 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
353 PULONG Hour, PULONG Minute, PULONG Second ) {
354 printf("RTCGeturrentDateTime\n");
355 }
356
357 VOID PpcHwDetect() {
358 printf("PpcHwDetect\n");
359 }
360
361 typedef unsigned int uint32_t;
362
363 void PpcInit( of_proxy the_ofproxy ) {
364 int len;
365 ofproxy = the_ofproxy;
366
367 chosen_package = ofw_finddevice( "/chosen" );
368
369 ofw_getprop( chosen_package, "stdin",
370 &stdin_handle, sizeof(stdin_handle) );
371
372 stdin_handle = REV(stdin_handle);
373
374 MachVtbl.ConsPutChar = PpcPutChar;
375 MachVtbl.ConsKbHit = PpcConsKbHit;
376 MachVtbl.ConsGetCh = PpcConsGetCh;
377
378 printf( "stdin_handle is %x\n", stdin_handle );
379
380 MachVtbl.VideoClearScreen = PpcVideoClearScreen;
381 MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
382 MachVtbl.VideoGetDisplaySize = PpcVideoGetDisplaySize;
383 MachVtbl.VideoGetBufferSize = PpcVideoGetBufferSize;
384 MachVtbl.VideoSetTextCursorPosition = PpcVideoSetTextCursorPosition;
385 MachVtbl.VideoHideShowTextCursor = PpcVideoHideShowTextCursor;
386 MachVtbl.VideoPutChar = PpcVideoPutChar;
387 MachVtbl.VideoCopyOffScreenBufferToVRAM =
388 PpcVideoCopyOffScreenBufferToVRAM;
389 MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
390 MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
391 MachVtbl.VideoGetPaletteColor = PpcVideoGetPaletteColor;
392 MachVtbl.VideoSync = PpcVideoSync;
393 MachVtbl.VideoPrepareForReactOS = PpcVideoPrepareForReactOS;
394
395 MachVtbl.GetMemoryMap = PpcGetMemoryMap;
396
397 MachVtbl.DiskGetBootVolume = PpcDiskGetBootVolume;
398 MachVtbl.DiskGetSystemVolume = PpcDiskGetSystemVolume;
399 MachVtbl.DiskGetBootPath = PpcDiskGetBootPath;
400 MachVtbl.DiskGetBootDevice = PpcDiskGetBootDevice;
401 MachVtbl.DiskBootingFromFloppy = PpcDiskBootingFromFloppy;
402 MachVtbl.DiskReadLogicalSectors = PpcDiskReadLogicalSectors;
403 MachVtbl.DiskGetPartitionEntry = PpcDiskGetPartitionEntry;
404 MachVtbl.DiskGetDriveGeometry = PpcDiskGetDriveGeometry;
405 MachVtbl.DiskGetCacheableBlockCount = PpcDiskGetCacheableBlockCount;
406
407 MachVtbl.RTCGetCurrentDateTime = PpcRTCGetCurrentDateTime;
408
409 MachVtbl.HwDetect = PpcHwDetect;
410
411 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
412
413 len = ofw_getprop(chosen_package, "bootargs",
414 CmdLine, sizeof(CmdLine));
415
416 if( len < 0 ) len = 0;
417 CmdLine[len] = 0;
418
419 BootMain( CmdLine );
420 }
421
422 void MachInit(const char *CmdLine) {
423 int len, i;
424 char *sep;
425
426 BootPart[0] = 0;
427 BootPath[0] = 0;
428
429 printf( "Determining boot device: [%s]\n", CmdLine );
430
431 printf( "Boot Args: %s\n", CmdLine );
432 sep = NULL;
433 for( i = 0; i < strlen(CmdLine); i++ ) {
434 if( strncmp(CmdLine + i, "boot=", 5) == 0) {
435 strcpy(BootPart, CmdLine + i + 5);
436 sep = strchr(BootPart, ' ');
437 if( sep )
438 *sep = 0;
439 break;
440 }
441 }
442
443 if( strlen(BootPart) == 0 ) {
444 len = ofw_getprop(chosen_package, "bootpath",
445 BootPath, sizeof(BootPath));
446
447 if( len < 0 ) len = 0;
448 BootPath[len] = 0;
449 printf( "Boot Path: %s\n", BootPath );
450
451 sep = strrchr(BootPath, ',');
452
453 strcpy(BootPart, BootPath);
454 if( sep ) {
455 BootPart[sep - BootPath] = 0;
456 }
457 }
458
459 printf( "FreeLDR starting (boot partition: %s)\n", BootPart );
460 }
461
462 /* Compatibility functions that don't do much */
463 void beep() {
464 }
465
466 UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address) {
467 return 0xff;
468 }
469
470 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
471 }
472
473 void DiskStopFloppyMotor() {
474 }
475
476 void BootOldLinuxKernel( unsigned long size ) {
477 ofw_exit();
478 }
479
480 void BootNewLinuxKernel() {
481 ofw_exit();
482 }
483
484 void ChainLoadBiosBootSectorCode() {
485 ofw_exit();
486 }