Fixed, separated mmu related functions. We now get correct translations
[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 #include "mmu.h"
23
24 #define TOTAL_HEAP_NEEDED (16 * 1024 * 1024) /* 16 megs */
25
26 extern void BootMain( char * );
27 extern char *GetFreeLoaderVersionString();
28 of_proxy ofproxy;
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 };
33 jmp_buf jmp;
34 volatile char *video_mem = 0;
35
36 void le_swap( void *start_addr_v,
37 void *end_addr_v,
38 void *target_addr_v ) {
39 long
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);
43 long tmp;
44 while( start_addr <= end_addr ) {
45 tmp = start_addr[0];
46 target_addr[0] = REV(start_addr[1]);
47 target_addr[1] = REV(tmp);
48 start_addr += 2;
49 target_addr += 2;
50 }
51 }
52
53 void PpcPutChar( int ch ) {
54 char buf[3];
55 if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; }
56 else { buf[0] = ch; buf[1] = 0; }
57 buf[2] = 0;
58 ofw_print_string( buf );
59 }
60
61 int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
62 static char buf[256];
63 int next = 0;
64 int gotname = 0;
65 int match = 0;
66 int i;
67
68 next = ofw_child( parent );
69
70 //printf( "next = %x\n", next );
71
72 gotname = ofw_getprop(parent, "name", buf, 256);
73
74 //printf( "gotname = %d\n", gotname );
75
76 match = !strncmp(buf, devname, strlen(devname));
77
78 if( !nth && match ) return parent;
79
80 for( i = 0; i < depth; i++ ) PpcPutChar( ' ' );
81
82 if( depth == 1 ) {
83 if( gotname > 0 ) {
84 printf( "%c Name: %s\n", match ? '*' : ' ', buf );
85 } else {
86 printf( "- No name attribute for %x\n", parent );
87 }
88 }
89
90 while( !match && next ) {
91 i = PpcFindDevice( depth+1, next, devname, nth );
92 if( i ) return i;
93 next = ofw_peer( next );
94 }
95
96 return 0;
97 }
98
99 BOOLEAN PpcConsKbHit() {
100 return FALSE;
101 }
102
103 int PpcConsGetCh() {
104 char buf;
105 ofw_read( stdin_handle, &buf, 1 );
106 return buf;
107 }
108
109 void PpcVideoClearScreen( UCHAR Attr ) {
110 ofw_print_string("ClearScreen\n");
111 }
112
113 VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
114 //ofw_print_string("GetDisplaySize\n");
115 *Width = 80;
116 *Height = 25;
117 *Depth = 16;
118 //printf("GetDisplaySize(%d,%d,%d)\n", *Width, *Height, *Depth);
119 }
120
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;
126 }
127
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() );
132 }
133 return VideoTextMode;
134 }
135
136 VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
137 printf("SetTextCursorPosition(%d,%d)\n", X,Y);
138 }
139
140 VOID PpcVideoHideShowTextCursor( BOOLEAN Show ) {
141 printf("HideShowTextCursor(%s)\n", Show ? "true" : "false");
142 }
143
144 VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
145 printf( "\033[%d;%dH%c", Y, X, Ch );
146 }
147
148 VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
149 int i,j;
150 ULONG w,h,d;
151 PCHAR ChBuf = Buffer;
152 int offset = 0;
153
154 PpcVideoGetDisplaySize( &w, &h, &d );
155
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);
162 }
163 }
164 }
165 }
166
167 BOOLEAN PpcVideoIsPaletteFixed() {
168 return FALSE;
169 }
170
171 VOID PpcVideoSetPaletteColor( UCHAR Color,
172 UCHAR Red, UCHAR Green, UCHAR Blue ) {
173 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color, Red, Green, Blue );
174 }
175
176 VOID PpcVideoGetPaletteColor( UCHAR Color,
177 UCHAR *Red, UCHAR *Green, UCHAR *Blue ) {
178 printf( "GetPaletteColor(%x)\n", Color);
179 }
180
181 VOID PpcVideoSync() {
182 printf( "Sync\n" );
183 }
184
185 VOID PpcVideoPrepareForReactOS() {
186 printf( "PrepareForReactOS\n");
187 }
188 /*
189 * Get memory the proper openfirmware way
190 */
191 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
192 ULONG MaxMemoryMapSize ) {
193 int i, memhandle, mmuhandle, returned, total = 0, num_mem = 0;
194 int memdata[256];
195
196 printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize);
197
198 if( mem_base ) {
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");
203 return 1;
204 }
205
206 ofw_getprop(chosen_package, "memory",
207 (char *)&memhandle, sizeof(memhandle));
208 ofw_getprop(chosen_package, "mmu",
209 (char *)&mmuhandle, sizeof(mmuhandle));
210
211 returned = ofw_getprop(memhandle, "available",
212 (char *)memdata, sizeof(memdata));
213
214 /* We need to leave some for open firmware. Let's claim up to 16 megs
215 * for now */
216
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;
228 num_mem++;
229 }
230 }
231
232 printf( "Returning memory map (%dk total)\n", total / 1024 );
233
234 return num_mem;
235 }
236
237 /* Strategy:
238 *
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.
242 */
243
244 BOOLEAN PpcDiskGetBootVolume( PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType ) {
245 *DriveNumber = 0;
246 *StartSector = 0;
247 *SectorCount = 0;
248 *FsType = FS_FAT;
249 return TRUE;
250 }
251
252 BOOLEAN PpcDiskGetSystemVolume( char *SystemPath,
253 char *RemainingPath,
254 PULONG Device,
255 PULONG DriveNumber,
256 PULONGLONG StartSector,
257 PULONGLONG SectorCount,
258 int *FsType ) {
259 char *remain = strchr(SystemPath, '\\');
260 if( remain ) {
261 strcpy( RemainingPath, remain+1 );
262 } else {
263 RemainingPath[0] = 0;
264 }
265 *Device = 0;
266 return PpcDiskGetBootVolume(DriveNumber, StartSector, SectorCount, FsType);
267 }
268
269 BOOLEAN PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
270 strncpy( OutBootPath, BootPath, Size );
271 return TRUE;
272 }
273
274 VOID PpcDiskGetBootDevice( PULONG BootDevice ) {
275 BootDevice[0] = BootDevice[1] = 0;
276 }
277
278 BOOLEAN PpcDiskBootingFromFloppy(VOID) {
279 return FALSE;
280 }
281
282 BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
283 ULONG SectorCount, PVOID Buffer ) {
284 int rlen = 0;
285
286 if( part_handle == -1 ) {
287 part_handle = ofw_open( BootPart );
288
289 if( part_handle == -1 ) {
290 printf("Could not open any disk devices we know about\n");
291 return FALSE;
292 }
293 }
294
295 if( part_handle == -1 ) {
296 printf("Got partition handle %x\n", part_handle);
297 return FALSE;
298 }
299
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));
304 return FALSE;
305 }
306 rlen = ofw_read( part_handle, Buffer, (ULONG)(SectorCount * 512) );
307 return rlen > 0;
308 }
309
310 BOOLEAN PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
311 PPARTITION_TABLE_ENTRY PartitionTableEntry ) {
312 printf("GetPartitionEntry(%d,%d)\n", DriveNumber, PartitionNumber);
313 return FALSE;
314 }
315
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;
321 return TRUE;
322 }
323
324 ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
325 printf("GetCacheableBlockCount\n");
326 return 1;
327 }
328
329 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
330 PULONG Hour, PULONG Minute, PULONG Second ) {
331 //printf("RTCGeturrentDateTime\n");
332 }
333
334 VOID PpcHwDetect() {
335 printf("PpcHwDetect\n");
336 }
337
338 BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) {
339 CHAR BootPath[256];
340 ULONG PartitionNumber;
341 ULONG DriveNumber;
342 PARTITION_TABLE_ENTRY PartEntry;
343 char *p;
344
345 if (!DissectArcPath(SystemPath, BootPath, &DriveNumber, &PartitionNumber))
346 {
347 return FALSE;
348 }
349
350 if (0 != PartitionNumber)
351 {
352 return TRUE;
353 }
354
355 if (! DiskGetActivePartitionEntry(DriveNumber,
356 &PartEntry,
357 &PartitionNumber) ||
358 PartitionNumber < 1 || 9 < PartitionNumber)
359 {
360 return FALSE;
361 }
362
363 p = SystemPath;
364 while ('\0' != *p && 0 != _strnicmp(p, "partition(", 10)) {
365 p++;
366 }
367 p = strchr(p, ')');
368 if (NULL == p || '0' != *(p - 1)) {
369 return FALSE;
370 }
371 *(p - 1) = '0' + PartitionNumber;
372
373 return TRUE;
374 }
375
376 typedef unsigned int uint32_t;
377
378 void PpcInit( of_proxy the_ofproxy ) {
379 int len, stdin_handle_chosen;
380 ofproxy = the_ofproxy;
381
382 ofw_print_string("Freeldr PowerPC Init\n");
383
384 chosen_package = ofw_finddevice( "/chosen" );
385
386 ofw_print_string("Freeldr: chosen_package is ");
387 ofw_print_number(chosen_package);
388 ofw_print_string("\n");
389
390 ofw_getprop( chosen_package, "stdin",
391 (char *)&stdin_handle_chosen, sizeof(stdin_handle_chosen) );
392
393 ofw_print_string("Freeldr: stdin_handle is ");
394 ofw_print_number(stdin_handle_chosen);
395 ofw_print_string("\n");
396
397 stdin_handle = stdin_handle_chosen;
398
399 /* stdin_handle = REV(stdin_handle); */
400
401 MachVtbl.ConsPutChar = PpcPutChar;
402 MachVtbl.ConsKbHit = PpcConsKbHit;
403 MachVtbl.ConsGetCh = PpcConsGetCh;
404
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));
408
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;
423
424 MachVtbl.GetMemoryMap = PpcGetMemoryMap;
425
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;
436
437 MachVtbl.RTCGetCurrentDateTime = PpcRTCGetCurrentDateTime;
438
439 MachVtbl.HwDetect = PpcHwDetect;
440
441 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
442
443 len = ofw_getprop(chosen_package, "bootargs",
444 CmdLine, sizeof(CmdLine));
445
446 if( len < 0 ) len = 0;
447 CmdLine[len] = 0;
448
449 BootMain( CmdLine );
450 }
451
452 void MachInit(const char *CmdLine) {
453 int len, i;
454 char *sep;
455
456 BootPart[0] = 0;
457 BootPath[0] = 0;
458
459 printf( "Determining boot device: [%s]\n", CmdLine );
460
461 printf( "Boot Args: %s\n", CmdLine );
462 sep = NULL;
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, ' ');
467 if( sep )
468 *sep = 0;
469 break;
470 }
471 }
472
473 if( strlen(BootPart) == 0 ) {
474 len = ofw_getprop(chosen_package, "bootpath",
475 BootPath, sizeof(BootPath));
476
477 if( len < 0 ) len = 0;
478 BootPath[len] = 0;
479 printf( "Boot Path: %s\n", BootPath );
480
481 sep = strrchr(BootPath, ',');
482
483 strcpy(BootPart, BootPath);
484 if( sep ) {
485 BootPart[sep - BootPath] = 0;
486 }
487 }
488
489 printf( "FreeLDR starting (boot partition: %s)\n", BootPart );
490 }
491
492 /* Compatibility functions that don't do much */
493 void beep() {
494 }
495
496 UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address) {
497 return 0xff;
498 }
499
500 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
501 }
502
503 void DiskStopFloppyMotor() {
504 }
505
506 void BootOldLinuxKernel( unsigned long size ) {
507 ofw_exit();
508 }
509
510 void BootNewLinuxKernel() {
511 ofw_exit();
512 }
513
514 void ChainLoadBiosBootSectorCode() {
515 ofw_exit();
516 }