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.
53 * $FreeBSD: src/sys/boot/pc98/boot2/boot.c,v 1.11 2003/09/08 09:11:20 obrien Exp $
54 * $DragonFly: src/sys/boot/pc98/boot2/Attic/boot.c,v 1.3 2003/11/10 06:08:38 dillon Exp $
59 #include <sys/reboot.h>
60 #include <machine/bootinfo.h>
62 #define ouraddr (BOOTSEG << 4) /* XXX */
64 #define BOOT_CONFIG_SIZE 512
65 #define BOOT_HELP_SIZE 2048
66 #define KERNEL_CONFIG_SIZE 512
67 #define NAMEBUF_LEN 1024 /* oversized to defend against gets() */
69 static char boot_config[BOOT_CONFIG_SIZE];
70 static char boot_help[BOOT_HELP_SIZE];
72 static char kernel_config[KERNEL_CONFIG_SIZE];
73 static char kernel_config_namebuf[NAMEBUF_LEN + sizeof "config"];
74 static char linebuf[NAMEBUF_LEN];
75 static char namebuf[NAMEBUF_LEN];
76 static struct bootinfo bootinfo;
79 static void getbootdev(char *ptr, int *howto);
80 static void loadprog(void);
81 static void readfile(char *path, char *buf, size_t nbytes);
90 unsigned char disk_equips;
93 /* Pick up the story from the Bios on geometry of disks */
96 for(ret = 0; ret < 2; ret ++) {
97 if (*(unsigned char*)V(0xA155d) & (1 << ret)) {
98 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
102 for(ret = 0; ret < N_BIOS_GEOM; ret ++)
103 bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
106 bootinfo.bi_basemem = memsize(0);
107 bootinfo.bi_extmem = memsize(1);
108 bootinfo.bi_memsizes_valid = 1;
113 /* set machine type to PC98_SYSTEM_PARAMETER */
118 * The default boot device is the first partition in the
119 * compatibility slice on the boot drive.
123 maj = (drive&0x70) >> 3; /* a good first bet */
124 if (maj == 4) { /* da */
125 disk_equips = *(unsigned char *)V(0xA1482);
127 for (i=0; i<(drive&0x0f); i++) {
128 int media = ((unsigned *)V(0xA1460))[i] & 0x1F;
130 if ((disk_equips >> i) & 1) /* HD */
132 else if (media == 7) /* MO */
146 /* Hard drive. Adjust. */
149 if (unit >= BOOT_HD_BIAS) {
151 * The drive is probably a SCSI drive with a unit
152 * number BOOT_HD_BIAS less than the BIOS drive
156 unit -= BOOT_HD_BIAS;
161 readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
162 name = "/boot/loader";
163 if (boot_config[0] != '\0') {
164 printf("boot.config: %s", boot_config);
165 getbootdev(boot_config, &loadflags);
170 /* print this all each time.. (saves space to do so) */
171 /* If we have looped, use the previous entries as defaults */
172 printf("\r \n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory, %s%s console\n"
173 "Boot default: %d:%s(%d,%c)%s\n"
176 ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
177 (loadflags & RB_SERIAL) ? "serial" : "internal",
178 (loadflags & RB_DUAL) ? "/dual" : "",
180 dosdev & 0x0f, devs[maj], unit, 'a' + part,
182 dosdev & 0x7f, devs[maj], unit, 'a' + part,
184 name ? name : "*specify_a_kernel_name*",
188 * Ignore flags from previous attempted boot, if any.
189 * XXX this is now too strict. Settings given in boot.config should
192 loadflags &= (RB_DUAL | RB_SERIAL);
195 * Be paranoid and make doubly sure that the input buffer is empty.
197 if (loadflags & (RB_DUAL | RB_SERIAL))
203 getbootdev(linebuf, &loadflags);
209 printf("Can't find %s\n", name);
212 /* if (inode.i_mode&IEXEC)
224 int addr; /* physical address.. not directly useable */
230 read((void *)&head, sizeof(head));
231 if ( N_BADMAG(head)) {
232 printf("Invalid format!\n");
236 poff = N_TXTOFF(head);
241 * We assume that the entry address is the same as the lowest text
242 * address and that the kernel startup code handles relocation by
243 * this address rounded down to a multiple of 16M.
245 startaddr = head.a_entry & 0x00FFFFFF;
247 printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
258 if(addr < 0x00100000)
261 * Bail out, instead of risking to damage the BIOS
262 * variables, the loader, or the adapter memory area.
263 * We don't support loading below 1 MB any more.
265 printf("Start address too low\n");
268 printf("text=0x%x ", head.a_text);
269 /********************************************************/
270 /* LOAD THE TEXT SEGMENT */
271 /********************************************************/
272 xread((void *)addr, head.a_text);
275 /********************************************************/
276 /* Load the Initialised data after the text */
277 /********************************************************/
278 while (addr & PAGE_MASK)
281 printf("data=0x%x ", head.a_data);
282 xread((void *)addr, head.a_data);
285 /********************************************************/
286 /* Skip over the uninitialised data */
288 /********************************************************/
289 printf("bss=0x%x ", head.a_bss);
292 * XXX however, we should be checking that we don't load ... into
293 * nonexistent memory. A full symbol table is unlikely to fit on 4MB
296 /* kzip & kernel will zero their own bss */
299 /* Pad to a page boundary. */
300 pad = (unsigned)addr & PAGE_MASK;
302 pad = PAGE_SIZE - pad;
305 bootinfo.bi_symtab = addr;
307 /********************************************************/
308 /* Copy the symbol table size */
309 /********************************************************/
310 pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
311 addr += sizeof(head.a_syms);
313 /********************************************************/
314 /* Load the symbol table */
315 /********************************************************/
316 printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
318 xread((void *)addr, head.a_syms);
321 /********************************************************/
322 /* Load the string table size */
323 /********************************************************/
324 read((void *)&i, sizeof(int));
325 pcpy(&i, (void *)addr, sizeof(int));
329 /********************************************************/
330 /* Load the string table */
331 /********************************************************/
332 printf("+0x%x+0x%x]\n", sizeof(int), i);
333 xread((void *)addr, i);
336 bootinfo.bi_esymtab = addr;
339 * For backwards compatibility, use the previously-unused adaptor
340 * and controller bitfields to hold the slice number.
342 bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);
344 bootinfo.bi_version = BOOTINFO_VERSION;
345 bootinfo.bi_kernelname = (u_int32_t)(name + ouraddr);
346 bootinfo.bi_nfs_diskless = 0;
347 bootinfo.bi_size = sizeof(bootinfo);
348 bootinfo.bi_bios_dev = dosdev;
351 * Load the kernel config file (if any). Its name is given by
352 * appending ".config" to the kernel name. Build the name inline
353 * because no str*() functions are available. The file has to be
354 * copied to &disklabel for userconfig. It can't be loaded there
355 * directly because the label is used late in readfile() in some
359 t = kernel_config_namebuf;
362 while ((*t++ = *s++) != '\0');
367 while ((*t++ = *s++) != '\0');
368 readfile(kernel_config_namebuf, kernel_config, KERNEL_CONFIG_SIZE);
369 pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE);
371 printf("total=0x%x entry point=0x%x\n", addr, startaddr);
372 startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
373 (unsigned)&bootinfo + ouraddr);
377 readfile(char *path, char *buf, size_t nbytes)
383 openstatus = openrd();
384 if (openstatus == 0) {
385 /* XXX no way to determine file size. */
388 buf[nbytes - 1] = '\0';
392 getbootdev(char *ptr, int *howto)
398 /* Copy the flags to save some bytes. */
404 while (c == ' ' || c == '\n')
407 while ((c = *++ptr) != '\0') {
408 if (c == ' ' || c == '\n')
436 while (c != '\0' && c != ' ' && c != '\n') {
442 if (f & RB_PROBEKBD) {
443 if (probe_keyboard()) {
444 f |= RB_DUAL | RB_SERIAL;
445 printf("No keyboard found\n");
447 printf("Keyboard found\n");
449 if (f & (RB_DUAL | RB_SERIAL))