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

Archive Download this file

Revision: 1039