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

Archive Download this file

Revision: 1450