Annotation of src/sys/arch/i386/i386/multiboot.c, Revision 1.8
1.8 ! jmmv 1: /* $NetBSD: multiboot.c,v 1.7 2006/10/12 01:30:42 christos Exp $ */
1.1 jmmv 2:
3: /*-
4: * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Julio M. Merino Vidal.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: #include <sys/cdefs.h>
1.8 ! jmmv 40: __KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.7 2006/10/12 01:30:42 christos Exp $");
1.1 jmmv 41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/cdefs_elf.h>
45: #include <sys/boot_flag.h>
46: #include <sys/exec.h>
47: #include <sys/exec_elf.h>
48: #include <sys/optstr.h>
1.8 ! jmmv 49: #include <sys/ksyms.h>
1.1 jmmv 50:
51: #include <machine/bootinfo.h>
52: #include <machine/multiboot.h>
53:
54: #if !defined(MULTIBOOT)
55: # error "MULTIBOOT not defined; this cannot happen."
56: #endif
57:
58: /* --------------------------------------------------------------------- */
59:
60: /*
1.8 ! jmmv 61: * Symbol and string table for the loaded kernel.
! 62: */
! 63:
! 64: struct multiboot_symbols {
! 65: caddr_t s_symstart;
! 66: size_t s_symsize;
! 67: caddr_t s_strstart;
! 68: size_t s_strsize;
! 69: };
! 70:
! 71: /* --------------------------------------------------------------------- */
! 72:
! 73: /*
1.1 jmmv 74: * External variables. All of them, with the exception of 'end', must
75: * be set at some point within this file.
1.6 mrg 76: *
77: * XXX these should be found in a header file!
1.1 jmmv 78: */
79: extern int biosbasemem;
80: extern int biosextmem;
1.6 mrg 81: extern int biosmem_implicit;
1.1 jmmv 82: extern int boothowto;
83: extern struct bootinfo bootinfo;
84: extern int end;
85: extern int * esym;
86:
87: /* --------------------------------------------------------------------- */
88:
89: /*
90: * Copy of the Multiboot information structure passed to us by the boot
91: * loader. The Multiboot_Info structure has some pointers adjusted to the
92: * other variables -- see multiboot_pre_reloc() -- so you oughtn't access
93: * them directly. In other words, always access them through the
94: * Multiboot_Info variable.
95: */
96: static char Multiboot_Cmdline[255];
97: static uint8_t Multiboot_Drives[255];
98: static struct multiboot_info Multiboot_Info;
99: static boolean_t Multiboot_Loader = FALSE;
100: static char Multiboot_Loader_Name[255];
101: static uint8_t Multiboot_Mmap[1024];
1.8 ! jmmv 102: static struct multiboot_symbols Multiboot_Symbols;
1.1 jmmv 103:
104: /* --------------------------------------------------------------------- */
105:
106: /*
107: * Prototypes for private functions.
108: */
109: static void bootinfo_add(struct btinfo_common *, int, int);
110: static void copy_syms(struct multiboot_info *);
111: static void setup_biosgeom(struct multiboot_info *);
112: static void setup_bootdisk(struct multiboot_info *);
113: static void setup_bootpath(struct multiboot_info *);
114: static void setup_console(struct multiboot_info *);
115: static void setup_howto(struct multiboot_info *);
116: static void setup_memory(struct multiboot_info *);
117: static void setup_memmap(struct multiboot_info *);
118:
119: /* --------------------------------------------------------------------- */
120:
121: /*
122: * Sets up the kernel if it was booted by a Multiboot-compliant boot
123: * loader. This is executed before the kernel has relocated itself.
124: * The main purpose of this function is to copy all the information
125: * passed in by the boot loader to a safe place, so that it is available
126: * after it has been relocated.
127: *
128: * WARNING: Because the kernel has not yet relocated itself to KERNBASE,
129: * special care has to be taken when accessing memory because absolute
130: * addresses (referring to kernel symbols) do not work. So:
131: *
132: * 1) Avoid jumps to absolute addresses (such as gotos and switches).
133: * 2) To access global variables use their physical address, which
134: * can be obtained using the RELOC macro.
135: */
136: void
137: multiboot_pre_reloc(struct multiboot_info *mi)
138: {
139: #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
140: struct multiboot_info *midest =
141: RELOC(struct multiboot_info *, &Multiboot_Info);
142:
143: *RELOC(boolean_t *, &Multiboot_Loader) = TRUE;
144: memcpy(midest, mi, sizeof(Multiboot_Info));
145:
146: if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) {
147: strncpy(RELOC(void *, Multiboot_Cmdline), mi->mi_cmdline,
148: sizeof(Multiboot_Cmdline));
149: midest->mi_cmdline = (char *)&Multiboot_Cmdline;
150: }
151:
152: if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) {
153: strncpy(RELOC(void *, Multiboot_Loader_Name),
154: mi->mi_loader_name, sizeof(Multiboot_Loader_Name));
155: midest->mi_loader_name = (char *)&Multiboot_Loader_Name;
156: }
157:
158: if (mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) {
159: memcpy(RELOC(void *, Multiboot_Mmap),
160: (void *)mi->mi_mmap_addr, mi->mi_mmap_length);
161: midest->mi_mmap_addr = (vaddr_t)&Multiboot_Mmap;
162: }
163:
164: if (mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) {
165: memcpy(RELOC(void *, Multiboot_Drives),
166: (void *)mi->mi_drives_addr, mi->mi_drives_length);
167: midest->mi_drives_addr = (vaddr_t)&Multiboot_Drives;
168: }
169:
170: copy_syms(mi);
171: #undef RELOC
172: }
173:
174: /* --------------------------------------------------------------------- */
175:
176: /*
177: * Sets up the kernel if it was booted by a Multiboot-compliant boot
178: * loader. This is executed just after the kernel has relocated itself.
179: * At this point, executing any kind of code is safe, keeping in mind
180: * that no devices have been initialized yet (not even the console!).
181: */
182: void
183: multiboot_post_reloc(void)
184: {
185: struct multiboot_info *mi;
186:
187: if (! Multiboot_Loader)
188: return;
189:
190: mi = &Multiboot_Info;
191: bootinfo.bi_nentries = 0;
192:
193: setup_memory(mi);
194: setup_console(mi);
195: setup_howto(mi);
196: setup_bootpath(mi);
197: setup_biosgeom(mi);
1.3 jmmv 198: setup_bootdisk(mi);
1.1 jmmv 199: setup_memmap(mi);
200: }
201:
202: /* --------------------------------------------------------------------- */
203:
204: /*
205: * Prints a summary of the information collected in the Multiboot
206: * information header (if present). Done as a separate function because
207: * the console has to be available.
208: */
209: void
210: multiboot_print_info(void)
211: {
212: struct multiboot_info *mi = &Multiboot_Info;
1.8 ! jmmv 213: struct multiboot_symbols *ms = &Multiboot_Symbols;
1.1 jmmv 214:
215: if (! Multiboot_Loader)
216: return;
217:
218: printf("multiboot: Information structure flags: 0x%08x\n",
219: mi->mi_flags);
220:
221: if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME)
222: printf("multiboot: Boot loader: %s\n", mi->mi_loader_name);
223:
224: if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
225: printf("multiboot: Command line: %s\n", mi->mi_cmdline);
226:
227: if (mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY)
228: printf("multiboot: %u KB lower memory, %u KB upper memory\n",
229: mi->mi_mem_lower, mi->mi_mem_upper);
230:
1.8 ! jmmv 231: if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
! 232: KASSERT(esym != 0);
! 233: printf("multiboot: Symbol table at %p, length %d bytes\n",
! 234: ms->s_symstart, ms->s_symsize);
! 235: printf("multiboot: String table at %p, length %d bytes\n",
! 236: ms->s_strstart, ms->s_strsize);
! 237: }
1.1 jmmv 238: }
239:
240: /* --------------------------------------------------------------------- */
241:
242: /*
243: * Adds the bootinfo entry given in 'item' to the bootinfo tables.
244: * Sets the item type to 'type' and its length to 'len'.
245: */
246: static void
247: bootinfo_add(struct btinfo_common *item, int type, int len)
248: {
249: int i;
250: struct bootinfo *bip = (struct bootinfo *)&bootinfo;
251: vaddr_t data;
252:
253: item->type = type;
254: item->len = len;
255:
256: data = (vaddr_t)&bip->bi_data;
257: for (i = 0; i < bip->bi_nentries; i++) {
258: struct btinfo_common *tmp;
259:
260: tmp = (struct btinfo_common *)data;
261: data += tmp->len;
262: }
263: if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) {
264: memcpy((void *)data, item, len);
265: bip->bi_nentries++;
266: }
267: }
268:
269: /* --------------------------------------------------------------------- */
270:
271: /*
272: * Copies the symbol table and the strings table passed in by the boot
273: * loader after the kernel's image, and sets up 'esym' accordingly so
274: * that this data is properly copied into upper memory during relocation.
275: *
276: * WARNING: This code runs before the kernel has relocated itself. See
277: * the note in multiboot_pre_reloc() for more information.
278: */
279: static void
280: copy_syms(struct multiboot_info *mi)
281: {
282: #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
283: int i;
284: Elf32_Shdr *symtabp, *strtabp;
1.8 ! jmmv 285: struct multiboot_symbols *ms;
! 286: size_t symsize, strsize;
! 287: paddr_t symaddr, straddr;
! 288: paddr_t symstart, strstart;
! 289:
1.1 jmmv 290:
291: /*
292: * Check if the Multiboot information header has symbols or not.
293: */
294: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS))
295: return;
296:
1.8 ! jmmv 297: ms = RELOC(struct multiboot_symbols *, &Multiboot_Symbols);
! 298:
1.1 jmmv 299: /*
300: * Locate a symbol table and its matching string table in the
301: * section headers passed in by the boot loader. Set 'symtabp'
302: * and 'strtabp' with pointers to the matching entries.
303: */
304: symtabp = strtabp = NULL;
305: for (i = 0; i < mi->mi_elfshdr_num && symtabp == NULL &&
306: strtabp == NULL; i++) {
307: Elf32_Shdr *shdrp;
308:
309: shdrp = &((Elf32_Shdr *)mi->mi_elfshdr_addr)[i];
310:
311: if ((shdrp->sh_type & SHT_SYMTAB) &&
312: shdrp->sh_link != SHN_UNDEF) {
313: Elf32_Shdr *shdrp2;
314:
315: shdrp2 = &((Elf32_Shdr *)mi->mi_elfshdr_addr)
316: [shdrp->sh_link];
317:
318: if (shdrp2->sh_type & SHT_STRTAB) {
319: symtabp = shdrp;
320: strtabp = shdrp2;
321: }
322: }
323: }
324: if (symtabp == NULL || strtabp == NULL)
325: return;
326:
1.8 ! jmmv 327: symaddr = symtabp->sh_addr;
! 328: straddr = strtabp->sh_addr;
! 329: symsize = symtabp->sh_size;
! 330: strsize = strtabp->sh_size;
1.1 jmmv 331:
332: /*
1.8 ! jmmv 333: * Copy the symbol and string tables just after the kernel's
! 334: * end address, in this order. Only the contents of these ELF
! 335: * sections are copied; headers are discarded. esym is later
! 336: * updated to point to the lowest "free" address after the tables
! 337: * so that they are mapped appropriately when enabling paging.
1.1 jmmv 338: *
1.8 ! jmmv 339: * We need to be careful to not overwrite valid data doing the
! 340: * copies, hence all the different cases below. We can assume
! 341: * that if the tables start before the kernel's end address,
! 342: * they will not grow over this address.
1.1 jmmv 343: */
1.8 ! jmmv 344: if ((paddr_t)symtabp < (paddr_t)&end - KERNBASE &&
! 345: (paddr_t)strtabp < (paddr_t)&end - KERNBASE) {
! 346: symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
! 347: strstart = symstart + symsize;
! 348: memcpy((void *)symstart, (void *)symaddr, symsize);
! 349: memcpy((void *)strstart, (void *)straddr, strsize);
! 350: } else if ((paddr_t)symtabp > (paddr_t)&end - KERNBASE &&
! 351: (paddr_t)strtabp < (paddr_t)&end - KERNBASE) {
! 352: symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
! 353: strstart = symstart + symsize;
! 354: memcpy((void *)symstart, (void *)symaddr, symsize);
! 355: memcpy((void *)strstart, (void *)straddr, strsize);
! 356: } else if ((paddr_t)symtabp < (paddr_t)&end - KERNBASE &&
! 357: (paddr_t)strtabp > (paddr_t)&end - KERNBASE) {
! 358: strstart = (paddr_t)((vaddr_t)&end - KERNBASE);
! 359: symstart = strstart + strsize;
! 360: memcpy((void *)strstart, (void *)straddr, strsize);
! 361: memcpy((void *)symstart, (void *)symaddr, symsize);
! 362: } else {
! 363: /* symtabp and strtabp are both over end */
! 364: if ((paddr_t)symtabp < (paddr_t)strtabp) {
! 365: symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
! 366: strstart = symstart + symsize;
! 367: memcpy((void *)symstart, (void *)symaddr, symsize);
! 368: memcpy((void *)strstart, (void *)straddr, strsize);
! 369: } else {
! 370: strstart = (paddr_t)((vaddr_t)&end - KERNBASE);
! 371: symstart = strstart + strsize;
! 372: memcpy((void *)strstart, (void *)straddr, strsize);
! 373: memcpy((void *)symstart, (void *)symaddr, symsize);
! 374: }
! 375: }
! 376: *RELOC(int *, &esym) = (int)(strstart + strsize + KERNBASE);
1.1 jmmv 377:
1.8 ! jmmv 378: ms->s_symstart = (caddr_t)(symstart + KERNBASE);
! 379: ms->s_symsize = symsize;
! 380: ms->s_strstart = (caddr_t)(strstart + KERNBASE);
! 381: ms->s_strsize = strsize;
1.1 jmmv 382: #undef RELOC
383: }
384:
385: /* --------------------------------------------------------------------- */
386:
387: /*
388: * Sets up the biosgeom bootinfo structure if the Multiboot information
389: * structure provides information about disk drives.
390: */
391: static void
392: setup_biosgeom(struct multiboot_info *mi)
393: {
394: size_t pos;
395: uint8_t bidata[1024];
396: struct btinfo_biosgeom *bi;
397:
398: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES))
399: return;
400:
401: memset(bidata, 0, sizeof(bidata));
402: bi = (struct btinfo_biosgeom *)bidata;
403: pos = 0;
404:
405: while (pos < mi->mi_drives_length) {
406: struct multiboot_drive *md;
407: struct bi_biosgeom_entry bbe;
408:
409: md = (struct multiboot_drive *)
410: &((uint8_t *)mi->mi_drives_addr)[pos];
411:
412: memset(&bbe, 0, sizeof(bbe));
413: bbe.sec = md->md_sectors;
414: bbe.head = md->md_heads;
415: bbe.cyl = md->md_cylinders;
416: bbe.dev = md->md_number;
417:
418: memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe));
419: bi->num++;
420:
421: pos += md->md_length;
422: }
423:
424: bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM,
425: sizeof(struct btinfo_biosgeom) +
426: bi->num * sizeof(struct bi_biosgeom_entry));
427: }
428:
429: /* --------------------------------------------------------------------- */
430:
431: /*
432: * Sets up the default root device if the Multiboot information
433: * structure provides information about the boot drive (where the kernel
434: * image was loaded from) or if the user gave a 'root' parameter on the
435: * boot command line.
436: */
437: static void
438: setup_bootdisk(struct multiboot_info *mi)
439: {
440: boolean_t found;
441: struct btinfo_rootdevice bi;
442:
443: found = FALSE;
444:
445: if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
446: found = optstr_get(mi->mi_cmdline, "root", bi.devname,
447: sizeof(bi.devname));
448:
449: if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) {
450: const char *devprefix;
451:
1.4 jmmv 452: /* Attempt to match the BIOS boot disk to a device. There
453: * is not much we can do to get it right. (Well, strictly
454: * speaking, we could, but it is certainly not worth the
455: * extra effort.) */
1.3 jmmv 456: switch (mi->mi_boot_device_drive) {
457: case 0x00: devprefix = "fd0"; break;
458: case 0x01: devprefix = "fd1"; break;
459: case 0x80: devprefix = "wd0"; break;
460: case 0x81: devprefix = "wd1"; break;
461: case 0x82: devprefix = "wd2"; break;
462: case 0x83: devprefix = "wd3"; break;
1.4 jmmv 463: default: devprefix = "wd0";
1.1 jmmv 464: }
465:
1.4 jmmv 466: strcpy(bi.devname, devprefix);
467: if (mi->mi_boot_device_part2 != 0xFF)
468: bi.devname[3] = mi->mi_boot_device_part2 + 'a';
469: else
470: bi.devname[3] = 'a';
471: bi.devname[4] = '\0';
1.1 jmmv 472:
1.4 jmmv 473: found = TRUE;
1.1 jmmv 474: }
475:
476: if (found) {
477: bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE,
478: sizeof(struct btinfo_rootdevice));
479: }
480: }
481:
482: /* --------------------------------------------------------------------- */
483:
484: /*
485: * Sets up the bootpath bootinfo structure with an appropriate kernel
486: * name derived from the boot command line. The Multiboot information
487: * structure does not provide this detail directly, so we try to derive
488: * it from the command line setting.
489: */
490: static void
491: setup_bootpath(struct multiboot_info *mi)
492: {
493: struct btinfo_bootpath bi;
494: char *cl, *cl2, old;
495: int len;
496:
497: if (strncmp(Multiboot_Loader_Name, "GNU GRUB ",
498: sizeof(Multiboot_Loader_Name)) > 0) {
499: cl = mi->mi_cmdline;
500: while (*cl != '\0' && *cl != '/')
501: cl++;
502: cl2 = cl;
503: len = 0;
504: while (*cl2 != '\0' && *cl2 != ' ') {
505: len++;
506: cl2++;
507: }
508:
509: old = *cl2;
510: *cl2 = '\0';
511: memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len));
512: *cl2 = old;
513: bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0';
514:
515: bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH,
516: sizeof(struct btinfo_bootpath));
517: }
518: }
519:
520: /* --------------------------------------------------------------------- */
521:
522: /*
523: * Sets up the console bootinfo structure if the user gave a 'console'
524: * argument on the boot command line. The Multiboot information
525: * structure gives no hint about this, so the only way to know where the
526: * console is is to let the user specify it.
527: *
528: * If there wasn't any 'console' argument, this does not generate any
529: * bootinfo entry, falling back to the kernel's default console.
530: *
531: * If there weren't any of 'console_speed' or 'console_addr' arguments,
532: * this falls back to the default values for the serial port.
533: */
534: static void
535: setup_console(struct multiboot_info *mi)
536: {
537: struct btinfo_console bi;
538: boolean_t found;
539:
540: found = FALSE;
541:
542: if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
543: found = optstr_get(mi->mi_cmdline, "console", bi.devname,
544: sizeof(bi.devname));
545:
546: if (found) {
547: if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) {
548: char tmp[10];
549:
550: found = optstr_get(mi->mi_cmdline, "console_speed",
551: tmp, sizeof(tmp));
552: if (found)
553: bi.speed = strtoul(tmp, NULL, 10);
554: else
555: bi.speed = 0; /* Use default speed. */
556:
557: found = optstr_get(mi->mi_cmdline, "console_addr",
558: tmp, sizeof(tmp));
559: if (found) {
560: if (tmp[0] == '0' && tmp[1] == 'x')
561: bi.addr = strtoul(tmp + 2, NULL, 16);
562: else
563: bi.addr = strtoul(tmp, NULL, 10);
564: } else
565: bi.addr = 0; /* Use default address. */
566: }
567:
568: bootinfo_add((struct btinfo_common *)&bi, BTINFO_CONSOLE,
569: sizeof(struct btinfo_console));
570: }
571: }
572:
573: /* --------------------------------------------------------------------- */
574:
575: /*
576: * Sets up the 'boothowto' variable based on the options given in the
577: * boot command line, if any.
578: */
579: static void
580: setup_howto(struct multiboot_info *mi)
581: {
582: char *cl;
583:
584: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE))
585: return;
586:
587: cl = mi->mi_cmdline;
588:
589: /* Skip kernel file name. */
590: while (*cl != '\0' && *cl != ' ')
591: cl++;
592: while (*cl != '\0' && *cl == ' ')
593: cl++;
594:
595: /* Check if there are flags and set 'howto' accordingly. */
596: if (*cl == '-') {
597: int howto = 0;
598:
599: cl++;
600: while (*cl != '\0' && *cl != ' ') {
601: BOOT_FLAG(*cl, howto);
602: cl++;
603: }
604: if (*cl == ' ')
605: cl++;
606:
607: boothowto = howto;
608: }
609: }
610:
611: /* --------------------------------------------------------------------- */
612:
613: /*
614: * Sets up the memmap bootinfo structure to describe available memory as
615: * given by the BIOS.
616: */
617: static void
618: setup_memmap(struct multiboot_info *mi)
619: {
620: char data[1024];
621: size_t i;
622: struct btinfo_memmap *bi;
623:
624: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP))
625: return;
626:
627: bi = (struct btinfo_memmap *)data;
628: bi->num = 0;
629:
630: i = 0;
631: while (i < mi->mi_mmap_length) {
632: struct multiboot_mmap *mm;
633: struct bi_memmap_entry *bie;
634:
635: bie = &bi->entry[bi->num];
636:
637: mm = (struct multiboot_mmap *)(mi->mi_mmap_addr + i);
638: bie->addr = mm->mm_base_addr;
639: bie->size = mm->mm_length;
640: if (mm->mm_type == 1)
641: bie->type = BIM_Memory;
642: else
643: bie->type = BIM_Reserved;
644:
645: bi->num++;
646: i += mm->mm_size + 4;
647: }
648:
649: bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP,
650: sizeof(data));
651: }
652:
653: /* --------------------------------------------------------------------- */
654:
655: /*
656: * Sets up the 'biosbasemem' and 'biosextmem' variables if the
657: * Multiboot information structure provides information about memory.
658: */
659: static void
660: setup_memory(struct multiboot_info *mi)
661: {
1.6 mrg 662:
1.1 jmmv 663: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY))
664: return;
665:
1.6 mrg 666: /* Make sure we don't override user-set variables. */
667: if (biosbasemem == 0) {
668: biosbasemem = mi->mi_mem_lower;
669: biosmem_implicit = 1;
670: }
671: if (biosextmem == 0) {
672: biosextmem = mi->mi_mem_upper;
673: biosmem_implicit = 1;
674: }
1.1 jmmv 675: }
676:
677: /* --------------------------------------------------------------------- */
678:
679: /*
1.8 ! jmmv 680: * Sets up the initial kernel symbol table. Returns true if this was
! 681: * passed in by Multiboot; false otherwise.
1.1 jmmv 682: */
1.8 ! jmmv 683: boolean_t
! 684: multiboot_ksyms_init(void)
1.1 jmmv 685: {
1.8 ! jmmv 686: struct multiboot_info *mi = &Multiboot_Info;
! 687: struct multiboot_symbols *ms = &Multiboot_Symbols;
1.1 jmmv 688:
1.8 ! jmmv 689: if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
! 690: KASSERT(esym != 0);
1.1 jmmv 691:
1.8 ! jmmv 692: ksyms_init_explicit(ms->s_symstart, ms->s_symsize,
! 693: ms->s_strstart, ms->s_strsize);
! 694: }
1.1 jmmv 695:
1.8 ! jmmv 696: return mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS;
1.1 jmmv 697: }
CVSweb <webmaster@jp.NetBSD.org>