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]
29 Copyright 1988, 1989, 1990, 1991, 1992
30 by Intel Corporation, Santa Clara, California.
34 Permission to use, copy, modify, and distribute this software and
35 its documentation for any purpose and without fee is hereby
36 granted, provided that the above copyright notice appears in all
37 copies and that both the copyright notice and this permission notice
38 appear in supporting documentation, and that the name of Intel
39 not be used in advertising or publicity pertaining to distribution
40 of the software without specific, written prior permission.
42 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
43 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
44 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
45 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
46 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
47 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
48 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 #include <sys/cdefs.h>
52 __FBSDID("$FreeBSD$");
56 #include <sys/reboot.h>
57 #include <machine/bootinfo.h>
59 #define ouraddr (BOOTSEG << 4) /* XXX */
61 #define BOOT_CONFIG_SIZE 512
62 #define BOOT_HELP_SIZE 2048
63 #define KERNEL_CONFIG_SIZE 512
64 #define NAMEBUF_LEN 1024 /* oversized to defend against gets() */
66 static char boot_config[BOOT_CONFIG_SIZE];
67 static char boot_help[BOOT_HELP_SIZE];
69 static char kernel_config[KERNEL_CONFIG_SIZE];
70 static char kernel_config_namebuf[NAMEBUF_LEN + sizeof "config"];
71 static char linebuf[NAMEBUF_LEN];
72 static char namebuf[NAMEBUF_LEN];
73 struct bootinfo bootinfo;
76 static void getbootdev(char *ptr, int *howto);
77 static void loadprog(void);
78 static void readfile(char *path, char *buf, size_t nbytes);
85 unsigned char disk_equips;
87 /* Pick up the story from the Bios on geometry of disks */
89 for(ret = 0; ret < 2; ret ++) {
90 if (*(unsigned char*)V(0xA155d) & (1 << ret)) {
91 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;
101 /* set machine type to PC98_SYSTEM_PARAMETER */
105 * The default boot device is the first partition in the
106 * compatibility slice on the boot drive.
109 maj = (drive&0x70) >> 3; /* a good first bet */
110 if (maj == 4) { /* da */
111 disk_equips = *(unsigned char *)V(0xA1482);
113 for (i=0; i<(drive&0x0f); i++) {
114 int media = ((unsigned *)V(0xA1460))[i] & 0x1F;
116 if ((disk_equips >> i) & 1) /* HD */
118 else if (media == 7) /* MO */
124 readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
125 name = "/boot/loader";
126 if (boot_config[0] != '\0') {
127 getbootdev(boot_config, &loadflags);
128 printf("boot.config: %s", boot_config);
133 /* print this all each time.. (saves space to do so) */
134 /* If we have looped, use the previous entries as defaults */
135 printf("\r \n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory, %s%s console\n"
136 "Boot default: %d:%s(%d,%c)%s\n"
139 ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
140 (loadflags & RB_SERIAL) ? "serial" : "internal",
141 (loadflags & RB_DUAL) ? "/dual" : "",
142 dosdev & 0x0f, devs[maj], unit, 'a' + part,
143 name ? name : "*specify_a_kernel_name*",
147 * Ignore flags from previous attempted boot, if any.
148 * XXX this is now too strict. Settings given in boot.config should
151 loadflags &= (RB_DUAL | RB_SERIAL);
154 * Be paranoid and make doubly sure that the input buffer is empty.
156 if (loadflags & (RB_DUAL | RB_SERIAL))
162 getbootdev(linebuf, &loadflags);
168 printf("Can't find %s\n", name);
171 /* if (inode.i_mode&IEXEC)
183 int addr; /* physical address.. not directly useable */
189 read((void *)&head, sizeof(head));
190 if ( N_BADMAG(head)) {
191 printf("Invalid format!\n");
195 poff = N_TXTOFF(head);
200 * We assume that the entry address is the same as the lowest text
201 * address and that the kernel startup code handles relocation by
202 * this address rounded down to a multiple of 16M.
204 startaddr = head.a_entry & 0x00FFFFFF;
206 printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
213 if(addr < 0x00100000)
216 * Bail out, instead of risking to damage the BIOS
217 * variables, the loader, or the adapter memory area.
218 * We don't support loading below 1 MB any more.
220 printf("Start address too low\n");
223 printf("text=0x%x ", head.a_text);
224 /********************************************************/
225 /* LOAD THE TEXT SEGMENT */
226 /********************************************************/
227 xread((void *)addr, head.a_text);
230 /********************************************************/
231 /* Load the Initialised data after the text */
232 /********************************************************/
233 while (addr & PAGE_MASK)
236 printf("data=0x%x ", head.a_data);
237 xread((void *)addr, head.a_data);
240 /********************************************************/
241 /* Skip over the uninitialised data */
243 /********************************************************/
244 printf("bss=0x%x ", head.a_bss);
247 * XXX however, we should be checking that we don't load ... into
248 * nonexistent memory. A full symbol table is unlikely to fit on 4MB
251 /* kzip & kernel will zero their own bss */
254 /* Pad to a page boundary. */
255 pad = (unsigned)addr & PAGE_MASK;
257 pad = PAGE_SIZE - pad;
260 bootinfo.bi_symtab = addr;
262 /********************************************************/
263 /* Copy the symbol table size */
264 /********************************************************/
265 pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
266 addr += sizeof(head.a_syms);
268 /********************************************************/
269 /* Load the symbol table */
270 /********************************************************/
271 printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
273 xread((void *)addr, head.a_syms);
276 /********************************************************/
277 /* Load the string table size */
278 /********************************************************/
279 read((void *)&i, sizeof(int));
280 pcpy(&i, (void *)addr, sizeof(int));
284 /********************************************************/
285 /* Load the string table */
286 /********************************************************/
287 printf("+0x%x+0x%x]\n", sizeof(int), i);
288 xread((void *)addr, i);
291 bootinfo.bi_esymtab = addr;
294 * For backwards compatibility, use the previously-unused adaptor
295 * and controller bitfields to hold the slice number.
297 bootdev = MAKEBOOTDEV(maj, slice, unit, part);
299 bootinfo.bi_version = BOOTINFO_VERSION;
300 bootinfo.bi_kernelname = (u_int32_t)(name + ouraddr);
301 bootinfo.bi_nfs_diskless = 0;
302 bootinfo.bi_size = sizeof(bootinfo);
303 bootinfo.bi_bios_dev = dosdev;
306 * Load the kernel config file (if any). Its name is given by
307 * appending ".config" to the kernel name. Build the name inline
308 * because no str*() functions are available. The file has to be
309 * copied to &disklabel for userconfig. It can't be loaded there
310 * directly because the label is used late in readfile() in some
314 t = kernel_config_namebuf;
317 while ((*t++ = *s++) != '\0');
322 while ((*t++ = *s++) != '\0');
323 readfile(kernel_config_namebuf, kernel_config, KERNEL_CONFIG_SIZE);
324 pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE);
326 printf("total=0x%x entry point=0x%x\n", addr, startaddr);
327 startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
328 (unsigned)&bootinfo + ouraddr);
332 readfile(char *path, char *buf, size_t nbytes)
338 openstatus = openrd();
339 if (openstatus == 0) {
340 /* XXX no way to determine file size. */
343 buf[nbytes - 1] = '\0';
347 getbootdev(char *ptr, int *howto)
353 /* Copy the flags to save some bytes. */
359 while (c == ' ' || c == '\n')
362 while ((c = *++ptr) != '\0') {
363 if (c == ' ' || c == '\n')
389 while (c != '\0' && c != ' ' && c != '\n') {
395 if (f & RB_PROBEKBD) {
396 if (probe_keyboard()) {
397 f |= RB_DUAL | RB_SERIAL;
398 printf("No keyboard found\n");
400 printf("Keyboard found\n");
402 if (f & (RB_DUAL | RB_SERIAL))