Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/trunkAutoResolution/i386/boot2/boot.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * All rights reserved. The CMU software License Agreement specifies
29 * the terms and conditions for use and redistribution.
30 */
31
32/*
33 * INTEL CORPORATION PROPRIETARY INFORMATION
34 *
35 * This software is supplied under the terms of a license agreement or
36 * nondisclosure agreement with Intel Corporation and may not be copied
37 * nor disclosed except in accordance with the terms of that agreement.
38 *
39 * Copyright 1988, 1989 by Intel Corporation
40 */
41
42/*
43 * Copyright 1993 NeXT Computer, Inc.
44 * All rights reserved.
45 */
46
47/*
48 * Completely reworked by Sam Streeper (sam_s@NeXT.com)
49 * Reworked again by Curtis Galloway (galloway@NeXT.com)
50 */
51
52
53#include "boot.h"
54#include "bootstruct.h"
55#include "fake_efi.h"
56#include "sl.h"
57#include "libsa.h"
58#include "ramdisk.h"
59#include "gui.h"
60#include "platform.h"
61#include "autoresolution.h" //autoresolution
62#include "edid.h"//||
63#include "modules.h"
64
65long gBootMode; /* defaults to 0 == kBootModeNormal */
66bool gOverrideKernel;
67static char gBootKernelCacheFile[512];
68static char gCacheNameAdler[64 + 256];
69char *gPlatformName = gCacheNameAdler;
70char gRootDevice[512];
71char gMKextName[512];
72char gMacOSVersion[8];
73bool gEnableCDROMRescan;
74bool gScanSingleDrive;
75
76int bvCount = 0;
77//intmenucount = 0;
78int gDeviceCount = 0;
79
80BVRef bvr;
81BVRef menuBVR;
82BVRef bvChain;
83bool useGUI;
84
85//static void selectBiosDevice(void);
86static unsigned long Adler32(unsigned char *buffer, long length);
87static bool checkOSVersion(const char * version);
88static bool getOSVersion();
89
90static bool gUnloadPXEOnExit = false;
91
92/*
93 * How long to wait (in seconds) to load the
94 * kernel after displaying the "boot:" prompt.
95 */
96#define kBootErrorTimeout 5
97
98/*
99 * Default path to kernel cache file
100 */
101//Slice - first one for Leopard
102#define kDefaultCachePathLeo "/System/Library/Caches/com.apple.kernelcaches/"
103#define kDefaultCachePathSnow "/System/Library/Caches/com.apple.kext.caches/Startup/"
104
105//==========================================================================
106// Zero the BSS.
107
108static void zeroBSS(void)
109{
110extern char _DATA__bss__begin, _DATA__bss__end;
111extern char _DATA__common__begin, _DATA__common__end;
112
113bzero(&_DATA__bss__begin, (&_DATA__bss__end - &_DATA__bss__begin));
114bzero(&_DATA__common__begin, (&_DATA__common__end - &_DATA__common__begin));
115}
116
117//==========================================================================
118// Malloc error function
119
120static void malloc_error(char *addr, size_t size, const char *file, int line)
121{
122stop("\nMemory allocation error! Addr=0x%x, Size=0x%x, File=%s, Line=%d\n", (unsigned)addr, (unsigned)size, file, line);
123}
124
125//==========================================================================
126//Initializes the runtime. Right now this means zeroing the BSS and initializing malloc.
127//
128void initialize_runtime(void)
129{
130zeroBSS();
131malloc_init(0, 0, 0, malloc_error);
132}
133
134//==========================================================================
135// execKernel - Load the kernel image (mach-o) and jump to its entry point.
136
137static int ExecKernel(void *binary)
138{
139entry_t kernelEntry;
140int ret;
141
142bootArgs->kaddr = bootArgs->ksize = 0;
143execute_hook("ExecKernel", (void*)binary, NULL, NULL, NULL);
144
145ret = DecodeKernel(binary,
146 &kernelEntry,
147 (char **) &bootArgs->kaddr,
148 (int *)&bootArgs->ksize );
149
150if ( ret != 0 )
151return ret;
152
153// Reserve space for boot args
154reserveKernBootStruct();
155
156// Notify modules that the kernel has been decoded
157execute_hook("DecodedKernel", (void*)binary, NULL, NULL, NULL);
158
159// Load boot drivers from the specifed root path.
160if (!gHaveKernelCache)
161LoadDrivers("/");
162
163
164clearActivityIndicator();
165
166if (gErrors) {
167printf("Errors encountered while starting up the computer.\n");
168printf("Pausing %d seconds...\n", kBootErrorTimeout);
169sleep(kBootErrorTimeout);
170}
171
172setupFakeEfi();
173
174md0Ramdisk();
175
176verbose("Starting Darwin %s\n",( archCpuType == CPU_TYPE_I386 ) ? "x86" : "x86_64");
177
178// Cleanup the PXE base code.
179
180if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) {
181if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess )
182{
183printf("nbpUnloadBaseCode error %d\n", (int) ret);
184sleep(2);
185}
186}
187
188bool dummyVal;
189if (getBoolForKey(kWaitForKeypressKey, &dummyVal, &bootInfo->bootConfig) && dummyVal) {
190printf("Press any key to continue...");
191getchar();
192}
193
194usb_loop();
195
196//autoresolution - Check if user disabled AutoResolution at the boot prompt.
197getBoolForKey(kAutoResolutionKey, &gAutoResolution, &bootInfo->bootConfig); //Azi: bootConfig ??
198
199// User disabled AutoResolution at boot prompt...
200if ((gAutoResolution == false) && map)
201{
202// restore and close Vbios for patch cancelation.
203restoreVbios(map);
204closeVbios(map);
205}
206
207//Azi: while testing, i didn't got any problems when booting without
208// closing Vbios... closing it just in case. (check again later!)
209if ((gAutoResolution == true) && map)
210{
211closeVbios(map);
212
213// gAutoResolution was just set to false on closeVbios();
214// we need it to be "true" for drawBootGraphics().
215gAutoResolution = true;
216}
217
218//Azi: closing Vbios after "if (gVerboseMode)" stuff eliminates the need for setting
219// AutoResolution = true above; but creates another bug when booting in TextMode with -v arg.
220// Simptoms include: staring some seconds at a nicely drawn white screen, after boot prompt.
221// Think i'm just going to end up removing setting gAutoResolution = false
222// on closeVbios().. the more i think, the less sense it makes doing it there!!
223//autoresolution - end
224
225 if (checkOSVersion("10.7"))
226 {
227 execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgs, NULL, NULL);// Notify modules that the kernel is about to be started
228 }
229 else
230 {
231 execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL);// Notify modules that the kernel is about to be started
232 }
233
234// If we were in text mode, switch to graphics mode.
235// This will draw the boot graphics unless we are in
236// verbose mode.
237
238if(gVerboseMode)
239 setVideoMode( GRAPHICS_MODE, 0 );
240else
241 drawBootGraphics();
242
243setupBooterLog();
244
245finalizeBootStruct();
246
247 if (checkOSVersion("10.7")) {
248
249// Masking out so that Lion doesn't doublefault
250outb(0x21, 0xff);/* Maskout all interrupts Pic1 */
251outb(0xa1, 0xff);/* Maskout all interrupts Pic2 */
252
253// Jump to kernel's entry point. There's no going back now.
254
255startprog( kernelEntry, bootArgs );
256}
257else {
258// Jump to kernel's entry point. There's no going back now.
259
260startprog( kernelEntry, bootArgsPreLion );
261}
262
263// Not reached
264return 0;
265}
266
267//==========================================================================
268// This is the entrypoint from real-mode which functions exactly as it did
269// before. Multiboot does its own runtime initialization, does some of its
270// own things, and then calls common_boot.
271void boot(int biosdev)
272{
273initialize_runtime();
274// Enable A20 gate before accessing memory above 1Mb.
275enableA20();
276common_boot(biosdev);
277}
278
279//==========================================================================
280// The 'main' function for the booter. Called by boot0 when booting
281// from a block device, or by the network booter.
282//
283// arguments:
284// biosdev - Value passed from boot1/NBP to specify the device
285// that the booter was loaded from.
286//
287// If biosdev is kBIOSDevNetwork, then this function will return if
288// booting was unsuccessful. This allows the PXE firmware to try the
289// next boot device on its list.
290void common_boot(int biosdev)
291{
292 int status;
293 char *bootFile;
294 unsigned long adler32;
295 bool quiet;
296 bool firstRun = true;
297 bool instantMenu;
298 bool rescanPrompt;
299 unsigned int allowBVFlags = kBVFlagSystemVolume|kBVFlagForeignBoot;
300 unsigned int denyBVFlags = kBVFlagEFISystem;
301
302 // Set reminder to unload the PXE base code. Neglect to unload
303 // the base code will result in a hang or kernel panic.
304 gUnloadPXEOnExit = true;
305
306 // Record the device that the booter was loaded from.
307 gBIOSDev = biosdev & kBIOSDevMask;
308
309 // Initialize boot info structure.
310 initKernBootStruct();
311
312initBooterLog();
313
314 // Setup VGA text mode.
315 // Not sure if it is safe to call setVideoMode() before the
316 // config table has been loaded. Call video_mode() instead.
317#if DEBUG
318 printf("before video_mode\n");
319#endif
320 video_mode( 2 ); // 80x25 mono text mode.
321#if DEBUG
322 printf("after video_mode\n");
323#endif
324
325 // Scan and record the system's hardware information.
326 scan_platform();
327
328 // First get info for boot volume.
329 scanBootVolumes(gBIOSDev, 0);
330 bvChain = getBVChainForBIOSDev(gBIOSDev);
331 setBootGlobals(bvChain);
332
333 // Load boot.plist config file
334 status = loadSystemConfig(&bootInfo->bootConfig);
335
336 if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->bootConfig) && quiet) {
337 gBootMode |= kBootModeQuiet;
338 }
339
340 // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
341 if (getBoolForKey(kInsantMenuKey, &instantMenu, &bootInfo->bootConfig) && instantMenu) {
342 firstRun = false;
343 }
344
345 // Loading preboot ramdisk if exists.
346 loadPrebootRAMDisk();
347
348 // Disable rescan option by default
349 gEnableCDROMRescan = false;
350
351 // Enable it with Rescan=y in system config
352 if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->bootConfig) && gEnableCDROMRescan) {
353 gEnableCDROMRescan = true;
354 }
355
356 // Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
357 rescanPrompt = false;
358 if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->bootConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev)) {
359 gEnableCDROMRescan = promptForRescanOption();
360 }
361
362 // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
363 if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) {
364 gScanSingleDrive = true;
365 }
366
367 // Create a list of partitions on device(s).
368 if (gScanSingleDrive) {
369 scanBootVolumes(gBIOSDev, &bvCount);
370 } else {
371 scanDisks(gBIOSDev, &bvCount);
372 }
373
374 // Create a separated bvr chain using the specified filters.
375 bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
376
377 gBootVolume = selectBootVolume(bvChain);
378
379// Intialize module system
380init_module_system();
381
382#if DEBUG
383 printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
384 printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
385 getchar();
386#endif
387
388useGUI = true;
389// Override useGUI default
390getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig);
391
392//autoresolution - default to false
393// http://forum.voodooprojects.org/index.php/topic,1227.0.html
394gAutoResolution = false;
395
396// Check if user enabled AutoResolution on Boot.plist...
397getBoolForKey(kAutoResolutionKey, &gAutoResolution, &bootInfo->bootConfig);
398
399// Patch the Video Bios with the extracted resolution, before initGui.
400if (gAutoResolution == true)
401{
402paramsAR[3] = 0;
403
404// Open the Vbios and store Vbios or Tables
405//Azi: doing this only if gAutoResolution = true
406map = openVbios(CT_UNKWN);
407
408//Get resolution from Graphics Mode key...
409int count = getNumberArrayFromProperty(kGraphicsModeKey, paramsAR, 4);
410// ... or EDID.
411if (count < 3)
412{
413getResolution(paramsAR); //Azi: hum...
414// check the DEBUG/PRINT stuff... also on TEXT MODE (this is not printing to screen). ???
415// don't forget we now have boot-log and it prints fine there.
416//Azi:autoresolution - these PRINT replace a previous existing #ifdef AUTORES_DEBUG
417// and were moved from gui.c, initGUI().
418PRINT("Resolution: %dx%d (EDID)\n",paramsAR[0], paramsAR[1]);
419}
420else //Azi: check theme.plist ??
421{
422PRINT("Resolution: %dx%d (Graphics Mode key)\n",paramsAR[0], paramsAR[1]);
423
424//Azi: hum...
425if ( paramsAR[2] == 256 ) paramsAR[2] = 8;
426if ( paramsAR[2] == 555 ) paramsAR[2] = 16;
427if ( paramsAR[2] == 888 ) paramsAR[2] = 32;
428}
429
430// perfom the actual Vbios patching
431if (paramsAR[0] != 0 && paramsAR[1] != 0)
432{
433patchVbios(map, paramsAR[0], paramsAR[1], paramsAR[2], 0, 0);
434}
435
436//Azi: passing resolution for TEXT MODE "verbose" boot. (check again later!)***
437if (bootArgs->Video.v_display == VGA_TEXT_MODE)
438{
439gui.screen.width = paramsAR[0];
440gui.screen.height = paramsAR[1];
441}
442
443// If the patch is working properly, we're almost done (we need? to close Vbios).
444// If not and it's just a matter of wrong resolution, we can try re-apply the patch;
445// see "case kF2Key:", options.c.
446}
447//autoresolution - end
448
449if (useGUI && initGUI())
450{
451// initGUI() returned with an error, disabling GUI.
452useGUI = false;
453}
454
455 setBootGlobals(bvChain);
456
457 // Parse args, load and start kernel.
458 while (1) {
459 const char *val;
460 int len;
461 int trycache;
462 long flags, cachetime, kerneltime, exttime, sleeptime, time;
463 int ret = -1;
464 void *binary = (void *)kLoadAddr;
465 bool tryresume;
466 bool tryresumedefault;
467 bool forceresume;
468bool usecache;
469
470 // additional variable for testing alternate kernel image locations on boot helper partitions.
471 char bootFileSpec[512];
472
473 // Initialize globals.
474
475 sysConfigValid = false;
476 gErrors = false;
477
478 status = getBootOptions(firstRun);
479 firstRun = false;
480 if (status == -1) continue;
481
482 status = processBootOptions();
483 // Status==1 means to chainboot
484 if ( status == 1 ) break;
485 // Status==-1 means that the config file couldn't be loaded or that gBootVolume is NULL
486 if ( status == -1 )
487 {
488 // gBootVolume == NULL usually means the user hit escape.
489 if(gBootVolume == NULL)
490 {
491 freeFilteredBVChain(bvChain);
492
493 if (gEnableCDROMRescan)
494 rescanBIOSDevice(gBIOSDev);
495
496 bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
497 setBootGlobals(bvChain);
498 setupDeviceList(&bootInfo->themeConfig);
499 }
500 continue;
501 }
502
503 // Other status (e.g. 0) means that we should proceed with boot.
504
505// Turn off any GUI elements
506if( bootArgs->Video.v_display == GRAPHICS_MODE )
507{
508gui.devicelist.draw = false;
509gui.bootprompt.draw = false;
510gui.menu.draw = false;
511gui.infobox.draw = false;
512gui.logo.draw = false;
513drawBackground();
514updateVRAM();
515}
516
517//Azi: autoresolution stuff moved to ExecKernel();
518// Closing Vbios here without restoring it, causes an allocation error.
519
520// Find out which version mac os we're booting.
521getOSVersion();
522
523if (platformCPUFeature(CPU_FEATURE_EM64T)) {
524archCpuType = CPU_TYPE_X86_64;
525} else {
526archCpuType = CPU_TYPE_I386;
527}
528if (getValueForKey(karch, &val, &len, &bootInfo->bootConfig)) {
529if (strncmp(val, "i386", 4) == 0) {
530archCpuType = CPU_TYPE_I386;
531}
532}
533
534// Notify moduals that we are attempting to boot
535execute_hook("PreBoot", NULL, NULL, NULL, NULL);
536
537if (!getBoolForKey (kWake, &tryresume, &bootInfo->bootConfig)) {
538tryresume = true;
539tryresumedefault = true;
540} else {
541tryresumedefault = false;
542}
543
544if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->bootConfig)) {
545forceresume = false;
546}
547
548if (forceresume) {
549tryresume = true;
550tryresumedefault = false;
551}
552
553while (tryresume) {
554const char *tmp;
555BVRef bvr;
556if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->bootConfig))
557val="/private/var/vm/sleepimage";
558
559// Do this first to be sure that root volume is mounted
560ret = GetFileInfo(0, val, &flags, &sleeptime);
561
562if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
563break;
564
565// Can't check if it was hibernation Wake=y is required
566if (bvr->modTime == 0 && tryresumedefault)
567break;
568
569if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
570break;
571
572if (!forceresume && ((sleeptime+3)<bvr->modTime)) {
573printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",bvr->modTime-sleeptime);
574break;
575}
576
577HibernateBoot((char *)val);
578break;
579}
580
581if(getBoolForKey(kUseKernelCache, &usecache, &bootInfo->bootConfig)) {
582if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) {
583strlcpy(gBootKernelCacheFile, val, len+1);
584}
585else {
586//Lion
587if (checkOSVersion("10.7")) {
588sprintf(gBootKernelCacheFile, "%skernelcache", kDefaultCachePathSnow);
589}
590// Snow Leopard
591else if (checkOSVersion("10.6")) {
592sprintf(gBootKernelCacheFile, "kernelcache_%s", (archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64");
593int lnam = sizeof(gBootKernelCacheFile) + 9; //with adler32
594//Slice - TODO ???
595// e.g. kernelcache_i386.E102928C.qSs0 = "unsaved" cache file.
596//
597// See kext_tools-180.2.1/kextcache_main.c:
598// "Source directory has changed since starting; "
599 // "not saving cache file %s."
600// or
601// "Source kernel has changed since starting; "
602 // "not saving cache file %s."
603
604char* name;
605long prev_time = 0;
606
607struct dirstuff* cacheDir = opendir(kDefaultCachePathSnow);
608
609while(readdir(cacheDir, (const char**)&name, &flags, &time) >= 0)
610{
611if(((flags & kFileTypeMask) != kFileTypeDirectory) && time > prev_time && strstr(name, gBootKernelCacheFile) && (name[lnam] != '.'))
612{
613sprintf(gBootKernelCacheFile, "%s%s", kDefaultCachePathSnow, name);
614prev_time = time;
615}
616}
617}
618else {
619// Reset cache name.
620bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
621
622sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile);
623
624adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
625
626sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePathLeo, adler32);
627}
628}
629}
630
631 // Check for cache file.
632 trycache = (usecache &&
633((gBootMode & kBootModeSafe) == 0) &&
634 !gOverrideKernel &&
635 (gBootFileType == kBlockDeviceType) &&
636 (gMKextName[0] == '\0') &&
637 (gBootKernelCacheFile[0] != '\0'));
638
639verbose("Loading Darwin %s\n", gMacOSVersion);
640
641 if (trycache) do {
642
643 // if we haven't found the kernel yet, don't use the cache
644 ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
645 if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
646 trycache = 0;
647 break;
648 }
649 ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
650 if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
651 || (cachetime < kerneltime)) {
652 trycache = 0;
653 break;
654 }
655 ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
656 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
657 && (cachetime < exttime)) {
658 trycache = 0;
659 break;
660 }
661 if (kerneltime > exttime) {
662 exttime = kerneltime;
663 }
664 if (cachetime != (exttime + 1)) {
665 trycache = 0;
666 break;
667 }
668 } while (0);
669
670 do {
671 if (trycache) {
672 bootFile = gBootKernelCacheFile;
673
674verbose("Loading kernel cache %s\n", bootFile);
675
676 if (checkOSVersion("10.7")) {
677 ret = LoadThinFatFile(bootFile, &binary);
678}
679else {
680 ret = LoadFile(bootFile);
681binary = (void *)kLoadAddr;
682}
683
684 if (ret >= 0)
685 break;
686
687verbose("Kernel cache did not loaded %s\n ", bootFile);
688 }
689
690 bootFile = bootInfo->bootFile;
691
692 // Try to load kernel image from alternate locations on boot helper partitions.
693 sprintf(bootFileSpec, "com.apple.boot.P/%s", bootFile);
694 ret = GetFileInfo(NULL, bootFileSpec, &flags, &time);
695 if (ret == -1)
696 {
697 sprintf(bootFileSpec, "com.apple.boot.R/%s", bootFile);
698 ret = GetFileInfo(NULL, bootFileSpec, &flags, &time);
699 if (ret == -1)
700 {
701 sprintf(bootFileSpec, "com.apple.boot.S/%s", bootFile);
702 ret = GetFileInfo(NULL, bootFileSpec, &flags, &time);
703 if (ret == -1)
704 {
705 // No alternate location found, using the original kernel image path.
706 strcpy(bootFileSpec, bootFile);
707 }
708 }
709 }
710
711 if (checkOSVersion("10.7"))
712 {
713 //Lion, dont load kernel if haz cache
714 if (!trycache) {
715 verbose("Loading kernel %s\n", bootFileSpec);
716 ret = LoadThinFatFile(bootFileSpec, &binary);
717 if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) {
718 archCpuType = CPU_TYPE_I386;
719 ret = LoadThinFatFile(bootFileSpec, &binary);
720 }
721 }
722else ret = 1;
723 }
724else {
725 //Snow Leopard or older
726 verbose("Loading kernel %s\n", bootFileSpec);
727 ret = LoadThinFatFile(bootFileSpec, &binary);
728 if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) {
729 archCpuType = CPU_TYPE_I386;
730 ret = LoadThinFatFile(bootFileSpec, &binary);
731 }
732 }
733 } while (0);
734
735 clearActivityIndicator();
736#if DEBUG
737 printf("Pausing...");
738 sleep(8);
739#endif
740
741 if (ret <= 0) {
742printf("Can't find %s\n", bootFile);
743
744sleep(1);
745
746 if (gBootFileType == kNetworkDeviceType) {
747 // Return control back to PXE. Don't unload PXE base code.
748 gUnloadPXEOnExit = false;
749 break;
750 }
751 } else {
752 /* Won't return if successful. */
753 ret = ExecKernel(binary);
754 }
755 }
756
757 // chainboot
758 if (status==1) {
759if (getVideoMode() == GRAPHICS_MODE) {// if we are already in graphics-mode,
760setVideoMode(VGA_TEXT_MODE, 0);// switch back to text mode
761}
762 }
763
764 if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
765nbpUnloadBaseCode();
766 }
767}
768
769/*!
770 Selects a new BIOS device, taking care to update the global state appropriately.
771 */
772/*
773static void selectBiosDevice(void)
774{
775 struct DiskBVMap *oldMap = diskResetBootVolumes(gBIOSDev);
776 CacheReset();
777 diskFreeMap(oldMap);
778 oldMap = NULL;
779
780 int dev = selectAlternateBootDevice(gBIOSDev);
781
782 BVRef bvchain = scanBootVolumes(dev, 0);
783 BVRef bootVol = selectBootVolume(bvchain);
784 gBootVolume = bootVol;
785 setRootVolume(bootVol);
786 gBIOSDev = dev;
787}
788*/
789
790bool checkOSVersion(const char * version)
791{
792return ((gMacOSVersion[0] == version[0]) && (gMacOSVersion[1] == version[1]) && (gMacOSVersion[2] == version[2]) && (gMacOSVersion[3] == version[3]));
793}
794
795bool getOSVersion()
796{
797bool valid = false;
798config_file_t systemVersion;
799const char *val;
800int len;
801
802if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion))
803{
804valid = true;
805}
806else if (!loadConfigFile("System/Library/CoreServices/ServerVersion.plist", &systemVersion))
807{
808valid = true;
809}
810
811if (valid)
812{
813if (getValueForKey(kProductVersion, &val, &len, &systemVersion))
814{
815// getValueForKey uses const char for val
816// so copy it and trim
817*gMacOSVersion = '\0';
818strncat(gMacOSVersion, val, MIN(len, 4));
819}
820else
821valid = false;
822}
823
824return valid;
825}
826
827#define BASE 65521L /* largest prime smaller than 65536 */
828#define NMAX 5000
829// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
830
831#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
832#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
833#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
834#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
835#define DO16(buf) DO8(buf,0); DO8(buf,8);
836
837unsigned long Adler32(unsigned char *buf, long len)
838{
839 unsigned long s1 = 1; // adler & 0xffff;
840 unsigned long s2 = 0; // (adler >> 16) & 0xffff;
841 unsigned long result;
842 int k;
843
844 while (len > 0) {
845 k = len < NMAX ? len : NMAX;
846 len -= k;
847 while (k >= 16) {
848 DO16(buf);
849 buf += 16;
850 k -= 16;
851 }
852 if (k != 0) do {
853 s1 += *buf++;
854 s2 += s1;
855 } while (--k);
856 s1 %= BASE;
857 s2 %= BASE;
858 }
859 result = (s2 << 16) | s1;
860 return OSSwapHostToBigInt32(result);
861}
862

Archive Download this file

Revision: 1055