Chameleon

Chameleon Svn Source Tree

Root/tags/2.1/i386/boot2/boot.c

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

Archive Download this file

Revision: 2381