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