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