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