Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/boot2/boot.c

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

Archive Download this file

Revision: 2060