2 * Mach Operating System
3 * Copyright (c) 1992, 1991 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
26 * from: Mach, [92/04/03 16:51:14 rvb]
27 * $FreeBSD: src/sys/i386/boot/biosboot/boot.c,v 1.76 1999/12/08 09:32:47 phk Exp $
32 Copyright 1988, 1989, 1990, 1991, 1992
33 by Intel Corporation, Santa Clara, California.
37 Permission to use, copy, modify, and distribute this software and
38 its documentation for any purpose and without fee is hereby
39 granted, provided that the above copyright notice appears in all
40 copies and that both the copyright notice and this permission notice
41 appear in supporting documentation, and that the name of Intel
42 not be used in advertising or publicity pertaining to distribution
43 of the software without specific, written prior permission.
45 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
46 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
47 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
48 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
49 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
50 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
51 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54 #include <sys/param.h>
57 #include <sys/reboot.h>
58 #include <machine/bootinfo.h>
60 #define ouraddr (BOOTSEG << 4) /* XXX */
62 #define BOOT_CONFIG_SIZE 512
63 #define BOOT_HELP_SIZE 2048
64 #define KERNEL_CONFIG_SIZE 512
65 #define NAMEBUF_LEN 1024 /* oversized to defend against gets() */
67 static char boot_config[BOOT_CONFIG_SIZE];
68 static char boot_help[BOOT_HELP_SIZE];
73 static char kernel_config[KERNEL_CONFIG_SIZE];
74 static char kernel_config_namebuf[NAMEBUF_LEN + sizeof "config"];
75 static char linebuf[NAMEBUF_LEN];
76 static char namebuf[NAMEBUF_LEN];
77 static struct bootinfo bootinfo;
80 static void getbootdev(char *ptr, int *howto);
81 static void loadprog(void);
82 static void readfile(char *path, char *buf, size_t nbytes);
90 /* Pick up the story from the Bios on geometry of disks */
92 for(ret = 0; ret < N_BIOS_GEOM; ret ++)
93 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
95 bootinfo.bi_basemem = memsize(0);
96 bootinfo.bi_extmem = memsize(1);
97 bootinfo.bi_memsizes_valid = 1;
102 * The default boot device is the first partition in the
103 * compatibility slice on the boot drive.
113 /* Hard drive. Adjust. */
116 if (unit >= BOOT_HD_BIAS) {
118 * The drive is probably a SCSI drive with a unit
119 * number BOOT_HD_BIAS less than the BIOS drive
123 unit -= BOOT_HD_BIAS;
128 readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
129 readfile("boot.help", boot_help, BOOT_HELP_SIZE);
134 * DAMN! I don't understand why this is not being set
135 * by the code in boot2.S
137 dflt_name= (char *)0x0000ffb0;
138 if( (*dflt_name++ == 'D') && (*dflt_name++ == 'N')) {
143 if (boot_config[0] != '\0') {
144 printf("boot.config: %s", boot_config);
145 getbootdev(boot_config, &loadflags);
150 /* print this all each time.. (saves space to do so) */
151 /* If we have looped, use the previous entries as defaults */
152 printf("\r \n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory, %s%s console\n"
153 "Boot default: %d:%s(%d,%c)%s\n"
156 ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
157 (loadflags & RB_SERIAL) ? "serial" : "internal",
158 (loadflags & RB_DUAL) ? "/dual" : "",
159 dosdev & 0x7f, devs[maj], unit, 'a' + part,
160 name ? name : "*specify_a_kernel_name*",
164 * Ignore flags from previous attempted boot, if any.
165 * XXX this is now too strict. Settings given in boot.config should
168 loadflags &= (RB_DUAL | RB_SERIAL);
171 * Be paranoid and make doubly sure that the input buffer is empty.
173 if (loadflags & (RB_DUAL | RB_SERIAL))
179 getbootdev(linebuf, &loadflags);
185 printf("Can't find %s\n", name);
188 /* if (inode.i_mode&IEXEC)
200 int addr; /* physical address.. not directly useable */
206 read((void *)&head, sizeof(head));
207 if ( N_BADMAG(head)) {
208 printf("Invalid format!\n");
212 poff = N_TXTOFF(head);
217 * We assume that the entry address is the same as the lowest text
218 * address and that the kernel startup code handles relocation by
219 * this address rounded down to a multiple of 16M.
221 startaddr = head.a_entry & 0x00FFFFFF;
223 printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
230 if(addr < 0x00100000)
233 * Bail out, instead of risking to damage the BIOS
234 * variables, the loader, or the adapter memory area.
235 * We don't support loading below 1 MB any more.
237 printf("Start address too low\n");
240 printf("text=0x%x ", head.a_text);
241 /********************************************************/
242 /* LOAD THE TEXT SEGMENT */
243 /********************************************************/
244 xread((void *)addr, head.a_text);
247 /********************************************************/
248 /* Load the Initialised data after the text */
249 /********************************************************/
250 while (addr & PAGE_MASK)
253 printf("data=0x%x ", head.a_data);
254 xread((void *)addr, head.a_data);
257 /********************************************************/
258 /* Skip over the uninitialised data */
260 /********************************************************/
261 printf("bss=0x%x ", head.a_bss);
264 * XXX however, we should be checking that we don't load ... into
265 * nonexistent memory. A full symbol table is unlikely to fit on 4MB
268 /* kzip & kernel will zero their own bss */
271 /* Pad to a page boundary. */
272 pad = (unsigned)addr & PAGE_MASK;
274 pad = PAGE_SIZE - pad;
277 bootinfo.bi_symtab = addr;
279 /********************************************************/
280 /* Copy the symbol table size */
281 /********************************************************/
282 pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
283 addr += sizeof(head.a_syms);
285 /********************************************************/
286 /* Load the symbol table */
287 /********************************************************/
288 printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
290 xread((void *)addr, head.a_syms);
293 /********************************************************/
294 /* Load the string table size */
295 /********************************************************/
296 read((void *)&i, sizeof(int));
297 pcpy(&i, (void *)addr, sizeof(int));
301 /********************************************************/
302 /* Load the string table */
303 /********************************************************/
304 printf("+0x%x+0x%x]\n", sizeof(int), i);
305 xread((void *)addr, i);
308 bootinfo.bi_esymtab = addr;
311 * For backwards compatibility, use the previously-unused adaptor
312 * and controller bitfields to hold the slice number.
314 bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);
316 bootinfo.bi_version = BOOTINFO_VERSION;
317 bootinfo.bi_kernelname = (u_int32_t)(name + ouraddr);
318 bootinfo.bi_nfs_diskless = 0;
319 bootinfo.bi_size = sizeof(bootinfo);
320 bootinfo.bi_bios_dev = dosdev;
323 * Load the kernel config file (if any). Its name is given by
324 * appending ".config" to the kernel name. Build the name inline
325 * because no str*() functions are available. The file has to be
326 * copied to &disklabel for userconfig. It can't be loaded there
327 * directly because the label is used late in readfile() in some
331 t = kernel_config_namebuf;
334 while ((*t++ = *s++) != '\0');
339 while ((*t++ = *s++) != '\0');
340 readfile(kernel_config_namebuf, kernel_config, KERNEL_CONFIG_SIZE);
341 pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE);
343 printf("total=0x%x entry point=0x%x\n", addr, startaddr);
344 startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
345 (unsigned)&bootinfo + ouraddr);
349 readfile(char *path, char *buf, size_t nbytes)
355 openstatus = openrd();
356 if (openstatus != 0) {
358 printf("Can't find file %s\n", name);
360 /* XXX no way to determine file size. */
363 buf[nbytes - 1] = '\0';
367 getbootdev(char *ptr, int *howto)
373 /* Copy the flags to save some bytes. */
379 while (c == ' ' || c == '\n')
382 while ((c = *++ptr) != '\0') {
383 if (c == ' ' || c == '\n')
411 while (c != '\0' && c != ' ' && c != '\n') {
417 if (f & RB_PROBEKBD) {
418 if (probe_keyboard()) {
419 f |= RB_DUAL | RB_SERIAL;
420 printf("No keyboard found\n");
422 printf("Keyboard found\n");
424 if (f & (RB_DUAL | RB_SERIAL))