]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/sl.subproj/main.c
BootX-36.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / main.c
CommitLineData
04fee52e
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * main.c - Main functions for BootX.
24 *
25 * Copyright (c) 1998-2000 Apple Computer, Inc.
26 *
27 * DRI: Josh de Cesare
28 */
29
30
31#include <sl.h>
32
33static void Start(void *unused1, void *unused2, ClientInterfacePtr ciPtr);
34static void Main(ClientInterfacePtr ciPtr);
35static long InitEverything(ClientInterfacePtr ciPtr);
36static long DecodeKernel(void);
37static long SetUpBootArgs(void);
38static long CallKernel(void);
39static void FailToBoot(long num);
40static long InitMemoryMap(void);
41static long GetOFVersion(void);
42static long TestForKey(long key);
43static long GetBootPaths(void);
44
45const unsigned long StartTVector[2] = {(unsigned long)Start, 0};
46
47char gStackBaseAddr[0x8000];
48
49char *gVectorSaveAddr;
50long gImageLastKernelAddr = 0;
51long gImageFirstBootXAddr = kLoadAddr;
52long gKernelEntryPoint;
53long gDeviceTreeAddr;
54long gDeviceTreeSize;
55long gBootArgsAddr;
56long gBootArgsSize;
57long gSymbolTableAddr;
58long gSymbolTableSize;
59
60long gBootSourceNumber = -1;
61long gBootSourceNumberMax;
62long gBootDeviceType;
63long gBootFileType;
64char gBootDevice[256];
65char gBootFile[256];
66char gRootDir[256];
67
68char gTempStr[4096];
69
70long *gDeviceTreeMMTmp = 0;
71
72long gOFVersion;
73
74char *gKeyMap;
75
76CICell gChosenPH;
77CICell gOptionsPH;
78CICell gScreenPH;
79CICell gMemoryMapPH;
80CICell gStdOutPH;
81
82CICell gMMUIH;
83CICell gMemoryIH;
84CICell gStdOutIH;
85CICell gKeyboardIH;
86
87// Private Functions
88
89static void Start(void *unused1, void *unused2, ClientInterfacePtr ciPtr)
90{
91 long newSP;
92
93 // Move the Stack to a chunk of the BSS
94 newSP = (long)gStackBaseAddr + sizeof(gStackBaseAddr) - 0x100;
95 __asm__ volatile("mr r1, %0" : : "r" (newSP));
96
97 Main(ciPtr);
98}
99
100
101static void Main(ClientInterfacePtr ciPtr)
102{
103 long ret;
104
105 ret = InitEverything(ciPtr);
106 if (ret != 0) Exit();
107
108 // Get or infer the boot paths.
109 ret = GetBootPaths();
110 if (ret != 0) FailToBoot(1);
111
112 DrawSplashScreen();
113
114 while (ret == 0) {
115 ret = LoadFile(gBootFile);
116 if (ret != -1) break;
117
118 ret = GetBootPaths();
119 if (ret != 0) FailToBoot(2);
120 }
121
122 ret = DecodeKernel();
123 if (ret != 0) FailToBoot(4);
124
125 ret = LoadDrivers(gRootDir);
126 if (ret != 0) FailToBoot(5);
127
128#if 0
129 ret = LoadDisplayDrivers();
130 if (ret != 0) FailToBoot(6);
131#endif
132
133 ret = SetUpBootArgs();
134 if (ret != 0) FailToBoot(7);
135
136 ret = CallKernel();
137
138 FailToBoot(8);
139}
140
141
142static long InitEverything(ClientInterfacePtr ciPtr)
143{
144 long ret, mem_base, mem_base2, size;
145 CICell keyboardPH;
146 char name[32];
147#if 0
148 char defaultBootDevice[256];
149#endif
150
151 // Init the OF Client Interface.
152 ret = InitCI(ciPtr);
153 if (ret != 0) return -1;
154
155 // Get the OF Version
156 gOFVersion = GetOFVersion();
157 if (gOFVersion == 0) return -1;
158
159 // Init the SL Words package.
160 ret = InitSLWords(gOFVersion);
161 if (ret != 0) return -1;
162
163 // Get the phandle for /options
164 gOptionsPH = FindDevice("/options");
165 if (gOptionsPH == -1) return -1;
166
167 // Get the phandle for /chosen
168 gChosenPH = FindDevice("/chosen");
169 if (gChosenPH == -1) return -1;
170
171 // Init the Memory Map.
172 ret = InitMemoryMap();
173 if (ret != 0) return -1;
174
175 // Get IHandles for the MMU and Memory
176 size = GetProp(gChosenPH, "mmu", (char *)&gMMUIH, 4);
177 if (size != 4) {
178 printf("Failed to get the IH for the MMU.\n");
179 return -1;
180 }
181 size = GetProp(gChosenPH, "memory", (char *)&gMemoryIH, 4);
182 if (size != 4) {
183 printf("Failed to get the IH for the Memory.\n");
184 return -1;
185 }
186
187 // Get stdout's IH, so that the boot display can be found.
188 ret = GetProp(gChosenPH, "stdout", (char *)&gStdOutIH, 4);
189 if (ret == 4) gStdOutPH = InstanceToPackage(gStdOutIH);
190 else gStdOutPH = gStdOutIH = 0;
191
192 // Try to find the keyboard using chosen
193 ret = GetProp(gChosenPH, "stdin", (char *)&gKeyboardIH, 4);
194 if (ret != 4) gKeyboardIH = 0;
195 else {
196 keyboardPH = InstanceToPackage(gKeyboardIH);
197 ret = GetProp(keyboardPH, "name", name, 31);
198 if (ret != -1) {
199 name[ret] = '\0';
200 if (strcmp(name, "keyboard") && strcmp(name, "kbd")) gKeyboardIH = 0;
201 } else gKeyboardIH = 0;
202 }
203
204 // Try to the find the keyboard using open if chosen did not work.
205 if (gKeyboardIH == 0) gKeyboardIH = Open("keyboard");
206 if (gKeyboardIH == 0) gKeyboardIH = Open("kbd");
207
208 // Get the key map set up, and make it up to date.
209 gKeyMap = InitKeyMap(gKeyboardIH);
210 if (gKeyMap == NULL) return -1;
211 UpdateKeyMap();
212
213#if 0
214 // On OF 3.x, if the Option key was pressed,
215 // set the default boot device and reboot.
216 if (gOFVersion >= kOFVersion3x) {
217 if (TestForKey(kOptKey)) {
218 size = GetProp(gOptionsPH, "default-boot-device", defaultBootDevice,255);
219 if (size == -1) {
220 Interpret_0_0("set-default boot-device");
221 } else {
222 defaultBootDevice[size] = '\0';
223 SetProp(gOptionsPH, "boot-device", defaultBootDevice, size);
224 SetProp(gOptionsPH, "boot-file", 0, 0);
225 }
226 Interpret_0_0("reset-all");
227 }
228 }
229#endif
230
231#if kFailToBoot
232 // 'cmd-s' or 'cmd-v' is pressed set outputLevel to kOutputLevelFull
233 if (TestForKey(kCommandKey) && (TestForKey('s') || TestForKey('v')))
234 SetOutputLevel(kOutputLevelFull);
235 else SetOutputLevel(kOutputLevelOff);
236#else
237 SetOutputLevel(kOutputLevelFull);
238#endif
239
240 // printf now works.
241 printf("\n\nMac OS X Loader\n");
242
243 mem_base = Claim(kMallocAddr, kMallocSize, 0);
244 if (mem_base == 0) {
245 printf("Claim for malloc failed.\n");
246 return -1;
247 }
248 malloc_init((char *)mem_base, kMallocSize);
249
250 // malloc now works.
251
252 // Claim the memory for the Load Addr
253 mem_base = Claim(kLoadAddr, kLoadSize, 0);
254 if (mem_base == 0) {
255 printf("Claim for Load Area failed.\n");
256 return -1;
257 }
258
259 // Claim the memory for the Image Addr
260 if (gOFVersion >= kOFVersion3x) {
261 mem_base = Claim(kImageAddr, kImageSize, 0);
262 if (mem_base == 0) {
263 printf("Claim for Image Area failed.\n");
264 return -1;
265 }
266 } else {
267 // Claim the 1:1 mapped chunks first.
268 mem_base = Claim(kImageAddr0, kImageSize0, 0);
269 mem_base2 = Claim(kImageAddr2, kImageSize2, 0);
270 if ((mem_base == 0) || (mem_base2 == 0)) {
271 printf("Claim for Image Area failed.\n");
272 return -1;
273 }
274
275 // Unmap the old xcoff stack.
276 CallMethod_2_0(gMMUIH, "unmap", 0x00380000, 0x00080000);
277
278 // Grap the physical memory then the logical.
279 CallMethod_3_1(gMemoryIH, "claim",
280 kImageAddr1Phys, kImageSize1, 0, &mem_base);
281 CallMethod_3_1(gMMUIH, "claim",
282 kImageAddr1, kImageSize1, 0, &mem_base2);
283 if ((mem_base == 0) || (mem_base2 == 0)) {
284 printf("Claim for Image Area failed.\n");
285 return -1;
286 }
287
288 // Map them together.
289 CallMethod_4_0(gMMUIH, "map",
290 kImageAddr1Phys, kImageAddr1, kImageSize1, 0);
291 }
292
293 bzero((char *)kImageAddr, kImageSize);
294
295 // Malloc some space for the Vector Save area.
296 gVectorSaveAddr = malloc(kVectorSize);
297 if (gVectorSaveAddr == 0) {
298 printf("Malloc for Vector Save Area failed.\n");
299 return -1;
300 }
301
302 // Find all the displays and set them up.
303 ret = InitDisplays();
304 if (ret != 0) {
305 printf("InitDisplays failed.\n");
306 return -1;
307 }
308
309 return 0;
310}
311
312
313static long DecodeKernel(void)
314{
315 long ret;
316
317 ret = DecodeMachO();
318 if (ret == -1) ret = DecodeElf();
319
320 return ret;
321}
322
323
324static long SetUpBootArgs(void)
325{
326 boot_args_ptr args;
327 CICell memoryPH;
328 long secure = 0, sym = 0, graphicsBoot = 1;
329 long ret, cnt, mem_size, size, dash;
330 long aKey, sKey, vKey, yKey, shiftKey, keyPos;
331 char ofBootArgs[128], *ofArgs, tc, keyStr[8], securityMode[33];
332
333 // Save file system cache statistics.
334 SetProp(gChosenPH, "BootXCacheHits", (char *)&gCacheHits, 4);
335 SetProp(gChosenPH, "BootXCacheMisses", (char *)&gCacheMisses, 4);
336 SetProp(gChosenPH, "BootXCacheEvicts", (char *)&gCacheEvicts, 4);
337
338 // Allocate some memory for the BootArgs.
339 gBootArgsSize = sizeof(boot_args);
340 gBootArgsAddr = AllocateKernelMemory(gBootArgsSize);
341
342 // Add the BootArgs to the memory-map.
343 AllocateMemoryRange("BootArgs", gBootArgsAddr, gBootArgsSize);
344
345 args = (boot_args_ptr)gBootArgsAddr;
346
347 args->Revision = kBootArgsRevision;
348 args->Version = kBootArgsVersion;
349 args->machineType = 0;
350
351 // Get the security-mode.
352 size = GetProp(gOptionsPH, "security-mode", securityMode, 32);
353 if (size != -1) {
354 securityMode[size] = '\0';
355 if (strcmp(securityMode, "none")) secure = 1;
356 }
357
358 // Check the Keyboard for 'a', 'cmd-s', 'cmd-v', 'y' and shift
359 UpdateKeyMap();
360 if (!secure) {
361 aKey = TestForKey('a');
362 sKey = TestForKey(kCommandKey) && TestForKey('s');
363 vKey = TestForKey(kCommandKey) && TestForKey('v');
364 yKey = TestForKey('y');
365 } else {
366 aKey = 0;
367 sKey = 0;
368 vKey = 0;
369 yKey = 0;
370 }
371 shiftKey = TestForKey(kShiftKey);
372
373 // if 'cmd-s' or 'cmd-v' was pressed do a text boot.
374 if (sKey || vKey) graphicsBoot = 0;
375
376 // if 'y' key was pressed send the symbols;
377 if (yKey) sym = 1;
378
379 // Create the command line.
380 if (gOFVersion < kOFVersion3x) {
381 ofBootArgs[0] = ' ';
382 size = GetProp(gChosenPH, "machargs", ofBootArgs + 1, 126);
383 if (size == -1) {
384 size = GetProp(gOptionsPH, "boot-command", ofBootArgs, 127);
385 if (size == -1) ofBootArgs[0] = '\0';
386 else ofBootArgs[size] = '\0';
387 // Look for " bootr" but skip the number.
388 if (!strncmp(ofBootArgs + 1, " bootr", 6)) {
389 strcpy(ofBootArgs, ofBootArgs + 7);
390 } else ofBootArgs[0] = '\0';
391 SetProp(gChosenPH, "machargs", ofBootArgs, strlen(ofBootArgs) + 1);
392 } else ofBootArgs[size] = '\0';
393 // Force boot-command to start with 0 bootr.
394 sprintf(gTempStr, "0 bootr%s", ofBootArgs);
395 SetProp(gOptionsPH, "boot-command", gTempStr, strlen(gTempStr));
396 } else {
397 size = GetProp(gOptionsPH, "boot-args", ofBootArgs, 127);
398 if (size == -1) ofBootArgs[0] = '\0';
399 else ofBootArgs[size] = '\0';
400 }
401
402 if (ofBootArgs[0] != '\0') {
403 // Look for special options and copy the rest.
404 dash = 0;
405 ofArgs = ofBootArgs;
406 while ((tc = *ofArgs) != '\0') {
407 tc = tolower(tc);
408
409 // Check for entering a dash arg.
410 if (tc == '-') {
411 dash = 1;
412 ofArgs++;
413 continue;
414 }
415
416 // Do special stuff if in a dash arg.
417 if (dash) {
418 if (tc == 'a') {
419 ofArgs++;
420 aKey = 0;
421 }
422 else if (tc == 's') {
423 graphicsBoot = 0;
424 ofArgs++;
425 sKey = 0;
426 }
427 else if (tc == 'v') {
428 graphicsBoot = 0;
429 ofArgs++;
430 vKey = 0;
431 }
432 else if (tc == 'x') {
433 ofArgs++;
434 shiftKey = 0;
435 }
436 else if (tc == 'y') {
437 sym = 1;
438 ofArgs++;
439 yKey = 0;
440 }
441 else {
442 // Check for exiting dash arg
443 if (isspace(tc)) dash = 0;
444
445 // Copy any non 'a', 's', 'v', 'x' or 'y'
446 ofArgs++;
447 }
448 } else {
449 // Not a dash arg so just copy it.
450 ofArgs++;
451 }
452 }
453 }
454
455 // Add any pressed keys (a, s, v, y, shift) to the command line
456 keyPos = 0;
457 if (aKey || sKey || vKey || yKey || shiftKey) {
458 keyStr[keyPos++] = '-';
459
460 if (aKey) keyStr[keyPos++] = 'a';
461 if (sKey) keyStr[keyPos++] = 's';
462 if (vKey) keyStr[keyPos++] = 'v';
463 if (yKey) keyStr[keyPos++] = 'y';
464 if (shiftKey) keyStr[keyPos++] = 'x';
465
466 keyStr[keyPos++] = ' ';
467 }
468 keyStr[keyPos++] = '\0';
469
470 // Send symbols?
471 if (!sym && !yKey) gSymbolTableAddr = 0;
472
473 sprintf(args->CommandLine, "%s%s symtab=%d",
474 keyStr, ofBootArgs, gSymbolTableAddr);
475
476 // Get the memory info
477 memoryPH = FindDevice("/memory");
478 if (memoryPH == -1) return -1;
479 size = GetProp(memoryPH, "reg", (char *)(args->PhysicalDRAM),
480 kMaxDRAMBanks * sizeof(DRAMBank));
481 if (size == 0) return -1;
482
483 // This is a hack to make the memory look like its all
484 // in one big bank.
485 mem_size = 0;
486 for (cnt = 0; cnt < kMaxDRAMBanks; cnt++) {
487 mem_size += args->PhysicalDRAM[cnt].size;
488 args->PhysicalDRAM[cnt].base = 0;
489 args->PhysicalDRAM[cnt].size = 0;
490 }
491 args->PhysicalDRAM[0].size = mem_size;
492
493 // Get the video info
494 GetMainScreenPH(&args->Video);
495 args->Video.v_display = graphicsBoot;
496
497 // Add the DeviceTree to the memory-map.
498 // The actuall address and size must be filled in later.
499 AllocateMemoryRange("DeviceTree", 0, 0);
500
501 ret = FlattenDeviceTree();
502 if (ret != 0) return -1;
503
504 // Fill in the address and size of the device tree.
505 if (gDeviceTreeAddr) {
506 gDeviceTreeMMTmp[0] = gDeviceTreeAddr;
507 gDeviceTreeMMTmp[1] = gDeviceTreeSize;
508 }
509
510 args->deviceTreeP = (void *)gDeviceTreeAddr;
511 args->deviceTreeLength = gDeviceTreeSize;
512 args->topOfKernelData = AllocateKernelMemory(0);
513
514 return 0;
515}
516
517
518static long CallKernel(void)
519{
520 long msr, cnt;
521
522 Quiesce();
523
524 printf("\nCall Kernel!\n");
525
526 msr = 0x00001000;
527 __asm__ volatile("mtmsr %0" : : "r" (msr));
528 __asm__ volatile("isync");
529
530 // Move the Execption Vectors
531 bcopy(gVectorSaveAddr, 0x0, kVectorSize);
532 for (cnt = 0; cnt < kVectorSize; cnt += 0x20) {
533 __asm__ volatile("dcbf 0, %0" : : "r" (cnt));
534 __asm__ volatile("icbi 0, %0" : : "r" (cnt));
535 }
536
537 // Move the Image1 save area for OF 1.x / 2.x
538 if (gOFVersion < kOFVersion3x) {
539 bcopy((char *)kImageAddr1Phys, (char *)kImageAddr1, kImageSize1);
540 for (cnt = kImageAddr1; cnt < kImageSize1; cnt += 0x20) {
541 __asm__ volatile("dcbf 0, %0" : : "r" (cnt));
542 __asm__ volatile("icbi 0, %0" : : "r" (cnt));
543 }
544 }
545
546 // Make sure everything get sync'd up.
547 __asm__ volatile("isync");
548 __asm__ volatile("sync");
549 __asm__ volatile("eieio");
550
551 (*(void (*)())gKernelEntryPoint)(gBootArgsAddr, kMacOSXSignature);
552
553 return -1;
554}
555
556
557static void FailToBoot(long num)
558{
559#if kFailToBoot
560 DrawBrokenSystemFolder();
561 while (1);
562 num = 0;
563#else
564 printf("FailToBoot: %d\n", num);
565 Enter(); // For debugging
566#endif
567}
568
569
570static long InitMemoryMap(void)
571{
572 long result;
573
574 result = Interpret_0_1(
575 " dev /chosen"
576 " new-device"
577 " \" memory-map\" device-name"
578 " active-package"
579 " device-end"
580 , &gMemoryMapPH);
581
582 return result;
583}
584
585
586static long GetOFVersion(void)
587{
588 CICell ph;
589 char versStr[256], *tmpStr;
590 long vers, size;
591
592 // Get the openprom package
593 ph = FindDevice("/openprom");
594 if (ph == -1) return 0;
595
596 // Get it's model property
597 size = GetProp(ph, "model", versStr, 255);
598 if (size == -1) return -1;
599 versStr[size] = '\0';
600
601 // Find the start of the number.
602 tmpStr = NULL;
603 if (!strncmp(versStr, "Open Firmware, ", 15)) {
604 tmpStr = versStr + 15;
605 } else if (!strncmp(versStr, "OpenFirmware ", 13)) {
606 tmpStr = versStr + 13;
607 } else return -1;
608
609 // Clasify by each instance as needed...
610 switch (*tmpStr) {
611 case '1' :
612 vers = kOFVersion1x;
613 break;
614
615 case '2' :
616 vers = kOFVersion2x;
617 break;
618
619 case '3' :
620 vers = kOFVersion3x;
621 break;
622
623 default :
624 vers = 0;
625 break;
626 }
627
628 return vers;
629}
630
631
632static long TestForKey(long key)
633{
634 long keyNum;
635 long bp;
636 char tc;
637
638 if (gOFVersion < kOFVersion3x) {
639 switch(key) {
640 case 'a' : keyNum = 7; break;
641 case 's' : keyNum = 6; break;
642 case 'v' : keyNum = 14; break;
643 case 'y' : keyNum = 23; break;
644 case kCommandKey : keyNum = 48; break;
645 case kOptKey : keyNum = 61; break;
646 case kShiftKey : keyNum = 63; break;
647 case kControlKey : keyNum = 49; break;
648 default : keyNum = -1; break;
649 }
650 } else {
651 switch(key) {
652 case 'a' : keyNum = 3; break;
653 case 's' : keyNum = 17; break;
654 case 'v' : keyNum = 30; break;
655 case 'y' : keyNum = 27; break;
656 case kCommandKey : keyNum = 228; break;
657 case kOptKey : keyNum = 229; break;
658 case kShiftKey : keyNum = 230; break;
659 case kControlKey : keyNum = 231; break;
660 default : keyNum = -1; break;
661 }
662
663 // Map the right modifier keys on to the left.
664 gKeyMap[28] |= gKeyMap[28] << 4;
665 }
666
667 if (keyNum == -1) return 0;
668
669 bp = keyNum & 7;
670 tc = gKeyMap[keyNum >> 3];
671
672 return (tc & (1 << bp)) != 0;
673}
674
675
676#define kBootpBootFileOffset (108)
677
678static long GetBootPaths(void)
679{
680 long ret, cnt, cnt2, cnt3, cnt4, size, partNum, bootplen, bsdplen;
681 char *filePath, *buffer;
682
683 if (gBootSourceNumber == -1) {
684 // Get the boot-device
685 size = GetProp(gChosenPH, "bootpath", gBootDevice, 255);
686 gBootDevice[size] = '\0';
687 if (gBootDevice[0] == '\0') {
688 size = GetProp(gOptionsPH, "boot-device", gBootDevice, 255);
689 gBootDevice[size] = '\0';
690 }
691 gBootDeviceType = GetDeviceType(gBootDevice);
692
693 // Get the boot-file
694 size = GetProp(gChosenPH, "bootargs", gBootFile, 256);
695 gBootFile[size] = '\0';
696
697 if (gBootFile[0] != '\0') {
698 gBootFileType = GetDeviceType(gBootFile);
699 gBootSourceNumberMax = 0;
700 } else {
701 gBootSourceNumber = 0;
702 gBootFileType = gBootDeviceType;
703 if (gBootFileType == kNetworkDeviceType) gBootSourceNumberMax = 1;
704 else gBootSourceNumberMax = 4;
705 }
706
707 if (gBootFileType == kNetworkDeviceType) {
708 SetProp(Peer(0), "net-boot", NULL, 0);
709 }
710 }
711
712 if (gBootSourceNumber >= gBootSourceNumberMax) return -1;
713
714 if (gBootSourceNumberMax != 0) {
715 switch (gBootFileType) {
716 case kNetworkDeviceType :
717 // Find the end of the device spec.
718 cnt = 0;
719 while (gBootDevice[cnt] != ':') cnt++;
720
721 // Copy the device spec with the ':'.
722 strncpy(gBootFile, gBootDevice, cnt + 1);
723
724 // Check for bootp-responce or bsdp-responce.
725 bootplen = GetPropLen(gChosenPH, "bootp-response");
726 bsdplen = GetPropLen(gChosenPH, "bsdp-response");
727 if ((bootplen > 0) || (bsdplen > 0)) {
728 if (bootplen > 0) {
729 buffer = malloc(bootplen);
730 GetProp(gChosenPH, "bootp-response", buffer, bootplen);
731 } else {
732 buffer = malloc(bsdplen);
733 GetProp(gChosenPH, "bsdp-response", buffer, bsdplen);
734 }
735
736 // Flip the slash's to back slash's while looking for the last one.
737 cnt = cnt2 = kBootpBootFileOffset;
738 while (buffer[cnt] != '\0') {
739 if (buffer[cnt] == '/') {
740 buffer[cnt] = '\\';
741 cnt2 = cnt + 1;
742 }
743 cnt++;
744 }
745
746 // Add a comma at the front.
747 buffer[kBootpBootFileOffset - 1] = ',';
748
749 // Append the the root dir to the device spec.
750 strncat(gBootFile, buffer + kBootpBootFileOffset - 1,
751 cnt2 - kBootpBootFileOffset + 1);
752
753 free(buffer);
754 } else {
755 // Look for the start of the root dir path.
756 cnt3 = cnt;
757 while (gBootDevice[cnt3] != ',') cnt3++;
758
759 // Find the end of the path. Look for a comma or null.
760 cnt2 = cnt3 + 1;
761 while ((gBootDevice[cnt2] != '\0') && (gBootDevice[cnt2] != ',')) cnt2++;
762
763 // Find the last back slash or comma in the path
764 cnt4 = cnt2 - 1;
765 while ((gBootDevice[cnt4] != ',') && (gBootDevice[cnt4] != '\\')) cnt4--;
766
767 // Copy the IP addresses if needed.
768 if (gOFVersion < kOFVersion3x) {
769 strncat(gBootFile, gBootDevice + cnt + 1, cnt3 - cnt - 1);
770 }
771
772 // Add on the directory path
773 strncat(gBootFile, gBootDevice + cnt3, cnt4 - cnt3 + 1);
774 }
775
776 // Add on the kernel name
777 strcat(gBootFile, "mach.macosx");
778
779 // Add on postfix
780 strcat(gBootFile, gBootDevice + cnt2);
781 break;
782
783 case kBlockDeviceType :
784 // Find the first ':'.
785 cnt = 0;
786 while ((gBootDevice[cnt] != '\0') && (gBootDevice[cnt] != ':')) cnt++;
787 if (gBootDevice[cnt] == '\0') return -1;
788
789 // Find the comma after the ':'.
790 cnt2 = cnt + 1;
791 while ((gBootDevice[cnt2] != '\0') && (gBootDevice[cnt] != ',')) cnt2++;
792
793 // Get just the partition number
794 strncpy(gBootFile, gBootDevice + cnt + 1, cnt2 - cnt - 1);
795 partNum = atoi(gBootFile);
796
797 if (gBootSourceNumber > 1) {
798 // Adjust the partition number to the root partition
799 if (gOFVersion < kOFVersion3x) {
800 partNum += 1;
801 } else {
802 partNum += 2;
803 }
804 }
805
806 // Construct the boot-file
807 strncpy(gBootFile, gBootDevice, cnt + 1);
808 sprintf(gBootFile + cnt + 1, "%d,%s\\mach_kernel",
809 partNum, ((gBootSourceNumber & 1) ? "" : "\\"));
810 break;
811
812 default:
813 printf("Failed to infer Boot Device Type.\n");
814 return -1;
815 break;
816 }
817 }
818
819 // Figure out the root dir.
820 ret = ConvertFileSpec(gBootFile, gRootDir, &filePath);
821 if (ret == -1) return -1;
822
823 strcat(gRootDir, ",");
824
825 // Add in any extra path to gRootDir.
826 cnt = 0;
827 while (filePath[cnt] != '\0') cnt++;
828
829 if (cnt != 0) {
830 for (cnt2 = cnt - 1; cnt2 >= 0; cnt2--) {
831 if (filePath[cnt2] == '\\') {
832 strncat(gRootDir, filePath, cnt2 + 1);
833 break;
834 }
835 }
836 }
837
838 SetProp(gChosenPH, "rootpath", gBootFile, strlen(gBootFile) + 1);
839
840 gBootSourceNumber++;
841
842 return 0;
843}
844
845// Public Functions
846
847long GetDeviceType(char *devSpec)
848{
849 CICell ph;
850 long size;
851 char deviceType[32];
852
853 ph = FindDevice(devSpec);
854 if (ph == -1) return -1;
855
856 size = GetProp(ph, "device_type", deviceType, 31);
857 if (size != -1) deviceType[size] = '\0';
858 else deviceType[0] = '\0';
859
860 if (strcmp(deviceType, "network") == 0) return kNetworkDeviceType;
861 if (strcmp(deviceType, "block") == 0) return kBlockDeviceType;
862
863 return kUnknownDeviceType;
864}
865
866
867long ConvertFileSpec(char *fileSpec, char *devSpec, char **filePath)
868{
869 long cnt;
870
871 // Find the first ':' in the fileSpec.
872 cnt = 0;
873 while ((fileSpec[cnt] != '\0') && (fileSpec[cnt] != ':')) cnt++;
874 if (fileSpec[cnt] == '\0') return -1;
875
876 // Find the next ',' in the fileSpec.
877 while ((fileSpec[cnt] != '\0') && (fileSpec[cnt] != ',')) cnt++;
878
879 // Copy the string to devSpec.
880 strncpy(devSpec, fileSpec, cnt);
881 devSpec[cnt] = '\0';
882
883 // If there is a filePath start it after the ',', otherwise NULL.
884 if (filePath != NULL) {
885 if (fileSpec[cnt] != '\0') {
886 *filePath = fileSpec + cnt + 1;
887 } else {
888 *filePath = NULL;
889 }
890 }
891
892 return 0;
893}
894
895
896long MatchThis(CICell phandle, char *string)
897{
898 long ret, length;
899 char *name, *model, *compatible;
900
901 ret = GetPackageProperty(phandle, "name", &name, &length);
902 if ((ret == -1) || (length == 0)) name = NULL;
903
904 ret = GetPackageProperty(phandle, "model", &model, &length);
905 if ((ret == -1) || (length == 0)) model = NULL;
906
907 ret = GetPackageProperty(phandle, "compatible", &compatible, &length);
908 if ((ret == -1) || (length == 0)) model = NULL;
909
910 if ((name != NULL) && strcmp(name, string) == 0) return 0;
911 if ((model != NULL) && strcmp(model, string) == 0) return 0;
912
913 if (compatible != NULL) {
914 while (*compatible != '\0') {
915 if (strcmp(compatible, string) == 0) return 0;
916
917 compatible += strlen(compatible) + 1;
918 }
919 }
920
921 return -1;
922}
923
924
925void *AllocateBootXMemory(long size)
926{
927 long addr = gImageFirstBootXAddr - size;
928
929 if (addr < gImageLastKernelAddr) return 0;
930
931 gImageFirstBootXAddr = addr;
932
933 return (void *)addr;
934}
935
936
937long AllocateKernelMemory(long size)
938{
939 long addr = gImageLastKernelAddr;
940
941 gImageLastKernelAddr += (size + 0xFFF) & ~0xFFF;
942
943 if (gImageLastKernelAddr > gImageFirstBootXAddr)
944 FailToBoot(-1);
945
946 return addr;
947}
948
949
950long AllocateMemoryRange(char *rangeName, long start, long length)
951{
952 long result, *buffer;
953
954 buffer = AllocateBootXMemory(2 * sizeof(long));
955 if (buffer == 0) return -1;
956
957 buffer[0] = start;
958 buffer[1] = length;
959
960 result = SetProp(gMemoryMapPH, rangeName, (char *)buffer, 2 * sizeof(long));
961 if (result == -1) return -1;
962
963 return 0;
964}
965
966
967unsigned long Alder32(unsigned char *buffer, long length)
968{
969 long cnt;
970 unsigned long result, lowHalf, highHalf;
971
972 lowHalf = 1;
973 highHalf = 0;
974
975 for (cnt = 0; cnt < length; cnt++) {
976 if ((cnt % 5000) == 0) {
977 lowHalf %= 65521L;
978 highHalf %= 65521L;
979 }
980
981 lowHalf += buffer[cnt];
982 highHalf += lowHalf;
983 }
984
985 lowHalf %= 65521L;
986 highHalf %= 65521L;
987
988 result = (highHalf << 16) | lowHalf;
989
990 return result;
991}