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/boot/pc98/boot2/boot.c,v 1.6.2.3 2003/01/13 08:52:53 nyan Exp $
28 * $DragonFly: src/sys/boot/pc98/boot2/Attic/boot.c,v 1.2 2003/06/17 04:28:18 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];
71 static char kernel_config[KERNEL_CONFIG_SIZE];
72 static char kernel_config_namebuf[NAMEBUF_LEN + sizeof "config"];
73 static char linebuf[NAMEBUF_LEN];
74 static char namebuf[NAMEBUF_LEN];
75 static struct bootinfo bootinfo;
78 static void getbootdev(char *ptr, int *howto);
79 static void loadprog(void);
80 static void readfile(char *path, char *buf, size_t nbytes);
89 unsigned char disk_equips;
92 /* Pick up the story from the Bios on geometry of disks */
95 for(ret = 0; ret < 2; ret ++) {
96 if (*(unsigned char*)V(0xA155d) & (1 << ret)) {
97 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
101 for(ret = 0; ret < N_BIOS_GEOM; ret ++)
102 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
105 bootinfo.bi_basemem = memsize(0);
106 bootinfo.bi_extmem = memsize(1);
107 bootinfo.bi_memsizes_valid = 1;
112 /* set machine type to PC98_SYSTEM_PARAMETER */
117 * The default boot device is the first partition in the
118 * compatibility slice on the boot drive.
122 maj = (drive&0x70) >> 3; /* a good first bet */
123 if (maj == 4) { /* da */
124 disk_equips = *(unsigned char *)V(0xA1482);
126 for (i=0; i<(drive&0x0f); i++) {
127 int media = ((unsigned *)V(0xA1460))[i] & 0x1F;
129 if ((disk_equips >> i) & 1) /* HD */
131 else if (media == 7) /* MO */
145 /* Hard drive. Adjust. */
148 if (unit >= BOOT_HD_BIAS) {
150 * The drive is probably a SCSI drive with a unit
151 * number BOOT_HD_BIAS less than the BIOS drive
155 unit -= BOOT_HD_BIAS;
160 readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
161 name = "/boot/loader";
162 if (boot_config[0] != '\0') {
163 printf("boot.config: %s", boot_config);
164 getbootdev(boot_config, &loadflags);
169 /* print this all each time.. (saves space to do so) */
170 /* If we have looped, use the previous entries as defaults */
171 printf("\r \n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory, %s%s console\n"
172 "Boot default: %d:%s(%d,%c)%s\n"
175 ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
176 (loadflags & RB_SERIAL) ? "serial" : "internal",
177 (loadflags & RB_DUAL) ? "/dual" : "",
179 dosdev & 0x0f, devs[maj], unit, 'a' + part,
181 dosdev & 0x7f, devs[maj], unit, 'a' + part,
183 name ? name : "*specify_a_kernel_name*",
187 * Ignore flags from previous attempted boot, if any.
188 * XXX this is now too strict. Settings given in boot.config should
191 loadflags &= (RB_DUAL | RB_SERIAL);
194 * Be paranoid and make doubly sure that the input buffer is empty.
196 if (loadflags & (RB_DUAL | RB_SERIAL))
202 getbootdev(linebuf, &loadflags);
208 printf("Can't find %s\n", name);
211 /* if (inode.i_mode&IEXEC)
223 int addr; /* physical address.. not directly useable */
229 read((void *)&head, sizeof(head));
230 if ( N_BADMAG(head)) {
231 printf("Invalid format!\n");
235 poff = N_TXTOFF(head);
240 * We assume that the entry address is the same as the lowest text
241 * address and that the kernel startup code handles relocation by
242 * this address rounded down to a multiple of 16M.
244 startaddr = head.a_entry & 0x00FFFFFF;
246 printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
257 if(addr < 0x00100000)
260 * Bail out, instead of risking to damage the BIOS
261 * variables, the loader, or the adapter memory area.
262 * We don't support loading below 1 MB any more.
264 printf("Start address too low\n");
267 printf("text=0x%x ", head.a_text);
268 /********************************************************/
269 /* LOAD THE TEXT SEGMENT */
270 /********************************************************/
271 xread((void *)addr, head.a_text);
274 /********************************************************/
275 /* Load the Initialised data after the text */
276 /********************************************************/
277 while (addr & PAGE_MASK)
280 printf("data=0x%x ", head.a_data);
281 xread((void *)addr, head.a_data);
284 /********************************************************/
285 /* Skip over the uninitialised data */
287 /********************************************************/
288 printf("bss=0x%x ", head.a_bss);
291 * XXX however, we should be checking that we don't load ... into
292 * nonexistent memory. A full symbol table is unlikely to fit on 4MB
295 /* kzip & kernel will zero their own bss */
298 /* Pad to a page boundary. */
299 pad = (unsigned)addr & PAGE_MASK;
301 pad = PAGE_SIZE - pad;
304 bootinfo.bi_symtab = addr;
306 /********************************************************/
307 /* Copy the symbol table size */
308 /********************************************************/
309 pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
310 addr += sizeof(head.a_syms);
312 /********************************************************/
313 /* Load the symbol table */
314 /********************************************************/
315 printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
317 xread((void *)addr, head.a_syms);
320 /********************************************************/
321 /* Load the string table size */
322 /********************************************************/
323 read((void *)&i, sizeof(int));
324 pcpy(&i, (void *)addr, sizeof(int));
328 /********************************************************/
329 /* Load the string table */
330 /********************************************************/
331 printf("+0x%x+0x%x]\n", sizeof(int), i);
332 xread((void *)addr, i);
335 bootinfo.bi_esymtab = addr;
338 * For backwards compatibility, use the previously-unused adaptor
339 * and controller bitfields to hold the slice number.
341 bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);
343 bootinfo.bi_version = BOOTINFO_VERSION;
344 bootinfo.bi_kernelname = (u_int32_t)(name + ouraddr);
345 bootinfo.bi_nfs_diskless = 0;
346 bootinfo.bi_size = sizeof(bootinfo);
347 bootinfo.bi_bios_dev = dosdev;
350 * Load the kernel config file (if any). Its name is given by
351 * appending ".config" to the kernel name. Build the name inline
352 * because no str*() functions are available. The file has to be
353 * copied to &disklabel for userconfig. It can't be loaded there
354 * directly because the label is used late in readfile() in some
358 t = kernel_config_namebuf;
361 while ((*t++ = *s++) != '\0');
366 while ((*t++ = *s++) != '\0');
367 readfile(kernel_config_namebuf, kernel_config, KERNEL_CONFIG_SIZE);
368 pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE);
370 printf("total=0x%x entry point=0x%x\n", addr, startaddr);
371 startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
372 (unsigned)&bootinfo + ouraddr);
376 readfile(char *path, char *buf, size_t nbytes)
382 openstatus = openrd();
383 if (openstatus == 0) {
384 /* XXX no way to determine file size. */
387 buf[nbytes - 1] = '\0';
391 getbootdev(char *ptr, int *howto)
397 /* Copy the flags to save some bytes. */
403 while (c == ' ' || c == '\n')
406 while ((c = *++ptr) != '\0') {
407 if (c == ' ' || c == '\n')
435 while (c != '\0' && c != ' ' && c != '\n') {
441 if (f & RB_PROBEKBD) {
442 if (probe_keyboard()) {
443 f |= RB_DUAL | RB_SERIAL;
444 printf("No keyboard found\n");
446 printf("Keyboard found\n");
448 if (f & (RB_DUAL | RB_SERIAL))