]>
git.saurik.com Git - apple/boot.git/blob - i386/boot2/boot.c
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
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.
33 * INTEL CORPORATION PROPRIETARY INFORMATION
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.
39 * Copyright 1988, 1989 by Intel Corporation
43 * Copyright 1993 NeXT Computer, Inc.
44 * All rights reserved.
48 * Completely reworked by Sam Streeper (sam_s@NeXT.com)
49 * Reworked again by Curtis Galloway (galloway@NeXT.com)
54 #include "bootstruct.h"
59 long gBootMode
; /* defaults to 0 == kBootModeNormal */
61 static char gBootKernelCacheFile
[512];
62 static char gCacheNameAdler
[64 + 256];
63 char *gPlatformName
= gCacheNameAdler
;
64 char gRootDevice
[512];
69 unsigned long Adler32(unsigned char *buffer
, long length
);
72 static BOOL gUnloadPXEOnExit
= 0;
75 * How long to wait (in seconds) to load the
76 * kernel after displaying the "boot:" prompt.
78 #define kBootErrorTimeout 5
81 * Default path to kernel cache file
83 #define kDefaultCachePath "/System/Library/Caches/com.apple.kernelcaches/kernelcache"
85 //==========================================================================
90 extern char _DATA__bss__begin
, _DATA__bss__end
;
91 extern char _DATA__common__begin
, _DATA__common__end
;
93 bzero( &_DATA__bss__begin
,
94 (&_DATA__bss__end
- &_DATA__bss__begin
) );
96 bzero( &_DATA__common__begin
,
97 (&_DATA__common__end
- &_DATA__common__begin
) );
100 //==========================================================================
101 // Malloc error function
103 static void malloc_error(char *addr
, size_t size
)
105 printf("\nMemory allocation error (0x%x, 0x%x)\n",
106 (unsigned)addr
, (unsigned)size
);
107 asm volatile ("hlt");
110 //==========================================================================
111 // execKernel - Load the kernel image (mach-o) and jump to its entry point.
113 static int ExecKernel(void *binary
)
119 bootArgs
->kaddr
= bootArgs
->ksize
= 0;
121 ret
= DecodeKernel(binary
,
123 (char **) &bootArgs
->kaddr
,
124 (int *)&bootArgs
->ksize
);
129 // Reserve space for boot args
130 reserveKernBootStruct();
132 // Load boot drivers from the specifed root path.
134 if (!gHaveKernelCache
) {
138 clearActivityIndicator();
141 printf("Errors encountered while starting up the computer.\n");
142 printf("Pausing %d seconds...\n", kBootErrorTimeout
);
143 sleep(kBootErrorTimeout
);
146 printf("Starting Darwin/x86");
148 // Cleanup the PXE base code.
150 if ( (gBootFileType
== kNetworkDeviceType
) && gUnloadPXEOnExit
) {
151 if ( (ret
= nbpUnloadBaseCode()) != nbpStatusSuccess
)
153 printf("nbpUnloadBaseCode error %d\n", (int) ret
);
158 // Unless Boot Graphics = No, Always switch to graphics mode
159 // just before starting the kernel.
161 if (!getBoolForKey(kBootGraphicsKey
, &bootGraphics
)) {
166 if (bootArgs
->Video
.v_display
== VGA_TEXT_MODE
) {
167 // If we were in text mode, switch to graphics mode.
168 // This will draw the boot graphics unless we are in
170 setVideoMode( GRAPHICS_MODE
);
172 // If we were already in graphics mode, clear the screen.
176 // Always set text mode to initialize video fields
177 // in the boot args structure.
178 setVideoMode( VGA_TEXT_MODE
);
179 setCursorType( kCursorTypeHidden
);
182 finalizeBootStruct();
184 // Jump to kernel's entry point. There's no going back now.
186 startprog( kernelEntry
, bootArgs
);
193 //==========================================================================
194 // Scan and record the system's hardware information.
196 static void scanHardware()
198 extern int ReadPCIBusInfo(PCI_bus_info_t
*);
199 extern void PCI_Bus_Init(PCI_bus_info_t
*);
201 ReadPCIBusInfo( &bootInfo
->pciInfo
);
204 // Initialize PCI matching support in the booter.
205 // Not used, commented out to minimize code size.
207 // PCI_Bus_Init( &bootInfo->pciInfo );
210 //==========================================================================
211 // The 'main' function for the booter. Called by boot0 when booting
212 // from a block device, or by the network booter.
215 // biosdev - Value passed from boot1/NBP to specify the device
216 // that the booter was loaded from.
218 // If biosdev is kBIOSDevNetwork, then this function will return if
219 // booting was unsuccessful. This allows the PXE firmware to try the
220 // next boot device on its list.
222 #define DLOG(x) outb(0x80, (x))
224 void boot(int biosdev
)
228 unsigned long adler32
;
236 malloc_init(0, 0, 0, malloc_error
);
238 // Enable A20 gate before accessing memory above 1Mb.
242 // Set reminder to unload the PXE base code. Neglect to unload
243 // the base code will result in a hang or kernel panic.
245 gUnloadPXEOnExit
= 1;
247 // Record the device that the booter was loaded from.
249 gBIOSDev
= biosdev
& kBIOSDevMask
;
251 // Initialize boot info structure.
253 initKernBootStruct( gBIOSDev
);
255 // Setup VGA text mode.
256 // Not sure if it is safe to call setVideoMode() before the
257 // config table has been loaded. Call video_mode() instead.
260 printf("before video_mode\n");
262 video_mode( 2 ); // 80x25 mono text mode.
264 printf("after video_mode\n");
267 // Check to see that this hardware is supported.
268 status
= checkForSupportedHardware();
270 stop("This hardware configuration is not supported by Darwin/x86. (%d)", status
);
273 // Scan hardware configuration.
276 // First get info for boot volume.
277 bvChain
= scanBootVolumes(gBIOSDev
, 0);
279 // Record default boot device.
280 gBootVolume
= selectBootVolume(bvChain
);
281 bootInfo
->kernDev
= MAKEKERNDEV(gBIOSDev
,
282 BIOS_DEV_UNIT(gBootVolume
),
283 gBootVolume
->part_no
);
285 // Load default config file from boot device.
286 status
= loadSystemConfig(0, 0);
288 if ( getBoolForKey( kQuietBootKey
, &quiet
) && quiet
) {
289 gBootMode
|= kBootModeQuiet
;
292 // Parse args, load and start kernel.
299 long flags
, cachetime
, kerneltime
, exttime
;
301 void *binary
= (void *)kLoadAddr
;
303 // Initialize globals.
308 status
= getBootOptions(firstRun
);
310 if (status
== -1) continue;
312 status
= processBootOptions();
313 if ( status
== 1 ) break;
314 if ( status
== -1 ) continue;
316 // Found and loaded a config file. Proceed with boot.
320 bzero(gCacheNameAdler
+ 64, sizeof(gCacheNameAdler
) - 64);
322 sprintf(gCacheNameAdler
+ 64, "%s,%s", gRootDevice
, bootInfo
->bootFile
);
324 adler32
= Adler32((unsigned char *)gCacheNameAdler
, sizeof(gCacheNameAdler
));
326 if (getValueForKey(kKernelCacheKey
, &val
, &len
) == YES
) {
327 strlcpy(gBootKernelCacheFile
, val
, len
+1);
329 sprintf(gBootKernelCacheFile
, "%s.%08lX", kDefaultCachePath
, adler32
);
332 // Check for cache file.
334 trycache
= (((gBootMode
& kBootModeSafe
) == 0) &&
335 (gOverrideKernel
== NO
) &&
336 (gBootFileType
== kBlockDeviceType
) &&
337 (gMKextName
[0] == '\0') &&
338 (gBootKernelCacheFile
[0] != '\0'));
340 printf("Loading Darwin/x86\n");
344 // if we haven't found the kernel yet, don't use the cache
345 ret
= GetFileInfo(NULL
, bootInfo
->bootFile
, &flags
, &kerneltime
);
346 if ((ret
!= 0) || ((flags
& kFileTypeMask
) != kFileTypeFlat
)) {
350 ret
= GetFileInfo(NULL
, gBootKernelCacheFile
, &flags
, &cachetime
);
351 if ((ret
!= 0) || ((flags
& kFileTypeMask
) != kFileTypeFlat
)
352 || (cachetime
< kerneltime
)) {
356 ret
= GetFileInfo("/System/Library/", "Extensions", &flags
, &exttime
);
357 if ((ret
== 0) && ((flags
& kFileTypeMask
) == kFileTypeDirectory
)
358 && (cachetime
< exttime
)) {
362 if (kerneltime
> exttime
) {
363 exttime
= kerneltime
;
365 if (cachetime
!= (exttime
+ 1)) {
373 bootFile
= gBootKernelCacheFile
;
374 verbose("Loading kernel cache %s\n", bootFile
);
375 ret
= LoadFile(bootFile
);
376 binary
= (void *)kLoadAddr
;
381 bootFile
= bootInfo
->bootFile
;
382 verbose("Loading kernel %s\n", bootFile
);
383 ret
= LoadThinFatFile(bootFile
, &binary
);
386 clearActivityIndicator();
388 printf("Pausing...");
393 error("Can't find %s\n", bootFile
);
395 if ( gBootFileType
== kNetworkDeviceType
)
397 // Return control back to PXE. Don't unload PXE base code.
398 gUnloadPXEOnExit
= 0;
402 /* Won't return if successful. */
403 ret
= ExecKernel(binary
);
408 if ((gBootFileType
== kNetworkDeviceType
) && gUnloadPXEOnExit
) {
413 #define BASE 65521L /* largest prime smaller than 65536 */
415 // NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
417 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
418 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
419 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
420 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
421 #define DO16(buf) DO8(buf,0); DO8(buf,8);
423 unsigned long Adler32(unsigned char *buf
, long len
)
425 unsigned long s1
= 1; // adler & 0xffff;
426 unsigned long s2
= 0; // (adler >> 16) & 0xffff;
427 unsigned long result
;
431 k
= len
< NMAX
? len
: NMAX
;
445 result
= (s2
<< 16) | s1
;
446 return OSSwapHostToBigInt32(result
);