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 $
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];
70 static char kernel_config[KERNEL_CONFIG_SIZE];
71 static char kernel_config_namebuf[NAMEBUF_LEN + sizeof "config"];
72 static char linebuf[NAMEBUF_LEN];
73 static char namebuf[NAMEBUF_LEN];
74 static struct bootinfo bootinfo;
77 static void getbootdev(char *ptr, int *howto);
78 static void loadprog(void);
79 static void readfile(char *path, char *buf, size_t nbytes);
88 unsigned char disk_equips;
91 /* Pick up the story from the Bios on geometry of disks */
94 for(ret = 0; ret < 2; ret ++) {
95 if (*(unsigned char*)V(0xA155d) & (1 << ret)) {
96 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
100 for(ret = 0; ret < N_BIOS_GEOM; ret ++)
101 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
104 bootinfo.bi_basemem = memsize(0);
105 bootinfo.bi_extmem = memsize(1);
106 bootinfo.bi_memsizes_valid = 1;
111 /* set machine type to PC98_SYSTEM_PARAMETER */
116 * The default boot device is the first partition in the
117 * compatibility slice on the boot drive.
121 maj = (drive&0x70) >> 3; /* a good first bet */
122 if (maj == 4) { /* da */
123 disk_equips = *(unsigned char *)V(0xA1482);
125 for (i=0; i<(drive&0x0f); i++) {
126 int media = ((unsigned *)V(0xA1460))[i] & 0x1F;
128 if ((disk_equips >> i) & 1) /* HD */
130 else if (media == 7) /* MO */
144 /* Hard drive. Adjust. */
147 if (unit >= BOOT_HD_BIAS) {
149 * The drive is probably a SCSI drive with a unit
150 * number BOOT_HD_BIAS less than the BIOS drive
154 unit -= BOOT_HD_BIAS;
159 readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
160 name = "/boot/loader";
161 if (boot_config[0] != '\0') {
162 printf("boot.config: %s", boot_config);
163 getbootdev(boot_config, &loadflags);
168 /* print this all each time.. (saves space to do so) */
169 /* If we have looped, use the previous entries as defaults */
170 printf("\r \n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory, %s%s console\n"
171 "Boot default: %d:%s(%d,%c)%s\n"
174 ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
175 (loadflags & RB_SERIAL) ? "serial" : "internal",
176 (loadflags & RB_DUAL) ? "/dual" : "",
178 dosdev & 0x0f, devs[maj], unit, 'a' + part,
180 dosdev & 0x7f, devs[maj], unit, 'a' + part,
182 name ? name : "*specify_a_kernel_name*",
186 * Ignore flags from previous attempted boot, if any.
187 * XXX this is now too strict. Settings given in boot.config should
190 loadflags &= (RB_DUAL | RB_SERIAL);
193 * Be paranoid and make doubly sure that the input buffer is empty.
195 if (loadflags & (RB_DUAL | RB_SERIAL))
201 getbootdev(linebuf, &loadflags);
207 printf("Can't find %s\n", name);
210 /* if (inode.i_mode&IEXEC)
222 int addr; /* physical address.. not directly useable */
228 read((void *)&head, sizeof(head));
229 if ( N_BADMAG(head)) {
230 printf("Invalid format!\n");
234 poff = N_TXTOFF(head);
239 * We assume that the entry address is the same as the lowest text
240 * address and that the kernel startup code handles relocation by
241 * this address rounded down to a multiple of 16M.
243 startaddr = head.a_entry & 0x00FFFFFF;
245 printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
256 if(addr < 0x00100000)
259 * Bail out, instead of risking to damage the BIOS
260 * variables, the loader, or the adapter memory area.
261 * We don't support loading below 1 MB any more.
263 printf("Start address too low\n");
266 printf("text=0x%x ", head.a_text);
267 /********************************************************/
268 /* LOAD THE TEXT SEGMENT */
269 /********************************************************/
270 xread((void *)addr, head.a_text);
273 /********************************************************/
274 /* Load the Initialised data after the text */
275 /********************************************************/
276 while (addr & PAGE_MASK)
279 printf("data=0x%x ", head.a_data);
280 xread((void *)addr, head.a_data);
283 /********************************************************/
284 /* Skip over the uninitialised data */
286 /********************************************************/
287 printf("bss=0x%x ", head.a_bss);
290 * XXX however, we should be checking that we don't load ... into
291 * nonexistent memory. A full symbol table is unlikely to fit on 4MB
294 /* kzip & kernel will zero their own bss */
297 /* Pad to a page boundary. */
298 pad = (unsigned)addr & PAGE_MASK;
300 pad = PAGE_SIZE - pad;
303 bootinfo.bi_symtab = addr;
305 /********************************************************/
306 /* Copy the symbol table size */
307 /********************************************************/
308 pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
309 addr += sizeof(head.a_syms);
311 /********************************************************/
312 /* Load the symbol table */
313 /********************************************************/
314 printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
316 xread((void *)addr, head.a_syms);
319 /********************************************************/
320 /* Load the string table size */
321 /********************************************************/
322 read((void *)&i, sizeof(int));
323 pcpy(&i, (void *)addr, sizeof(int));
327 /********************************************************/
328 /* Load the string table */
329 /********************************************************/
330 printf("+0x%x+0x%x]\n", sizeof(int), i);
331 xread((void *)addr, i);
334 bootinfo.bi_esymtab = addr;
337 * For backwards compatibility, use the previously-unused adaptor
338 * and controller bitfields to hold the slice number.
340 bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);
342 bootinfo.bi_version = BOOTINFO_VERSION;
343 bootinfo.bi_kernelname = (u_int32_t)(name + ouraddr);
344 bootinfo.bi_nfs_diskless = 0;
345 bootinfo.bi_size = sizeof(bootinfo);
346 bootinfo.bi_bios_dev = dosdev;
349 * Load the kernel config file (if any). Its name is given by
350 * appending ".config" to the kernel name. Build the name inline
351 * because no str*() functions are available. The file has to be
352 * copied to &disklabel for userconfig. It can't be loaded there
353 * directly because the label is used late in readfile() in some
357 t = kernel_config_namebuf;
360 while ((*t++ = *s++) != '\0');
365 while ((*t++ = *s++) != '\0');
366 readfile(kernel_config_namebuf, kernel_config, KERNEL_CONFIG_SIZE);
367 pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE);
369 printf("total=0x%x entry point=0x%x\n", addr, startaddr);
370 startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
371 (unsigned)&bootinfo + ouraddr);
375 readfile(char *path, char *buf, size_t nbytes)
381 openstatus = openrd();
382 if (openstatus == 0) {
383 /* XXX no way to determine file size. */
386 buf[nbytes - 1] = '\0';
390 getbootdev(char *ptr, int *howto)
396 /* Copy the flags to save some bytes. */
402 while (c == ' ' || c == '\n')
405 while ((c = *++ptr) != '\0') {
406 if (c == ' ' || c == '\n')
434 while (c != '\0' && c != ' ' && c != '\n') {
440 if (f & RB_PROBEKBD) {
441 if (probe_keyboard()) {
442 f |= RB_DUAL | RB_SERIAL;
443 printf("No keyboard found\n");
445 printf("Keyboard found\n");
447 if (f & (RB_DUAL | RB_SERIAL))