Chameleon

Chameleon Svn Source Tree

Root/trunk/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 * INTEL CORPORATION PROPRIETARY INFORMATION
33 *
34 * This software is supplied under the terms of a license agreement or
35 * nondisclosure agreement with Intel Corporation and may not be copied
36 * nor disclosed except in accordance with the terms of that agreement.
37 *
38 *Copyright 1988, 1989 by Intel Corporation
39 *
40 *
41 * Copyright 1993 NeXT Computer, Inc.
42 * All rights reserved.
43 *
44 * Completely reworked by Sam Streeper (sam_s@NeXT.com)
45 * Reworked again by Curtis Galloway (galloway@NeXT.com)
46 */
47
48#include "boot.h"
49#include "bootstruct.h"
50#include "fake_efi.h"
51#include "sl.h"
52#include "libsa.h"
53#include "ramdisk.h"
54#include "gui.h"
55#include "platform.h"
56#include "modules.h"
57#include "device_tree.h"
58
59#ifndef DEBUG_BOOT2
60#define DEBUG_BOOT2 0
61#endif
62
63#ifndef DEBUG_INTERRUPTS
64#define DEBUG_INTERRUPTS 0
65#endif
66
67#if DEBUG_BOOT2
68#define DBG(x...)printf(x)
69#else
70#define DBG(x...)msglog(x)
71#endif
72
73/*
74 * How long to wait (in seconds) to load the
75 * kernel after displaying the "boot:" prompt.
76 */
77#define kBootErrorTimeout 5
78
79boolgOverrideKernel;
80boolgEnableCDROMRescan;
81boolgScanSingleDrive;
82booluseGUI;
83
84#if DEBUG_INTERRUPTS
85static intinterruptsAvailable = 0;
86#endif
87
88static boolgUnloadPXEOnExit = false;
89
90static chargCacheNameAdler[64 + 256];
91char*gPlatformName = gCacheNameAdler;
92
93chargRootDevice[ROOT_DEVICE_SIZE];
94chargMKextName[512];
95intbvCount = 0;
96intgDeviceCount = 0;
97//intmenucount = 0;
98longgBootMode; /* defaults to 0 == kBootModeNormal */
99
100BVRefbvr;
101BVRefmenuBVR;
102BVRefbvChain;
103
104static unsigned longAdler32(unsigned char *buffer, long length);
105//static voidselectBiosDevice(void);
106
107/** options.c **/
108extern char *msgbuf;
109void showTextBuffer(char *buf, int size);
110
111//==========================================================================
112// Zero the BSS.
113
114static void zeroBSS(void)
115{
116extern char bss_start __asm("section$start$__DATA$__bss");
117extern char bss_end __asm("section$end$__DATA$__bss");
118extern char common_start __asm("section$start$__DATA$__common");
119extern char common_end __asm("section$end$__DATA$__common");
120
121bzero(&bss_start, (&bss_end - &bss_start));
122bzero(&common_start, (&common_end - &common_start));
123}
124
125//==========================================================================
126// Malloc error function
127
128static void malloc_error(char *addr, size_t size, const char *file, int line)
129{
130stop("\nMemory allocation error! Addr: 0x%x, Size: 0x%x, File: %s, Line: %d\n",
131 (unsigned)addr, (unsigned)size, file, line);
132}
133
134//==========================================================================
135//Initializes the runtime. Right now this means zeroing the BSS and initializing malloc.
136//
137void initialize_runtime(void)
138{
139zeroBSS();
140malloc_init(0, 0, 0, malloc_error);
141}
142
143//==========================================================================
144// ExecKernel - Load the kernel image (mach-o) and jump to its entry point.
145
146static int ExecKernel(void *binary)
147{
148intret;
149entry_tkernelEntry;
150
151bootArgs->kaddr = bootArgs->ksize = 0;
152// ===============================================================================
153
154 // OS X Mountain Lion 10.8
155if ( MacOSVerCurrent >= MacOSVer2Int("10.8") ) // Mountain Lion and Up!
156{
157// cparm
158bool KPRebootOption= false;
159bool HiDPIOption= false;
160getBoolForKey(kRebootOnPanic, &KPRebootOption, &bootInfo->chameleonConfig);
161if ( KPRebootOption )
162{
163bootArgs->flags |= kBootArgsFlagRebootOnPanic;
164}
165
166// cparm
167getBoolForKey(kEnableHiDPI, &HiDPIOption, &bootInfo->chameleonConfig);
168
169if ( HiDPIOption )
170{
171bootArgs->flags |= kBootArgsFlagHiDPI;
172}
173}
174
175// OS X Yosemite 10.10
176if ( MacOSVerCurrent >= MacOSVer2Int("10.10") ) // Yosemite and Up!
177{
178// Pike R. Alpha
179bool FlagBlackOption= false;
180getBoolForKey(kBlackMode, &FlagBlackOption, &bootInfo->chameleonConfig);
181if ( FlagBlackOption )
182{
183//bootArgs->flags |= kBootArgsFlagBlack;
184bootArgs->flags |= kBootArgsFlagBlackBg; // Micky1979
185}
186}
187
188// OS X El Capitan 10.11
189if ( MacOSVerCurrent >= MacOSVer2Int("10.11") ) // El Capitan and Up!
190{
191// ErmaC
192intcsrValue;
193
194#if 0
195/*
196 * A special BootArgs flag "kBootArgsFlagCSRBoot"
197 * is set in the Recovery or Installation environment.
198 * This flag is kind of overkill by turning off all the protections
199 */
200
201if (isRecoveryHD)
202{
203// SIP can be controlled with or without FileNVRAM.kext (Pike R. Alpha)
204bootArgs->flags|=(kBootArgsFlagCSRActiveConfig + kBootArgsFlagCSRConfigMode + kBootArgsFlagCSRBoot);
205}
206#endif
207
208bootArgs->flags|= kBootArgsFlagCSRActiveConfig;
209
210// Set limit to 7bit
211if ( getIntForKey(KCsrActiveConfig, &csrValue, &bootInfo->chameleonConfig) && (csrValue >= 0 && csrValue <= 127) )
212{
213bootArgs->csrActiveConfig= csrValue;
214}
215else
216{
217// zenith432
218bootArgs->csrActiveConfig= 0x67;
219}
220verbose("CsrActiveConfig set to 0x%x\n", bootArgs->csrActiveConfig);
221bootArgs->csrCapabilities= CSR_VALID_FLAGS;
222bootArgs->boot_SMC_plimit= 0;
223 }
224
225// ===============================================================================
226
227execute_hook("ExecKernel", (void *)binary, NULL, NULL, NULL);
228
229ret = DecodeKernel(binary,
230 &kernelEntry,
231 (char **) &bootArgs->kaddr,
232 (int *)&bootArgs->ksize);
233
234if ( ret != 0 )
235{
236printf("Decoding kernel failed.\n");
237pause();
238return ret;
239}
240
241// Reserve space for boot args
242reserveKernBootStruct();
243
244// Notify modules that the kernel has been decoded
245execute_hook("DecodedKernel", (void *)binary, (void *)bootArgs->kaddr, (void *)bootArgs->ksize, NULL);
246
247setupFakeEfi();
248
249// Load boot drivers from the specifed root path.
250//if (!gHaveKernelCache)
251{
252LoadDrivers("/");
253}
254
255execute_hook("DriversLoaded", (void *)binary, NULL, NULL, NULL);
256
257clearActivityIndicator();
258
259if (gErrors)
260{
261printf("Errors encountered while starting up the computer.\n");
262printf("Pausing %d seconds...\n", kBootErrorTimeout);
263sleep(kBootErrorTimeout);
264}
265
266md0Ramdisk();
267
268// Cleanup the PXE base code.
269
270if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit )
271{
272if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess )
273{
274printf("nbpUnloadBaseCode error %d\n", (int)ret);
275sleep(2);
276}
277}
278
279bool dummyVal;
280if (getBoolForKey(kWaitForKeypressKey, &dummyVal, &bootInfo->chameleonConfig) && dummyVal)
281{
282showTextBuffer(msgbuf, strlen(msgbuf));
283}
284
285usb_loop();
286
287#if DEBUG
288if (interruptsAvailable) ShowInterruptCounters();
289#endif
290
291// If we were in text mode, switch to graphics mode.
292// This will draw the boot graphics unless we are in
293// verbose mode.
294if (gVerboseMode)
295{
296setVideoMode(GRAPHICS_MODE, 0);
297}
298else
299{
300drawBootGraphics();
301}
302
303DBG("Starting Darwin/%s [%s]\n",( archCpuType == CPU_TYPE_I386 ) ? "x86" : "x86_64", gDarwinBuildVerStr);
304DBG("Boot Args: %s\n", bootArgs->CommandLine);
305
306setupBooterLog();
307
308finalizeBootStruct();
309
310// Jump to kernel's entry point. There's no going back now.
311if ( MacOSVerCurrent < MacOSVer2Int("10.7") )
312{
313// Notify modules that the kernel is about to be started
314execute_hook("Kernel Start", (void *)kernelEntry, (void *)bootArgsLegacy, NULL, NULL);
315
316startprog( kernelEntry, bootArgsLegacy );
317}
318else
319{
320// Notify modules that the kernel is about to be started
321execute_hook("Kernel Start", (void *)kernelEntry, (void *)bootArgs, NULL, NULL);
322
323// Masking out so that Lion doesn't doublefault
324outb(0x21, 0xff);/* Maskout all interrupts Pic1 */
325outb(0xa1, 0xff);/* Maskout all interrupts Pic2 */
326
327startprog( kernelEntry, bootArgs );
328}
329
330// Not reached
331__builtin_unreachable();
332}
333
334//==========================================================================
335// LoadKernelCache - Try to load Kernel Cache.
336// return the length of the loaded cache file or -1 on error
337long LoadKernelCache(const char *cacheFile, void **binary)
338{
339charkernelCacheFile[512];
340charkernelCachePath[512];
341longflags, ret=-1;
342unsigned longadler32 = 0;
343u_int32_t time, cachetime, kerneltime, exttime;
344
345if((gBootMode & kBootModeSafe) != 0)
346{
347DBG("Kernel Cache ignored.\n");
348return -1;
349}
350
351// Use specify kernel cache file if not empty
352if (cacheFile[0] != 0)
353{
354strlcpy(kernelCacheFile, cacheFile, sizeof(kernelCacheFile));
355verbose("Specified kernel cache file path: %s\n", cacheFile);
356}
357else
358{
359// Leopard prelink kernel cache file
360if ( MacOSVerCurrent >= MacOSVer2Int("10.4") && MacOSVerCurrent <= MacOSVer2Int("10.5") ) // OSX is 10.4 or 10.5
361{
362// Reset cache name.
363bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
364snprintf(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64, "%s,%s", gRootDevice, bootInfo->bootFile);
365adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
366snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%s.%08lX", kDefaultCachePathLeo, adler32);
367verbose("Reseted kernel cache file path: %s\n", kernelCacheFile);
368
369}
370// Snow Leopard prelink kernel cache file
371else if ( MacOSVerCurrent >= MacOSVer2Int("10.6") && MacOSVerCurrent < MacOSVer2Int("10.7") )
372{
373snprintf(kernelCacheFile, sizeof(kernelCacheFile), "kernelcache_%s",
374(archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64");
375
376intlnam = strlen(kernelCacheFile) + 9; //with adler32
377char*name;
378u_int32_tprev_time = 0;
379
380struct dirstuff *cacheDir = opendir(kDefaultCachePathSnow);
381
382/* TODO: handle error? */
383if (cacheDir)
384{
385while(readdir(cacheDir, (const char**)&name, &flags, &time) >= 0)
386{
387if (((flags & kFileTypeMask) != kFileTypeDirectory) && time > prev_time
388&& strstr(name, kernelCacheFile) && (name[lnam] != '.'))
389{
390snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%s%s", kDefaultCachePathSnow, name);
391prev_time = time;
392}
393}
394verbose("Kernel Cache file path (Mac OS X 10.6): %s\n", kernelCacheFile);
395}
396closedir(cacheDir);
397}
398else if ( MacOSVerCurrent >= MacOSVer2Int("10.7") && MacOSVerCurrent < MacOSVer2Int("10.10") )
399{
400// Lion, Mountain Lion and Mavericks prelink kernel cache file
401// for 10.7 10.8 10.9
402snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%skernelcache", kDefaultCachePathSnow);
403verbose("Kernel Cache file path (Mac OS X 10.7 and newer): %s\n", kernelCacheFile);
404
405}
406else
407{
408// Yosemite and El Capitan prelink kernel cache file
409// for 10.10 10.11
410snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%sprelinkedkernel", kDefaultCachePathYosemite);
411verbose("Kernel Cache file path (Mac OS X 10.10 and newer): %s\n", kernelCacheFile);
412}
413}
414
415// Check if the kernel cache file exists
416ret = -1;
417
418if (gBootVolume->flags & kBVFlagBooter)
419{
420snprintf(kernelCachePath, sizeof(kernelCachePath), "/com.apple.boot.P/%s", kernelCacheFile);
421ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
422
423if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat))
424{
425snprintf(kernelCachePath, sizeof(kernelCachePath), "/com.apple.boot.R/%s", kernelCacheFile);
426ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
427
428if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat))
429{
430snprintf(kernelCachePath, sizeof(kernelCachePath), "/com.apple.boot.S/%s", kernelCacheFile);
431ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
432
433if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat))
434{
435strncpy(kernelCachePath, "/com.apple.recovery.boot/kernelcache", sizeof(kernelCachePath) );
436ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
437
438if ((flags & kFileTypeMask) != kFileTypeFlat)
439{
440ret = -1;
441}
442}
443}
444}
445}
446
447// If not found, use the original kernel cache path.
448if (ret == -1)
449{
450strlcpy(kernelCachePath, kernelCacheFile, sizeof(kernelCachePath));
451ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
452
453if ((flags & kFileTypeMask) != kFileTypeFlat)
454{
455ret = -1;
456}
457}
458
459// Exit if kernel cache file wasn't found
460if (ret == -1)
461{
462DBG("No Kernel Cache File '%s' found\n", kernelCacheFile);
463return -1;
464}
465
466// Check if the kernel cache file is more recent (mtime)
467// than the kernel file or the S/L/E directory
468ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
469
470// Check if the kernel file is more recent than the cache file
471if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat) && (kerneltime > cachetime))
472{
473DBG("Kernel file '%s' is more recent than Kernel Cache '%s'! Ignoring Kernel Cache.\n", bootInfo->bootFile, kernelCacheFile);
474return -1;
475}
476
477ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
478
479// Check if the S/L/E directory time is more recent than the cache file
480if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) && (exttime > cachetime))
481{
482DBG("Folder '/System/Library/Extensions' is more recent than Kernel Cache file '%s'! Ignoring Kernel Cache.\n", kernelCacheFile);
483return -1;
484}
485
486// Since the kernel cache file exists and is the most recent try to load it
487DBG("Loading Kernel Cache from: '%s%s' (%s)\n", gBootVolume->label, gBootVolume->altlabel, gBootVolume->type_name);
488
489ret = LoadThinFatFile(kernelCachePath, binary);
490return ret; // ret contain the length of the binary
491}
492
493//==========================================================================
494// This is the entrypoint from real-mode which functions exactly as it did
495// before. Multiboot does its own runtime initialization, does some of its
496// own things, and then calls common_boot.
497void boot(int biosdev)
498{
499// Enable A20 gate before accessing memory above 1Mb.
500// Note: malloc_init(), called via initialize_runtime() writes
501// memory >= 1Mb, so A20 must be enabled before calling it. - zenith432
502zeroBSS();
503enableA20();
504malloc_init(0, 0, 0, malloc_error);
505common_boot(biosdev);
506}
507
508//==========================================================================
509// The 'main' function for the booter. Called by boot0 when booting
510// from a block device, or by the network booter.
511//
512// arguments:
513// biosdev - Value passed from boot1/NBP to specify the device
514// that the booter was loaded from.
515//
516// If biosdev is kBIOSDevNetwork, then this function will return if
517// booting was unsuccessful. This allows the PXE firmware to try the
518// next boot device on its list.
519void common_boot(int biosdev)
520{
521bool quiet;
522bool firstRun = true;
523bool instantMenu;
524bool rescanPrompt;
525intstatus;
526unsigned intallowBVFlags = kBVFlagSystemVolume | kBVFlagForeignBoot;
527unsigned intdenyBVFlags = kBVFlagEFISystem;
528
529// Set reminder to unload the PXE base code. Neglect to unload
530// the base code will result in a hang or kernel panic.
531gUnloadPXEOnExit = true;
532
533// Record the device that the booter was loaded from.
534gBIOSDev = biosdev & kBIOSDevMask;
535
536// Initialize boot-log
537initBooterLog();
538
539#if DEBUG_INTERRUPTS
540// Enable interrupts
541interruptsAvailable = SetupInterrupts();
542if (interruptsAvailable)
543{
544EnableInterrupts();
545}
546#endif
547
548// Initialize boot info structure.
549initKernBootStruct();
550
551// Setup VGA text mode.
552// Not sure if it is safe to call setVideoMode() before the
553// config table has been loaded. Call video_mode() instead.
554#if DEBUG
555printf("before video_mode\n");
556#endif
557video_mode( 2 ); // 80x25 mono text mode.
558#if DEBUG
559printf("after video_mode\n");
560#endif
561
562// Scan and record the system's hardware information.
563scan_platform();
564
565// First get info for boot volume.
566scanBootVolumes(gBIOSDev, 0);
567bvChain = getBVChainForBIOSDev(gBIOSDev);
568setBootGlobals(bvChain);
569
570// Load boot.plist config file
571status = loadChameleonConfig(&bootInfo->chameleonConfig, bvChain);
572
573if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->chameleonConfig) && quiet)
574{
575gBootMode |= kBootModeQuiet;
576}
577
578// Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
579if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->chameleonConfig) && instantMenu)
580{
581firstRun = false;
582}
583
584// Loading preboot ramdisk if exists.
585loadPrebootRAMDisk();
586
587// Disable rescan option by default
588gEnableCDROMRescan = false;
589
590// Enable it with Rescan=y in system config
591if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->chameleonConfig)&& gEnableCDROMRescan)
592{
593gEnableCDROMRescan = true;
594}
595
596// Disable rescanPrompt option by default
597rescanPrompt = false;
598
599// Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
600if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->chameleonConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev))
601{
602gEnableCDROMRescan = promptForRescanOption();
603}
604
605// Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
606if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->chameleonConfig) && gScanSingleDrive)
607{
608gScanSingleDrive = true;
609}
610
611// Create a list of partitions on device(s).
612if (gScanSingleDrive)
613{
614scanBootVolumes(gBIOSDev, &bvCount);
615}
616else
617{
618scanDisks(gBIOSDev, &bvCount);
619}
620
621// Create a separated bvr chain using the specified filters.
622bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
623
624gBootVolume = selectBootVolume(bvChain);
625
626// Intialize module system
627init_module_system();
628
629#if DEBUG
630printf("Default: %d, ->biosdev: %d, ->part_no: %d ->flags: 0x%08X\n",
631gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
632printf("bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: 0x%08X\n",
633gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
634getchar();
635#endif
636
637useGUI = true;
638// Override useGUI default
639getBoolForKey(kGUIKey, &useGUI, &bootInfo->chameleonConfig);
640if (useGUI && initGUI())
641{
642// initGUI() returned with an error, disabling GUI.
643useGUI = false;
644}
645
646setBootGlobals(bvChain);
647
648// Parse args, load and start kernel.
649while (1)
650{
651booltryresume, tryresumedefault, forceresume;
652booluseKernelCache = true; // by default try to use the prelinked kernel
653const char*val;
654intlen, ret = -1;
655longflags;
656u_int32_tsleeptime, time;
657void*binary = (void *)kLoadAddr;
658
659charbootFile[sizeof(bootInfo->bootFile)];
660charbootFilePath[512];
661charkernelCacheFile[512];
662
663// Initialize globals.
664sysConfigValid = false;
665gErrors = false;
666
667status = getBootOptions(firstRun);
668firstRun = false;
669if (status == -1) continue;
670
671status = processBootOptions();
672// Status == 1 means to chainboot
673if ( status ==1 ) break;
674// Status == -1 means that the config file couldn't be loaded or that gBootVolume is NULL
675if ( status == -1 )
676{
677// gBootVolume == NULL usually means the user hit escape.
678if (gBootVolume == NULL)
679{
680freeFilteredBVChain(bvChain);
681
682if (gEnableCDROMRescan)
683rescanBIOSDevice(gBIOSDev);
684
685bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
686setBootGlobals(bvChain);
687setupDeviceList(&bootInfo->themeConfig);
688}
689continue;
690}
691
692// Other status (e.g. 0) means that we should proceed with boot.
693
694// Turn off any GUI elements
695if ( bootArgs->Video.v_display == GRAPHICS_MODE )
696{
697gui.devicelist.draw = false;
698gui.bootprompt.draw = false;
699gui.menu.draw = false;
700gui.infobox.draw = false;
701gui.logo.draw = false;
702drawBackground();
703updateVRAM();
704}
705
706if (platformCPUFeature(CPU_FEATURE_EM64T))
707{
708archCpuType = CPU_TYPE_X86_64;
709}
710else
711{
712archCpuType = CPU_TYPE_I386;
713}
714
715if (getValueForKey(karch, &val, &len, &bootInfo->chameleonConfig))
716{
717if (strncmp(val, "x86_64", sizeof("x86_64") ) == 0)
718{
719archCpuType = CPU_TYPE_X86_64;
720}
721else if (strncmp(val, "i386", sizeof("i386") ) == 0)
722{
723archCpuType = CPU_TYPE_I386;
724}
725else
726{
727DBG("Incorrect parameter for option 'arch =' , please use x86_64 or i386\n");
728}
729}
730
731if (getValueForKey(kKernelArchKey, &val, &len, &bootInfo->chameleonConfig))
732{
733if (strncmp(val, "i386", sizeof("i386") ) == 0)
734{
735archCpuType = CPU_TYPE_I386;
736}
737}
738
739// Notify modules that we are attempting to boot
740execute_hook("PreBoot", NULL, NULL, NULL, NULL);
741
742if (!getBoolForKey (kWake, &tryresume, &bootInfo->chameleonConfig))
743{
744tryresume = true;
745tryresumedefault = true;
746}
747else
748{
749tryresumedefault = false;
750}
751
752if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->chameleonConfig))
753{
754forceresume = false;
755}
756
757if (forceresume)
758{
759tryresume = true;
760tryresumedefault = false;
761}
762
763while (tryresume)
764{
765const char *tmp;
766BVRef bvr;
767if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->chameleonConfig))
768val = "/private/var/vm/sleepimage";
769
770// Do this first to be sure that root volume is mounted
771ret = GetFileInfo(0, val, &flags, &sleeptime);
772
773if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
774break;
775
776// Can't check if it was hibernation Wake=y is required
777if (bvr->modTime == 0 && tryresumedefault)
778break;
779
780if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
781break;
782
783if (!forceresume && ((sleeptime+3)<bvr->modTime))
784{
785#if DEBUG
786printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",
787bvr->modTime-sleeptime);
788#endif
789break;
790}
791
792HibernateBoot((char *)val);
793break;
794}
795
796getBoolForKey(kUseKernelCache, &useKernelCache, &bootInfo->chameleonConfig);
797if (useKernelCache)
798{
799do
800{
801// Determine the name of the Kernel Cache
802if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig))
803{
804if (val[0] == '\\')
805{
806len--;
807val++;
808}
809/* FIXME: check len vs sizeof(kernelCacheFile) */
810strlcpy(kernelCacheFile, val, len + 1);
811}
812else
813{
814kernelCacheFile[0] = 0; // Use default kernel cache file
815}
816
817if (gOverrideKernel && kernelCacheFile[0] == 0)
818{
819DBG("Using a non default kernel (%s) without specifying 'Kernel Cache' path, KernelCache will not be used\n", bootInfo->bootFile);
820useKernelCache = false;
821break;
822}
823
824if (gMKextName[0] != 0)
825{
826DBG("Using a specific MKext Cache (%s), KernelCache will not be used\n", gMKextName);
827useKernelCache = false;
828break;
829}
830
831if (gBootFileType != kBlockDeviceType)
832{
833useKernelCache = false;
834}
835
836} while(0);
837}
838else
839{
840DBG("Kernel Cache using disabled by user.\n");
841}
842
843do
844{
845if (useKernelCache)
846{
847ret = LoadKernelCache(kernelCacheFile, &binary);
848if (ret >= 0)
849{
850break;
851}
852}
853
854bool bootFileWithDevice = false;
855// Check if bootFile start with a device ex: bt(0,0)/Extra/mach_kernel
856if (strncmp(bootInfo->bootFile, "bt(", sizeof("bt(") ) == 0 ||
857strncmp(bootInfo->bootFile, "hd(", sizeof("hd(") ) == 0 ||
858strncmp(bootInfo->bootFile, "rd(", sizeof("rd(") ) == 0)
859{
860bootFileWithDevice = true;
861}
862
863// bootFile must start with a / if it not start with a device name
864if (!bootFileWithDevice && (bootInfo->bootFile)[0] != '/')
865{
866if ( !YOSEMITE && !ELCAPITAN ) //Is not Yosemite 10.10 or El Capitan 10.11
867{
868snprintf(bootFile, sizeof(bootFile), "/%s", bootInfo->bootFile); // append a leading /
869}
870else
871{
872snprintf(bootFile, sizeof(bootFile), kDefaultKernelPathForYos"%s", bootInfo->bootFile); // Yosemite or El Capitan
873}
874}
875else
876{
877strlcpy(bootFile, bootInfo->bootFile, sizeof(bootFile));
878}
879
880// Try to load kernel image from alternate locations on boot helper partitions.
881ret = -1;
882if ((gBootVolume->flags & kBVFlagBooter) && !bootFileWithDevice)
883{
884snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.P%s", bootFile);
885ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
886if (ret == -1)
887{
888snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.R%s", bootFile);
889ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
890if (ret == -1)
891{
892snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.S%s", bootFile);
893ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
894}
895}
896}
897if (ret == -1)
898{
899// No alternate location found, using the original kernel image path.
900strlcpy(bootFilePath, bootFile, sizeof(bootFilePath));
901}
902
903DBG("Loading kernel from: '%s' (%s)\n", gBootVolume->label, gBootVolume->type_name);
904ret = LoadThinFatFile(bootFilePath, &binary);
905if (ret <= 0 && archCpuType == CPU_TYPE_X86_64)
906{
907archCpuType = CPU_TYPE_I386;
908ret = LoadThinFatFile(bootFilePath, &binary);
909}
910} while (0);
911
912clearActivityIndicator();
913
914#if DEBUG
915printf("Pausing...");
916sleep(8);
917#endif
918
919if (ret <= 0)
920{
921printf("Can't find boot file: '%s'\n", bootFile);
922sleep(1);
923
924if (gBootFileType == kNetworkDeviceType)
925{
926// Return control back to PXE. Don't unload PXE base code.
927gUnloadPXEOnExit = false;
928break;
929}
930pause();
931
932}
933else
934{
935/* Won't return if successful. */
936ret = ExecKernel(binary);
937}
938}
939
940// chainboot
941if (status == 1)
942{
943// if we are already in graphics-mode,
944if (getVideoMode() == GRAPHICS_MODE)
945{
946setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode.
947}
948}
949
950if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit)
951{
952nbpUnloadBaseCode();
953}
954
955#if DEBUG_INTERRUPTS
956if (interruptsAvailable)
957{
958DisableInterrupts();
959}
960#endif
961
962}
963
964
965// =========================================================================
966
967/*!
968Selects a new BIOS device, taking care to update the global state appropriately.
969 */
970/*
971static void selectBiosDevice(void)
972{
973struct DiskBVMap *oldMap = diskResetBootVolumes(gBIOSDev);
974CacheReset();
975diskFreeMap(oldMap);
976oldMap = NULL;
977
978int dev = selectAlternateBootDevice(gBIOSDev);
979
980BVRef bvchain = scanBootVolumes(dev, 0);
981BVRef bootVol = selectBootVolume(bvchain);
982gBootVolume = bootVol;
983setRootVolume(bootVol);
984gBIOSDev = dev;
985}
986*/
987
988// =========================================================================
989bool checkOSVersion(const char *version)
990{
991if ( '\0' != version[4] )
992{
993return !memcmp(&gMacOSVersion[0], &version[0], 5);
994}
995else
996{
997return !memcmp(&gMacOSVersion[0], &version[0], 4);
998}
999}
1000
1001uint32_t getMacOSVerCurrent()
1002{
1003MacOSVerCurrent = MacOSVer2Int(gBootVolume->OSVersion);
1004return MacOSVerCurrent;
1005}
1006
1007// =========================================================================
1008unsigned long Adler32(unsigned char *buf, long len)
1009{
1010#define BASE 65521L /* largest prime smaller than 65536 */
1011#define NMAX 5000
1012// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
1013
1014#define DO1(buf, i){s1 += buf[i]; s2 += s1;}
1015#define DO2(buf, i)DO1(buf, i); DO1(buf, i + 1);
1016#define DO4(buf, i)DO2(buf, i); DO2(buf, i + 2);
1017#define DO8(buf, i)DO4(buf, i); DO4(buf, i + 4);
1018#define DO16(buf)DO8(buf, 0); DO8(buf, 8);
1019
1020int k;
1021
1022unsigned long s1 = 1; // adler & 0xffff;
1023unsigned long s2 = 0; // (adler >> 16) & 0xffff;
1024unsigned long result;
1025
1026while (len > 0) {
1027k = len < NMAX ? len : NMAX;
1028len -= k;
1029while (k >= 16)
1030{
1031DO16(buf);
1032buf += 16;
1033k -= 16;
1034}
1035
1036if (k != 0)
1037{
1038do
1039{
1040s1 += *buf++;
1041s2 += s1;
1042} while (--k);
1043}
1044
1045s1 %= BASE;
1046s2 %= BASE;
1047}
1048
1049result = (s2 << 16) | s1;
1050
1051return OSSwapHostToBigInt32(result);
1052}
1053

Archive Download this file

Revision: 2815