Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2597