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

Archive Download this file

Revision: 2564