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

Archive Download this file

Revision: 2111