]> git.saurik.com Git - apple/boot.git/blame - i386/boot2/boot.c
boot-111.tar.gz
[apple/boot.git] / i386 / boot2 / boot.c
CommitLineData
14c7c974
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
f083c6c3
A
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14c7c974
A
14 *
15 * The Original Code and all software distributed under the License are
f083c6c3 16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14c7c974
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
f083c6c3
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
14c7c974
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
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 */
75b89a82 52
14c7c974 53#include "boot.h"
f083c6c3
A
54#include "bootstruct.h"
55#include "sl.h"
14c7c974 56
14c7c974
A
57/*
58 * The user asked for boot graphics.
59 */
75b89a82 60BOOL gBootGraphics = NO;
75b89a82 61long gBootMode = kBootModeNormal;
f083c6c3 62static char gBootKernelCacheFile[512];
14c7c974 63
75b89a82 64static BOOL gUnloadPXEOnExit = 0;
14c7c974
A
65
66/*
47b0a8bd
A
67 * How long to wait (in seconds) to load the
68 * kernel after displaying the "boot:" prompt.
14c7c974 69 */
75b89a82 70#define kBootErrorTimeout 5
14c7c974 71
f083c6c3
A
72/*
73 * Default path to kernel cache file
74 */
75#define kDefaultCachePath "/System/Library/Caches/com.apple.kernelcaches/kernelcache"
76
14c7c974
A
77//==========================================================================
78// Zero the BSS.
79
75b89a82 80static void zeroBSS()
14c7c974
A
81{
82 extern char _DATA__bss__begin, _DATA__bss__end;
83 extern char _DATA__common__begin, _DATA__common__end;
84
85 bzero( &_DATA__bss__begin,
86 (&_DATA__bss__end - &_DATA__bss__begin) );
47b0a8bd 87
14c7c974
A
88 bzero( &_DATA__common__begin,
89 (&_DATA__common__end - &_DATA__common__begin) );
90}
91
f083c6c3
A
92//==========================================================================
93// Malloc error function
94
95static void malloc_error(char *addr, size_t size)
96{
97 printf("\nMemory allocation error (0x%x, 0x%x)\n",
98 (unsigned)addr, (unsigned)size);
99 asm("hlt");
100}
101
14c7c974 102//==========================================================================
47b0a8bd 103// execKernel - Load the kernel image (mach-o) and jump to its entry point.
14c7c974 104
f083c6c3 105static int ExecKernel(void *binary)
14c7c974 106{
14c7c974 107 entry_t kernelEntry;
47b0a8bd
A
108 int ret;
109
f083c6c3 110 bootArgs->kaddr = bootArgs->ksize = 0;
47b0a8bd 111
f083c6c3
A
112 ret = DecodeKernel(binary,
113 &kernelEntry,
114 (char **) &bootArgs->kaddr,
115 &bootArgs->ksize );
14c7c974
A
116
117 if ( ret != 0 )
118 return ret;
119
f083c6c3
A
120 // Reserve space for boot args
121 reserveKernBootStruct();
122
75b89a82 123 // Load boot drivers from the specifed root path.
14c7c974 124
f083c6c3
A
125 if (!gHaveKernelCache) {
126 LoadDrivers("/");
127 }
128
14c7c974 129 clearActivityIndicator();
14c7c974 130
75b89a82 131 if (gErrors) {
14c7c974 132 printf("Errors encountered while starting up the computer.\n");
75b89a82
A
133 printf("Pausing %d seconds...\n", kBootErrorTimeout);
134 sleep(kBootErrorTimeout);
14c7c974
A
135 }
136
75b89a82 137 printf("Starting Darwin/x86");
14c7c974
A
138
139 turnOffFloppy();
140
47b0a8bd
A
141 // Connect to APM BIOS.
142
14c7c974
A
143 if ( getBoolForKey("APM") )
144 {
145 if ( APMPresent() ) APMConnect32();
146 }
147
f083c6c3 148 // Cleanup the PXE base code.
14c7c974 149
f083c6c3 150 if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) {
14c7c974
A
151 if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess )
152 {
75b89a82
A
153 printf("nbpUnloadBaseCode error %d\n", (int) ret);
154 sleep(2);
14c7c974
A
155 }
156 }
157
75b89a82 158 // Switch to desired video mode just before starting the kernel.
14c7c974 159
75b89a82 160 setVideoMode( gBootGraphics ? GRAPHICS_MODE : TEXT_MODE );
14c7c974
A
161
162 // Jump to kernel's entry point. There's no going back now.
163
f083c6c3 164 startprog( kernelEntry, bootArgs );
14c7c974
A
165
166 // Not reached
167
168 return 0;
169}
170
171//==========================================================================
75b89a82 172// Scan and record the system's hardware information.
14c7c974
A
173
174static void scanHardware()
175{
75b89a82
A
176 extern int ReadPCIBusInfo(PCI_bus_info_t *);
177 extern void PCI_Bus_Init(PCI_bus_info_t *);
14c7c974 178
f083c6c3 179 ReadPCIBusInfo( &bootArgs->pciInfo );
75b89a82
A
180
181 //
182 // Initialize PCI matching support in the booter.
183 // Not used, commented out to minimize code size.
184 //
f083c6c3 185 // PCI_Bus_Init( &bootArgs->pciInfo );
14c7c974
A
186}
187
188//==========================================================================
75b89a82
A
189// The 'main' function for the booter. Called by boot0 when booting
190// from a block device, or by the network booter.
14c7c974
A
191//
192// arguments:
75b89a82
A
193// biosdev - Value passed from boot1/NBP to specify the device
194// that the booter was loaded from.
14c7c974 195//
75b89a82 196// If biosdev is kBIOSDevNetwork, then this function will return if
14c7c974 197// booting was unsuccessful. This allows the PXE firmware to try the
75b89a82 198// next boot device on its list.
14c7c974 199
75b89a82 200void boot(int biosdev)
14c7c974 201{
75b89a82 202 int status;
f083c6c3 203 char *bootFile;
14c7c974
A
204
205 zeroBSS();
206
f083c6c3
A
207 // Initialize malloc
208
209 malloc_init(0, 0, 0, malloc_error);
210
47b0a8bd 211 // Enable A20 gate before accessing memory above 1Mb.
14c7c974
A
212
213 enableA20();
214
75b89a82
A
215 // Set reminder to unload the PXE base code. Neglect to unload
216 // the base code will result in a hang or kernel panic.
217
75b89a82 218 gUnloadPXEOnExit = 1;
14c7c974 219
75b89a82
A
220 // Record the device that the booter was loaded from.
221
222 gBIOSDev = biosdev & kBIOSDevMask;
14c7c974
A
223
224 // Initialize boot info structure.
225
75b89a82 226 initKernBootStruct( gBIOSDev );
14c7c974
A
227
228 // Setup VGA text mode.
75b89a82
A
229 // Not sure if it is safe to call setVideoMode() before the
230 // config table has been loaded. Call video_mode() instead.
14c7c974 231
75b89a82 232 video_mode( 2 ); // 80x25 mono text mode.
14c7c974 233
14c7c974
A
234 // Scan hardware configuration.
235
236 scanHardware();
237
75b89a82 238 // Display banner and show hardware info.
14c7c974 239
75b89a82 240 setCursorPosition( 0, 0, 0 );
f083c6c3 241 printf( bootBanner, bootArgs->convmem, bootArgs->extmem );
75b89a82 242 printVBEInfo();
14c7c974
A
243
244 // Parse args, load and start kernel.
245
246 while (1)
247 {
f083c6c3
A
248 const char *val;
249 int len, trycache;
250 long flags, cachetime, time;
251 int ret = -1;
252
14c7c974
A
253 // Initialize globals.
254
47b0a8bd 255 sysConfigValid = 0;
75b89a82 256 gErrors = 0;
14c7c974 257
f083c6c3
A
258 // Reset config space.
259 bootArgs->configEnd = bootArgs->config;
260
75b89a82
A
261 getBootOptions();
262 status = processBootOptions();
263 if ( status == 1 ) break;
264 if ( status == -1 ) continue;
14c7c974
A
265
266 // Found and loaded a config file. Proceed with boot.
267
f083c6c3 268 // Check for cache file.
14c7c974 269
f083c6c3
A
270 if (getValueForKey(kKernelCacheKey, &val, &len)) {
271 strncpy(gBootKernelCacheFile, val, len);
272 gBootKernelCacheFile[len] = '\0';
273 } else {
274 strcpy(gBootKernelCacheFile, kDefaultCachePath);
14c7c974 275 }
14c7c974 276
f083c6c3
A
277 trycache = (((gBootMode & kBootModeSafe) == 0) &&
278 (gBootFileType == kBlockDeviceType) &&
279 (gBootKernelCacheFile[0] != '\0'));
280
281 printf("Loading Darwin/x86\n");
282
283 if (trycache) do {
284
285 // if we haven't found the kernel yet, don't use the cache
286 ret = GetFileInfo(NULL, bootArgs->bootFile, &flags, &time);
287 if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
288 trycache = 0;
289 break;
290 }
291 ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
292 if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
293 || (cachetime < time)) {
294 trycache = 0;
295 break;
296 }
297 ret = GetFileInfo("/System/Library/", "Extensions", &flags, &time);
298 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
299 && (cachetime < time)) {
300 trycache = 0;
301 break;
302 }
303 } while (0);
304
305 do {
306 if (trycache) {
307 bootFile = gBootKernelCacheFile;
308 verbose("Loading kernel cache %s\n", bootFile);
309 ret = LoadFile(bootFile);
310 if (ret >= 0) {
311 break;
312 }
313 }
314 bootFile = bootArgs->bootFile;
315 verbose("Loading kernel %s\n", bootFile);
316 ret = LoadFile(bootFile);
317 } while (0);
318
319 clearActivityIndicator();
320
321 if (ret < 0) {
322 error("Can't find %s\n", bootFile);
323
324 if ( gBootFileType == kBIOSDevTypeFloppy )
14c7c974
A
325 {
326 // floppy in drive, but failed to load kernel.
75b89a82
A
327 gBIOSDev = kBIOSDevTypeHardDrive;
328 initKernBootStruct( gBIOSDev );
329 printf("Attempt to load from hard drive.");
14c7c974 330 }
f083c6c3 331 else if ( gBootFileType == kNetworkDeviceType )
14c7c974 332 {
75b89a82
A
333 // Return control back to PXE. Don't unload PXE base code.
334 gUnloadPXEOnExit = 0;
335 break;
14c7c974 336 }
f083c6c3
A
337 } else {
338 /* Won't return if successful. */
339 ret = ExecKernel((void *)kLoadAddr);
14c7c974 340 }
f083c6c3 341
14c7c974 342 } /* while(1) */
75b89a82 343
f083c6c3
A
344 if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
345 nbpUnloadBaseCode();
346 }
14c7c974 347}