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 $
28 * $DragonFly: src/sys/i386/boot/biosboot/Attic/boot.c,v 1.2 2003/06/17 04:28:34 dillon Exp $
33 Copyright 1988, 1989, 1990, 1991, 1992
34 by Intel Corporation, Santa Clara, California.
38 Permission to use, copy, modify, and distribute this software and
39 its documentation for any purpose and without fee is hereby
40 granted, provided that the above copyright notice appears in all
41 copies and that both the copyright notice and this permission notice
42 appear in supporting documentation, and that the name of Intel
43 not be used in advertising or publicity pertaining to distribution
44 of the software without specific, written prior permission.
46 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
47 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
48 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
49 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
50 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
51 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
52 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
55 #include <sys/param.h>
58 #include <sys/reboot.h>
59 #include <machine/bootinfo.h>
61 #define ouraddr (BOOTSEG << 4) /* XXX */
63 #define BOOT_CONFIG_SIZE 512
64 #define BOOT_HELP_SIZE 2048
65 #define KERNEL_CONFIG_SIZE 512
66 #define NAMEBUF_LEN 1024 /* oversized to defend against gets() */
68 static char boot_config[BOOT_CONFIG_SIZE];
69 static char boot_help[BOOT_HELP_SIZE];
74 static char kernel_config[KERNEL_CONFIG_SIZE];
75 static char kernel_config_namebuf[NAMEBUF_LEN + sizeof "config"];
76 static char linebuf[NAMEBUF_LEN];
77 static char namebuf[NAMEBUF_LEN];
78 static struct bootinfo bootinfo;
81 static void getbootdev(char *ptr, int *howto);
82 static void loadprog(void);
83 static void readfile(char *path, char *buf, size_t nbytes);
91 /* Pick up the story from the Bios on geometry of disks */
93 for(ret = 0; ret < N_BIOS_GEOM; ret ++)
94 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
96 bootinfo.bi_basemem = memsize(0);
97 bootinfo.bi_extmem = memsize(1);
98 bootinfo.bi_memsizes_valid = 1;
103 * The default boot device is the first partition in the
104 * compatibility slice on the boot drive.
114 /* Hard drive. Adjust. */
117 if (unit >= BOOT_HD_BIAS) {
119 * The drive is probably a SCSI drive with a unit
120 * number BOOT_HD_BIAS less than the BIOS drive
124 unit -= BOOT_HD_BIAS;
129 readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
130 readfile("boot.help", boot_help, BOOT_HELP_SIZE);
135 * DAMN! I don't understand why this is not being set
136 * by the code in boot2.S
138 dflt_name= (char *)0x0000ffb0;
139 if( (*dflt_name++ == 'D') && (*dflt_name++ == 'N')) {
144 if (boot_config[0] != '\0') {
145 printf("boot.config: %s", boot_config);
146 getbootdev(boot_config, &loadflags);
151 /* print this all each time.. (saves space to do so) */
152 /* If we have looped, use the previous entries as defaults */
153 printf("\r \n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory, %s%s console\n"
154 "Boot default: %d:%s(%d,%c)%s\n"
157 ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
158 (loadflags & RB_SERIAL) ? "serial" : "internal",
159 (loadflags & RB_DUAL) ? "/dual" : "",
160 dosdev & 0x7f, devs[maj], unit, 'a' + part,
161 name ? name : "*specify_a_kernel_name*",
165 * Ignore flags from previous attempted boot, if any.
166 * XXX this is now too strict. Settings given in boot.config should
169 loadflags &= (RB_DUAL | RB_SERIAL);
172 * Be paranoid and make doubly sure that the input buffer is empty.
174 if (loadflags & (RB_DUAL | RB_SERIAL))
180 getbootdev(linebuf, &loadflags);
186 printf("Can't find %s\n", name);
189 /* if (inode.i_mode&IEXEC)
201 int addr; /* physical address.. not directly useable */
207 read((void *)&head, sizeof(head));
208 if ( N_BADMAG(head)) {
209 printf("Invalid format!\n");
213 poff = N_TXTOFF(head);
218 * We assume that the entry address is the same as the lowest text
219 * address and that the kernel startup code handles relocation by
220 * this address rounded down to a multiple of 16M.
222 startaddr = head.a_entry & 0x00FFFFFF;
224 printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
231 if(addr < 0x00100000)
234 * Bail out, instead of risking to damage the BIOS
235 * variables, the loader, or the adapter memory area.
236 * We don't support loading below 1 MB any more.
238 printf("Start address too low\n");
241 printf("text=0x%x ", head.a_text);
242 /********************************************************/
243 /* LOAD THE TEXT SEGMENT */
244 /********************************************************/
245 xread((void *)addr, head.a_text);
248 /********************************************************/
249 /* Load the Initialised data after the text */
250 /********************************************************/
251 while (addr & PAGE_MASK)
254 printf("data=0x%x ", head.a_data);
255 xread((void *)addr, head.a_data);
258 /********************************************************/
259 /* Skip over the uninitialised data */
261 /********************************************************/
262 printf("bss=0x%x ", head.a_bss);
265 * XXX however, we should be checking that we don't load ... into
266 * nonexistent memory. A full symbol table is unlikely to fit on 4MB
269 /* kzip & kernel will zero their own bss */
272 /* Pad to a page boundary. */
273 pad = (unsigned)addr & PAGE_MASK;
275 pad = PAGE_SIZE - pad;
278 bootinfo.bi_symtab = addr;
280 /********************************************************/
281 /* Copy the symbol table size */
282 /********************************************************/
283 pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
284 addr += sizeof(head.a_syms);
286 /********************************************************/
287 /* Load the symbol table */
288 /********************************************************/
289 printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
291 xread((void *)addr, head.a_syms);
294 /********************************************************/
295 /* Load the string table size */
296 /********************************************************/
297 read((void *)&i, sizeof(int));
298 pcpy(&i, (void *)addr, sizeof(int));
302 /********************************************************/
303 /* Load the string table */
304 /********************************************************/
305 printf("+0x%x+0x%x]\n", sizeof(int), i);
306 xread((void *)addr, i);
309 bootinfo.bi_esymtab = addr;
312 * For backwards compatibility, use the previously-unused adaptor
313 * and controller bitfields to hold the slice number.
315 bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);
317 bootinfo.bi_version = BOOTINFO_VERSION;
318 bootinfo.bi_kernelname = (u_int32_t)(name + ouraddr);
319 bootinfo.bi_nfs_diskless = 0;
320 bootinfo.bi_size = sizeof(bootinfo);
321 bootinfo.bi_bios_dev = dosdev;
324 * Load the kernel config file (if any). Its name is given by
325 * appending ".config" to the kernel name. Build the name inline
326 * because no str*() functions are available. The file has to be
327 * copied to &disklabel for userconfig. It can't be loaded there
328 * directly because the label is used late in readfile() in some
332 t = kernel_config_namebuf;
335 while ((*t++ = *s++) != '\0');
340 while ((*t++ = *s++) != '\0');
341 readfile(kernel_config_namebuf, kernel_config, KERNEL_CONFIG_SIZE);
342 pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE);
344 printf("total=0x%x entry point=0x%x\n", addr, startaddr);
345 startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
346 (unsigned)&bootinfo + ouraddr);
350 readfile(char *path, char *buf, size_t nbytes)
356 openstatus = openrd();
357 if (openstatus != 0) {
359 printf("Can't find file %s\n", name);
361 /* XXX no way to determine file size. */
364 buf[nbytes - 1] = '\0';
368 getbootdev(char *ptr, int *howto)
374 /* Copy the flags to save some bytes. */
380 while (c == ' ' || c == '\n')
383 while ((c = *++ptr) != '\0') {
384 if (c == ' ' || c == '\n')
412 while (c != '\0' && c != ' ' && c != '\n') {
418 if (f & RB_PROBEKBD) {
419 if (probe_keyboard()) {
420 f |= RB_DUAL | RB_SERIAL;
421 printf("No keyboard found\n");
423 printf("Keyboard found\n");
425 if (f & (RB_DUAL | RB_SERIAL))