Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / i386 / i386 / multiboot.c
blob03411461cf6a67e52104d31683a69befe31239cc
1 /* $NetBSD: multiboot.c,v 1.18 2008/11/30 18:21:34 martin Exp $ */
3 /*-
4 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Julio M. Merino Vidal.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.18 2008/11/30 18:21:34 martin Exp $");
35 #include "opt_multiboot.h"
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>
44 #include <sys/ksyms.h>
46 #include <machine/bootinfo.h>
47 #include <machine/multiboot.h>
49 #if !defined(MULTIBOOT)
50 # error "MULTIBOOT not defined; this cannot happen."
51 #endif
53 /* --------------------------------------------------------------------- */
56 * Symbol and string table for the loaded kernel.
59 struct multiboot_symbols {
60 void * s_symstart;
61 size_t s_symsize;
62 void * s_strstart;
63 size_t s_strsize;
66 /* --------------------------------------------------------------------- */
69 * External variables. All of them, with the exception of 'end', must
70 * be set at some point within this file.
72 * XXX these should be found in a header file!
74 extern int biosbasemem;
75 extern int biosextmem;
76 extern int biosmem_implicit;
77 extern int boothowto;
78 extern struct bootinfo bootinfo;
79 extern int end;
80 extern int * esym;
82 /* --------------------------------------------------------------------- */
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.
91 static char Multiboot_Cmdline[255];
92 static uint8_t Multiboot_Drives[255];
93 static struct multiboot_info Multiboot_Info;
94 static bool Multiboot_Loader = false;
95 static char Multiboot_Loader_Name[255];
96 static uint8_t Multiboot_Mmap[1024];
97 static struct multiboot_symbols Multiboot_Symbols;
99 /* --------------------------------------------------------------------- */
102 * Prototypes for private functions.
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 *);
114 /* --------------------------------------------------------------------- */
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.
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:
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.
131 void
132 multiboot_pre_reloc(struct multiboot_info *mi)
134 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
135 struct multiboot_info *midest =
136 RELOC(struct multiboot_info *, &Multiboot_Info);
138 *RELOC(bool *, &Multiboot_Loader) = true;
139 memcpy(midest, mi, sizeof(Multiboot_Info));
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;
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;
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;
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;
165 copy_syms(mi);
166 #undef RELOC
169 /* --------------------------------------------------------------------- */
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!).
177 void
178 multiboot_post_reloc(void)
180 struct multiboot_info *mi;
182 if (! Multiboot_Loader)
183 return;
185 mi = &Multiboot_Info;
186 bootinfo.bi_nentries = 0;
188 setup_memory(mi);
189 setup_console(mi);
190 setup_howto(mi);
191 setup_bootpath(mi);
192 setup_biosgeom(mi);
193 setup_bootdisk(mi);
194 setup_memmap(mi);
197 /* --------------------------------------------------------------------- */
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.
204 void
205 multiboot_print_info(void)
207 struct multiboot_info *mi = &Multiboot_Info;
208 struct multiboot_symbols *ms = &Multiboot_Symbols;
210 if (! Multiboot_Loader)
211 return;
213 printf("multiboot: Information structure flags: 0x%08x\n",
214 mi->mi_flags);
216 if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME)
217 printf("multiboot: Boot loader: %s\n", mi->mi_loader_name);
219 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
220 printf("multiboot: Command line: %s\n", mi->mi_cmdline);
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);
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);
235 /* --------------------------------------------------------------------- */
238 * Adds the bootinfo entry given in 'item' to the bootinfo tables.
239 * Sets the item type to 'type' and its length to 'len'.
241 static void
242 bootinfo_add(struct btinfo_common *item, int type, int len)
244 int i;
245 struct bootinfo *bip = (struct bootinfo *)&bootinfo;
246 vaddr_t data;
248 item->type = type;
249 item->len = len;
251 data = (vaddr_t)&bip->bi_data;
252 for (i = 0; i < bip->bi_nentries; i++) {
253 struct btinfo_common *tmp;
255 tmp = (struct btinfo_common *)data;
256 data += tmp->len;
258 if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) {
259 memcpy((void *)data, item, len);
260 bip->bi_nentries++;
264 /* --------------------------------------------------------------------- */
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.
271 * WARNING: This code runs before the kernel has relocated itself. See
272 * the note in multiboot_pre_reloc() for more information.
274 static void
275 copy_syms(struct multiboot_info *mi)
277 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
278 int i;
279 Elf32_Shdr *symtabp, *strtabp;
280 struct multiboot_symbols *ms;
281 size_t symsize, strsize;
282 paddr_t symaddr, straddr;
283 paddr_t symstart, strstart;
287 * Check if the Multiboot information header has symbols or not.
289 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS))
290 return;
292 ms = RELOC(struct multiboot_symbols *, &Multiboot_Symbols);
295 * Locate a symbol table and its matching string table in the
296 * section headers passed in by the boot loader. Set 'symtabp'
297 * and 'strtabp' with pointers to the matching entries.
299 symtabp = strtabp = NULL;
300 for (i = 0; i < mi->mi_elfshdr_num && symtabp == NULL &&
301 strtabp == NULL; i++) {
302 Elf32_Shdr *shdrp;
304 shdrp = &((Elf32_Shdr *)mi->mi_elfshdr_addr)[i];
306 if ((shdrp->sh_type & SHT_SYMTAB) &&
307 shdrp->sh_link != SHN_UNDEF) {
308 Elf32_Shdr *shdrp2;
310 shdrp2 = &((Elf32_Shdr *)mi->mi_elfshdr_addr)
311 [shdrp->sh_link];
313 if (shdrp2->sh_type & SHT_STRTAB) {
314 symtabp = shdrp;
315 strtabp = shdrp2;
319 if (symtabp == NULL || strtabp == NULL)
320 return;
322 symaddr = symtabp->sh_addr;
323 straddr = strtabp->sh_addr;
324 symsize = symtabp->sh_size;
325 strsize = strtabp->sh_size;
328 * Copy the symbol and string tables just after the kernel's
329 * end address, in this order. Only the contents of these ELF
330 * sections are copied; headers are discarded. esym is later
331 * updated to point to the lowest "free" address after the tables
332 * so that they are mapped appropriately when enabling paging.
334 * We need to be careful to not overwrite valid data doing the
335 * copies, hence all the different cases below. We can assume
336 * that if the tables start before the kernel's end address,
337 * they will not grow over this address.
339 if ((paddr_t)symtabp < (paddr_t)&end - KERNBASE &&
340 (paddr_t)strtabp < (paddr_t)&end - KERNBASE) {
341 symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
342 strstart = symstart + symsize;
343 memcpy((void *)symstart, (void *)symaddr, symsize);
344 memcpy((void *)strstart, (void *)straddr, strsize);
345 } else if ((paddr_t)symtabp > (paddr_t)&end - KERNBASE &&
346 (paddr_t)strtabp < (paddr_t)&end - KERNBASE) {
347 symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
348 strstart = symstart + symsize;
349 memcpy((void *)symstart, (void *)symaddr, symsize);
350 memcpy((void *)strstart, (void *)straddr, strsize);
351 } else if ((paddr_t)symtabp < (paddr_t)&end - KERNBASE &&
352 (paddr_t)strtabp > (paddr_t)&end - KERNBASE) {
353 strstart = (paddr_t)((vaddr_t)&end - KERNBASE);
354 symstart = strstart + strsize;
355 memcpy((void *)strstart, (void *)straddr, strsize);
356 memcpy((void *)symstart, (void *)symaddr, symsize);
357 } else {
358 /* symtabp and strtabp are both over end */
359 if ((paddr_t)symtabp < (paddr_t)strtabp) {
360 symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
361 strstart = symstart + symsize;
362 memcpy((void *)symstart, (void *)symaddr, symsize);
363 memcpy((void *)strstart, (void *)straddr, strsize);
364 } else {
365 strstart = (paddr_t)((vaddr_t)&end - KERNBASE);
366 symstart = strstart + strsize;
367 memcpy((void *)strstart, (void *)straddr, strsize);
368 memcpy((void *)symstart, (void *)symaddr, symsize);
371 *RELOC(int *, &esym) =
372 (int)(symstart + symsize + strsize + KERNBASE);
374 ms->s_symstart = (void *)(symstart + KERNBASE);
375 ms->s_symsize = symsize;
376 ms->s_strstart = (void *)(strstart + KERNBASE);
377 ms->s_strsize = strsize;
378 #undef RELOC
381 /* --------------------------------------------------------------------- */
384 * Sets up the biosgeom bootinfo structure if the Multiboot information
385 * structure provides information about disk drives.
387 static void
388 setup_biosgeom(struct multiboot_info *mi)
390 size_t pos;
391 uint8_t bidata[1024];
392 struct btinfo_biosgeom *bi;
394 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES))
395 return;
397 memset(bidata, 0, sizeof(bidata));
398 bi = (struct btinfo_biosgeom *)bidata;
399 pos = 0;
401 while (pos < mi->mi_drives_length) {
402 struct multiboot_drive *md;
403 struct bi_biosgeom_entry bbe;
405 md = (struct multiboot_drive *)
406 &((uint8_t *)mi->mi_drives_addr)[pos];
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;
414 memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe));
415 bi->num++;
417 pos += md->md_length;
420 bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM,
421 sizeof(struct btinfo_biosgeom) +
422 bi->num * sizeof(struct bi_biosgeom_entry));
425 /* --------------------------------------------------------------------- */
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.
433 static void
434 setup_bootdisk(struct multiboot_info *mi)
436 bool found;
437 struct btinfo_rootdevice bi;
439 found = false;
441 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
442 found = optstr_get(mi->mi_cmdline, "root", bi.devname,
443 sizeof(bi.devname));
445 if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) {
446 const char *devprefix;
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.) */
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;
459 default: devprefix = "wd0";
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';
469 found = true;
472 if (found) {
473 bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE,
474 sizeof(struct btinfo_rootdevice));
478 /* --------------------------------------------------------------------- */
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.
486 static void
487 setup_bootpath(struct multiboot_info *mi)
489 struct btinfo_bootpath bi;
490 char *cl, *cl2, old;
491 int len;
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++;
505 old = *cl2;
506 *cl2 = '\0';
507 memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len));
508 *cl2 = old;
509 bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0';
511 bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH,
512 sizeof(struct btinfo_bootpath));
516 /* --------------------------------------------------------------------- */
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.
524 * If there wasn't any 'console' argument, this does not generate any
525 * bootinfo entry, falling back to the kernel's default console.
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.
530 static void
531 setup_console(struct multiboot_info *mi)
533 struct btinfo_console bi;
534 bool found;
536 found = false;
538 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
539 found = optstr_get(mi->mi_cmdline, "console", bi.devname,
540 sizeof(bi.devname));
542 if (found) {
543 bool valid;
545 if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) {
546 char tmp[10];
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. */
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. */
565 valid = true;
566 } else if (strncmp(bi.devname, "pc", sizeof(bi.devname)) == 0)
567 valid = true;
568 else
569 valid = false;
571 if (valid)
572 bootinfo_add((struct btinfo_common *)&bi,
573 BTINFO_CONSOLE, sizeof(struct btinfo_console));
577 /* --------------------------------------------------------------------- */
580 * Sets up the 'boothowto' variable based on the options given in the
581 * boot command line, if any.
583 static void
584 setup_howto(struct multiboot_info *mi)
586 char *cl;
588 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE))
589 return;
591 cl = mi->mi_cmdline;
593 /* Skip kernel file name. */
594 while (*cl != '\0' && *cl != ' ')
595 cl++;
596 while (*cl != '\0' && *cl == ' ')
597 cl++;
599 /* Check if there are flags and set 'howto' accordingly. */
600 if (*cl == '-') {
601 int howto = 0;
603 cl++;
604 while (*cl != '\0' && *cl != ' ') {
605 BOOT_FLAG(*cl, howto);
606 cl++;
608 if (*cl == ' ')
609 cl++;
611 boothowto = howto;
615 /* --------------------------------------------------------------------- */
618 * Sets up the memmap bootinfo structure to describe available memory as
619 * given by the BIOS.
621 static void
622 setup_memmap(struct multiboot_info *mi)
624 char data[1024];
625 size_t i;
626 struct btinfo_memmap *bi;
628 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP))
629 return;
631 bi = (struct btinfo_memmap *)data;
632 bi->num = 0;
634 i = 0;
635 while (i < mi->mi_mmap_length) {
636 struct multiboot_mmap *mm;
637 struct bi_memmap_entry *bie;
639 bie = &bi->entry[bi->num];
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;
649 bi->num++;
650 i += mm->mm_size + 4;
653 bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP,
654 sizeof(data));
657 /* --------------------------------------------------------------------- */
660 * Sets up the 'biosbasemem' and 'biosextmem' variables if the
661 * Multiboot information structure provides information about memory.
663 static void
664 setup_memory(struct multiboot_info *mi)
667 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY))
668 return;
670 /* Make sure we don't override user-set variables. */
671 if (biosbasemem == 0) {
672 biosbasemem = mi->mi_mem_lower;
673 biosmem_implicit = 1;
675 if (biosextmem == 0) {
676 biosextmem = mi->mi_mem_upper;
677 biosmem_implicit = 1;
681 /* --------------------------------------------------------------------- */
684 * Sets up the initial kernel symbol table. Returns true if this was
685 * passed in by Multiboot; false otherwise.
687 bool
688 multiboot_ksyms_addsyms_elf(void)
690 struct multiboot_info *mi = &Multiboot_Info;
691 struct multiboot_symbols *ms = &Multiboot_Symbols;
693 if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
694 Elf32_Ehdr ehdr;
696 KASSERT(esym != 0);
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);
707 ksyms_addsyms_explicit((void *)&ehdr,
708 ms->s_symstart, ms->s_symsize,
709 ms->s_strstart, ms->s_strsize);
712 return mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS;