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

Archive Download this file

Revision: 2835