xref: /netbsd-src/sys/arch/x86/x86/multiboot2.c (revision 76646d9e03c9615328f50b26f06c9b57e12e065b)
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