Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/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
155 // OS X Mountain Lion 10.8
156if ( MacOSVerCurrent >= MacOSVer2Int("10.8") ) // Mountain Lion and Up!
157{
158// cparm
159bool KPRebootOption= false;
160bool HiDPIOption= false;
161getBoolForKey(kRebootOnPanic, &KPRebootOption, &bootInfo->chameleonConfig);
162if ( KPRebootOption )
163{
164bootArgs->flags |= kBootArgsFlagRebootOnPanic;
165}
166
167// cparm
168getBoolForKey(kEnableHiDPI, &HiDPIOption, &bootInfo->chameleonConfig);
169
170if ( HiDPIOption )
171{
172bootArgs->flags |= kBootArgsFlagHiDPI;
173}
174}
175
176// OS X Yosemite 10.10
177if ( MacOSVerCurrent >= MacOSVer2Int("10.10") ) // Yosemite and Up!
178{
179// Pike R. Alpha
180bool FlagBlackOption= false;
181getBoolForKey(kBlackMode, &FlagBlackOption, &bootInfo->chameleonConfig);
182if ( FlagBlackOption )
183{
184//bootArgs->flags |= kBootArgsFlagBlack;
185bootArgs->flags |= kBootArgsFlagBlackBg; // Micky1979
186}
187}
188
189// OS X El Capitan 10.11
190if ( MacOSVerCurrent >= MacOSVer2Int("10.11") ) // El Capitan and Up!
191{
192// ErmaC
193intcrsValue;
194
195#if 0
196/*
197 * A special BootArgs flag "kBootArgsFlagCSRBoot"
198 * is set in the Recovery or Installation environment.
199 * This flag is kind of overkill by turning off all the protections
200 */
201
202if (isRecoveryHD)
203{
204// SIP can be controlled with or without FileNVRAM.kext (Pike R. Alpha)
205bootArgs->flags|=(kBootArgsFlagCSRActiveConfig + kBootArgsFlagCSRConfigMode + kBootArgsFlagCSRBoot);
206}
207#endif
208
209bootArgs->flags|= kBootArgsFlagCSRActiveConfig;
210
211// Set limit to 7bit
212if ( getIntForKey(kCsrActiveConfig, &crsValue, &bootInfo->chameleonConfig) && (crsValue >= 0 && crsValue <= 127) )
213{
214bootArgs->csrActiveConfig= crsValue;
215}
216else
217{
218// zenith432
219bootArgs->csrActiveConfig= 0x67;
220}
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 );
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
323startprog( kernelEntry, bootArgs );
324}
325
326// Not reached
327__builtin_unreachable();
328}
329
330//==========================================================================
331// LoadKernelCache - Try to load Kernel Cache.
332// return the length of the loaded cache file or -1 on error
333long LoadKernelCache(const char *cacheFile, void **binary)
334{
335charkernelCacheFile[512];
336charkernelCachePath[512];
337longflags, ret=-1;
338unsigned longadler32 = 0;
339u_int32_t time, cachetime, kerneltime, exttime;
340
341if((gBootMode & kBootModeSafe) != 0)
342{
343DBG("Kernel Cache ignored.\n");
344return -1;
345}
346
347// Use specify kernel cache file if not empty
348if (cacheFile[0] != 0)
349{
350strlcpy(kernelCacheFile, cacheFile, sizeof(kernelCacheFile));
351verbose("Specified kernel cache file path: %s\n", cacheFile);
352}
353else
354{
355// Leopard prelink kernel cache file
356if ( MacOSVerCurrent >= MacOSVer2Int("10.4") && MacOSVerCurrent <= MacOSVer2Int("10.5") ) // OSX is 10.4 or 10.5
357{
358// Reset cache name.
359bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
360snprintf(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64, "%s,%s", gRootDevice, bootInfo->bootFile);
361adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
362snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%s.%08lX", kDefaultCachePathLeo, adler32);
363verbose("Reseted kernel cache file path: %s\n", kernelCacheFile);
364
365}
366// Snow Leopard prelink kernel cache file
367else if ( MacOSVerCurrent >= MacOSVer2Int("10.6") && MacOSVerCurrent < MacOSVer2Int("10.7") )
368{
369snprintf(kernelCacheFile, sizeof(kernelCacheFile), "kernelcache_%s",
370(archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64");
371
372intlnam = strlen(kernelCacheFile) + 9; //with adler32
373char*name;
374u_int32_tprev_time = 0;
375
376struct dirstuff *cacheDir = opendir(kDefaultCachePathSnow);
377
378/* TODO: handle error? */
379if (cacheDir)
380{
381while(readdir(cacheDir, (const char**)&name, &flags, &time) >= 0)
382{
383if (((flags & kFileTypeMask) != kFileTypeDirectory) && time > prev_time
384&& strstr(name, kernelCacheFile) && (name[lnam] != '.'))
385{
386snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%s%s", kDefaultCachePathSnow, name);
387prev_time = time;
388}
389}
390verbose("Kernel Cache file path (Mac OS X 10.6): %s\n", kernelCacheFile);
391}
392closedir(cacheDir);
393}
394else if ( MacOSVerCurrent >= MacOSVer2Int("10.7") && MacOSVerCurrent < MacOSVer2Int("10.10") )
395{
396// Lion, Mountain Lion and Mavericks prelink kernel cache file
397// for 10.7 10.8 10.9
398snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%skernelcache", kDefaultCachePathSnow);
399verbose("Kernel Cache file path (Mac OS X 10.7 and newer): %s\n", kernelCacheFile);
400
401}
402else
403{
404// Yosemite and El Capitan prelink kernel cache file
405// for 10.10 10.11
406snprintf(kernelCacheFile, sizeof(kernelCacheFile), "%sprelinkedkernel", kDefaultCachePathYosemite);
407verbose("Kernel Cache file path (OS X 10.10 and newer): %s\n", kernelCacheFile);
408}
409}
410
411// Check if the kernel cache file exists
412ret = -1;
413
414if (gBootVolume->flags & kBVFlagBooter)
415{
416snprintf(kernelCachePath, sizeof(kernelCachePath), "/com.apple.boot.P/%s", kernelCacheFile);
417ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
418
419if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat))
420{
421snprintf(kernelCachePath, sizeof(kernelCachePath), "/com.apple.boot.R/%s", kernelCacheFile);
422ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
423
424if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat))
425{
426snprintf(kernelCachePath, sizeof(kernelCachePath), "/com.apple.boot.S/%s", kernelCacheFile);
427ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
428
429if ((ret == -1) || ((flags & kFileTypeMask) != kFileTypeFlat))
430{
431strncpy(kernelCachePath, "/com.apple.recovery.boot/kernelcache", sizeof(kernelCachePath) );
432ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
433
434if ((flags & kFileTypeMask) != kFileTypeFlat)
435{
436ret = -1;
437}
438}
439}
440}
441}
442
443// If not found, use the original kernel cache path.
444if (ret == -1)
445{
446strlcpy(kernelCachePath, kernelCacheFile, sizeof(kernelCachePath));
447ret = GetFileInfo(NULL, kernelCachePath, &flags, &cachetime);
448
449if ((flags & kFileTypeMask) != kFileTypeFlat)
450{
451ret = -1;
452}
453}
454
455// Exit if kernel cache file wasn't found
456if (ret == -1)
457{
458DBG("No Kernel Cache File '%s' found\n", kernelCacheFile);
459return -1;
460}
461
462// Check if the kernel cache file is more recent (mtime)
463// than the kernel file or the S/L/E directory
464ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
465
466// Check if the kernel file is more recent than the cache file
467if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat) && (kerneltime > cachetime))
468{
469DBG("Kernel file '%s' is more recent than Kernel Cache '%s'! Ignoring Kernel Cache.\n", bootInfo->bootFile, kernelCacheFile);
470return -1;
471}
472
473ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
474
475// Check if the S/L/E directory time is more recent than the cache file
476if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) && (exttime > cachetime))
477{
478DBG("Folder '/System/Library/Extensions' is more recent than Kernel Cache file '%s'! Ignoring Kernel Cache.\n", kernelCacheFile);
479return -1;
480}
481
482// Since the kernel cache file exists and is the most recent try to load it
483DBG("Loading Kernel Cache from: '%s%s' (%s)\n", gBootVolume->label, gBootVolume->altlabel, gBootVolume->type_name);
484
485ret = LoadThinFatFile(kernelCachePath, binary);
486return ret; // ret contain the length of the binary
487}
488
489//==========================================================================
490// This is the entrypoint from real-mode which functions exactly as it did
491// before. Multiboot does its own runtime initialization, does some of its
492// own things, and then calls common_boot.
493void boot(int biosdev)
494{
495// Enable A20 gate before accessing memory above 1Mb.
496// Note: malloc_init(), called via initialize_runtime() writes
497// memory >= 1Mb, so A20 must be enabled before calling it. - zenith432
498enableA20();
499initialize_runtime();
500common_boot(biosdev);
501}
502
503//==========================================================================
504// The 'main' function for the booter. Called by boot0 when booting
505// from a block device, or by the network booter.
506//
507// arguments:
508// biosdev - Value passed from boot1/NBP to specify the device
509// that the booter was loaded from.
510//
511// If biosdev is kBIOSDevNetwork, then this function will return if
512// booting was unsuccessful. This allows the PXE firmware to try the
513// next boot device on its list.
514void common_boot(int biosdev)
515{
516bool quiet;
517bool firstRun = true;
518bool instantMenu;
519bool rescanPrompt;
520intstatus;
521unsigned intallowBVFlags = kBVFlagSystemVolume | kBVFlagForeignBoot;
522unsigned intdenyBVFlags = kBVFlagEFISystem;
523
524// Set reminder to unload the PXE base code. Neglect to unload
525// the base code will result in a hang or kernel panic.
526gUnloadPXEOnExit = true;
527
528// Record the device that the booter was loaded from.
529gBIOSDev = biosdev & kBIOSDevMask;
530
531// Initialize boot-log
532initBooterLog();
533
534#if DEBUG_INTERRUPTS
535// Enable interrupts
536interruptsAvailable = SetupInterrupts();
537if (interruptsAvailable)
538{
539EnableInterrupts();
540}
541#endif
542
543// Initialize boot info structure.
544initKernBootStruct();
545
546// Setup VGA text mode.
547// Not sure if it is safe to call setVideoMode() before the
548// config table has been loaded. Call video_mode() instead.
549#if DEBUG
550printf("before video_mode\n");
551#endif
552video_mode( 2 ); // 80x25 mono text mode.
553#if DEBUG
554printf("after video_mode\n");
555#endif
556
557// Scan and record the system's hardware information.
558scan_platform();
559
560// First get info for boot volume.
561scanBootVolumes(gBIOSDev, 0);
562bvChain = getBVChainForBIOSDev(gBIOSDev);
563setBootGlobals(bvChain);
564
565// Load boot.plist config file
566status = loadChameleonConfig(&bootInfo->chameleonConfig, bvChain);
567
568if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->chameleonConfig) && quiet)
569{
570gBootMode |= kBootModeQuiet;
571}
572
573// Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
574if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->chameleonConfig) && instantMenu)
575{
576firstRun = false;
577}
578
579// Loading preboot ramdisk if exists.
580loadPrebootRAMDisk();
581
582// Disable rescan option by default
583gEnableCDROMRescan = false;
584
585// Enable it with Rescan=y in system config
586if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->chameleonConfig)&& gEnableCDROMRescan)
587{
588gEnableCDROMRescan = true;
589}
590
591// Disable rescanPrompt option by default
592rescanPrompt = false;
593
594// Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
595if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->chameleonConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev))
596{
597gEnableCDROMRescan = promptForRescanOption();
598}
599
600// Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
601if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->chameleonConfig) && gScanSingleDrive)
602{
603gScanSingleDrive = true;
604}
605
606// Create a list of partitions on device(s).
607if (gScanSingleDrive)
608{
609scanBootVolumes(gBIOSDev, &bvCount);
610}
611else
612{
613scanDisks(gBIOSDev, &bvCount);
614}
615
616// Create a separated bvr chain using the specified filters.
617bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
618
619gBootVolume = selectBootVolume(bvChain);
620
621// Intialize module system
622init_module_system();
623
624#if DEBUG
625printf("Default: %d, ->biosdev: %d, ->part_no: %d ->flags: 0x%08X\n",
626gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
627printf("bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: 0x%08X\n",
628gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
629getchar();
630#endif
631
632useGUI = true;
633// Override useGUI default
634getBoolForKey(kGUIKey, &useGUI, &bootInfo->chameleonConfig);
635if (useGUI && initGUI())
636{
637// initGUI() returned with an error, disabling GUI.
638useGUI = false;
639}
640
641setBootGlobals(bvChain);
642
643// Parse args, load and start kernel.
644while (1)
645{
646booltryresume, tryresumedefault, forceresume;
647booluseKernelCache = true; // by default try to use the prelinked kernel
648const char*val;
649intlen, ret = -1;
650longflags;
651u_int32_tsleeptime, time;
652void*binary = (void *)kLoadAddr;
653
654charbootFile[sizeof(bootInfo->bootFile)];
655charbootFilePath[512];
656charkernelCacheFile[512];
657
658// Initialize globals.
659sysConfigValid = false;
660gErrors = false;
661
662status = getBootOptions(firstRun);
663firstRun = false;
664if (status == -1) continue;
665
666status = processBootOptions();
667// Status == 1 means to chainboot
668if ( status ==1 ) break;
669// Status == -1 means that the config file couldn't be loaded or that gBootVolume is NULL
670if ( status == -1 )
671{
672// gBootVolume == NULL usually means the user hit escape.
673if (gBootVolume == NULL)
674{
675freeFilteredBVChain(bvChain);
676
677if (gEnableCDROMRescan)
678rescanBIOSDevice(gBIOSDev);
679
680bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
681setBootGlobals(bvChain);
682setupDeviceList(&bootInfo->themeConfig);
683}
684continue;
685}
686
687// Other status (e.g. 0) means that we should proceed with boot.
688
689// Turn off any GUI elements
690if ( bootArgs->Video.v_display == GRAPHICS_MODE )
691{
692gui.devicelist.draw = false;
693gui.bootprompt.draw = false;
694gui.menu.draw = false;
695gui.infobox.draw = false;
696gui.logo.draw = false;
697drawBackground();
698updateVRAM();
699}
700
701if (platformCPUFeature(CPU_FEATURE_EM64T))
702{
703archCpuType = CPU_TYPE_X86_64;
704}
705else
706{
707archCpuType = CPU_TYPE_I386;
708}
709
710if (getValueForKey(karch, &val, &len, &bootInfo->chameleonConfig))
711{
712if (strncmp(val, "x86_64", sizeof("x86_64") ) == 0)
713{
714archCpuType = CPU_TYPE_X86_64;
715}
716else if (strncmp(val, "i386", sizeof("i386") ) == 0)
717{
718archCpuType = CPU_TYPE_I386;
719}
720else
721{
722DBG("Incorrect parameter for option 'arch =' , please use x86_64 or i386\n");
723}
724}
725
726if (getValueForKey(kKernelArchKey, &val, &len, &bootInfo->chameleonConfig))
727{
728if (strncmp(val, "i386", sizeof("i386") ) == 0)
729{
730archCpuType = CPU_TYPE_I386;
731}
732}
733
734// Notify modules that we are attempting to boot
735execute_hook("PreBoot", NULL, NULL, NULL, NULL);
736
737if (!getBoolForKey (kWake, &tryresume, &bootInfo->chameleonConfig))
738{
739tryresume = true;
740tryresumedefault = true;
741}
742else
743{
744tryresumedefault = false;
745}
746
747if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->chameleonConfig))
748{
749forceresume = false;
750}
751
752if (forceresume)
753{
754tryresume = true;
755tryresumedefault = false;
756}
757
758while (tryresume)
759{
760const char *tmp;
761BVRef bvr;
762if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->chameleonConfig))
763val = "/private/var/vm/sleepimage";
764
765// Do this first to be sure that root volume is mounted
766ret = GetFileInfo(0, val, &flags, &sleeptime);
767
768if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
769break;
770
771// Can't check if it was hibernation Wake=y is required
772if (bvr->modTime == 0 && tryresumedefault)
773break;
774
775if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
776break;
777
778if (!forceresume && ((sleeptime+3)<bvr->modTime))
779{
780#if DEBUG
781printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",
782bvr->modTime-sleeptime);
783#endif
784break;
785}
786
787HibernateBoot((char *)val);
788break;
789}
790
791getBoolForKey(kUseKernelCache, &useKernelCache, &bootInfo->chameleonConfig);
792if (useKernelCache)
793{
794do
795{
796// Determine the name of the Kernel Cache
797if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig))
798{
799if (val[0] == '\\')
800{
801len--;
802val++;
803}
804/* FIXME: check len vs sizeof(kernelCacheFile) */
805strlcpy(kernelCacheFile, val, len + 1);
806}
807else
808{
809kernelCacheFile[0] = 0; // Use default kernel cache file
810}
811
812if (gOverrideKernel && kernelCacheFile[0] == 0)
813{
814DBG("Using a non default kernel (%s) without specifying 'Kernel Cache' path, KernelCache will not be used\n", bootInfo->bootFile);
815useKernelCache = false;
816break;
817}
818
819if (gMKextName[0] != 0)
820{
821DBG("Using a specific MKext Cache (%s), KernelCache will not be used\n", gMKextName);
822useKernelCache = false;
823break;
824}
825
826if (gBootFileType != kBlockDeviceType)
827{
828useKernelCache = false;
829}
830
831} while(0);
832}
833else
834{
835DBG("Kernel Cache using disabled by user.\n");
836}
837
838do
839{
840if (useKernelCache)
841{
842ret = LoadKernelCache(kernelCacheFile, &binary);
843if (ret >= 0)
844{
845break;
846}
847}
848
849bool bootFileWithDevice = false;
850// Check if bootFile start with a device ex: bt(0,0)/Extra/mach_kernel
851if (strncmp(bootInfo->bootFile, "bt(", sizeof("bt(") ) == 0 ||
852strncmp(bootInfo->bootFile, "hd(", sizeof("hd(") ) == 0 ||
853strncmp(bootInfo->bootFile, "rd(", sizeof("rd(") ) == 0)
854{
855bootFileWithDevice = true;
856}
857
858// bootFile must start with a / if it not start with a device name
859if (!bootFileWithDevice && (bootInfo->bootFile)[0] != '/')
860{
861if ( !YOSEMITE || !ELCAPITAN ) //Is not Yosemite 10.10 or El Capitan 10.11
862{
863snprintf(bootFile, sizeof(bootFile), "/%s", bootInfo->bootFile); // append a leading /
864}
865else
866{
867snprintf(bootFile, sizeof(bootFile), kDefaultKernelPathForYos"%s", bootInfo->bootFile); // Yosemite or El Capitan
868}
869}
870else
871{
872strlcpy(bootFile, bootInfo->bootFile, sizeof(bootFile));
873}
874
875// Try to load kernel image from alternate locations on boot helper partitions.
876ret = -1;
877if ((gBootVolume->flags & kBVFlagBooter) && !bootFileWithDevice)
878{
879snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.P%s", bootFile);
880ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
881if (ret == -1)
882{
883snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.R%s", bootFile);
884ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
885if (ret == -1)
886{
887snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.S%s", bootFile);
888ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
889}
890}
891}
892if (ret == -1)
893{
894// No alternate location found, using the original kernel image path.
895strlcpy(bootFilePath, bootFile, sizeof(bootFilePath));
896}
897
898DBG("Loading kernel from: '%s' (%s)\n", gBootVolume->label, gBootVolume->type_name);
899ret = LoadThinFatFile(bootFilePath, &binary);
900if (ret <= 0 && archCpuType == CPU_TYPE_X86_64)
901{
902archCpuType = CPU_TYPE_I386;
903ret = LoadThinFatFile(bootFilePath, &binary);
904}
905} while (0);
906
907clearActivityIndicator();
908
909#if DEBUG
910printf("Pausing...");
911sleep(8);
912#endif
913
914if (ret <= 0)
915{
916printf("Can't find boot file: '%s'\n", bootFile);
917sleep(1);
918
919if (gBootFileType == kNetworkDeviceType)
920{
921// Return control back to PXE. Don't unload PXE base code.
922gUnloadPXEOnExit = false;
923break;
924}
925pause();
926
927}
928else
929{
930/* Won't return if successful. */
931ret = ExecKernel(binary);
932}
933}
934
935// chainboot
936if (status == 1)
937{
938// if we are already in graphics-mode,
939if (getVideoMode() == GRAPHICS_MODE)
940{
941setVideoMode( VGA_TEXT_MODE ); // switch back to text mode.
942}
943}
944
945if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit)
946{
947nbpUnloadBaseCode();
948}
949
950#if DEBUG_INTERRUPTS
951if (interruptsAvailable)
952{
953DisableInterrupts();
954}
955#endif
956
957}
958
959
960// =========================================================================
961
962/*!
963Selects a new BIOS device, taking care to update the global state appropriately.
964 */
965/*
966static void selectBiosDevice(void)
967{
968struct DiskBVMap *oldMap = diskResetBootVolumes(gBIOSDev);
969CacheReset();
970diskFreeMap(oldMap);
971oldMap = NULL;
972
973int dev = selectAlternateBootDevice(gBIOSDev);
974
975BVRef bvchain = scanBootVolumes(dev, 0);
976BVRef bootVol = selectBootVolume(bvchain);
977gBootVolume = bootVol;
978setRootVolume(bootVol);
979gBIOSDev = dev;
980}
981*/
982
983// =========================================================================
984bool checkOSVersion(const char *version)
985{
986if ( '\0' != version[4] )
987{
988return !memcmp(&gMacOSVersion[0], &version[0], 5);
989}
990else
991{
992return !memcmp(&gMacOSVersion[0], &version[0], 4);
993}
994}
995
996uint32_t getMacOSVerCurrent()
997{
998MacOSVerCurrent = MacOSVer2Int(gBootVolume->OSVersion);
999return MacOSVerCurrent;
1000}
1001
1002// =========================================================================
1003unsigned long Adler32(unsigned char *buf, long len)
1004{
1005#define BASE 65521L /* largest prime smaller than 65536 */
1006#define NMAX 5000
1007// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
1008
1009#define DO1(buf, i){s1 += buf[i]; s2 += s1;}
1010#define DO2(buf, i)DO1(buf, i); DO1(buf, i + 1);
1011#define DO4(buf, i)DO2(buf, i); DO2(buf, i + 2);
1012#define DO8(buf, i)DO4(buf, i); DO4(buf, i + 4);
1013#define DO16(buf)DO8(buf, 0); DO8(buf, 8);
1014
1015int k;
1016
1017unsigned long s1 = 1; // adler & 0xffff;
1018unsigned long s2 = 0; // (adler >> 16) & 0xffff;
1019unsigned long result;
1020
1021while (len > 0) {
1022k = len < NMAX ? len : NMAX;
1023len -= k;
1024while (k >= 16)
1025{
1026DO16(buf);
1027buf += 16;
1028k -= 16;
1029}
1030
1031if (k != 0)
1032{
1033do
1034{
1035s1 += *buf++;
1036s2 += s1;
1037} while (--k);
1038}
1039
1040s1 %= BASE;
1041s2 %= BASE;
1042}
1043
1044result = (s2 << 16) | s1;
1045
1046return OSSwapHostToBigInt32(result);
1047}
1048

Archive Download this file

Revision: 2808