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