]>
git.saurik.com Git - apple/bootx.git/blob - bootx.tproj/sl.subproj/main.c
f4b8fae9ae396ce05f45cdce0986c86529ff74e2
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * main.c - Main functions for BootX.
28 * Copyright (c) 1998-2003 Apple Computer, Inc.
36 static void Start(void *unused1
, void *unused2
, ClientInterfacePtr ciPtr
);
37 static void Main(ClientInterfacePtr ciPtr
);
38 static long InitEverything(ClientInterfacePtr ciPtr
);
39 static long DecodeKernel(void);
40 static long SetUpBootArgs(void);
41 static long CallKernel(void);
42 static void FailToBoot(long num
);
43 static long InitMemoryMap(void);
44 static long GetOFVersion(void);
45 static long TestForKey(long key
);
46 static long GetBootPaths(void);
48 const unsigned long StartTVector
[2] = {(unsigned long)Start
, 0};
50 char gStackBaseAddr
[0x8000];
52 char *gVectorSaveAddr
;
53 long gImageLastKernelAddr
= 0;
54 long gImageFirstBootXAddr
= kLoadAddr
;
55 long gKernelEntryPoint
;
60 long gSymbolTableAddr
;
61 long gSymbolTableSize
;
63 long gBootSourceNumber
= -1;
64 long gBootSourceNumberMax
;
65 long gBootMode
= kBootModeNormal
;
68 char gBootDevice
[256];
74 long *gDeviceTreeMMTmp
= 0;
94 static char gOFVectorSave
[kVectorSize
];
95 static unsigned long gOFMSRSave
;
96 static unsigned long gOFSPRG0Save
;
97 static unsigned long gOFSPRG1Save
;
98 static unsigned long gOFSPRG2Save
;
99 static unsigned long gOFSPRG3Save
;
103 static void Start(void *unused1
, void *unused2
, ClientInterfacePtr ciPtr
)
107 // Move the Stack to a chunk of the BSS
108 newSP
= (long)gStackBaseAddr
+ sizeof(gStackBaseAddr
) - 0x100;
109 __asm__
volatile("mr r1, %0" : : "r" (newSP
));
115 static void Main(ClientInterfacePtr ciPtr
)
119 ret
= InitEverything(ciPtr
);
120 if (ret
!= 0) Exit();
122 // Get or infer the boot paths.
123 ret
= GetBootPaths();
124 if (ret
!= 0) FailToBoot(1);
129 ret
= LoadFile(gBootFile
);
130 if (ret
!= -1) break;
132 ret
= GetBootPaths();
133 if (ret
!= 0) FailToBoot(2);
136 ret
= DecodeKernel();
137 if (ret
!= 0) FailToBoot(3);
139 ret
= LoadDrivers(gRootDir
);
140 if (ret
!= 0) FailToBoot(4);
144 ret
= SetUpBootArgs();
145 if (ret
!= 0) FailToBoot(5);
153 static long InitEverything(ClientInterfacePtr ciPtr
)
155 long ret
, mem_base
, mem_base2
, size
;
157 char name
[32], securityMode
[33];
159 // Init the OF Client Interface.
161 if (ret
!= 0) return -1;
163 // Get the OF Version
164 gOFVersion
= GetOFVersion();
165 if (gOFVersion
== 0) return -1;
167 // Get the address and size cells for the root.
168 GetProp(Peer(0), "#address-cells", (char *)&gRootAddrCells
, 4);
169 GetProp(Peer(0), "#size-cells", (char *)&gRootSizeCells
, 4);
170 if ((gRootAddrCells
> 2) || (gRootAddrCells
> 2)) return -1;
172 // Init the SL Words package.
174 if (ret
!= 0) return -1;
176 // Get the phandle for /options
177 gOptionsPH
= FindDevice("/options");
178 if (gOptionsPH
== -1) return -1;
180 // Get the phandle for /chosen
181 gChosenPH
= FindDevice("/chosen");
182 if (gChosenPH
== -1) return -1;
184 // Init the Memory Map.
185 ret
= InitMemoryMap();
186 if (ret
!= 0) return -1;
188 // Get IHandles for the MMU and Memory
189 size
= GetProp(gChosenPH
, "mmu", (char *)&gMMUIH
, 4);
191 printf("Failed to get the IH for the MMU.\n");
194 size
= GetProp(gChosenPH
, "memory", (char *)&gMemoryIH
, 4);
196 printf("Failed to get the IH for the Memory.\n");
200 // Get stdout's IH, so that the boot display can be found.
201 ret
= GetProp(gChosenPH
, "stdout", (char *)&gStdOutIH
, 4);
202 if (ret
== 4) gStdOutPH
= InstanceToPackage(gStdOutIH
);
203 else gStdOutPH
= gStdOutIH
= 0;
205 // Try to find the keyboard using chosen
206 ret
= GetProp(gChosenPH
, "stdin", (char *)&gKeyboardIH
, 4);
207 if (ret
!= 4) gKeyboardIH
= 0;
209 keyboardPH
= InstanceToPackage(gKeyboardIH
);
210 ret
= GetProp(keyboardPH
, "name", name
, 31);
213 if (strcmp(name
, "keyboard") && strcmp(name
, "kbd")) gKeyboardIH
= 0;
214 } else gKeyboardIH
= 0;
217 // Try to the find the keyboard using open if chosen did not work.
218 if (gKeyboardIH
== 0) gKeyboardIH
= Open("keyboard");
219 if (gKeyboardIH
== 0) gKeyboardIH
= Open("kbd");
221 // Get the key map set up, and make it up to date.
222 gKeyMap
= InitKeyMap(gKeyboardIH
);
223 if (gKeyMap
== NULL
) return -1;
226 // Test for Secure Boot Mode.
227 size
= GetProp(gOptionsPH
, "security-mode", securityMode
, 32);
229 securityMode
[size
] = '\0';
230 if (strcmp(securityMode
, "none")) gBootMode
|= kBootModeSecure
;
234 // 'cmd-s' or 'cmd-v' is pressed set outputLevel to kOutputLevelFull
235 if (((gBootMode
& kBootModeSecure
) == 0) && TestForKey(kCommandKey
) &&
236 (TestForKey('s') || TestForKey('v'))) {
237 SetOutputLevel(kOutputLevelFull
);
239 SetOutputLevel(kOutputLevelOff
);
242 SetOutputLevel(kOutputLevelFull
);
246 printf("\n\nMac OS X Loader\n");
248 // Test for Safe Boot Mode.
249 if (((gBootMode
& kBootModeSecure
) == 0) && TestForKey(kShiftKey
)) {
250 gBootMode
|= kBootModeSafe
;
253 // Claim memory for the FS Cache.
254 if (Claim(kFSCacheAddr
, kFSCacheSize
, 0) == 0) {
255 printf("Claim for fs cache failed.\n");
259 // Claim memory for malloc.
260 if (Claim(kMallocAddr
, kMallocSize
, 0) == 0) {
261 printf("Claim for malloc failed.\n");
264 malloc_init((char *)kMallocAddr
, kMallocSize
);
266 // Claim memory for the Load Addr.
267 mem_base
= Claim(kLoadAddr
, kLoadSize
, 0);
269 printf("Claim for Load Area failed.\n");
273 // Claim the memory for the Image Addr
274 if (gOFVersion
>= kOFVersion3x
) {
275 mem_base
= Claim(kImageAddr
, kImageSize
, 0);
277 printf("Claim for Image Area failed.\n");
281 // Claim the 1:1 mapped chunks first.
282 mem_base
= Claim(kImageAddr0
, kImageSize0
, 0);
283 mem_base2
= Claim(kImageAddr2
, kImageSize2
, 0);
284 if ((mem_base
== 0) || (mem_base2
== 0)) {
285 printf("Claim for Image Area failed.\n");
289 // Unmap the old xcoff stack.
290 CallMethod(2, 0, gMMUIH
, "unmap", 0x00380000, 0x00080000);
292 // Grap the physical memory then the logical.
293 CallMethod(3, 1, gMemoryIH
, "claim",
294 kImageAddr1Phys
, kImageSize1
, 0, &mem_base
);
295 CallMethod(3, 1, gMMUIH
, "claim",
296 kImageAddr1
, kImageSize1
, 0, &mem_base2
);
297 if ((mem_base
== 0) || (mem_base2
== 0)) {
298 printf("Claim for Image Area failed.\n");
302 // Map them together.
303 CallMethod(4, 0, gMMUIH
, "map",
304 kImageAddr1Phys
, kImageAddr1
, kImageSize1
, 0);
307 bzero((char *)kImageAddr
, kImageSize
);
309 // Allocate some space for the Vector Save area.
310 gVectorSaveAddr
= AllocateBootXMemory(kVectorSize
);
311 if (gVectorSaveAddr
== 0) {
312 printf("Allocation for the Vector Save Area failed.\n");
316 // Find all the displays and set them up.
317 ret
= InitDisplays();
319 printf("InitDisplays failed.\n");
327 long ThinFatBinary(void **binary
, unsigned long *length
)
331 ret
= ThinFatBinaryMachO(binary
, length
);
332 if (ret
== -1) ret
= ThinFatBinaryElf(binary
, length
);
338 static long DecodeKernel(void)
340 void *binary
= (void *)kLoadAddr
;
343 ThinFatBinary(&binary
, 0);
345 ret
= DecodeMachO(binary
);
346 if (ret
== -1) ret
= DecodeElf(binary
);
352 static long SetUpBootArgs(void)
356 long graphicsBoot
= 1;
357 long ret
, cnt
, size
, dash
;
358 long sKey
, vKey
, keyPos
;
359 char ofBootArgs
[128], *ofArgs
, tc
, keyStr
[8];
360 unsigned char mem_regs
[kMaxDRAMBanks
*16];
361 unsigned long mem_banks
, bank_shift
;
363 // Save file system cache statistics.
364 SetProp(gChosenPH
, "BootXCacheHits", (char *)&gCacheHits
, 4);
365 SetProp(gChosenPH
, "BootXCacheMisses", (char *)&gCacheMisses
, 4);
366 SetProp(gChosenPH
, "BootXCacheEvicts", (char *)&gCacheEvicts
, 4);
368 // Allocate some memory for the BootArgs.
369 gBootArgsSize
= sizeof(boot_args
);
370 gBootArgsAddr
= AllocateKernelMemory(gBootArgsSize
);
372 // Add the BootArgs to the memory-map.
373 AllocateMemoryRange("BootArgs", gBootArgsAddr
, gBootArgsSize
);
375 args
= (boot_args_ptr
)gBootArgsAddr
;
377 args
->Revision
= kBootArgsRevision
;
378 args
->Version
= kBootArgsVersion1
;
379 args
->machineType
= 0;
381 // Check the Keyboard for 'cmd-s' and 'cmd-v'
383 if ((gBootMode
& kBootModeSecure
) == 0) {
384 sKey
= TestForKey(kCommandKey
) && TestForKey('s');
385 vKey
= TestForKey(kCommandKey
) && TestForKey('v');
391 // if 'cmd-s' or 'cmd-v' was pressed do a text boot.
392 if (sKey
|| vKey
) graphicsBoot
= 0;
394 // Create the command line.
395 if (gOFVersion
< kOFVersion3x
) {
397 size
= GetProp(gChosenPH
, "machargs", ofBootArgs
+ 1, 126);
399 size
= GetProp(gOptionsPH
, "boot-command", ofBootArgs
, 127);
400 if (size
== -1) ofBootArgs
[0] = '\0';
401 else ofBootArgs
[size
] = '\0';
402 // Look for " bootr" but skip the number.
403 if (!strncmp(ofBootArgs
+ 1, " bootr", 6)) {
404 strcpy(ofBootArgs
, ofBootArgs
+ 7);
405 } else ofBootArgs
[0] = '\0';
406 SetProp(gChosenPH
, "machargs", ofBootArgs
, strlen(ofBootArgs
) + 1);
407 } else ofBootArgs
[size
] = '\0';
408 // Force boot-command to start with 0 bootr.
409 sprintf(gTempStr
, "0 bootr%s", ofBootArgs
);
410 SetProp(gOptionsPH
, "boot-command", gTempStr
, strlen(gTempStr
));
412 size
= GetProp(gOptionsPH
, "boot-args", ofBootArgs
, 127);
413 if (size
== -1) ofBootArgs
[0] = '\0';
414 else ofBootArgs
[size
] = '\0';
417 if (ofBootArgs
[0] != '\0') {
418 // Look for special options and copy the rest.
421 while ((tc
= *ofArgs
) != '\0') {
424 // Check for entering a dash arg.
431 // Do special stuff if in a dash arg.
437 } else if (tc
== 'v') {
442 // Check for exiting dash arg
443 if (isspace(tc
)) dash
= 0;
445 // Copy any non 's' or 'v'
449 // Not a dash arg so just copy it.
455 // Add any pressed keys (s, v, shift) to the command line
457 if (sKey
|| vKey
|| (gBootMode
& kBootModeSafe
)) {
458 keyStr
[keyPos
++] = '-';
460 if (sKey
) keyStr
[keyPos
++] = 's';
461 if (vKey
) keyStr
[keyPos
++] = 'v';
462 if (gBootMode
& kBootModeSafe
) keyStr
[keyPos
++] = 'x';
464 keyStr
[keyPos
++] = ' ';
466 keyStr
[keyPos
++] = '\0';
468 sprintf(args
->CommandLine
, "%s%s", keyStr
, ofBootArgs
);
470 // If the address or size cells are larger than 1, use page numbers
471 // and signify Boot Args Version 2.
472 if ((gRootAddrCells
== 1) && (gRootSizeCells
== 1)) bank_shift
= 0;
475 args
->Version
= kBootArgsVersion2
;
478 // Get the information about the memory banks
479 memoryPH
= FindDevice("/memory");
480 if (memoryPH
== -1) return -1;
481 size
= GetProp(memoryPH
, "reg", mem_regs
, kMaxDRAMBanks
* 16);
482 if (size
== 0) return -1;
483 mem_banks
= size
/ (4 * (gRootAddrCells
+ gRootSizeCells
));
484 if (mem_banks
> kMaxDRAMBanks
) mem_banks
= kMaxDRAMBanks
;
486 // Convert the reg properties to 32 bit values
487 for (cnt
= 0; cnt
< mem_banks
; cnt
++) {
488 if (gRootAddrCells
== 1) {
489 args
->PhysicalDRAM
[cnt
].base
=
490 *(unsigned long *)(mem_regs
+ cnt
* 4 * (gRootAddrCells
+ gRootSizeCells
)) >> bank_shift
;
492 args
->PhysicalDRAM
[cnt
].base
=
493 *(unsigned long long *)(mem_regs
+ cnt
* 4 * (gRootAddrCells
+ gRootSizeCells
)) >> bank_shift
;
497 if (gRootSizeCells
== 1) {
498 args
->PhysicalDRAM
[cnt
].size
=
499 *(unsigned long *)(mem_regs
+ cnt
* 4 * (gRootAddrCells
+ gRootSizeCells
) + 4 * gRootAddrCells
) >> bank_shift
;
501 args
->PhysicalDRAM
[cnt
].size
=
502 *(unsigned long long *)(mem_regs
+ cnt
* 4 * (gRootAddrCells
+ gRootSizeCells
) + 4 * gRootAddrCells
) >> bank_shift
;
507 // Collapse the memory banks into contiguous chunks
508 for (cnt
= 0; cnt
< mem_banks
- 1; cnt
++) {
509 if ((args
->PhysicalDRAM
[cnt
+ 1].base
!= 0) &&
510 ((args
->PhysicalDRAM
[cnt
].base
+ args
->PhysicalDRAM
[cnt
].size
) !=
511 args
->PhysicalDRAM
[cnt
+ 1].base
)) continue;
513 args
->PhysicalDRAM
[cnt
].size
+= args
->PhysicalDRAM
[cnt
+ 1].size
;
514 bcopy(args
->PhysicalDRAM
+ cnt
+ 2, args
->PhysicalDRAM
+ cnt
+ 1, (mem_banks
- cnt
- 2) * sizeof(DRAMBank
));
518 bzero(args
->PhysicalDRAM
+ mem_banks
, (kMaxDRAMBanks
- mem_banks
) * sizeof(DRAMBank
));
520 // Get the video info
521 GetMainScreenPH(&args
->Video
);
522 args
->Video
.v_display
= graphicsBoot
;
524 // Add the DeviceTree to the memory-map.
525 // The actuall address and size must be filled in later.
526 AllocateMemoryRange("DeviceTree", 0, 0);
528 ret
= FlattenDeviceTree();
529 if (ret
!= 0) return -1;
531 // Fill in the address and size of the device tree.
532 if (gDeviceTreeAddr
) {
533 gDeviceTreeMMTmp
[0] = gDeviceTreeAddr
;
534 gDeviceTreeMMTmp
[1] = gDeviceTreeSize
;
537 args
->deviceTreeP
= (void *)gDeviceTreeAddr
;
538 args
->deviceTreeLength
= gDeviceTreeSize
;
539 args
->topOfKernelData
= AllocateKernelMemory(0);
545 static long CallKernel(void)
547 unsigned long msr
, cnt
;
551 printf("\nCall Kernel!\n");
554 __asm__
volatile("mfmsr %0" : "=r" (gOFMSRSave
));
555 __asm__
volatile("mfsprg %0, 0" : "=r" (gOFSPRG0Save
));
556 __asm__
volatile("mfsprg %0, 1" : "=r" (gOFSPRG1Save
));
557 __asm__
volatile("mfsprg %0, 2" : "=r" (gOFSPRG2Save
));
558 __asm__
volatile("mfsprg %0, 3" : "=r" (gOFSPRG3Save
));
560 // Turn off translations
562 __asm__
volatile("sync");
563 __asm__
volatile("mtmsr %0" : : "r" (msr
));
564 __asm__
volatile("isync");
566 // Save the OF's Exceptions Vectors
567 bcopy(0x0, gOFVectorSave
, kVectorSize
);
569 // Move the Exception Vectors
570 bcopy(gVectorSaveAddr
, 0x0, kVectorSize
);
571 for (cnt
= 0; cnt
< kVectorSize
; cnt
+= 0x20) {
572 __asm__
volatile("dcbf 0, %0" : : "r" (cnt
));
573 __asm__
volatile("icbi 0, %0" : : "r" (cnt
));
576 // Move the Image1 save area for OF 1.x / 2.x
577 if (gOFVersion
< kOFVersion3x
) {
578 bcopy((char *)kImageAddr1Phys
, (char *)kImageAddr1
, kImageSize1
);
579 for (cnt
= kImageAddr1
; cnt
< kImageSize1
; cnt
+= 0x20) {
580 __asm__
volatile("dcbf 0, %0" : : "r" (cnt
));
581 __asm__
volatile("icbi 0, %0" : : "r" (cnt
));
585 // Make sure everything get sync'd up.
586 __asm__
volatile("isync");
587 __asm__
volatile("sync");
588 __asm__
volatile("eieio");
590 // Call the Kernel's entry point
591 (*(void (*)())gKernelEntryPoint
)(gBootArgsAddr
, kMacOSXSignature
);
593 // Restore OF's Exception Vectors
594 bcopy(gOFVectorSave
, 0x0, 0x3000);
595 for (cnt
= 0; cnt
< kVectorSize
; cnt
+= 0x20) {
596 __asm__
volatile("dcbf 0, %0" : : "r" (cnt
));
597 __asm__
volatile("icbi 0, %0" : : "r" (cnt
));
600 // Restore SPRs for OF
601 __asm__
volatile("mtsprg 0, %0" : : "r" (gOFSPRG0Save
));
602 __asm__
volatile("mtsprg 1, %0" : : "r" (gOFSPRG1Save
));
603 __asm__
volatile("mtsprg 2, %0" : : "r" (gOFSPRG2Save
));
604 __asm__
volatile("mtsprg 3, %0" : : "r" (gOFSPRG3Save
));
606 // Restore translations
607 __asm__
volatile("sync");
608 __asm__
volatile("mtmsr %0" : : "r" (gOFMSRSave
));
609 __asm__
volatile("isync");
615 static void FailToBoot(long num
)
618 DrawFailedBootPicture();
622 printf("FailToBoot: %d\n", num
);
623 Enter(); // For debugging
628 static long InitMemoryMap(void)
632 result
= Interpret(0, 1,
635 " \" memory-map\" device-name"
644 static long GetOFVersion(void)
647 char versStr
[256], *tmpStr
;
650 // Get the openprom package
651 ph
= FindDevice("/openprom");
652 if (ph
== -1) return 0;
654 // Get it's model property
655 size
= GetProp(ph
, "model", versStr
, 255);
656 if (size
== -1) return -1;
657 versStr
[size
] = '\0';
659 // Find the start of the number.
661 if (!strncmp(versStr
, "Open Firmware, ", 15)) {
662 tmpStr
= versStr
+ 15;
663 } else if (!strncmp(versStr
, "OpenFirmware ", 13)) {
664 tmpStr
= versStr
+ 13;
667 // Clasify by each instance as needed...
694 static long TestForKey(long key
)
700 if (gOFVersion
< kOFVersion3x
) {
702 case 'a' : keyNum
= 7; break;
703 case 's' : keyNum
= 6; break;
704 case 'v' : keyNum
= 14; break;
705 case 'y' : keyNum
= 23; break;
706 case kCommandKey
: keyNum
= 48; break;
707 case kOptKey
: keyNum
= 61; break;
708 case kShiftKey
: keyNum
= 63; break;
709 case kControlKey
: keyNum
= 49; break;
710 default : keyNum
= -1; break;
714 case 'a' : keyNum
= 3; break;
715 case 's' : keyNum
= 17; break;
716 case 'v' : keyNum
= 30; break;
717 case 'y' : keyNum
= 27; break;
718 case kCommandKey
: keyNum
= 228; break;
719 case kOptKey
: keyNum
= 229; break;
720 case kShiftKey
: keyNum
= 230; break;
721 case kControlKey
: keyNum
= 231; break;
722 default : keyNum
= -1; break;
725 // Map the right modifier keys on to the left.
726 gKeyMap
[28] |= gKeyMap
[28] << 4;
729 if (keyNum
== -1) return 0;
732 tc
= gKeyMap
[keyNum
>> 3];
734 return (tc
& (1 << bp
)) != 0;
738 #define kBootpBootFileOffset (108)
740 static long GetBootPaths(void)
742 long ret
, cnt
, cnt2
, cnt3
, cnt4
, size
, partNum
, bootplen
, bsdplen
;
743 char *filePath
, *buffer
;
745 if (gBootSourceNumber
== -1) {
746 // Get the boot-device
747 size
= GetProp(gChosenPH
, "bootpath", gBootDevice
, 255);
748 gBootDevice
[size
] = '\0';
749 if (gBootDevice
[0] == '\0') {
750 size
= GetProp(gOptionsPH
, "boot-device", gBootDevice
, 255);
751 gBootDevice
[size
] = '\0';
753 gBootDeviceType
= GetDeviceType(gBootDevice
);
756 size
= GetProp(gChosenPH
, "bootargs", gBootFile
, 256);
757 gBootFile
[size
] = '\0';
759 if (gBootFile
[0] != '\0') {
760 gBootFileType
= GetDeviceType(gBootFile
);
761 gBootSourceNumberMax
= 0;
763 gBootSourceNumber
= 0;
764 gBootFileType
= gBootDeviceType
;
765 if (gBootFileType
== kNetworkDeviceType
) gBootSourceNumberMax
= 1;
767 if (gOFVersion
< kOFVersion3x
) {
768 gBootSourceNumberMax
= 4;
770 gBootSourceNumberMax
= 6;
775 if (gBootFileType
== kNetworkDeviceType
) {
776 SetProp(Peer(0), "net-boot", NULL
, 0);
780 if (gBootSourceNumber
>= gBootSourceNumberMax
) return -1;
782 if (gBootSourceNumberMax
!= 0) {
783 switch (gBootFileType
) {
784 case kNetworkDeviceType
:
785 // Find the end of the device spec.
787 while (gBootDevice
[cnt
] != ':') cnt
++;
789 // Copy the device spec with the ':'.
790 strncpy(gBootFile
, gBootDevice
, cnt
+ 1);
792 // Check for bootp-responce or bsdp-responce.
793 bootplen
= GetPropLen(gChosenPH
, "bootp-response");
794 bsdplen
= GetPropLen(gChosenPH
, "bsdp-response");
795 if ((bootplen
> 0) || (bsdplen
> 0)) {
797 buffer
= malloc(bootplen
);
798 GetProp(gChosenPH
, "bootp-response", buffer
, bootplen
);
800 buffer
= malloc(bsdplen
);
801 GetProp(gChosenPH
, "bsdp-response", buffer
, bsdplen
);
804 // Flip the slash's to back slash's while looking for the last one.
805 cnt
= cnt2
= kBootpBootFileOffset
;
806 while (buffer
[cnt
] != '\0') {
807 if (buffer
[cnt
] == '/') {
814 // Add a comma at the front.
815 buffer
[kBootpBootFileOffset
- 1] = ',';
817 // Append the the root dir to the device spec.
818 strncat(gBootFile
, buffer
+ kBootpBootFileOffset
- 1,
819 cnt2
- kBootpBootFileOffset
+ 1);
823 // Look for the start of the root dir path.
825 while (gBootDevice
[cnt3
] != ',') cnt3
++;
827 // Find the end of the path. Look for a comma or null.
829 while ((gBootDevice
[cnt2
] != '\0') && (gBootDevice
[cnt2
] != ',')) cnt2
++;
831 // Find the last back slash or comma in the path
833 while ((gBootDevice
[cnt4
] != ',') && (gBootDevice
[cnt4
] != '\\')) cnt4
--;
835 // Copy the IP addresses if needed.
836 if (gOFVersion
< kOFVersion3x
) {
837 strncat(gBootFile
, gBootDevice
+ cnt
+ 1, cnt3
- cnt
- 1);
840 // Add on the directory path
841 strncat(gBootFile
, gBootDevice
+ cnt3
, cnt4
- cnt3
+ 1);
844 // Add on the kernel name
845 strcat(gBootFile
, "mach.macosx");
848 strcat(gBootFile
, gBootDevice
+ cnt2
);
851 case kBlockDeviceType
:
852 // Find the first ':'.
854 while ((gBootDevice
[cnt
] != '\0') && (gBootDevice
[cnt
] != ':')) cnt
++;
855 if (gBootDevice
[cnt
] == '\0') return -1;
857 // Find the comma after the ':'.
859 while ((gBootDevice
[cnt2
] != '\0') && (gBootDevice
[cnt
] != ',')) cnt2
++;
861 // Get just the partition number
862 strncpy(gBootFile
, gBootDevice
+ cnt
+ 1, cnt2
- cnt
- 1);
863 partNum
= atoi(gBootFile
);
865 // Adjust the partition number.
866 // Pass 0 & 1, no offset. Pass 2 & 3, offset 1, Pass 4 & 5, offset 2.
867 partNum
+= gBootSourceNumber
/ 2;
869 // Construct the boot-file
870 strncpy(gBootFile
, gBootDevice
, cnt
+ 1);
871 sprintf(gBootFile
+ cnt
+ 1, "%d,%s\\mach_kernel",
872 partNum
, ((gBootSourceNumber
& 1) ? "" : "\\"));
876 printf("Failed to infer Boot Device Type.\n");
882 // Figure out the root dir.
883 ret
= ConvertFileSpec(gBootFile
, gRootDir
, &filePath
);
884 if (ret
== -1) return -1;
886 strcat(gRootDir
, ",");
888 // Add in any extra path to gRootDir.
890 while (filePath
[cnt
] != '\0') cnt
++;
893 for (cnt2
= cnt
- 1; cnt2
>= 0; cnt2
--) {
894 if (filePath
[cnt2
] == '\\') {
895 strncat(gRootDir
, filePath
, cnt2
+ 1);
901 SetProp(gChosenPH
, "rootpath", gBootFile
, strlen(gBootFile
) + 1);
910 long GetDeviceType(char *devSpec
)
916 ph
= FindDevice(devSpec
);
917 if (ph
== -1) return -1;
919 size
= GetProp(ph
, "device_type", deviceType
, 31);
920 if (size
!= -1) deviceType
[size
] = '\0';
921 else deviceType
[0] = '\0';
923 if (strcmp(deviceType
, "network") == 0) return kNetworkDeviceType
;
924 if (strcmp(deviceType
, "block") == 0) return kBlockDeviceType
;
926 return kUnknownDeviceType
;
930 long ConvertFileSpec(char *fileSpec
, char *devSpec
, char **filePath
)
934 // Find the first ':' in the fileSpec.
936 while ((fileSpec
[cnt
] != '\0') && (fileSpec
[cnt
] != ':')) cnt
++;
937 if (fileSpec
[cnt
] == '\0') return -1;
939 // Find the next ',' in the fileSpec.
940 while ((fileSpec
[cnt
] != '\0') && (fileSpec
[cnt
] != ',')) cnt
++;
942 // Copy the string to devSpec.
943 strncpy(devSpec
, fileSpec
, cnt
);
946 // If there is a filePath start it after the ',', otherwise NULL.
947 if (filePath
!= NULL
) {
948 if (fileSpec
[cnt
] != '\0') {
949 *filePath
= fileSpec
+ cnt
+ 1;
959 long MatchThis(CICell phandle
, char *string
)
962 char *name
, *model
, *compatible
;
964 ret
= GetPackageProperty(phandle
, "name", &name
, &length
);
965 if ((ret
== -1) || (length
== 0)) name
= NULL
;
967 ret
= GetPackageProperty(phandle
, "model", &model
, &length
);
968 if ((ret
== -1) || (length
== 0)) model
= NULL
;
970 ret
= GetPackageProperty(phandle
, "compatible", &compatible
, &length
);
971 if ((ret
== -1) || (length
== 0)) model
= NULL
;
973 if ((name
!= NULL
) && strcmp(name
, string
) == 0) return 0;
974 if ((model
!= NULL
) && strcmp(model
, string
) == 0) return 0;
976 if (compatible
!= NULL
) {
977 while (*compatible
!= '\0') {
978 if (strcmp(compatible
, string
) == 0) return 0;
980 compatible
+= strlen(compatible
) + 1;
988 void *AllocateBootXMemory(long size
)
990 long addr
= gImageFirstBootXAddr
- size
;
992 if (addr
< gImageLastKernelAddr
) return 0;
994 gImageFirstBootXAddr
= addr
;
1000 long AllocateKernelMemory(long size
)
1002 long addr
= gImageLastKernelAddr
;
1004 gImageLastKernelAddr
+= (size
+ 0xFFF) & ~0xFFF;
1006 if (gImageLastKernelAddr
> gImageFirstBootXAddr
)
1013 long AllocateMemoryRange(char *rangeName
, long start
, long length
)
1015 long result
, *buffer
;
1017 buffer
= AllocateBootXMemory(2 * sizeof(long));
1018 if (buffer
== 0) return -1;
1023 result
= SetProp(gMemoryMapPH
, rangeName
, (char *)buffer
, 2 * sizeof(long));
1024 if (result
== -1) return -1;
1030 unsigned long Alder32(unsigned char *buffer
, long length
)
1033 unsigned long result
, lowHalf
, highHalf
;
1038 for (cnt
= 0; cnt
< length
; cnt
++) {
1039 if ((cnt
% 5000) == 0) {
1044 lowHalf
+= buffer
[cnt
];
1045 highHalf
+= lowHalf
;
1051 result
= (highHalf
<< 16) | lowHalf
;