]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/boot/pc98/boot2/boot.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / boot / pc98 / boot2 / boot.c
1 /*
2  * Mach Operating System
3  * Copyright (c) 1992, 1991 Carnegie Mellon University
4  * All Rights Reserved.
5  *
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.
11  *
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.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie Mellon
24  * the rights to redistribute these changes.
25  *
26  *      from: Mach, [92/04/03  16:51:14  rvb]
27  */
28 /*
29   Copyright 1988, 1989, 1990, 1991, 1992
30    by Intel Corporation, Santa Clara, California.
31
32                 All Rights Reserved
33
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.
41
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.
49 */
50
51 #include <sys/cdefs.h>
52 __FBSDID("$FreeBSD$");
53
54 #include "boot.h"
55 #include <a.out.h>
56 #include <sys/reboot.h>
57 #include <machine/bootinfo.h>
58
59 #define ouraddr (BOOTSEG << 4)          /* XXX */
60
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() */
65
66 static char boot_config[BOOT_CONFIG_SIZE];
67 static char boot_help[BOOT_HELP_SIZE];
68 char *name;
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;
74 int loadflags;
75
76 static void getbootdev(char *ptr, int *howto);
77 static void loadprog(void);
78 static void readfile(char *path, char *buf, size_t nbytes);
79
80 /* NORETURN */
81 void
82 boot(int drive)
83 {
84         int i, ret;
85         unsigned char disk_equips;
86
87         /* Pick up the story from the Bios on geometry of disks */
88
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);
92                 }
93         }
94
95         bootinfo.bi_basemem = memsize(0);
96         bootinfo.bi_extmem = memsize(1);
97         bootinfo.bi_memsizes_valid = 1;
98
99         gateA20();
100
101         /* set machine type to PC98_SYSTEM_PARAMETER */
102         machine_check();
103
104         /*
105          * The default boot device is the first partition in the
106          * compatibility slice on the boot drive.
107          */
108         dosdev = drive;
109         maj = (drive&0x70) >> 3;                /* a good first bet */
110         if (maj == 4) { /* da */
111                 disk_equips = *(unsigned char *)V(0xA1482);
112                 unit = 0;
113                 for (i=0; i<(drive&0x0f); i++) {
114                         int media = ((unsigned *)V(0xA1460))[i] & 0x1F;
115
116                         if ((disk_equips >> i) & 1)     /* HD */
117                                 unit++;
118                         else if (media == 7)            /* MO */
119                                 unit++;
120                 }
121         } else {
122                 unit = drive & 0x0f;
123         }
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);
129                 if (openrd() != 0)
130                         name = "kernel";
131         }
132 loadstart:
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"
137                "%s\n"
138                "boot: ",
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*",
144                boot_help);
145
146         /*
147          * Ignore flags from previous attempted boot, if any.
148          * XXX this is now too strict.  Settings given in boot.config should
149          * not be changed.
150          */
151         loadflags &= (RB_DUAL | RB_SERIAL);
152
153         /*
154          * Be paranoid and make doubly sure that the input buffer is empty.
155          */
156         if (loadflags & (RB_DUAL | RB_SERIAL))
157                 init_serial();
158
159         if (!gets(linebuf))
160                 putchar('\n');
161         else
162                 getbootdev(linebuf, &loadflags);
163         if (name == NULL)
164                 goto loadstart;
165         ret = openrd();
166         if (ret != 0) {
167                 if (ret > 0)
168                         printf("Can't find %s\n", name);
169                 goto loadstart;
170         }
171 /*      if (inode.i_mode&IEXEC)
172                 loadflags |= RB_KDB;
173 */
174         loadprog();
175         goto loadstart;
176 }
177
178 static void
179 loadprog(void)
180 {
181         struct exec head;
182         int startaddr;
183         int addr;       /* physical address.. not directly useable */
184         int bootdev;
185         int i;
186         unsigned pad;
187         char *s, *t;
188
189         read((void *)&head, sizeof(head));
190         if ( N_BADMAG(head)) {
191                 printf("Invalid format!\n");
192                 return;
193         }
194
195         poff = N_TXTOFF(head);
196         /*if(poff==0)
197                 poff = 32;*/
198
199         /*
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.
203          */
204         startaddr = head.a_entry & 0x00FFFFFF;
205         addr =  startaddr;
206         printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
207                         , dosdev & 0x0f
208                         , devs[maj]
209                         , unit
210                         , 'a'+part
211                         , name
212                         , addr);
213         if(addr < 0x00100000)
214         {
215                 /*
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.
219                  */
220                 printf("Start address too low\n");
221                 return;
222         }
223         printf("text=0x%x ", head.a_text);
224         /********************************************************/
225         /* LOAD THE TEXT SEGMENT                                */
226         /********************************************************/
227         xread((void *)addr, head.a_text);
228         addr += head.a_text;
229
230         /********************************************************/
231         /* Load the Initialised data after the text             */
232         /********************************************************/
233         while (addr & PAGE_MASK)
234                 *(char *)addr++ = 0;
235
236         printf("data=0x%x ", head.a_data);
237         xread((void *)addr, head.a_data);
238         addr += head.a_data;
239
240         /********************************************************/
241         /* Skip over the uninitialised data                     */
242         /* (but clear it)                                       */
243         /********************************************************/
244         printf("bss=0x%x ", head.a_bss);
245
246 /*
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
249  * machines.
250  */
251         /* kzip & kernel will zero their own bss */
252         addr += head.a_bss;
253
254         /* Pad to a page boundary. */
255         pad = (unsigned)addr & PAGE_MASK;
256         if (pad != 0) {
257                 pad = PAGE_SIZE - pad;
258                 addr += pad;
259         }
260         bootinfo.bi_symtab = addr;
261
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);
267
268         /********************************************************/
269         /* Load the symbol table                                */
270         /********************************************************/
271         printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
272                head.a_syms);
273         xread((void *)addr, head.a_syms);
274         addr += head.a_syms;
275
276         /********************************************************/
277         /* Load the string table size                           */
278         /********************************************************/
279         read((void *)&i, sizeof(int));
280         pcpy(&i, (void *)addr, sizeof(int));
281         i -= sizeof(int);
282         addr += sizeof(int);
283
284         /********************************************************/
285         /* Load the string table                                */
286         /********************************************************/
287        printf("+0x%x+0x%x]\n", sizeof(int), i);
288         xread((void *)addr, i);
289         addr += i;
290
291         bootinfo.bi_esymtab = addr;
292
293         /*
294          * For backwards compatibility, use the previously-unused adaptor
295          * and controller bitfields to hold the slice number.
296          */
297         bootdev = MAKEBOOTDEV(maj, slice, unit, part);
298
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;
304
305         /*
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
311          * unusual cases.
312          */
313         s = name;
314         t = kernel_config_namebuf;
315         do
316                 ;
317         while ((*t++ = *s++) != '\0');
318         s = ".config";
319         --t;
320         do
321                 ;
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);
325
326         printf("total=0x%x entry point=0x%x\n", addr, startaddr);
327         startprog(startaddr, loadflags | RB_BOOTINFO, bootdev,
328                   (unsigned)&bootinfo + ouraddr);
329 }
330
331 static void
332 readfile(char *path, char *buf, size_t nbytes)
333 {
334         int openstatus;
335
336         buf[0] = '\0';
337         name = path;
338         openstatus = openrd();
339         if (openstatus == 0) {
340                 /* XXX no way to determine file size. */
341                 read(buf, nbytes);
342         }
343         buf[nbytes - 1] = '\0';
344 }
345
346 static void
347 getbootdev(char *ptr, int *howto)
348 {
349         char c;
350         int f;
351         char *p;
352
353         /* Copy the flags to save some bytes. */
354         f = *howto;
355
356         c = *ptr;
357         for (;;) {
358 nextarg:
359                 while (c == ' ' || c == '\n')
360                         c = *++ptr;
361                 if (c == '-')
362                         while ((c = *++ptr) != '\0') {
363                                 if (c == ' ' || c == '\n')
364                                         goto nextarg;
365                                 if (c == 'a')
366                                         f |= RB_ASKNAME;
367                                 if (c == 'C')
368                                         f |= RB_CDROM;
369                                 if (c == 'D')
370                                         f ^= RB_DUAL;
371                                 if (c == 'd')
372                                         f |= RB_KDB;
373                                 if (c == 'g')
374                                         f |= RB_GDB;
375                                 if (c == 'h')
376                                         f ^= RB_SERIAL;
377                                 if (c == 'P')
378                                         f |= RB_PROBEKBD;
379                                 if (c == 'r')
380                                         f |= RB_DFLTROOT;
381                                 if (c == 's')
382                                         f |= RB_SINGLE;
383                                 if (c == 'v')
384                                         f |= RB_VERBOSE;
385                         }
386                 if (c == '\0')
387                         break;
388                 p = name = namebuf;
389                 while (c != '\0' && c != ' ' && c != '\n') {
390                         *p++ = c;
391                         c = *++ptr;
392                 }
393                 *p = '\0';
394         }
395         if (f & RB_PROBEKBD) {
396                 if (probe_keyboard()) {
397                         f |= RB_DUAL | RB_SERIAL;
398                         printf("No keyboard found\n");
399                 } else
400                         printf("Keyboard found\n");
401         }
402         if (f & (RB_DUAL | RB_SERIAL))
403                 init_serial();
404         *howto = f;
405 }