Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/Chameleon/i386/boot2/boot.c

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

Archive Download this file

Revision: 307