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