Added freeldr and hal from PPC branch, along with needed headers and
[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 "ppcmmu/mmu.h"
22 #include "of.h"
23 #include "ppcboot.h"
24 #include "prep.h"
25 #include "compat.h"
26
27 extern void BootMain( LPSTR CmdLine );
28 extern PCHAR GetFreeLoaderVersionString();
29 extern ULONG CacheSizeLimit;
30 of_proxy ofproxy;
31 void *PageDirectoryStart, *PageDirectoryEnd;
32 static int chosen_package, stdin_handle, stdout_handle,
33 part_handle = -1, kernel_mem = 0;
34 int mmu_handle = 0, FixedMemory = 0;
35 BOOLEAN AcpiPresent = FALSE;
36 char BootPath[0x100] = { 0 }, BootPart[0x100] = { 0 }, CmdLine[0x100] = { "bootprep" };
37 jmp_buf jmp;
38 volatile char *video_mem = 0;
39 boot_infos_t BootInfo;
40
41 void PpcOfwPutChar( int ch ) {
42 char buf[3];
43 if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; }
44 else { buf[0] = ch; buf[1] = 0; }
45 buf[2] = 0;
46 ofw_write(stdout_handle, buf, strlen(buf));
47 }
48
49 int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
50 static char buf[256];
51 int next = 0;
52 int gotname = 0;
53 int match = 0;
54 int i;
55
56 next = ofw_child( parent );
57
58 //printf( "next = %x\n", next );
59
60 gotname = ofw_getprop(parent, "name", buf, 256);
61
62 //printf( "gotname = %d\n", gotname );
63
64 match = !strncmp(buf, devname, strlen(devname));
65
66 if( !nth && match ) return parent;
67
68 for( i = 0; i < depth; i++ ) PpcOfwPutChar( ' ' );
69
70 if( depth == 1 ) {
71 if( gotname > 0 ) {
72 printf( "%c Name: %s\n", match ? '*' : ' ', buf );
73 } else {
74 printf( "- No name attribute for %x\n", parent );
75 }
76 }
77
78 while( !match && next ) {
79 i = PpcFindDevice( depth+1, next, devname, nth );
80 if( i ) return i;
81 next = ofw_peer( next );
82 }
83
84 return 0;
85 }
86
87 BOOLEAN PpcConsKbHit() {
88 return FALSE;
89 }
90
91 int PpcConsGetCh() {
92 char buf;
93 ofw_read( stdin_handle, &buf, 1 );
94 return buf;
95 }
96
97 void PpcVideoClearScreen( UCHAR Attr ) {
98 }
99
100 VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
101 *Width = 80;
102 *Height = 25;
103 *Depth = 16;
104 }
105
106 ULONG PpcVideoGetBufferSize() {
107 ULONG Width, Height, Depth;
108 MachVideoGetDisplaySize( &Width, &Height, &Depth );
109 return Width * Height * Depth / 8;
110 }
111
112 VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init ) {
113 //printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
114 if( Init && !video_mem ) {
115 video_mem = MmAllocateMemory( PpcVideoGetBufferSize() );
116 }
117 return VideoTextMode;
118 }
119
120 VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
121 printf("SetTextCursorPosition(%d,%d)\n", X,Y);
122 }
123
124 VOID PpcVideoHideShowTextCursor( BOOLEAN Show ) {
125 printf("HideShowTextCursor(%s)\n", Show ? "true" : "false");
126 }
127
128 VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
129 printf( "\033[%d;%dH%c", Y, X, Ch );
130 }
131
132 VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
133 int i,j;
134 ULONG w,h,d;
135 PCHAR ChBuf = Buffer;
136 int offset = 0;
137
138 MachVideoGetDisplaySize( &w, &h, &d );
139
140 for( i = 0; i < h; i++ ) {
141 for( j = 0; j < w; j++ ) {
142 offset = (j * 2) + (i * w * 2);
143 if( ChBuf[offset] != video_mem[offset] ) {
144 video_mem[offset] = ChBuf[offset];
145 MachVideoPutChar(ChBuf[offset],0,j+1,i+1);
146 }
147 }
148 }
149 }
150
151 BOOLEAN PpcVideoIsPaletteFixed() {
152 return FALSE;
153 }
154
155 VOID PpcVideoSetPaletteColor( UCHAR Color,
156 UCHAR Red, UCHAR Green, UCHAR Blue ) {
157 printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color, Red, Green, Blue );
158 }
159
160 VOID PpcVideoGetPaletteColor( UCHAR Color,
161 UCHAR *Red, UCHAR *Green, UCHAR *Blue ) {
162 printf( "GetPaletteColor(%x)\n", Color);
163 }
164
165 VOID PpcVideoSync() {
166 printf( "Sync\n" );
167 }
168
169 static int prom_next_node(int *nodep)
170 {
171 int node;
172
173 if ((node = *nodep) != 0
174 && (*nodep = ofw_child(node)) != 0)
175 return 1;
176 if ((*nodep = ofw_peer(node)) != 0)
177 return 1;
178 for (;;) {
179 if ((node = ofw_parent(node)) == 0)
180 return 0;
181 if ((*nodep = ofw_peer(node)) != 0)
182 return 1;
183 }
184 }
185
186 /* Appropriated from linux' btext.c
187 * author:
188 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
189 */
190 VOID PpcVideoPrepareForReactOS(BOOLEAN Setup) {
191 int i, j, k, /* display_handle, */ display_package, display_size = 0;
192 int node, ret, elts;
193 int device_address;
194 //pci_reg_property display_regs[8];
195 char type[256], path[256], name[256];
196 char logo[] = {
197 " "
198 " XXXXXX "
199 " X X "
200 " X X X X "
201 " X X "
202 " X XXXX X "
203 " X XX X "
204 " X X "
205 " XXXXXX "
206 " "
207 };
208 int logo_x = 10, logo_y = 10;
209 int logo_scale_x = 8, logo_scale_y = 8;
210
211
212 for( node = ofw_finddevice("/"); prom_next_node(&node); ) {
213 memset(type, 0, sizeof(type));
214 memset(path, 0, sizeof(path));
215
216 ret = ofw_getprop(node, "name", name, sizeof(name));
217
218 if(ofw_getprop(node, "device_type", type, sizeof(type)) <= 0) {
219 printf("Could not get type for node %x\n", node);
220 continue;
221 }
222
223 printf("Node %x ret %d name %s type %s\n", node, ret, name, type);
224
225 if(strcmp(type, "display") == 0) break;
226 }
227
228 if(!node) return;
229
230 if(ofw_package_to_path(node, path, sizeof(path)) < 0) {
231 printf("could not get path for display package %x\n", node);
232 return;
233 }
234
235 printf("Opening display package: %s\n", path);
236 display_package = ofw_finddevice(path);
237 printf("display package %x\n", display_package);
238
239 BootInfo.dispDeviceRect[0] = BootInfo.dispDeviceRect[1] = 0;
240
241 ofw_getprop(display_package, "width",
242 (void *)&BootInfo.dispDeviceRect[2], sizeof(int));
243 ofw_getprop(display_package, "height",
244 (void *)&BootInfo.dispDeviceRect[3], sizeof(int));
245 ofw_getprop(display_package, "depth",
246 (void *)&BootInfo.dispDeviceDepth, sizeof(int));
247 ofw_getprop(display_package, "linebytes",
248 (void *)&BootInfo.dispDeviceRowBytes, sizeof(int));
249
250 BootInfo.dispDeviceRect[2] = BootInfo.dispDeviceRect[2];
251 BootInfo.dispDeviceRect[3] = BootInfo.dispDeviceRect[3];
252 BootInfo.dispDeviceDepth = BootInfo.dispDeviceDepth;
253 BootInfo.dispDeviceRowBytes = BootInfo.dispDeviceRowBytes;
254
255 if(ofw_getprop
256 (display_package,
257 "address",
258 (void *)&device_address,
259 sizeof(device_address)) < 1) {
260 printf("Could not get device base\n");
261 return;
262 }
263
264 BootInfo.dispDeviceBase = (PVOID)(device_address);
265
266 display_size = BootInfo.dispDeviceRowBytes * BootInfo.dispDeviceRect[3];
267
268 printf("Display size is %x bytes (%x per row times %x rows)\n",
269 display_size,
270 BootInfo.dispDeviceRowBytes,
271 BootInfo.dispDeviceRect[3]);
272
273 printf("display is at %x\n", BootInfo.dispDeviceBase);
274
275 for( i = 0; i < logo_y * logo_scale_y; i++ ) {
276 for( j = 0; j < logo_x * logo_scale_x; j++ ) {
277 elts = (j/logo_scale_x) + ((i/logo_scale_y) * logo_x);
278
279 for( k = 0; k < BootInfo.dispDeviceDepth/8; k++ ) {
280 SetPhysByte(((ULONG_PTR)BootInfo.dispDeviceBase)+
281 k +
282 ((j * (BootInfo.dispDeviceDepth/8)) +
283 (i * (BootInfo.dispDeviceRowBytes))),
284 logo[elts] == ' ' ? 0 : 255);
285 }
286 }
287 }
288 }
289
290 /*
291 * Get memory the proper openfirmware way
292 */
293 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
294 ULONG MaxMemoryMapSize ) {
295 int i, memhandle, returned, total = 0, slots = 0;
296 int memdata[0x40];
297
298 printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize);
299
300 memhandle = ofw_finddevice("/memory");
301
302 returned = ofw_getprop(memhandle, "available",
303 (char *)memdata, sizeof(memdata));
304
305 printf("Returned data: %d\n", returned);
306 if( returned == -1 ) {
307 printf("getprop /memory[@reg] failed\n");
308 return 0;
309 }
310
311 for( i = 0; i < returned; i++ ) {
312 printf("%x ", memdata[i]);
313 }
314 printf("\n");
315
316 for( i = 0; i < returned / 2; i++ ) {
317 BiosMemoryMap[slots].Type = 1/*MEMTYPE_USABLE*/;
318 BiosMemoryMap[slots].BaseAddress = memdata[i*2];
319 BiosMemoryMap[slots].Length = memdata[i*2+1];
320 printf("MemoryMap[%d] = (%x:%x)\n",
321 i,
322 (int)BiosMemoryMap[slots].BaseAddress,
323 (int)BiosMemoryMap[slots].Length);
324
325 /* Hack for pearpc */
326 if( kernel_mem ) {
327 BiosMemoryMap[slots].Length = kernel_mem * 1024;
328 if( !FixedMemory ) {
329 ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
330 (int)BiosMemoryMap[slots].Length,
331 0x1000);
332 FixedMemory = BiosMemoryMap[slots].BaseAddress;
333 }
334 total += BiosMemoryMap[slots].Length;
335 slots++;
336 break;
337 /* Normal way */
338 } else if( BiosMemoryMap[slots].Length &&
339 ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
340 (int)BiosMemoryMap[slots].Length,
341 0x1000) ) {
342 total += BiosMemoryMap[slots].Length;
343 slots++;
344 }
345 }
346
347 printf( "Returning memory map (%dk total)\n", total / 1024 );
348
349 return slots;
350 }
351
352 /* Strategy:
353 *
354 * For now, it'll be easy enough to use the boot command line as our boot path.
355 * Treat it as the path of a disk partition. We might even be able to get
356 * away with grabbing a partition image by tftp in this scenario.
357 */
358
359 BOOLEAN PpcDiskGetBootVolume( PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType ) {
360 *DriveNumber = 0;
361 *StartSector = 0;
362 *SectorCount = 0;
363 *FsType = FS_FAT;
364 return TRUE;
365 }
366
367 BOOLEAN PpcDiskGetSystemVolume( char *SystemPath,
368 char *RemainingPath,
369 PULONG Device,
370 PULONG DriveNumber,
371 PULONGLONG StartSector,
372 PULONGLONG SectorCount,
373 int *FsType ) {
374 char *remain = strchr(SystemPath, '\\');
375 if( remain ) {
376 strcpy( RemainingPath, remain+1 );
377 } else {
378 RemainingPath[0] = 0;
379 }
380 *Device = 0;
381 return MachDiskGetBootVolume(DriveNumber, StartSector, SectorCount, FsType);
382 }
383
384 BOOLEAN PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
385 strncpy( OutBootPath, BootPath, Size );
386 return TRUE;
387 }
388
389 VOID PpcDiskGetBootDevice( PULONG BootDevice ) {
390 BootDevice[0] = BootDevice[1] = 0;
391 }
392
393 BOOLEAN PpcDiskBootingFromFloppy(VOID) {
394 return FALSE;
395 }
396
397 BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
398 ULONG SectorCount, PVOID Buffer ) {
399 int rlen = 0;
400
401 if( part_handle == -1 ) {
402 part_handle = ofw_open( BootPart );
403
404 if( part_handle == -1 ) {
405 printf("Could not open any disk devices we know about\n");
406 return FALSE;
407 }
408 }
409
410 if( part_handle == -1 ) {
411 printf("Got partition handle %x\n", part_handle);
412 return FALSE;
413 }
414
415 if( ofw_seek( part_handle,
416 (ULONG)(SectorNumber >> 25),
417 (ULONG)((SectorNumber * 512) & 0xffffffff) ) ) {
418 printf("Seek to %x failed\n", (ULONG)(SectorNumber * 512));
419 return FALSE;
420 }
421
422 rlen = ofw_read( part_handle, Buffer, (ULONG)(SectorCount * 512) );
423 return rlen > 0;
424 }
425
426 BOOLEAN PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
427 PPARTITION_TABLE_ENTRY PartitionTableEntry ) {
428 printf("GetPartitionEntry(%d,%d)\n", DriveNumber, PartitionNumber);
429 return FALSE;
430 }
431
432 BOOLEAN PpcDiskGetDriveGeometry( ULONG DriveNumber, PGEOMETRY DriveGeometry ) {
433 printf("GetGeometry(%d)\n", DriveNumber);
434 DriveGeometry->BytesPerSector = 512;
435 DriveGeometry->Heads = 16;
436 DriveGeometry->Sectors = 63;
437 return TRUE;
438 }
439
440 ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
441 printf("GetCacheableBlockCount\n");
442 return 1;
443 }
444
445 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
446 PULONG Hour, PULONG Minute, PULONG Second ) {
447 //printf("RTCGeturrentDateTime\n");
448 }
449
450 VOID PpcHwDetect() {
451 printf("PpcHwDetect\n");
452 }
453
454 BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) {
455 CHAR BootPath[256];
456 ULONG PartitionNumber;
457 ULONG DriveNumber;
458 PARTITION_TABLE_ENTRY PartEntry;
459 char *p;
460
461 if (!DissectArcPath(SystemPath, BootPath, &DriveNumber, &PartitionNumber))
462 {
463 return FALSE;
464 }
465
466 if (0 != PartitionNumber)
467 {
468 return TRUE;
469 }
470
471 if (! DiskGetActivePartitionEntry(DriveNumber,
472 &PartEntry,
473 &PartitionNumber) ||
474 PartitionNumber < 1 || 9 < PartitionNumber)
475 {
476 return FALSE;
477 }
478
479 p = SystemPath;
480 while ('\0' != *p && 0 != _strnicmp(p, "partition(", 10)) {
481 p++;
482 }
483 p = strchr(p, ')');
484 if (NULL == p || '0' != *(p - 1)) {
485 return FALSE;
486 }
487 *(p - 1) = '0' + PartitionNumber;
488
489 return TRUE;
490 }
491
492 extern int _bss;
493 typedef unsigned int uint32_t;
494
495 void PpcOfwInit()
496 {
497 chosen_package = ofw_finddevice( "/chosen" );
498
499 ofw_getprop(chosen_package, "bootargs",
500 CmdLine, sizeof(CmdLine));
501 ofw_getprop( chosen_package, "stdin",
502 (char *)&stdin_handle, sizeof(stdin_handle) );
503 ofw_getprop( chosen_package, "stdout",
504 (char *)&stdout_handle, sizeof(stdout_handle) );
505 ofw_getprop( chosen_package, "mmu",
506 (char *)&mmu_handle, sizeof(mmu_handle) );
507
508 MachVtbl.ConsPutChar = PpcOfwPutChar;
509 MachVtbl.ConsKbHit = PpcConsKbHit;
510 MachVtbl.ConsGetCh = PpcConsGetCh;
511
512 printf( "chosen_package %x, stdin_handle is %x\n",
513 chosen_package, stdin_handle );
514 printf("virt2phys (0xe00000,D) -> %x\n", PpcVirt2phys(0xe00000,0));
515 printf("virt2phys (0xe01000,D) -> %x\n", PpcVirt2phys(0xe01000,0));
516
517 MachVtbl.VideoClearScreen = PpcVideoClearScreen;
518 MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
519 MachVtbl.VideoGetDisplaySize = PpcVideoGetDisplaySize;
520 MachVtbl.VideoGetBufferSize = PpcVideoGetBufferSize;
521 MachVtbl.VideoSetTextCursorPosition = PpcVideoSetTextCursorPosition;
522 MachVtbl.VideoHideShowTextCursor = PpcVideoHideShowTextCursor;
523 MachVtbl.VideoPutChar = PpcVideoPutChar;
524 MachVtbl.VideoCopyOffScreenBufferToVRAM =
525 PpcVideoCopyOffScreenBufferToVRAM;
526 MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
527 MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
528 MachVtbl.VideoGetPaletteColor = PpcVideoGetPaletteColor;
529 MachVtbl.VideoSync = PpcVideoSync;
530 MachVtbl.VideoPrepareForReactOS = PpcVideoPrepareForReactOS;
531
532 MachVtbl.GetMemoryMap = PpcGetMemoryMap;
533
534 MachVtbl.DiskNormalizeSystemPath = PpcDiskNormalizeSystemPath;
535 MachVtbl.DiskGetBootVolume = PpcDiskGetBootVolume;
536 MachVtbl.DiskGetSystemVolume = PpcDiskGetSystemVolume;
537 MachVtbl.DiskGetBootPath = PpcDiskGetBootPath;
538 MachVtbl.DiskGetBootDevice = PpcDiskGetBootDevice;
539 MachVtbl.DiskBootingFromFloppy = PpcDiskBootingFromFloppy;
540 MachVtbl.DiskReadLogicalSectors = PpcDiskReadLogicalSectors;
541 MachVtbl.DiskGetPartitionEntry = PpcDiskGetPartitionEntry;
542 MachVtbl.DiskGetDriveGeometry = PpcDiskGetDriveGeometry;
543 MachVtbl.DiskGetCacheableBlockCount = PpcDiskGetCacheableBlockCount;
544
545 MachVtbl.RTCGetCurrentDateTime = PpcRTCGetCurrentDateTime;
546
547 MachVtbl.HwDetect = PpcHwDetect;
548
549 // Allow forcing prep for broken OFW
550 if(!strncmp(CmdLine, "bootprep", 8))
551 {
552 printf("Going to PREP init...\n");
553 PpcPrepInit();
554 return;
555 }
556
557 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
558
559 BootMain( CmdLine );
560 }
561
562 void PpcInit( of_proxy the_ofproxy ) {
563 ofproxy = the_ofproxy;
564 if(ofproxy) PpcOfwInit();
565 else PpcPrepInit();
566 }
567
568 void MachInit(const char *CmdLine) {
569 int i, len;
570 char *sep;
571
572 BootPart[0] = 0;
573 BootPath[0] = 0;
574
575 printf( "Determining boot device: [%s]\n", CmdLine );
576
577 sep = NULL;
578 for( i = 0; i < strlen(CmdLine); i++ ) {
579 if( strncmp(CmdLine + i, "boot=", 5) == 0) {
580 strcpy(BootPart, CmdLine + i + 5);
581 sep = strchr(BootPart, ',');
582 if( sep )
583 *sep = 0;
584 while(CmdLine[i] && CmdLine[i]!=',') i++;
585 }
586 if( strncmp(CmdLine + i, "mem=", 4) == 0) {
587 kernel_mem = atoi(CmdLine+i+4);
588 printf("Allocate %dk kernel memory\n", kernel_mem);
589 while(CmdLine[i] && CmdLine[i]!=',') i++;
590 }
591 }
592
593 if( strlen(BootPart) == 0 ) {
594 len = ofw_getprop(chosen_package, "bootpath",
595 BootPath, sizeof(BootPath));
596
597 if( len < 0 ) len = 0;
598 BootPath[len] = 0;
599 printf( "Boot Path: %s\n", BootPath );
600
601 sep = strrchr(BootPath, ',');
602
603 strcpy(BootPart, BootPath);
604 if( sep ) {
605 BootPart[sep - BootPath] = 0;
606 }
607 }
608
609 printf( "FreeLDR starting (boot partition: %s)\n", BootPart );
610 }
611
612 /* Compatibility functions that don't do much */
613 void beep() {
614 }
615
616 UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address) {
617 return GetPhysByte(((ULONG)Address)+0x80000000);
618 }
619
620 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
621 SetPhysByte(((ULONG)Address)+0x80000000, Value);
622 }
623
624 void DiskStopFloppyMotor() {
625 }
626
627 void BootOldLinuxKernel( unsigned long size ) {
628 ofw_exit();
629 }
630
631 void BootNewLinuxKernel() {
632 ofw_exit();
633 }
634
635 void ChainLoadBiosBootSectorCode() {
636 ofw_exit();
637 }
638
639 void DbgBreakPoint() {
640 ofw_exit();
641 }