Annotation of src/sys/arch/i386/i386/multiboot.c, Revision 1.20
1.20 ! jym 1: /* $NetBSD: multiboot.c,v 1.19 2009/02/22 18:05:42 ahoka 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.20 ! jym 33: __KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.19 2009/02/22 18:05:42 ahoka 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.20 ! jym 342: } else if ((void *)symtabp > RELOC(void *, &end) &&
! 343: (void *)strtabp < RELOC(void *, &end)) {
! 344: symstart = RELOC(Elf32_Addr, &end);
1.8 jmmv 345: strstart = symstart + symsize;
1.20 ! jym 346: } else if ((void *)symtabp < RELOC(void *, &end) &&
! 347: (void *)strtabp > RELOC(void *, &end)) {
! 348: strstart = RELOC(Elf32_Addr, &end);
1.8 jmmv 349: symstart = strstart + strsize;
350: } else {
351: /* symtabp and strtabp are both over end */
1.20 ! jym 352: if (symtabp < strtabp) {
! 353: symstart = RELOC(Elf32_Addr, &end);
1.8 jmmv 354: strstart = symstart + symsize;
355: } else {
1.20 ! jym 356: strstart = RELOC(Elf32_Addr, &end);
1.8 jmmv 357: symstart = strstart + strsize;
358: }
359: }
1.20 ! jym 360:
! 361: memcpy((void *)strstart, (void *)straddr, strsize);
! 362: memcpy((void *)symstart, (void *)symaddr, symsize);
! 363:
1.15 jmmv 364: *RELOC(int *, &esym) =
365: (int)(symstart + symsize + strsize + KERNBASE);
1.1 jmmv 366:
1.11 christos 367: ms->s_symstart = (void *)(symstart + KERNBASE);
1.8 jmmv 368: ms->s_symsize = symsize;
1.11 christos 369: ms->s_strstart = (void *)(strstart + KERNBASE);
1.8 jmmv 370: ms->s_strsize = strsize;
1.1 jmmv 371: #undef RELOC
372: }
373:
374: /* --------------------------------------------------------------------- */
375:
376: /*
377: * Sets up the biosgeom bootinfo structure if the Multiboot information
378: * structure provides information about disk drives.
379: */
380: static void
381: setup_biosgeom(struct multiboot_info *mi)
382: {
383: size_t pos;
384: uint8_t bidata[1024];
385: struct btinfo_biosgeom *bi;
386:
387: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES))
388: return;
389:
390: memset(bidata, 0, sizeof(bidata));
391: bi = (struct btinfo_biosgeom *)bidata;
392: pos = 0;
393:
394: while (pos < mi->mi_drives_length) {
395: struct multiboot_drive *md;
396: struct bi_biosgeom_entry bbe;
397:
398: md = (struct multiboot_drive *)
399: &((uint8_t *)mi->mi_drives_addr)[pos];
400:
401: memset(&bbe, 0, sizeof(bbe));
402: bbe.sec = md->md_sectors;
403: bbe.head = md->md_heads;
404: bbe.cyl = md->md_cylinders;
405: bbe.dev = md->md_number;
406:
407: memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe));
408: bi->num++;
409:
410: pos += md->md_length;
411: }
412:
413: bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM,
414: sizeof(struct btinfo_biosgeom) +
415: bi->num * sizeof(struct bi_biosgeom_entry));
416: }
417:
418: /* --------------------------------------------------------------------- */
419:
420: /*
421: * Sets up the default root device if the Multiboot information
422: * structure provides information about the boot drive (where the kernel
423: * image was loaded from) or if the user gave a 'root' parameter on the
424: * boot command line.
425: */
426: static void
427: setup_bootdisk(struct multiboot_info *mi)
428: {
1.10 thorpej 429: bool found;
1.1 jmmv 430: struct btinfo_rootdevice bi;
431:
1.12 thorpej 432: found = false;
1.1 jmmv 433:
434: if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
435: found = optstr_get(mi->mi_cmdline, "root", bi.devname,
436: sizeof(bi.devname));
437:
438: if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) {
439: const char *devprefix;
440:
1.4 jmmv 441: /* Attempt to match the BIOS boot disk to a device. There
442: * is not much we can do to get it right. (Well, strictly
443: * speaking, we could, but it is certainly not worth the
444: * extra effort.) */
1.3 jmmv 445: switch (mi->mi_boot_device_drive) {
446: case 0x00: devprefix = "fd0"; break;
447: case 0x01: devprefix = "fd1"; break;
448: case 0x80: devprefix = "wd0"; break;
449: case 0x81: devprefix = "wd1"; break;
450: case 0x82: devprefix = "wd2"; break;
451: case 0x83: devprefix = "wd3"; break;
1.4 jmmv 452: default: devprefix = "wd0";
1.1 jmmv 453: }
454:
1.4 jmmv 455: strcpy(bi.devname, devprefix);
456: if (mi->mi_boot_device_part2 != 0xFF)
457: bi.devname[3] = mi->mi_boot_device_part2 + 'a';
458: else
459: bi.devname[3] = 'a';
460: bi.devname[4] = '\0';
1.1 jmmv 461:
1.12 thorpej 462: found = true;
1.1 jmmv 463: }
464:
465: if (found) {
466: bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE,
467: sizeof(struct btinfo_rootdevice));
468: }
469: }
470:
471: /* --------------------------------------------------------------------- */
472:
473: /*
474: * Sets up the bootpath bootinfo structure with an appropriate kernel
475: * name derived from the boot command line. The Multiboot information
476: * structure does not provide this detail directly, so we try to derive
477: * it from the command line setting.
478: */
479: static void
480: setup_bootpath(struct multiboot_info *mi)
481: {
482: struct btinfo_bootpath bi;
483: char *cl, *cl2, old;
484: int len;
485:
486: if (strncmp(Multiboot_Loader_Name, "GNU GRUB ",
487: sizeof(Multiboot_Loader_Name)) > 0) {
488: cl = mi->mi_cmdline;
489: while (*cl != '\0' && *cl != '/')
490: cl++;
491: cl2 = cl;
492: len = 0;
493: while (*cl2 != '\0' && *cl2 != ' ') {
494: len++;
495: cl2++;
496: }
497:
498: old = *cl2;
499: *cl2 = '\0';
500: memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len));
501: *cl2 = old;
502: bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0';
503:
504: bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH,
505: sizeof(struct btinfo_bootpath));
506: }
507: }
508:
509: /* --------------------------------------------------------------------- */
510:
511: /*
512: * Sets up the console bootinfo structure if the user gave a 'console'
513: * argument on the boot command line. The Multiboot information
514: * structure gives no hint about this, so the only way to know where the
515: * console is is to let the user specify it.
516: *
517: * If there wasn't any 'console' argument, this does not generate any
518: * bootinfo entry, falling back to the kernel's default console.
519: *
520: * If there weren't any of 'console_speed' or 'console_addr' arguments,
521: * this falls back to the default values for the serial port.
522: */
523: static void
524: setup_console(struct multiboot_info *mi)
525: {
526: struct btinfo_console bi;
1.10 thorpej 527: bool found;
1.1 jmmv 528:
1.12 thorpej 529: found = false;
1.1 jmmv 530:
531: if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
532: found = optstr_get(mi->mi_cmdline, "console", bi.devname,
533: sizeof(bi.devname));
534:
535: if (found) {
1.14 jmmv 536: bool valid;
537:
1.1 jmmv 538: if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) {
539: char tmp[10];
540:
541: found = optstr_get(mi->mi_cmdline, "console_speed",
542: tmp, sizeof(tmp));
543: if (found)
544: bi.speed = strtoul(tmp, NULL, 10);
545: else
546: bi.speed = 0; /* Use default speed. */
547:
548: found = optstr_get(mi->mi_cmdline, "console_addr",
549: tmp, sizeof(tmp));
550: if (found) {
551: if (tmp[0] == '0' && tmp[1] == 'x')
552: bi.addr = strtoul(tmp + 2, NULL, 16);
553: else
554: bi.addr = strtoul(tmp, NULL, 10);
555: } else
556: bi.addr = 0; /* Use default address. */
557:
1.14 jmmv 558: valid = true;
559: } else if (strncmp(bi.devname, "pc", sizeof(bi.devname)) == 0)
560: valid = true;
561: else
562: valid = false;
563:
564: if (valid)
565: bootinfo_add((struct btinfo_common *)&bi,
566: BTINFO_CONSOLE, sizeof(struct btinfo_console));
1.1 jmmv 567: }
568: }
569:
570: /* --------------------------------------------------------------------- */
571:
572: /*
573: * Sets up the 'boothowto' variable based on the options given in the
574: * boot command line, if any.
575: */
576: static void
577: setup_howto(struct multiboot_info *mi)
578: {
579: char *cl;
580:
581: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE))
582: return;
583:
584: cl = mi->mi_cmdline;
585:
586: /* Skip kernel file name. */
587: while (*cl != '\0' && *cl != ' ')
588: cl++;
589: while (*cl != '\0' && *cl == ' ')
590: cl++;
591:
592: /* Check if there are flags and set 'howto' accordingly. */
593: if (*cl == '-') {
594: int howto = 0;
595:
596: cl++;
597: while (*cl != '\0' && *cl != ' ') {
598: BOOT_FLAG(*cl, howto);
599: cl++;
600: }
601: if (*cl == ' ')
602: cl++;
603:
604: boothowto = howto;
605: }
606: }
607:
608: /* --------------------------------------------------------------------- */
609:
610: /*
611: * Sets up the memmap bootinfo structure to describe available memory as
612: * given by the BIOS.
613: */
614: static void
615: setup_memmap(struct multiboot_info *mi)
616: {
617: char data[1024];
618: size_t i;
619: struct btinfo_memmap *bi;
620:
621: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP))
622: return;
623:
624: bi = (struct btinfo_memmap *)data;
625: bi->num = 0;
626:
627: i = 0;
628: while (i < mi->mi_mmap_length) {
629: struct multiboot_mmap *mm;
630: struct bi_memmap_entry *bie;
631:
632: bie = &bi->entry[bi->num];
633:
634: mm = (struct multiboot_mmap *)(mi->mi_mmap_addr + i);
635: bie->addr = mm->mm_base_addr;
636: bie->size = mm->mm_length;
637: if (mm->mm_type == 1)
638: bie->type = BIM_Memory;
639: else
640: bie->type = BIM_Reserved;
641:
642: bi->num++;
643: i += mm->mm_size + 4;
644: }
645:
646: bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP,
647: sizeof(data));
648: }
649:
650: /* --------------------------------------------------------------------- */
651:
652: /*
653: * Sets up the 'biosbasemem' and 'biosextmem' variables if the
654: * Multiboot information structure provides information about memory.
655: */
656: static void
657: setup_memory(struct multiboot_info *mi)
658: {
1.6 mrg 659:
1.1 jmmv 660: if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY))
661: return;
662:
1.6 mrg 663: /* Make sure we don't override user-set variables. */
664: if (biosbasemem == 0) {
665: biosbasemem = mi->mi_mem_lower;
666: biosmem_implicit = 1;
667: }
668: if (biosextmem == 0) {
669: biosextmem = mi->mi_mem_upper;
670: biosmem_implicit = 1;
671: }
1.1 jmmv 672: }
673:
674: /* --------------------------------------------------------------------- */
675:
676: /*
1.8 jmmv 677: * Sets up the initial kernel symbol table. Returns true if this was
678: * passed in by Multiboot; false otherwise.
1.1 jmmv 679: */
1.10 thorpej 680: bool
1.19 ahoka 681: multiboot_ksyms_addsyms_elf(void)
1.1 jmmv 682: {
1.8 jmmv 683: struct multiboot_info *mi = &Multiboot_Info;
684: struct multiboot_symbols *ms = &Multiboot_Symbols;
1.1 jmmv 685:
1.8 jmmv 686: if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
1.9 jmmv 687: Elf32_Ehdr ehdr;
688:
1.8 jmmv 689: KASSERT(esym != 0);
1.1 jmmv 690:
1.9 jmmv 691: memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
692: ehdr.e_ident[EI_CLASS] = ELFCLASS32;
693: ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
694: ehdr.e_ident[EI_VERSION] = EV_CURRENT;
695: ehdr.e_type = ET_EXEC;
696: ehdr.e_machine = EM_386;
697: ehdr.e_version = 1;
698: ehdr.e_ehsize = sizeof(ehdr);
699:
1.18 martin 700: ksyms_addsyms_explicit((void *)&ehdr,
1.9 jmmv 701: ms->s_symstart, ms->s_symsize,
1.8 jmmv 702: ms->s_strstart, ms->s_strsize);
703: }
1.1 jmmv 704:
1.8 jmmv 705: return mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS;
1.1 jmmv 706: }
CVSweb <webmaster@jp.NetBSD.org>