1 /* $NetBSD: multiboot2.c,v 1.8 2021/10/07 12:52:27 msaitoh Exp $ */
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>
33 __KERNEL_RCSID(0, "$NetBSD: multiboot2.c,v 1.8 2021/10/07 12:52:27 msaitoh Exp $");
34
35 #include "opt_multiboot.h"
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>
44 #include <sys/ksyms.h>
45 #include <sys/common_ansi.h>
46 #include <sys/intr.h>
47
48 #include <x86/efi.h>
49
50 #include <machine/bootinfo.h>
51 #include <arch/i386/include/multiboot2.h>
52
53 #ifdef _LOCORE64
54 typedef uint64_t locore_vaddr_t;
55 typedef Elf64_Shdr locore_Elf_Shdr;
56 typedef Elf64_Word locore_Elf_Word;
57 typedef Elf64_Addr locore_Elf_Addr;
58 #else
59 typedef vaddr_t locore_vaddr_t;
60 typedef Elf_Shdr locore_Elf_Shdr;
61 typedef Elf_Word locore_Elf_Word;
62 typedef Elf_Addr locore_Elf_Addr;
63 #endif
64
65 #if !defined(MULTIBOOT)
66 # error "MULTIBOOT not defined; this cannot happen."
67 #endif
68
69 /*
70 * This is an attempt to get an early debug output. It
71 * requires EFI Boot Services, and it does not work anyway:
72 * it causes EFI to try to handle interrupts while the kernel
73 * already took that over, hence we get a reboot.
74 */
75 #define BS_PRINT(efisystbl, wstring) \
76 efi_systbl->st_coutif->ei_outputstring(efi_systbl->st_coutif, \
77 (efi_char *)__UNCONST(wstring))
78
79 struct multiboot_symbols {
80 uint32_t s_symstart;
81 uint32_t s_symsize;
82 uint32_t s_strstart;
83 uint32_t s_strsize;
84 };
85
86 void multiboot2_copy_syms(struct multiboot_tag_elf_sections *,
87 struct multiboot_symbols *,
88 bool *, int **, void *, vaddr_t);
89 /*
90 * Because of clashes between multiboot.h and multiboot2.h we
91 * cannot include both, and we need to redefine here:
92 */
93 void multiboot2_pre_reloc(char *);
94 void multiboot2_post_reloc(void);
95 void multiboot2_print_info(void);
96 bool multiboot2_ksyms_addsyms_elf(void);
97
98 extern int biosbasemem;
99 extern int biosextmem;
100 #ifdef __i386__
101 extern int biosmem_implicit;
102 #endif
103 extern int boothowto;
104 extern struct bootinfo bootinfo;
105 extern int end;
106 extern int * esym;
107 extern char start;
108
109 /*
110 * There is no way to perform dynamic allocation
111 * at this time, hence we need to waste memory,
112 * with the hope data will fit.
113 */
114 char multiboot_info[16384] = "\0\0\0\0";
115 bool multiboot2_enabled = false;
116 bool has_syms = false;
117 struct multiboot_symbols Multiboot_Symbols;
118
119 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
120
121 static void
efi_exit_bs(struct efi_systbl * efi_systbl,void * efi_ih)122 efi_exit_bs(struct efi_systbl *efi_systbl, void *efi_ih)
123 {
124 struct efi_bs *efi_bs;
125 struct efi_md *desc;
126 uintn bufsize, key, size;
127 uint32_t vers;
128
129 if (efi_systbl == NULL)
130 panic("EFI system table is NULL");
131
132 if (efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG)
133 panic("EFI system table signature is wrong");
134
135 efi_bs = efi_systbl->st_bs;
136
137 if (efi_bs == NULL)
138 panic("EFI BS is NULL");
139
140 if (efi_bs->bs_hdr.th_sig != EFI_BS_SIG)
141 panic("EFI BS signature is wrong");
142
143 if (efi_ih == NULL)
144 panic("EFI IH is NULL");
145
146 bufsize = 16384;
147
148 if (efi_bs->bs_allocatepool(EFI_MD_TYPE_DATA,
149 bufsize, (void **)&desc) != 0)
150 panic("EFI AllocatePool failed");
151
152 if (efi_bs->bs_getmemorymap(&bufsize, desc, &key, &size, &vers) == 0)
153 goto exit_bs;
154
155 (void)efi_bs->bs_freepool((void *)desc);
156
157 if (efi_bs->bs_allocatepool(EFI_MD_TYPE_DATA,
158 bufsize, (void **)&desc) != 0)
159 panic("EFI AllocatePool failed");
160
161 if (efi_bs->bs_getmemorymap(&bufsize, desc, &key, &size, &vers) != 0)
162 panic("EFI GetMemoryMap failed");
163
164 exit_bs:
165 if (efi_bs->bs_exitbootservices(efi_ih, key) != 0)
166 panic("EFI ExitBootServices failed");
167
168 return;
169 }
170
171 void
multiboot2_copy_syms(struct multiboot_tag_elf_sections * mbt_elf,struct multiboot_symbols * ms,bool * has_symsp,int ** esymp,void * endp,vaddr_t kernbase)172 multiboot2_copy_syms(struct multiboot_tag_elf_sections *mbt_elf,
173 struct multiboot_symbols *ms,
174 bool *has_symsp, int **esymp, void *endp,
175 vaddr_t kernbase)
176 {
177 int i;
178 locore_Elf_Shdr *symtabp, *strtabp;
179 locore_Elf_Word symsize, strsize;
180 locore_Elf_Addr symaddr, straddr;
181 locore_Elf_Addr symstart, strstart;
182 locore_Elf_Addr cp1src, cp1dst;
183 locore_Elf_Word cp1size;
184 locore_Elf_Addr cp2src, cp2dst;
185 locore_Elf_Word cp2size;
186
187 /*
188 * Locate a symbol table and its matching string table in the
189 * section headers passed in by the boot loader. Set 'symtabp'
190 * and 'strtabp' with pointers to the matching entries.
191 */
192 symtabp = strtabp = NULL;
193 for (i = 0; i < mbt_elf->num && symtabp == NULL &&
194 strtabp == NULL; i++) {
195 locore_Elf_Shdr *shdrp;
196
197 shdrp = &((locore_Elf_Shdr *)mbt_elf->sections)[i];
198
199 if ((shdrp->sh_type == SHT_SYMTAB) &&
200 shdrp->sh_link != SHN_UNDEF) {
201 locore_Elf_Shdr *shdrp2;
202
203 shdrp2 = &((locore_Elf_Shdr *)mbt_elf->sections)
204 [shdrp->sh_link];
205
206 if (shdrp2->sh_type == SHT_STRTAB) {
207 symtabp = (locore_Elf_Shdr *)shdrp;
208 strtabp = (locore_Elf_Shdr *)shdrp2;
209 }
210 }
211 }
212 if (symtabp == NULL || strtabp == NULL)
213 return;
214
215 symaddr = symtabp->sh_addr;
216 straddr = strtabp->sh_addr;
217 symsize = symtabp->sh_size;
218 strsize = strtabp->sh_size;
219
220 /*
221 * Copy the symbol and string tables just after the kernel's
222 * end address, in this order. Only the contents of these ELF
223 * sections are copied; headers are discarded. esym is later
224 * updated to point to the lowest "free" address after the tables
225 * so that they are mapped appropriately when enabling paging.
226 *
227 * We need to be careful to not overwrite valid data doing the
228 * copies, hence all the different cases below. We can assume
229 * that if the tables start before the kernel's end address,
230 * they will not grow over this address.
231 */
232 if ((void *)(uintptr_t)symaddr < endp &&
233 (void *)(uintptr_t)straddr < endp) {
234 cp1src = symaddr; cp1size = symsize;
235 cp2src = straddr; cp2size = strsize;
236 } else if ((void *)(uintptr_t)symaddr > endp &&
237 (void *)(uintptr_t)straddr < endp) {
238 cp1src = symaddr; cp1size = symsize;
239 cp2src = straddr; cp2size = strsize;
240 } else if ((void *)(uintptr_t)symaddr < endp &&
241 (void *)(uintptr_t)straddr > endp) {
242 cp1src = straddr; cp1size = strsize;
243 cp2src = symaddr; cp2size = symsize;
244 } else {
245 /* symaddr and straddr are both over end */
246 if (symaddr < straddr) {
247 cp1src = symaddr; cp1size = symsize;
248 cp2src = straddr; cp2size = strsize;
249 } else {
250 cp1src = straddr; cp1size = strsize;
251 cp2src = symaddr; cp2size = symsize;
252 }
253 }
254
255 cp1dst = (locore_Elf_Addr)(uintptr_t)endp;
256 cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size;
257
258 (void)memcpy((void *)(uintptr_t)cp1dst,
259 (void *)(uintptr_t)cp1src, cp1size);
260 (void)memcpy((void *)(uintptr_t)cp2dst,
261 (void *)(uintptr_t)cp2src, cp2size);
262
263 symstart = (cp1src == symaddr) ? cp1dst : cp2dst;
264 strstart = (cp1src == straddr) ? cp1dst : cp2dst;
265
266 ms->s_symstart = symstart + kernbase;
267 ms->s_symsize = symsize;
268 ms->s_strstart = strstart + kernbase;
269 ms->s_strsize = strsize;
270
271 *has_symsp = true;
272 *esymp = (int *)((uintptr_t)endp + symsize + strsize + kernbase);
273
274 }
275
276 void
multiboot2_pre_reloc(char * mbi)277 multiboot2_pre_reloc(char *mbi)
278 {
279 uint32_t mbi_size;
280 void *mbidest = RELOC(void *, multiboot_info);
281 char *cp;
282 struct multiboot_tag_module *mbt;
283 struct multiboot_tag_elf_sections *mbt_elf = NULL;
284 struct efi_systbl *efi_systbl = NULL;
285 void *efi_ih = NULL;
286 bool has_bs = false;
287
288 mbi_size = *(uint32_t *)mbi;
289 if (mbi_size < sizeof(multiboot_info))
290 memcpy(mbidest, mbi, mbi_size);
291 else
292 panic("multiboot_info too big"); /* will not show up */
293
294 *RELOC(bool *, &multiboot2_enabled) = true;
295
296 for (cp = mbi + (2 * sizeof(uint32_t));
297 cp - mbi < mbi_size;
298 cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) {
299 mbt = (struct multiboot_tag_module *)cp;
300 switch (mbt->type) {
301 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
302 mbt_elf = (struct multiboot_tag_elf_sections *)mbt;
303 break;
304 #ifdef __LP64__
305 case MULTIBOOT_TAG_TYPE_EFI64:
306 efi_systbl = (struct efi_systbl *)
307 ((struct multiboot_tag_efi64 *)mbt)->pointer;
308 break;
309 case MULTIBOOT_TAG_TYPE_EFI64_IH:
310 efi_ih = (void *)
311 ((struct multiboot_tag_efi64_ih *)mbt)->pointer;
312 break;
313 #else
314 case MULTIBOOT_TAG_TYPE_EFI32:
315 efi_systbl = (struct efi_systbl *)
316 ((struct multiboot_tag_efi32 *)mbt)->pointer;
317 break;
318 case MULTIBOOT_TAG_TYPE_EFI32_IH:
319 efi_ih = (void *)
320 ((struct multiboot_tag_efi32_ih *)mbt)->pointer;
321 break;
322 #endif
323 case MULTIBOOT_TAG_TYPE_EFI_BS:
324 #if notyet
325 has_bs = true;
326 #endif
327 break;
328 default:
329 break;
330 }
331 }
332
333 /* Broken */
334 if (has_bs)
335 efi_exit_bs(efi_systbl, efi_ih);
336
337 if (mbt_elf)
338 multiboot2_copy_syms(mbt_elf,
339 RELOC(struct multiboot_symbols *, &Multiboot_Symbols),
340 RELOC(bool *, &has_syms),
341 RELOC(int **, &esym),
342 RELOC(void *, &end),
343 KERNBASE);
344
345 return;
346 }
347
348 static struct btinfo_common *
bootinfo_init(int type,int len)349 bootinfo_init(int type, int len)
350 {
351 int i;
352 struct bootinfo *bip = (struct bootinfo *)&bootinfo;
353 vaddr_t data;
354
355 data = (vaddr_t)&bip->bi_data;
356 for (i = 0; i < bip->bi_nentries; i++) {
357 struct btinfo_common *tmp;
358
359 tmp = (struct btinfo_common *)data;
360 data += tmp->len;
361 }
362 if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) {
363 /* Initialize the common part */
364 struct btinfo_common *item = (struct btinfo_common *)data;
365 item->type = type;
366 item->len = len;
367 bip->bi_nentries++;
368 return item;
369 } else {
370 return NULL;
371 }
372 }
373
374 static void
bootinfo_add(struct btinfo_common * item,int type,int len)375 bootinfo_add(struct btinfo_common *item, int type, int len)
376 {
377 struct btinfo_common *bip = bootinfo_init(type, len);
378 if (bip == NULL)
379 return;
380
381 /* Copy the data after the common part over */
382 memcpy(&bip[1], &item[1], len - sizeof(*item));
383 }
384
385 static void
mbi_cmdline(struct multiboot_tag_string * mbt)386 mbi_cmdline(struct multiboot_tag_string *mbt)
387 {
388 char *cmdline = mbt->string;
389 struct btinfo_console bic;
390 struct btinfo_rootdevice bir;
391 char *cl;
392
393 if (optstr_get(cmdline, "console", bic.devname, sizeof(bic.devname))) {
394 if (strncmp(bic.devname, "com", sizeof(bic.devname)) == 0) {
395 char opt[10];
396
397 if (optstr_get(cmdline, "console_speed",
398 opt, sizeof(opt)))
399 bic.speed = strtoul(opt, NULL, 10);
400 else
401 bic.speed = 0; /* Use default speed. */
402
403 if (optstr_get(cmdline, "console_addr",
404 opt, sizeof(opt))) {
405 if (opt[0] == '0' && opt[1] == 'x')
406 bic.addr = strtoul(opt + 2, NULL, 16);
407 else
408 bic.addr = strtoul(opt, NULL, 10);
409 } else {
410 bic.addr = 0; /* Use default address. */
411 }
412
413 bootinfo_add((struct btinfo_common *)&bic,
414 BTINFO_CONSOLE, sizeof(bic));
415
416 }
417
418 if (strncmp(bic.devname, "pc", sizeof(bic.devname)) == 0)
419 bootinfo_add((struct btinfo_common *)&bic,
420 BTINFO_CONSOLE, sizeof(bic));
421 }
422
423 if (optstr_get(cmdline, "root", bir.devname, sizeof(bir.devname)))
424 bootinfo_add((struct btinfo_common *)&bir, BTINFO_ROOTDEVICE,
425 sizeof(bir));
426
427 /*
428 * Parse boot flags (-s and friends)
429 */
430 cl = cmdline;
431
432 /* Skip kernel file name. */
433 while (*cl != '\0' && *cl != ' ')
434 cl++;
435 while (*cl == ' ')
436 cl++;
437
438 /* Check if there are flags and set 'howto' accordingly. */
439 if (*cl == '-') {
440 int howto = 0;
441
442 cl++;
443 while (*cl != '\0' && *cl != ' ') {
444 BOOT_FLAG(*cl, howto);
445 cl++;
446 }
447 if (*cl == ' ')
448 cl++;
449
450 boothowto = howto;
451 }
452
453 return;
454 }
455
456 static void
mbi_modules(char * mbi,uint32_t mbi_size,int module_count)457 mbi_modules(char *mbi, uint32_t mbi_size, int module_count)
458 {
459 char *cp;
460 struct multiboot_tag_module *mbt;
461 size_t bim_len;
462 struct bi_modulelist_entry *bie;
463 struct btinfo_modulelist *bim;
464
465 bim_len = sizeof(*bim) + (module_count * sizeof(*bie));
466 bim = (struct btinfo_modulelist *)bootinfo_init(BTINFO_MODULELIST,
467 bim_len);
468 if (bim == NULL)
469 return;
470
471 bim->num = module_count;
472 bim->endpa = end;
473
474 bie = (struct bi_modulelist_entry *)(bim + 1);
475
476 for (cp = mbi + (2 * sizeof(uint32_t));
477 cp - mbi < mbi_size;
478 cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) {
479 mbt = (struct multiboot_tag_module *)cp;
480 if (mbt->type != MULTIBOOT_TAG_TYPE_MODULE)
481 continue;
482
483 strncpy(bie->path, mbt->cmdline, sizeof(bie->path));
484 bie->type = BI_MODULE_ELF;
485 bie->len = mbt->mod_end - mbt->mod_start;
486 bie->base = mbt->mod_start;
487
488 bie++;
489 }
490 }
491
492 static void
mbi_basic_meminfo(struct multiboot_tag_basic_meminfo * mbt)493 mbi_basic_meminfo(struct multiboot_tag_basic_meminfo *mbt)
494 {
495 /* Make sure we don't override user-set variables. */
496 if (biosbasemem == 0) {
497 biosbasemem = mbt->mem_lower;
498 #ifdef __i386__
499 biosmem_implicit = 1;
500 #endif
501 }
502 if (biosextmem == 0) {
503 biosextmem = mbt->mem_upper;
504 #ifdef __i386__
505 biosmem_implicit = 1;
506 #endif
507 }
508
509 return;
510 }
511
512 static void
mbi_bootdev(struct multiboot_tag_bootdev * mbt)513 mbi_bootdev(struct multiboot_tag_bootdev *mbt)
514 {
515 struct btinfo_bootdisk bid;
516
517 bid.labelsector = -1;
518 bid.biosdev = mbt->biosdev;
519 bid.partition = mbt->slice;
520
521 bootinfo_add((struct btinfo_common *)&bid,
522 BTINFO_BOOTDISK, sizeof(bid));
523 }
524
525 static void
mbi_mmap(struct multiboot_tag_mmap * mbt)526 mbi_mmap(struct multiboot_tag_mmap *mbt)
527 {
528 struct btinfo_memmap *bim;
529 int num;
530 char *cp;
531
532 if (mbt->entry_version != 0)
533 return;
534
535 /* Determine size */
536 num = 0;
537 for (cp = (char *)(mbt + 1);
538 cp - (char *)mbt < mbt->size;
539 cp += mbt->entry_size) {
540 num++;
541 }
542
543 bim = (struct btinfo_memmap *)bootinfo_init(BTINFO_MEMMAP,
544 sizeof(num) + num * sizeof(struct bi_memmap_entry));
545 if (bim == NULL)
546 return;
547 bim->num = 0;
548
549 for (cp = (char *)(mbt + 1);
550 cp - (char *)mbt < mbt->size;
551 cp += mbt->entry_size) {
552 struct multiboot_mmap_entry *mbe;
553 struct bi_memmap_entry *bie;
554
555 mbe = (struct multiboot_mmap_entry *)cp;
556 bie = &bim->entry[bim->num];
557
558 bie->addr = mbe->addr;
559 bie->size = mbe->len;
560 switch (mbe->type) {
561 case MULTIBOOT_MEMORY_AVAILABLE:
562 bie->type = BIM_Memory;
563 break;
564 case MULTIBOOT_MEMORY_RESERVED:
565 bie->type = BIM_Reserved;
566 break;
567 case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
568 bie->type = BIM_ACPI;
569 break;
570 case MULTIBOOT_MEMORY_NVS:
571 bie->type = BIM_NVS;
572 break;
573 case MULTIBOOT_MEMORY_BADRAM:
574 default:
575 bie->type = BIM_Unusable;
576 break;
577 }
578
579 bim->num++;
580 }
581
582 KASSERT(bim->num == num);
583 }
584
585 static void
mbi_vbe(struct multiboot_tag_vbe * mbt,struct btinfo_framebuffer * bif)586 mbi_vbe(struct multiboot_tag_vbe *mbt, struct btinfo_framebuffer *bif)
587 {
588 bif->vbemode = mbt->vbe_mode;
589 return;
590 }
591
592 static void
mbi_framebuffer(struct multiboot_tag_framebuffer * mbt,struct btinfo_framebuffer * bif)593 mbi_framebuffer(struct multiboot_tag_framebuffer *mbt,
594 struct btinfo_framebuffer *bif)
595 {
596 bif->physaddr = mbt->common.framebuffer_addr;
597 bif->width = mbt->common.framebuffer_width;
598 bif->height = mbt->common.framebuffer_height;
599 bif->depth = mbt->common.framebuffer_bpp;
600 bif->stride = mbt->common.framebuffer_pitch;
601
602 return;
603 }
604
605 static void
mbi_efi32(struct multiboot_tag_efi32 * mbt)606 mbi_efi32(struct multiboot_tag_efi32 *mbt)
607 {
608 struct btinfo_efi bie;
609
610 bie.systblpa = mbt->pointer;
611 bie.flags = BI_EFI_32BIT;
612
613 bootinfo_add((struct btinfo_common *)&bie, BTINFO_EFI, sizeof(bie));
614 }
615
616 static void
mbi_efi64(struct multiboot_tag_efi64 * mbt)617 mbi_efi64(struct multiboot_tag_efi64 *mbt)
618 {
619 struct btinfo_efi bie;
620
621 bie.systblpa = mbt->pointer;
622
623 bootinfo_add((struct btinfo_common *)&bie, BTINFO_EFI, sizeof(bie));
624 }
625
626 static void
mbi_efi_mmap(struct multiboot_tag_efi_mmap * mbt)627 mbi_efi_mmap(struct multiboot_tag_efi_mmap *mbt)
628 {
629 struct btinfo_efimemmap *bie;
630 size_t bie_len;
631
632 if (mbt->descr_vers != 0)
633 return;
634
635 bie_len = sizeof(*bie) + mbt->size - sizeof(*mbt);
636 bie = (struct btinfo_efimemmap *)bootinfo_init(BTINFO_EFIMEMMAP,
637 bie_len);
638 if (bie == NULL)
639 return;
640
641 bie->num = (mbt->size - sizeof(*mbt)) / mbt->descr_size;
642 bie->version = mbt->descr_vers;
643 bie->size = mbt->descr_size;
644 memcpy(bie->memmap, mbt + 1, mbt->size - sizeof(*mbt));
645 }
646
647 void
multiboot2_post_reloc(void)648 multiboot2_post_reloc(void)
649 {
650 uint32_t mbi_size;
651 struct multiboot_tag *mbt;
652 char *mbi = multiboot_info;
653 char *cp;
654 int module_count = 0;
655 struct btinfo_framebuffer fbinfo;
656 bool has_fbinfo = false;
657
658 if (multiboot2_enabled == false)
659 goto out;
660
661 mbi_size = *(uint32_t *)multiboot_info;
662 if (mbi_size < 2 * sizeof(uint32_t))
663 goto out;
664
665 bootinfo.bi_nentries = 0;
666
667 memset(&fbinfo, 0, sizeof(fbinfo));
668
669 for (cp = mbi + (2 * sizeof(uint32_t));
670 cp - mbi < mbi_size;
671 cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) {
672 mbt = (struct multiboot_tag *)cp;
673 switch (mbt->type) {
674 case MULTIBOOT_TAG_TYPE_CMDLINE:
675 mbi_cmdline((void *)mbt);
676 break;
677 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
678 break;
679 case MULTIBOOT_TAG_TYPE_MMAP:
680 mbi_mmap((void *)mbt);
681 break;
682 case MULTIBOOT_TAG_TYPE_MODULE:
683 module_count++;
684 break;
685 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
686 mbi_basic_meminfo((void *)mbt);
687 break;
688 case MULTIBOOT_TAG_TYPE_BOOTDEV:
689 mbi_bootdev((void *)mbt);
690 break;
691 case MULTIBOOT_TAG_TYPE_VBE:
692 mbi_vbe((void *)mbt, &fbinfo);
693 break;
694 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
695 mbi_framebuffer((void *)mbt, &fbinfo);
696 has_fbinfo = true;
697 break;
698 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
699 case MULTIBOOT_TAG_TYPE_APM:
700 break;
701 case MULTIBOOT_TAG_TYPE_EFI32:
702 mbi_efi32((void *)mbt);
703 break;
704 case MULTIBOOT_TAG_TYPE_EFI64:
705 mbi_efi64((void *)mbt);
706 break;
707 case MULTIBOOT_TAG_TYPE_SMBIOS:
708 case MULTIBOOT_TAG_TYPE_ACPI_OLD:
709 case MULTIBOOT_TAG_TYPE_ACPI_NEW:
710 case MULTIBOOT_TAG_TYPE_NETWORK:
711 break;
712 case MULTIBOOT_TAG_TYPE_EFI_MMAP:
713 mbi_efi_mmap((void *)mbt);
714 break;
715 case MULTIBOOT_TAG_TYPE_EFI_BS:
716 case MULTIBOOT_TAG_TYPE_EFI32_IH:
717 case MULTIBOOT_TAG_TYPE_EFI64_IH:
718 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
719 case MULTIBOOT_TAG_TYPE_END:
720 default:
721 break;
722 }
723 }
724
725 if (has_fbinfo)
726 bootinfo_add((struct btinfo_common *)&fbinfo,
727 BTINFO_FRAMEBUFFER, sizeof(fbinfo));
728
729 if (module_count > 0)
730 mbi_modules(mbi, mbi_size, module_count);
731
732 out:
733 return;
734 }
735
736
737 #ifdef DEBUG
738 static void
mbi_hexdump(char * addr,size_t len)739 mbi_hexdump(char *addr, size_t len)
740 {
741 int i,j;
742
743 for (i = 0; i < len; i += 16) {
744 printf(" %p ", addr + i);
745 for (j = 0; j < 16 && i + j < len; j++) {
746 char *cp = addr + i + j;
747 printf("%s%s%x",
748 (i+j) % 4 ? "" : " ",
749 (unsigned char)*cp < 0x10 ? "0" : "",
750 (unsigned char)*cp);
751 }
752 printf("\n");
753 }
754
755 return;
756 }
757 #endif
758
759 static const char *
mbi_tag_name(uint32_t type)760 mbi_tag_name(uint32_t type)
761 {
762 const char *tag_name;
763
764 switch (type) {
765 case MULTIBOOT_TAG_TYPE_END:
766 tag_name = "";
767 break;
768 case MULTIBOOT_TAG_TYPE_CMDLINE:
769 tag_name = "command line"; break;
770 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
771 tag_name = "boot loader name"; break;
772 case MULTIBOOT_TAG_TYPE_MODULE:
773 tag_name = "module"; break;
774 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
775 tag_name = "basic meminfo"; break;
776 case MULTIBOOT_TAG_TYPE_BOOTDEV:
777 tag_name = "boot device"; break;
778 case MULTIBOOT_TAG_TYPE_MMAP:
779 tag_name = "memory map"; break;
780 case MULTIBOOT_TAG_TYPE_VBE:
781 tag_name = "VESA BIOS Extensions"; break;
782 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
783 tag_name = "framebuffer"; break;
784 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
785 tag_name = "ELF sections"; break;
786 case MULTIBOOT_TAG_TYPE_APM:
787 tag_name = "APM"; break;
788 case MULTIBOOT_TAG_TYPE_EFI32:
789 tag_name = "EFI system table"; break;
790 case MULTIBOOT_TAG_TYPE_EFI64:
791 tag_name = "EFI system table"; break;
792 case MULTIBOOT_TAG_TYPE_SMBIOS:
793 tag_name = "SMBIOS"; break;
794 case MULTIBOOT_TAG_TYPE_ACPI_OLD:
795 tag_name = "ACPI 2"; break;
796 case MULTIBOOT_TAG_TYPE_ACPI_NEW:
797 tag_name = "ACPI 3"; break;
798 case MULTIBOOT_TAG_TYPE_NETWORK:
799 tag_name = "network"; break;
800 case MULTIBOOT_TAG_TYPE_EFI_MMAP:
801 tag_name = "EFI memory map"; break;
802 case MULTIBOOT_TAG_TYPE_EFI_BS:
803 tag_name = "EFI boot services available"; break;
804 case MULTIBOOT_TAG_TYPE_EFI32_IH:
805 tag_name = "EFI ImageHandle"; break;
806 case MULTIBOOT_TAG_TYPE_EFI64_IH:
807 tag_name = "EFI ImaheHandle"; break;
808 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
809 tag_name = "load base"; break;
810 default:
811 tag_name = ""; break;
812 }
813
814 return tag_name;
815 }
816
817 void
multiboot2_print_info(void)818 multiboot2_print_info(void)
819 {
820 struct multiboot_tag *mbt;
821 char *cp;
822 uint32_t total_size;
823 uint32_t reserved;
824 #ifdef DEBUG
825 int i = 0;
826 #endif
827
828 if (multiboot2_enabled == false)
829 goto out;
830
831 total_size = *(uint32_t *)multiboot_info;
832 reserved = *(uint32_t *)multiboot_info + 1;
833 mbt = (struct multiboot_tag *)(uint32_t *)multiboot_info + 2;
834
835 for (cp = multiboot_info + sizeof(total_size) + sizeof(reserved);
836 cp - multiboot_info < total_size;
837 cp = cp + roundup(mbt->size, MULTIBOOT_TAG_ALIGN)) {
838 const char *tag_name;
839
840 mbt = (struct multiboot_tag *)cp;
841 tag_name = mbi_tag_name(mbt->type);
842
843 #ifdef DEBUG
844 printf("multiboot2: tag[%d].type = %d(%s), .size = %d ",
845 i++, mbt->type, tag_name, mbt->size);
846 #else
847 if (*tag_name == '\0')
848 break;
849
850 printf("multiboot2: %s ", mbi_tag_name(mbt->type));
851 #endif
852
853 switch (mbt->type) {
854 case MULTIBOOT_TAG_TYPE_CMDLINE:
855 printf("%s\n",
856 ((struct multiboot_tag_string *)mbt)->string);
857 break;
858 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
859 printf("%s\n",
860 ((struct multiboot_tag_string *)mbt)->string);
861 break;
862 case MULTIBOOT_TAG_TYPE_MODULE:
863 printf("0x%08x - 0x%08x %s\n",
864 ((struct multiboot_tag_module *)mbt)->mod_start,
865 ((struct multiboot_tag_module *)mbt)->mod_end,
866 ((struct multiboot_tag_module *)mbt)->cmdline);
867 break;
868 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: {
869 struct multiboot_tag_basic_meminfo *meminfo;
870
871 meminfo = (struct multiboot_tag_basic_meminfo *)mbt;
872 printf("ower = %uKB, upper = %uKB\n",
873 meminfo->mem_lower, meminfo->mem_upper);
874 break;
875 }
876 case MULTIBOOT_TAG_TYPE_BOOTDEV:
877 printf ("biosdev = 0x%x, slice = %d, part = %d\n",
878 ((struct multiboot_tag_bootdev *)mbt)->biosdev,
879 ((struct multiboot_tag_bootdev *)mbt)->slice,
880 ((struct multiboot_tag_bootdev *)mbt)->part);
881 break;
882 case MULTIBOOT_TAG_TYPE_MMAP: {
883 struct multiboot_tag_mmap *memmap;
884 multiboot_memory_map_t *mmap;
885 uint32_t entry_size;
886 uint32_t entry_version;
887
888 memmap = (struct multiboot_tag_mmap *)mbt;
889 entry_size = memmap->entry_size;
890 entry_version = memmap->entry_version;
891 printf ("entry version = %d\n", entry_version);
892
893 if (entry_version != 0)
894 break;
895
896 for (mmap = ((struct multiboot_tag_mmap *)mbt)->entries;
897 (char *)mmap - (char *)mbt < mbt->size;
898 mmap = (void *)((char *)mmap + entry_size))
899 printf(" 0x%016"PRIx64" @ 0x%016"PRIx64" "
900 "type 0x%x\n",
901 (uint64_t)mmap->len, (uint64_t)mmap->addr,
902 mmap->type);
903 break;
904 }
905 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: {
906 struct multiboot_tag_framebuffer *fb = (void *)mbt;
907
908 printf ("%dx%dx%d @ 0x%"PRIx64"\n",
909 fb->common.framebuffer_width,
910 fb->common.framebuffer_height,
911 fb->common.framebuffer_bpp,
912 (uint64_t)fb->common.framebuffer_addr);
913 #ifdef DEBUG
914 mbi_hexdump((char *)mbt, mbt->size);
915 #endif
916 break;
917 }
918 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
919 printf("num = %d, entsize = %d, shndx = %d\n",
920 ((struct multiboot_tag_elf_sections *)mbt)->num,
921 ((struct multiboot_tag_elf_sections *)mbt)->entsize,
922 ((struct multiboot_tag_elf_sections *)mbt)->shndx);
923 #ifdef DEBUG
924 mbi_hexdump((char *)mbt, mbt->size);
925 #endif
926 break;
927 case MULTIBOOT_TAG_TYPE_APM:
928 printf("version = %d, cseg = 0x%x, offset = 0x%x, "
929 "cseg_16 = 0x%x, dseg = 0x%x, flags = 0x%x, "
930 "cseg_len = %d, cseg_16_len = %d, "
931 "dseg_len = %d\n",
932 ((struct multiboot_tag_apm *)mbt)->version,
933 ((struct multiboot_tag_apm *)mbt)->cseg,
934 ((struct multiboot_tag_apm *)mbt)->offset,
935 ((struct multiboot_tag_apm *)mbt)->cseg_16,
936 ((struct multiboot_tag_apm *)mbt)->dseg,
937 ((struct multiboot_tag_apm *)mbt)->flags,
938 ((struct multiboot_tag_apm *)mbt)->cseg_len,
939 ((struct multiboot_tag_apm *)mbt)->cseg_16_len,
940 ((struct multiboot_tag_apm *)mbt)->dseg_len);
941 break;
942 case MULTIBOOT_TAG_TYPE_EFI32:
943 printf("0x%x\n",
944 ((struct multiboot_tag_efi32 *)mbt)->pointer);
945 break;
946 case MULTIBOOT_TAG_TYPE_EFI64:
947 printf("0x%"PRIx64"\n", (uint64_t)
948 ((struct multiboot_tag_efi64 *)mbt)->pointer);
949 break;
950 case MULTIBOOT_TAG_TYPE_SMBIOS:
951 printf("major = %d, minor = %d\n",
952 ((struct multiboot_tag_smbios *)mbt)->major,
953 ((struct multiboot_tag_smbios *)mbt)->minor);
954 #ifdef DEBUG
955 mbi_hexdump((char *)mbt, mbt->size);
956 #endif
957 break;
958 case MULTIBOOT_TAG_TYPE_ACPI_OLD:
959 printf("\n");
960 #ifdef DEBUG
961 mbi_hexdump((char *)mbt, mbt->size);
962 #endif
963 break;
964 case MULTIBOOT_TAG_TYPE_ACPI_NEW:
965 printf("\n");
966 #ifdef DEBUG
967 mbi_hexdump((char *)mbt, mbt->size);
968 #endif
969 break;
970 case MULTIBOOT_TAG_TYPE_NETWORK:
971 printf("\n");
972 #ifdef DEBUG
973 mbi_hexdump((char *)mbt, mbt->size);
974 #endif
975 break;
976 case MULTIBOOT_TAG_TYPE_EFI_MMAP:
977 printf("\n");
978 #ifdef DEBUG
979 mbi_hexdump((char *)mbt, mbt->size);
980 #endif
981 break;
982 case MULTIBOOT_TAG_TYPE_EFI_BS:
983 printf("\n");
984 break;
985 case MULTIBOOT_TAG_TYPE_EFI32_IH:
986 printf("0x%"PRIx32"\n",
987 ((struct multiboot_tag_efi32_ih *)mbt)->pointer);
988 break;
989 case MULTIBOOT_TAG_TYPE_EFI64_IH:
990 printf("0x%"PRIx64"\n", (uint64_t)
991 ((struct multiboot_tag_efi64_ih *)mbt)->pointer);
992 break;
993 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: {
994 struct multiboot_tag_load_base_addr *ld = (void *)mbt;
995 printf("0x%x\n", ld->load_base_addr);
996 break;
997 }
998 case MULTIBOOT_TAG_TYPE_END:
999 printf("\n");
1000 break;
1001 default:
1002 printf("\n");
1003 #ifdef DEBUG
1004 mbi_hexdump((char *)mbt, mbt->size);
1005 #endif
1006 break;
1007 }
1008 }
1009
1010 out:
1011 return;
1012 }
1013
1014
1015
1016
1017 /*
1018 * Sets up the initial kernel symbol table. Returns true if this was
1019 * passed in by Multiboot; false otherwise.
1020 */
1021 bool
multiboot2_ksyms_addsyms_elf(void)1022 multiboot2_ksyms_addsyms_elf(void)
1023 {
1024 struct multiboot_symbols *ms = &Multiboot_Symbols;
1025 vaddr_t symstart = (vaddr_t)ms->s_symstart;
1026 vaddr_t strstart = (vaddr_t)ms->s_strstart;
1027 Elf_Ehdr ehdr;
1028
1029 if (!multiboot2_enabled || !has_syms)
1030 return false;
1031
1032 KASSERT(esym != 0);
1033
1034 #ifdef __LP64__
1035 /* Adjust pointer as 64 bits */
1036 symstart &= 0xffffffff;
1037 symstart |= ((vaddr_t)KERNBASE_HI << 32);
1038 strstart &= 0xffffffff;
1039 strstart |= ((vaddr_t)KERNBASE_HI << 32);
1040 #endif
1041
1042 memset(&ehdr, 0, sizeof(ehdr));
1043 memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
1044 ehdr.e_ident[EI_CLASS] = ELFCLASS;
1045 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
1046 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1047 ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
1048 ehdr.e_ident[EI_ABIVERSION] = 0;
1049 ehdr.e_type = ET_EXEC;
1050 #ifdef __amd64__
1051 ehdr.e_machine = EM_X86_64;
1052 #elif __i386__
1053 ehdr.e_machine = EM_386;
1054 #else
1055 #error "Unknown ELF machine type"
1056 #endif
1057 ehdr.e_version = 1;
1058 ehdr.e_entry = (Elf_Addr)&start;
1059 ehdr.e_ehsize = sizeof(ehdr);
1060
1061 ksyms_addsyms_explicit((void *)&ehdr,
1062 (void *)symstart, ms->s_symsize,
1063 (void *)strstart, ms->s_strsize);
1064
1065 return true;
1066 }
1067