1e69278a5870cd1559428cd218d16b7808177a3d
[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 int mmu_initialized = 0;
291 int mem_range_end;
292 VOID PpcInitializeMmu(int max_mem)
293 {
294 if(!mmu_initialized)
295 {
296 MmuInit();
297 MmuDbgInit(0, 0x800003f8);
298 MmuSetMemorySize(mem_range_end > max_mem ? mem_range_end : max_mem);
299 //MmuDbgEnter(0x20);
300 mmu_initialized = 1;
301 }
302 }
303
304 ULONG PpcPrepGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
305 ULONG MaxMemoryMapSize );
306
307 /*
308 * Get memory the proper openfirmware way
309 */
310 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
311 ULONG MaxMemoryMapSize ) {
312 int i, memhandle, returned, total = 0, slots = 0;
313 int memdata[0x40];
314
315 printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize);
316
317 memhandle = ofw_finddevice("/memory");
318
319 returned = ofw_getprop(memhandle, "available",
320 (char *)memdata, sizeof(memdata));
321
322 printf("Returned data: %d\n", returned);
323 if( returned == -1 ) {
324 printf("getprop /memory[@reg] failed\n");
325 return PpcPrepGetMemoryMap( BiosMemoryMap, MaxMemoryMapSize );
326 }
327
328 for( i = 0; i < returned; i++ ) {
329 printf("%x ", memdata[i]);
330 }
331 printf("\n");
332
333 for( i = 0; i < returned / 2; i++ ) {
334 BiosMemoryMap[slots].Type = BiosMemoryUsable;
335 BiosMemoryMap[slots].BaseAddress = memdata[i*2];
336 BiosMemoryMap[slots].Length = memdata[i*2+1];
337 printf("MemoryMap[%d] = (%x:%x)\n",
338 i,
339 (int)BiosMemoryMap[slots].BaseAddress,
340 (int)BiosMemoryMap[slots].Length);
341
342 // Track end of ram
343 if (BiosMemoryMap[slots].BaseAddress + BiosMemoryMap[slots].Length >
344 mem_range_end)
345 {
346 mem_range_end =
347 BiosMemoryMap[slots].BaseAddress + BiosMemoryMap[slots].Length;
348 }
349
350 /* Hack for pearpc */
351 if( kernel_mem ) {
352 BiosMemoryMap[slots].Length = kernel_mem * 1024;
353 if( !FixedMemory ) {
354 ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
355 (int)BiosMemoryMap[slots].Length,
356 0x1000);
357 FixedMemory = BiosMemoryMap[slots].BaseAddress;
358 }
359 total += BiosMemoryMap[slots].Length;
360 slots++;
361 break;
362 /* Normal way */
363 } else if( BiosMemoryMap[slots].Length &&
364 ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
365 (int)BiosMemoryMap[slots].Length,
366 0x1000) ) {
367 total += BiosMemoryMap[slots].Length;
368 slots++;
369 }
370 }
371
372 printf( "Returning memory map (%dk total)\n", total / 1024 );
373
374 return slots;
375 }
376
377 /* Strategy:
378 *
379 * For now, it'll be easy enough to use the boot command line as our boot path.
380 * Treat it as the path of a disk partition. We might even be able to get
381 * away with grabbing a partition image by tftp in this scenario.
382 */
383
384 BOOLEAN PpcDiskGetBootVolume( PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType ) {
385 *DriveNumber = 0;
386 *StartSector = 0;
387 *SectorCount = 0;
388 *FsType = FS_FAT;
389 return TRUE;
390 }
391
392 BOOLEAN PpcDiskGetSystemVolume( char *SystemPath,
393 char *RemainingPath,
394 PULONG Device,
395 PULONG DriveNumber,
396 PULONGLONG StartSector,
397 PULONGLONG SectorCount,
398 int *FsType ) {
399 char *remain = strchr(SystemPath, '\\');
400 if( remain ) {
401 strcpy( RemainingPath, remain+1 );
402 } else {
403 RemainingPath[0] = 0;
404 }
405 *Device = 0;
406 // Hack to be a bit easier on ram
407 CacheSizeLimit = 64 * 1024;
408 return MachDiskGetBootVolume(DriveNumber, StartSector, SectorCount, FsType);
409 }
410
411 BOOLEAN PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
412 strncpy( OutBootPath, BootPath, Size );
413 return TRUE;
414 }
415
416 VOID PpcDiskGetBootDevice( PULONG BootDevice ) {
417 BootDevice[0] = BootDevice[1] = 0;
418 }
419
420 BOOLEAN PpcDiskBootingFromFloppy(VOID) {
421 return FALSE;
422 }
423
424 BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
425 ULONG SectorCount, PVOID Buffer ) {
426 int rlen = 0;
427
428 if( part_handle == -1 ) {
429 part_handle = ofw_open( BootPart );
430
431 if( part_handle == -1 ) {
432 printf("Could not open any disk devices we know about\n");
433 return FALSE;
434 }
435 }
436
437 if( part_handle == -1 ) {
438 printf("Got partition handle %x\n", part_handle);
439 return FALSE;
440 }
441
442 if( ofw_seek( part_handle,
443 (ULONG)(SectorNumber >> 25),
444 (ULONG)((SectorNumber * 512) & 0xffffffff) ) ) {
445 printf("Seek to %x failed\n", (ULONG)(SectorNumber * 512));
446 return FALSE;
447 }
448
449 rlen = ofw_read( part_handle, Buffer, (ULONG)(SectorCount * 512) );
450 return rlen > 0;
451 }
452
453 BOOLEAN PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
454 PPARTITION_TABLE_ENTRY PartitionTableEntry ) {
455 printf("GetPartitionEntry(%d,%d)\n", DriveNumber, PartitionNumber);
456 return FALSE;
457 }
458
459 BOOLEAN PpcDiskGetDriveGeometry( ULONG DriveNumber, PGEOMETRY DriveGeometry ) {
460 printf("GetGeometry(%d)\n", DriveNumber);
461 DriveGeometry->BytesPerSector = 512;
462 DriveGeometry->Heads = 16;
463 DriveGeometry->Sectors = 63;
464 return TRUE;
465 }
466
467 ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
468 printf("GetCacheableBlockCount\n");
469 return 1;
470 }
471
472 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
473 PULONG Hour, PULONG Minute, PULONG Second ) {
474 //printf("RTCGeturrentDateTime\n");
475 }
476
477 /* Recursively copy the device tree into our representation
478 * It'll be passed to HAL.
479 *
480 * When NT was first done on PPC, it was on PReP hardware, which is very
481 * like PC hardware (really, just a PPC on a PC motherboard). HAL can guess
482 * the addresses of needed resources in this scheme as it can on x86.
483 *
484 * Most PPC hardware doesn't assign fixed addresses to hardware, which is
485 * the problem that open firmware partially solves. It allows hardware makers
486 * much more leeway in building PPC systems. Unfortunately, because
487 * openfirmware as originally specified neither captures nor standardizes
488 * all possible information, and also because of bugs, most OSs use a hybrid
489 * configuration scheme that relies both on verification of devices and
490 * recording information from openfirmware to be treated as hints.
491 */
492 VOID OfwCopyDeviceTree(PPPC_DEVICE_TREE tree, int innode)
493 {
494 int proplen = 0, node = innode;
495 char *prev_name, cur_name[64], data[256], *slash;
496
497 /* Add properties */
498 for (prev_name = ""; ofw_nextprop(node, prev_name, cur_name) == 1; )
499 {
500 proplen = ofw_getproplen(node, cur_name);
501 if (proplen > 256 || proplen < 0)
502 {
503 printf("Warning: not getting prop %s (too long: %d)\n",
504 cur_name, proplen);
505 continue;
506 }
507 ofw_getprop(node, cur_name, data, sizeof(data));
508 PpcDevTreeAddProperty(tree, 0, cur_name, data, proplen);
509 strcpy(data, cur_name);
510 prev_name = data;
511 }
512
513 /* Subdevices */
514 for (node = ofw_child(node); node; node = ofw_peer(node))
515 {
516 ofw_package_to_path(node, data, sizeof(data));
517 slash = strrchr(data, '/');
518 if (slash) slash++; else continue;
519 PpcDevTreeAddDevice(tree, 0, slash);
520 OfwCopyDeviceTree(tree, node);
521 PpcDevTreeCloseDevice(tree);
522 }
523 }
524
525 VOID PpcHwDetect() {
526 PPC_DEVICE_TREE tree;
527 int node = ofw_finddevice("/");
528
529 /* Start the tree */
530 if(!PpcDevTreeInitialize
531 (&tree,
532 PAGE_SIZE, sizeof(long long),
533 (PPC_DEVICE_ALLOC)MmAllocateMemory,
534 (PPC_DEVICE_FREE)MmFreeMemory))
535 return;
536
537 OfwCopyDeviceTree(&tree,node);
538
539 PpcDevTreeCloseDevice(&tree);
540
541 BootInfo.machine = tree.head;
542 }
543
544 BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) {
545 CHAR BootPath[256];
546 ULONG PartitionNumber;
547 ULONG DriveNumber;
548 PARTITION_TABLE_ENTRY PartEntry;
549 char *p;
550
551 if (!DissectArcPath(SystemPath, BootPath, &DriveNumber, &PartitionNumber))
552 {
553 return FALSE;
554 }
555
556 if (0 != PartitionNumber)
557 {
558 return TRUE;
559 }
560
561 if (! DiskGetActivePartitionEntry(DriveNumber,
562 &PartEntry,
563 &PartitionNumber) ||
564 PartitionNumber < 1 || 9 < PartitionNumber)
565 {
566 return FALSE;
567 }
568
569 p = SystemPath;
570 while ('\0' != *p && 0 != _strnicmp(p, "partition(", 10)) {
571 p++;
572 }
573 p = strchr(p, ')');
574 if (NULL == p || '0' != *(p - 1)) {
575 return FALSE;
576 }
577 *(p - 1) = '0' + PartitionNumber;
578
579 return TRUE;
580 }
581
582 extern int _bss;
583 //typedef unsigned int uint32_t;
584
585 void PpcDefaultMachVtbl()
586 {
587 MachVtbl.ConsPutChar = PpcOfwPutChar;
588 MachVtbl.ConsKbHit = PpcConsKbHit;
589 MachVtbl.ConsGetCh = PpcConsGetCh;
590 MachVtbl.VideoClearScreen = PpcVideoClearScreen;
591 MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
592 MachVtbl.VideoGetDisplaySize = PpcVideoGetDisplaySize;
593 MachVtbl.VideoGetBufferSize = PpcVideoGetBufferSize;
594 MachVtbl.VideoSetTextCursorPosition = PpcVideoSetTextCursorPosition;
595 MachVtbl.VideoHideShowTextCursor = PpcVideoHideShowTextCursor;
596 MachVtbl.VideoPutChar = PpcVideoPutChar;
597 MachVtbl.VideoCopyOffScreenBufferToVRAM =
598 PpcVideoCopyOffScreenBufferToVRAM;
599 MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
600 MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
601 MachVtbl.VideoGetPaletteColor = PpcVideoGetPaletteColor;
602 MachVtbl.VideoSync = PpcVideoSync;
603 MachVtbl.VideoPrepareForReactOS = PpcVideoPrepareForReactOS;
604
605 MachVtbl.GetMemoryMap = PpcGetMemoryMap;
606
607 MachVtbl.DiskNormalizeSystemPath = PpcDiskNormalizeSystemPath;
608 MachVtbl.DiskGetBootVolume = PpcDiskGetBootVolume;
609 MachVtbl.DiskGetSystemVolume = PpcDiskGetSystemVolume;
610 MachVtbl.DiskGetBootPath = PpcDiskGetBootPath;
611 MachVtbl.DiskGetBootDevice = PpcDiskGetBootDevice;
612 MachVtbl.DiskBootingFromFloppy = PpcDiskBootingFromFloppy;
613 MachVtbl.DiskReadLogicalSectors = PpcDiskReadLogicalSectors;
614 MachVtbl.DiskGetPartitionEntry = PpcDiskGetPartitionEntry;
615 MachVtbl.DiskGetDriveGeometry = PpcDiskGetDriveGeometry;
616 MachVtbl.DiskGetCacheableBlockCount = PpcDiskGetCacheableBlockCount;
617
618 MachVtbl.RTCGetCurrentDateTime = PpcRTCGetCurrentDateTime;
619
620 MachVtbl.HwDetect = PpcHwDetect;
621 }
622
623 void PpcOfwInit()
624 {
625 chosen_package = ofw_finddevice( "/chosen" );
626
627 ofw_getprop(chosen_package, "bootargs",
628 CmdLine, sizeof(CmdLine));
629 ofw_getprop( chosen_package, "stdin",
630 (char *)&stdin_handle, sizeof(stdin_handle) );
631 ofw_getprop( chosen_package, "stdout",
632 (char *)&stdout_handle, sizeof(stdout_handle) );
633 ofw_getprop( chosen_package, "mmu",
634 (char *)&mmu_handle, sizeof(mmu_handle) );
635
636 // Allow forcing prep for broken OFW
637 if(!strncmp(CmdLine, "bootprep", 8))
638 {
639 printf("Going to PREP init...\n");
640 PpcPrepInit();
641 return;
642 }
643
644 printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
645
646 BootMain( CmdLine );
647 }
648
649 void PpcInit( of_proxy the_ofproxy ) {
650 ofproxy = the_ofproxy;
651 PpcDefaultMachVtbl();
652 if(ofproxy) PpcOfwInit();
653 else PpcPrepInit();
654 }
655
656 void MachInit(const char *CmdLine) {
657 int i, len;
658 char *sep;
659
660 BootPart[0] = 0;
661 BootPath[0] = 0;
662
663 printf( "Determining boot device: [%s]\n", CmdLine );
664
665 sep = NULL;
666 for( i = 0; i < strlen(CmdLine); i++ ) {
667 if( strncmp(CmdLine + i, "boot=", 5) == 0) {
668 strcpy(BootPart, CmdLine + i + 5);
669 sep = strchr(BootPart, ',');
670 if( sep )
671 *sep = 0;
672 while(CmdLine[i] && CmdLine[i]!=',') i++;
673 }
674 if( strncmp(CmdLine + i, "mem=", 4) == 0) {
675 kernel_mem = atoi(CmdLine+i+4);
676 printf("Allocate %dk kernel memory\n", kernel_mem);
677 while(CmdLine[i] && CmdLine[i]!=',') i++;
678 }
679 }
680
681 if( strlen(BootPart) == 0 ) {
682 if (ofproxy)
683 len = ofw_getprop(chosen_package, "bootpath",
684 BootPath, sizeof(BootPath));
685 else
686 len = 0;
687 if( len < 0 ) len = 0;
688 BootPath[len] = 0;
689 printf( "Boot Path: %s\n", BootPath );
690
691 sep = strrchr(BootPath, ',');
692
693 strcpy(BootPart, BootPath);
694 if( sep ) {
695 BootPart[sep - BootPath] = 0;
696 }
697 }
698
699 printf( "FreeLDR starting (boot partition: %s)\n", BootPart );
700 }
701
702 /* Compatibility functions that don't do much */
703 void beep() {
704 }
705
706 UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address) {
707 return GetPhysByte(((ULONG)Address)+0x80000000);
708 }
709
710 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
711 SetPhysByte(((ULONG)Address)+0x80000000, Value);
712 }
713
714 void DiskStopFloppyMotor() {
715 }
716
717 void BootOldLinuxKernel( unsigned long size ) {
718 ofw_exit();
719 }
720
721 void BootNewLinuxKernel() {
722 ofw_exit();
723 }
724
725 void ChainLoadBiosBootSectorCode() {
726 ofw_exit();
727 }
728
729 void DbgBreakPoint() {
730 __asm__("twi 31,0,0");
731 }