]>
git.saurik.com Git - apple/boot.git/blob - i386/boot2/boot.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 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 1.1 (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)
55 #include "kernBootStruct.h"
60 * The user asked for boot graphics.
62 static BOOL gWantBootGraphics
= NO
;
65 * The device that the booter was loaded from.
69 extern char * gFilename
;
70 extern BOOL sysConfigValid
;
71 extern char bootPrompt
[];
73 extern BOOL gVerboseMode
;
74 extern BOOL gSilentBoot
;
79 static void getBootString();
82 * How long to wait (in seconds) to load the
83 * kernel after displaying the "boot:" prompt.
85 #define kBootTimeout 10
87 //==========================================================================
93 extern char _DATA__bss__begin
, _DATA__bss__end
;
94 extern char _DATA__common__begin
, _DATA__common__end
;
96 bzero( &_DATA__bss__begin
,
97 (&_DATA__bss__end
- &_DATA__bss__begin
) );
99 bzero( &_DATA__common__begin
,
100 (&_DATA__common__end
- &_DATA__common__begin
) );
103 //==========================================================================
104 // execKernel - Load the kernel image (mach-o) and jump to its entry point.
109 register KERNBOOTSTRUCT
* kbp
= kernBootStruct
;
110 static struct mach_header head
;
114 verbose("Loading kernel %s\n", kbp
->bootFile
);
116 // Perform the actual load.
118 kbp
->kaddr
= kbp
->ksize
= 0;
120 ret
= loadprog( kbp
->kernDev
,
124 (char **) &kbp
->kaddr
,
127 clearActivityIndicator();
132 // Load boot drivers from the specifed root.
135 clearActivityIndicator();
138 printf("Errors encountered while starting up the computer.\n");
139 printf("Pausing %d seconds...\n", kBootTimeout
);
143 message("Starting Darwin/x86", 0);
147 // Connect to APM BIOS.
149 if ( getBoolForKey("APM") )
151 if ( APMPresent() ) APMConnect32();
154 // Cleanup the PXE base code.
156 if ( gBootDev
== kBootDevNetwork
)
158 if ( (ret
= nbpUnloadBaseCode()) != nbpStatusSuccess
)
160 printf("nbpUnloadBaseCode error %d\n", (int) ret
); sleep(2);
164 // Switch to graphics mode just before starting the kernel.
166 if ( gWantBootGraphics
)
168 setMode(GRAPHICS_MODE
);
171 // Jump to kernel's entry point. There's no going back now.
173 startprog(kernelEntry
);
180 //==========================================================================
181 // Scan and record the system's PCI bus information.
183 static void scanHardware()
185 extern int ReadPCIBusInfo(PCI_bus_info_t
*);
186 extern void PCI_Bus_Init(PCI_bus_info_t
*);
188 ReadPCIBusInfo( &kernBootStruct
->pciInfo
);
189 PCI_Bus_Init( &kernBootStruct
->pciInfo
);
192 //==========================================================================
193 // The 'main' function for the booter. This function is called by the
194 // assembly routine init(), which is in turn called by boot1 or by
198 // bootdev - Value passed from boot1/NBP to specify the device
199 // that the booter was loaded from. See boot.h for the list
200 // of allowable values.
202 // If bootdev is kBootDevNetwork, then this function will return if
203 // booting was unsuccessful. This allows the PXE firmware to try the
204 // next bootable device on its list. If bootdev is not kBootDevNetwork,
205 // this function will not return control back to the caller.
210 register KERNBOOTSTRUCT
* kbp
= kernBootStruct
;
215 // Enable A20 gate before accessing memory above 1Mb.
219 // Remember the device that the booter was loaded from.
223 // Initialize boot info structure.
225 initKernBootStruct();
227 // Setup VGA text mode.
231 // Scan hardware configuration.
235 // Display boot prompt.
237 printf( bootPrompt
, kbp
->convmem
, kbp
->extmem
, kBootTimeout
);
239 // Parse args, load and start kernel.
243 // Initialize globals.
248 // Make sure we are in VGA text mode.
252 // Set up kbp->kernDev to reflect the boot device.
254 if ( bootdev
== kBootDevHardDisk
)
256 if (kbp
->numIDEs
> 0)
258 kbp
->kernDev
= DEV_HD
;
262 kbp
->kernDev
= DEV_SD
;
265 else if ( bootdev
== kBootDevFloppyDisk
)
267 kbp
->kernDev
= DEV_FLOPPY
;
271 kbp
->kernDev
= DEV_EN
;
275 // Display boot prompt and get user supplied boot string.
279 if ( bootdev
!= kBootDevNetwork
)
281 // To force loading config file off same device as kernel,
282 // open kernel file to force device change if necessary.
284 fd
= open(kbp
->bootFile
, 0);
285 if (fd
>= 0) close(fd
);
288 if ( sysConfigValid
== 0 )
290 if (kbp
->kernDev
== DEV_EN
)
291 break; // return control back to PXE
293 continue; // keep looping
296 // Found and loaded a config file. Proceed with boot.
298 gWantBootGraphics
= getBoolForKey( kBootGraphicsKey
);
299 gSilentBoot
= getBoolForKey( kQuietBootKey
);
301 message("Loading Darwin/x86", 0);
303 if ( (fd
= openfile(kbp
->bootFile
, 0)) >= 0 )
305 execKernel(fd
); // will not return on success
309 error("Can't find %s\n", kbp
->bootFile
);
311 if ( bootdev
== kBootDevFloppyDisk
)
313 // floppy in drive, but failed to load kernel.
314 bootdev
= kBootDevHardDisk
;
315 message("Couldn't start up the computer using this "
318 else if ( bootdev
== kBootDevNetwork
)
320 break; // Return control back to PXE.
326 //==========================================================================
327 // Skip spaces/tabs characters.
330 skipblanks(char ** cp
)
332 while ( **(cp
) == ' ' || **(cp
) == '\t' )
336 //==========================================================================
337 // Load the help file and display the file contents on the screen.
339 static void showHelp()
341 #define BOOT_DIR_DISK "/usr/standalone/i386/"
342 #define BOOT_DIR_NET ""
343 #define makeFilePath(x) \
344 (gBootDev == kBootDevNetwork) ? BOOT_DIR_NET x : BOOT_DIR_DISK x
347 char * help
= makeFilePath("BootHelp.txt");
349 if ( (fd
= open(help
, 0)) >= 0 )
351 char * buffer
= malloc( file_size(fd
) );
352 read(fd
, buffer
, file_size(fd
) - 1);
354 printf("%s", buffer
);
359 //==========================================================================
360 // Returns 1 if the string pointed by 'cp' contains an user-specified
361 // kernel image file name. Used by getBootString() function.
364 containsKernelName(const char * cp
)
370 // Convert char to lower case.
374 // Must start with a letter or a '/'.
376 if ( (c
< 'a' || c
> 'z') && ( c
!= '/' ) )
379 // Keep consuming characters until we hit a separator.
381 while ( *cp
&& (*cp
!= '=') && (*cp
!= ' ') && (*cp
!= '\t') )
384 // Only SPACE or TAB separator is accepted.
385 // Reject everything else.
393 //==========================================================================
394 // Display the "boot:" prompt and copies the user supplied string to
395 // kernBootStruct->bootString. The kernel image file name is written
396 // to kernBootStruct->bootFile.
401 char line
[BOOT_STRING_LEN
];
405 static int timeout
= kBootTimeout
;
411 // If there were errors, don't timeout on boot prompt since
412 // the same error is likely to occur again.
414 if ( errors
) timeout
= 0;
417 // Print the boot prompt and wait a few seconds for user input.
420 count
= Gets(line
, sizeof(line
), timeout
, "boot: ", "");
423 // If something was typed, don't use automatic boot again.
424 // The boot: prompt will not timeout and go away until
425 // the user hits the return key.
427 if ( count
) timeout
= 0;
431 // If user typed '?', then display the usage message.
439 // Load config table file specified by the user, or fallback
440 // to the default one.
443 getValueForBootKey(cp
, "config", &val
, &count
);
444 loadSystemConfig(val
, count
);
445 if ( !sysConfigValid
)
450 // Did the user specify a kernel file name at the boot prompt?
452 if ( containsKernelName(cp
) == 0 )
454 // User did not type a kernel image file name on the boot prompt.
455 // This is fine, read the default kernel file name from the
458 if ( getValueForKey(kKernelNameKey
, &val
, &count
) )
460 strncpy(kernBootStruct
->bootFile
, val
, count
);
465 // Get the kernel name from the user-supplied boot string,
466 // and copy the name to the buffer provided.
468 char * namep
= kernBootStruct
->bootFile
;
470 while ( *cp
&& !(*cp
== ' ' || *cp
== '\t') )
476 // Verbose flag specified.
478 gVerboseMode
= getValueForBootKey(cp
, "-v", &val
, &count
);
480 // Save the boot string in kernBootStruct->bootString.
482 if ( getValueForKey(kKernelFlagsKey
, &val
, &count
) && count
)
484 strncpy( kernBootStruct
->bootString
, val
, count
);
488 strcat(kernBootStruct
->bootString
, " ");
489 strcat(kernBootStruct
->bootString
, cp
);