1/*	$NetBSD: multiboot.c,v 1.26 2019/10/18 01:38:28 manu 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: multiboot.c,v 1.26 2019/10/18 01:38:28 manu 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
46#include <machine/bootinfo.h>
47#include <machine/multiboot.h>
48
49#if !defined(MULTIBOOT)
50#  error "MULTIBOOT not defined; this cannot happen."
51#endif
52
53/* --------------------------------------------------------------------- */
54
55/*
56 * Symbol and string table for the loaded kernel.
57 */
58
59struct multiboot_symbols {
60	void *		s_symstart;
61	size_t		s_symsize;
62	void *		s_strstart;
63	size_t		s_strsize;
64};
65
66/* --------------------------------------------------------------------- */
67
68/*
69 * External variables.  All of them, with the exception of 'end', must
70 * be set at some point within this file.
71 *
72 * XXX these should be found in a header file!
73 */
74extern int		biosbasemem;
75extern int		biosextmem;
76extern int		biosmem_implicit;
77extern int		boothowto;
78extern struct bootinfo	bootinfo;
79extern int		end;
80extern int *		esym;
81
82/* --------------------------------------------------------------------- */
83
84/*
85 * Copy of the Multiboot information structure passed to us by the boot
86 * loader.  The Multiboot_Info structure has some pointers adjusted to the
87 * other variables -- see multiboot1_pre_reloc() -- so you oughtn't access
88 * them directly.  In other words, always access them through the
89 * Multiboot_Info variable.
90 */
91static char			Multiboot_Cmdline[255];
92static uint8_t			Multiboot_Drives[255];
93static struct multiboot_info	Multiboot_Info;
94static bool			Multiboot_Loader = false;
95static char			Multiboot_Loader_Name[255];
96static uint8_t			Multiboot_Mmap[1024];
97static struct multiboot_symbols	Multiboot_Symbols;
98
99/* --------------------------------------------------------------------- */
100
101/*
102 * Prototypes for private functions.
103 */
104static void	bootinfo_add(struct btinfo_common *, int, int);
105static void	copy_syms(struct multiboot_info *);
106static void	setup_biosgeom(struct multiboot_info *);
107static void	setup_bootdisk(struct multiboot_info *);
108static void	setup_bootpath(struct multiboot_info *);
109static void	setup_console(struct multiboot_info *);
110static void	setup_howto(struct multiboot_info *);
111static void	setup_memory(struct multiboot_info *);
112static void	setup_memmap(struct multiboot_info *);
113
114/* --------------------------------------------------------------------- */
115
116/*
117 * Sets up the kernel if it was booted by a Multiboot-compliant boot
118 * loader.  This is executed before the kernel has relocated itself.
119 * The main purpose of this function is to copy all the information
120 * passed in by the boot loader to a safe place, so that it is available
121 * after it has been relocated.
122 *
123 * WARNING: Because the kernel has not yet relocated itself to KERNBASE,
124 * special care has to be taken when accessing memory because absolute
125 * addresses (referring to kernel symbols) do not work.  So:
126 *
127 *     1) Avoid jumps to absolute addresses (such as gotos and switches).
128 *     2) To access global variables use their physical address, which
129 *        can be obtained using the RELOC macro.
130 */
131void
132multiboot1_pre_reloc(struct multiboot_info *mi)
133{
134#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
135	struct multiboot_info *midest =
136	    RELOC(struct multiboot_info *, &Multiboot_Info);
137
138	*RELOC(bool *, &Multiboot_Loader) = true;
139	memcpy(midest, mi, sizeof(Multiboot_Info));
140
141	if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) {
142		strncpy(RELOC(void *, Multiboot_Cmdline), mi->mi_cmdline,
143		    sizeof(Multiboot_Cmdline));
144		midest->mi_cmdline = (char *)&Multiboot_Cmdline;
145	}
146
147	if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) {
148		strncpy(RELOC(void *, Multiboot_Loader_Name),
149		    mi->mi_loader_name, sizeof(Multiboot_Loader_Name));
150		midest->mi_loader_name = (char *)&Multiboot_Loader_Name;
151	}
152
153	if (mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) {
154		memcpy(RELOC(void *, Multiboot_Mmap),
155		    (void *)mi->mi_mmap_addr, mi->mi_mmap_length);
156		midest->mi_mmap_addr = (vaddr_t)&Multiboot_Mmap;
157	}
158
159	if (mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) {
160		memcpy(RELOC(void *, Multiboot_Drives),
161		    (void *)mi->mi_drives_addr, mi->mi_drives_length);
162		midest->mi_drives_addr = (vaddr_t)&Multiboot_Drives;
163	}
164
165	copy_syms(mi);
166#undef RELOC
167}
168
169/* --------------------------------------------------------------------- */
170
171/*
172 * Sets up the kernel if it was booted by a Multiboot-compliant boot
173 * loader.  This is executed just after the kernel has relocated itself.
174 * At this point, executing any kind of code is safe, keeping in mind
175 * that no devices have been initialized yet (not even the console!).
176 */
177void
178multiboot1_post_reloc(void)
179{
180	struct multiboot_info *mi;
181
182	if (! Multiboot_Loader)
183		return;
184
185	mi = &Multiboot_Info;
186	bootinfo.bi_nentries = 0;
187
188	setup_memory(mi);
189	setup_console(mi);
190	setup_howto(mi);
191	setup_bootpath(mi);
192	setup_biosgeom(mi);
193	setup_bootdisk(mi);
194	setup_memmap(mi);
195}
196
197/* --------------------------------------------------------------------- */
198
199/*
200 * Prints a summary of the information collected in the Multiboot
201 * information header (if present).  Done as a separate function because
202 * the console has to be available.
203 */
204void
205multiboot1_print_info(void)
206{
207	struct multiboot_info *mi = &Multiboot_Info;
208	struct multiboot_symbols *ms = &Multiboot_Symbols;
209
210	if (! Multiboot_Loader)
211		return;
212
213	printf("multiboot: Information structure flags: 0x%08x\n",
214	    mi->mi_flags);
215
216	if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME)
217		printf("multiboot: Boot loader: %s\n", mi->mi_loader_name);
218
219	if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
220		printf("multiboot: Command line: %s\n", mi->mi_cmdline);
221
222	if (mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY)
223		printf("multiboot: %u KB lower memory, %u KB upper memory\n",
224		    mi->mi_mem_lower, mi->mi_mem_upper);
225
226	if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
227		KASSERT(esym != 0);
228		printf("multiboot: Symbol table at %p, length %d bytes\n",
229		    ms->s_symstart, ms->s_symsize);
230		printf("multiboot: String table at %p, length %d bytes\n",
231		    ms->s_strstart, ms->s_strsize);
232	}
233}
234
235/* --------------------------------------------------------------------- */
236
237/*
238 * Adds the bootinfo entry given in 'item' to the bootinfo tables.
239 * Sets the item type to 'type' and its length to 'len'.
240 */
241static void
242bootinfo_add(struct btinfo_common *item, int type, int len)
243{
244	int i;
245	struct bootinfo *bip = (struct bootinfo *)&bootinfo;
246	vaddr_t data;
247
248	item->type = type;
249	item->len = len;
250
251	data = (vaddr_t)&bip->bi_data;
252	for (i = 0; i < bip->bi_nentries; i++) {
253		struct btinfo_common *tmp;
254
255		tmp = (struct btinfo_common *)data;
256		data += tmp->len;
257	}
258	if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) {
259		memcpy((void *)data, item, len);
260		bip->bi_nentries++;
261	}
262}
263
264/* --------------------------------------------------------------------- */
265
266/*
267 * Copies the symbol table and the strings table passed in by the boot
268 * loader after the kernel's image, and sets up 'esym' accordingly so
269 * that this data is properly copied into upper memory during relocation.
270 *
271 * WARNING: This code runs before the kernel has relocated itself.  See
272 * the note in multiboot1_pre_reloc() for more information.
273 */
274static void
275copy_syms(struct multiboot_info *mi)
276{
277#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
278	int i;
279	struct multiboot_symbols *ms;
280	Elf32_Shdr *symtabp, *strtabp;
281	Elf32_Word symsize, strsize;
282	Elf32_Addr symaddr, straddr;
283	Elf32_Addr symstart, strstart;
284
285	/*
286	 * Check if the Multiboot information header has symbols or not.
287	 */
288	if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS))
289		return;
290
291	ms = RELOC(struct multiboot_symbols *, &Multiboot_Symbols);
292
293	/*
294	 * Locate a symbol table and its matching string table in the
295	 * section headers passed in by the boot loader.  Set 'symtabp'
296	 * and 'strtabp' with pointers to the matching entries.
297	 */
298	symtabp = strtabp = NULL;
299	for (i = 0; i < mi->mi_elfshdr_num && symtabp == NULL &&
300	    strtabp == NULL; i++) {
301		Elf32_Shdr *shdrp;
302
303		shdrp = &((Elf32_Shdr *)mi->mi_elfshdr_addr)[i];
304
305		if ((shdrp->sh_type == SHT_SYMTAB) &&
306		    shdrp->sh_link != SHN_UNDEF) {
307			Elf32_Shdr *shdrp2;
308
309			shdrp2 = &((Elf32_Shdr *)mi->mi_elfshdr_addr)
310			    [shdrp->sh_link];
311
312			if (shdrp2->sh_type == SHT_STRTAB) {
313				symtabp = shdrp;
314				strtabp = shdrp2;
315			}
316		}
317	}
318	if (symtabp == NULL || strtabp == NULL)
319		return;
320
321	symaddr = symtabp->sh_addr;
322	straddr = strtabp->sh_addr;
323	symsize = symtabp->sh_size;
324	strsize = strtabp->sh_size;
325
326	/*
327	 * Copy the symbol and string tables just after the kernel's
328	 * end address, in this order.  Only the contents of these ELF
329	 * sections are copied; headers are discarded.  esym is later
330	 * updated to point to the lowest "free" address after the tables
331	 * so that they are mapped appropriately when enabling paging.
332	 *
333	 * We need to be careful to not overwrite valid data doing the
334	 * copies, hence all the different cases below.  We can assume
335	 * that if the tables start before the kernel's end address,
336	 * they will not grow over this address.
337	 */
338        if ((void *)symtabp < RELOC(void *, &end) &&
339	    (void *)strtabp < RELOC(void *, &end)) {
340		symstart = RELOC(Elf32_Addr, &end);
341		strstart = symstart + symsize;
342		memcpy((void *)symstart, (void *)symaddr, symsize);
343		memcpy((void *)strstart, (void *)straddr, strsize);
344        } else if ((void *)symtabp > RELOC(void *, &end) &&
345	           (void *)strtabp < RELOC(void *, &end)) {
346		symstart = RELOC(Elf32_Addr, &end);
347		strstart = symstart + symsize;
348		memcpy((void *)symstart, (void *)symaddr, symsize);
349		memcpy((void *)strstart, (void *)straddr, strsize);
350        } else if ((void *)symtabp < RELOC(void *, &end) &&
351	           (void *)strtabp > RELOC(void *, &end)) {
352		strstart = RELOC(Elf32_Addr, &end);
353		symstart = strstart + strsize;
354		memcpy((void *)strstart, (void *)straddr, strsize);
355		memcpy((void *)symstart, (void *)symaddr, symsize);
356	} else {
357		/* symtabp and strtabp are both over end */
358		if (symtabp < strtabp) {
359			symstart = RELOC(Elf32_Addr, &end);
360			strstart = symstart + symsize;
361			memcpy((void *)symstart, (void *)symaddr, symsize);
362			memcpy((void *)strstart, (void *)straddr, strsize);
363		} else {
364			strstart = RELOC(Elf32_Addr, &end);
365			symstart = strstart + strsize;
366			memcpy((void *)strstart, (void *)straddr, strsize);
367			memcpy((void *)symstart, (void *)symaddr, symsize);
368		}
369	}
370
371	*RELOC(int *, &esym) =
372	    (int)(symstart + symsize + strsize + KERNBASE);
373
374	ms->s_symstart = (void *)(symstart + KERNBASE);
375	ms->s_symsize  = symsize;
376	ms->s_strstart = (void *)(strstart + KERNBASE);
377	ms->s_strsize  = strsize;
378#undef RELOC
379}
380
381/* --------------------------------------------------------------------- */
382
383/*
384 * Sets up the biosgeom bootinfo structure if the Multiboot information
385 * structure provides information about disk drives.
386 */
387static void
388setup_biosgeom(struct multiboot_info *mi)
389{
390	size_t pos;
391	uint8_t bidata[1024];
392	struct btinfo_biosgeom *bi;
393
394	if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES))
395		return;
396
397	memset(bidata, 0, sizeof(bidata));
398	bi = (struct btinfo_biosgeom *)bidata;
399	pos = 0;
400
401	while (pos < mi->mi_drives_length) {
402		struct multiboot_drive *md;
403		struct bi_biosgeom_entry bbe;
404
405		md = (struct multiboot_drive *)
406		    &((uint8_t *)mi->mi_drives_addr)[pos];
407
408		memset(&bbe, 0, sizeof(bbe));
409		bbe.sec = md->md_sectors;
410		bbe.head = md->md_heads;
411		bbe.cyl = md->md_cylinders;
412		bbe.dev = md->md_number;
413
414		memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe));
415		bi->num++;
416
417		pos += md->md_length;
418	}
419
420	bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM,
421	    sizeof(struct btinfo_biosgeom) +
422	    bi->num * sizeof(struct bi_biosgeom_entry));
423}
424
425/* --------------------------------------------------------------------- */
426
427/*
428 * Sets up the default root device if the Multiboot information
429 * structure provides information about the boot drive (where the kernel
430 * image was loaded from) or if the user gave a 'root' parameter on the
431 * boot command line.
432 */
433static void
434setup_bootdisk(struct multiboot_info *mi)
435{
436	bool found;
437	struct btinfo_rootdevice bi;
438
439	found = false;
440
441	if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
442		found = optstr_get(mi->mi_cmdline, "root", bi.devname,
443		    sizeof(bi.devname));
444
445	if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) {
446		const char *devprefix;
447
448		/* Attempt to match the BIOS boot disk to a device.  There
449		 * is not much we can do to get it right.  (Well, strictly
450		 * speaking, we could, but it is certainly not worth the
451		 * extra effort.) */
452		switch (mi->mi_boot_device_drive) {
453		case 0x00:	devprefix = "fd0";	break;
454		case 0x01:	devprefix = "fd1";	break;
455		case 0x80:	devprefix = "wd0";	break;
456		case 0x81:	devprefix = "wd1";	break;
457		case 0x82:	devprefix = "wd2";	break;
458		case 0x83:	devprefix = "wd3";	break;
459		default:	devprefix = "wd0";
460		}
461
462		strcpy(bi.devname, devprefix);
463		if (mi->mi_boot_device_part2 != 0xFF)
464			bi.devname[3] = mi->mi_boot_device_part2 + 'a';
465		else
466			bi.devname[3] = 'a';
467		bi.devname[4] = '\0';
468
469		found = true;
470	}
471
472	if (found) {
473		bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE,
474		    sizeof(struct btinfo_rootdevice));
475	}
476}
477
478/* --------------------------------------------------------------------- */
479
480/*
481 * Sets up the bootpath bootinfo structure with an appropriate kernel
482 * name derived from the boot command line.  The Multiboot information
483 * structure does not provide this detail directly, so we try to derive
484 * it from the command line setting.
485 */
486static void
487setup_bootpath(struct multiboot_info *mi)
488{
489	struct btinfo_bootpath bi;
490	char *cl, *cl2, old;
491	int len;
492
493	if (strncmp(Multiboot_Loader_Name, "GNU GRUB ",
494	    sizeof(Multiboot_Loader_Name)) > 0) {
495		cl = mi->mi_cmdline;
496		while (*cl != '\0' && *cl != '/')
497			cl++;
498		cl2 = cl;
499		len = 0;
500		while (*cl2 != '\0' && *cl2 != ' ') {
501			len++;
502			cl2++;
503		}
504
505		old = *cl2;
506		*cl2 = '\0';
507		memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len));
508		*cl2 = old;
509		bi.bootpath[MIN(sizeof(bi.bootpath) - 1, len)] = '\0';
510
511		bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH,
512		    sizeof(struct btinfo_bootpath));
513	}
514}
515
516/* --------------------------------------------------------------------- */
517
518/*
519 * Sets up the console bootinfo structure if the user gave a 'console'
520 * argument on the boot command line.  The Multiboot information
521 * structure gives no hint about this, so the only way to know where the
522 * console is to let the user specify it.
523 *
524 * If there wasn't any 'console' argument, this does not generate any
525 * bootinfo entry, falling back to the kernel's default console.
526 *
527 * If there weren't any of 'console_speed' or 'console_addr' arguments,
528 * this falls back to the default values for the serial port.
529 */
530static void
531setup_console(struct multiboot_info *mi)
532{
533	struct btinfo_console bi;
534	bool found;
535
536	found = false;
537
538	if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
539		found = optstr_get(mi->mi_cmdline, "console", bi.devname,
540		    sizeof(bi.devname));
541
542	if (found) {
543		bool valid;
544
545		if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) {
546			char tmp[10];
547
548			found = optstr_get(mi->mi_cmdline, "console_speed",
549			    tmp, sizeof(tmp));
550			if (found)
551				bi.speed = strtoul(tmp, NULL, 10);
552			else
553				bi.speed = 0; /* Use default speed. */
554
555			found = optstr_get(mi->mi_cmdline, "console_addr",
556			    tmp, sizeof(tmp));
557			if (found) {
558				if (tmp[0] == '0' && tmp[1] == 'x')
559					bi.addr = strtoul(tmp + 2, NULL, 16);
560				else
561					bi.addr = strtoul(tmp, NULL, 10);
562			} else
563				bi.addr = 0; /* Use default address. */
564
565			valid = true;
566		} else if (strncmp(bi.devname, "pc", sizeof(bi.devname)) == 0)
567			valid = true;
568		else
569			valid = false;
570
571		if (valid)
572			bootinfo_add((struct btinfo_common *)&bi,
573			    BTINFO_CONSOLE, sizeof(struct btinfo_console));
574	}
575}
576
577/* --------------------------------------------------------------------- */
578
579/*
580 * Sets up the 'boothowto' variable based on the options given in the
581 * boot command line, if any.
582 */
583static void
584setup_howto(struct multiboot_info *mi)
585{
586	char *cl;
587
588	if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE))
589		return;
590
591	cl = mi->mi_cmdline;
592
593	/* Skip kernel file name. */
594	while (*cl != '\0' && *cl != ' ')
595		cl++;
596	while (*cl == ' ')
597		cl++;
598
599	/* Check if there are flags and set 'howto' accordingly. */
600	if (*cl == '-') {
601		int howto = 0;
602
603		cl++;
604		while (*cl != '\0' && *cl != ' ') {
605			BOOT_FLAG(*cl, howto);
606			cl++;
607		}
608		if (*cl == ' ')
609			cl++;
610
611		boothowto = howto;
612	}
613}
614
615/* --------------------------------------------------------------------- */
616
617/*
618 * Sets up the memmap bootinfo structure to describe available memory as
619 * given by the BIOS.
620 */
621static void
622setup_memmap(struct multiboot_info *mi)
623{
624	char data[1024];
625	size_t i;
626	struct btinfo_memmap *bi;
627
628	if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP))
629		return;
630
631	bi = (struct btinfo_memmap *)data;
632	bi->num = 0;
633
634	i = 0;
635	while (i < mi->mi_mmap_length) {
636		struct multiboot_mmap *mm;
637		struct bi_memmap_entry *bie;
638
639		bie = &bi->entry[bi->num];
640
641		mm = (struct multiboot_mmap *)(mi->mi_mmap_addr + i);
642		bie->addr = mm->mm_base_addr;
643		bie->size = mm->mm_length;
644		if (mm->mm_type == 1)
645			bie->type = BIM_Memory;
646		else
647			bie->type = BIM_Reserved;
648
649		bi->num++;
650		i += mm->mm_size + 4;
651	}
652
653	bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP,
654	    sizeof(data));
655}
656
657/* --------------------------------------------------------------------- */
658
659/*
660 * Sets up the 'biosbasemem' and 'biosextmem' variables if the
661 * Multiboot information structure provides information about memory.
662 */
663static void
664setup_memory(struct multiboot_info *mi)
665{
666
667	if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY))
668		return;
669
670	/* Make sure we don't override user-set variables. */
671	if (biosbasemem == 0) {
672		biosbasemem = mi->mi_mem_lower;
673		biosmem_implicit = 1;
674	}
675	if (biosextmem == 0) {
676		biosextmem = mi->mi_mem_upper;
677		biosmem_implicit = 1;
678	}
679}
680
681/* --------------------------------------------------------------------- */
682
683/*
684 * Sets up the initial kernel symbol table.  Returns true if this was
685 * passed in by Multiboot; false otherwise.
686 */
687bool
688multiboot1_ksyms_addsyms_elf(void)
689{
690	struct multiboot_info *mi = &Multiboot_Info;
691	struct multiboot_symbols *ms = &Multiboot_Symbols;
692
693	if (! Multiboot_Loader)
694		return false;
695
696	if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
697		Elf32_Ehdr ehdr;
698
699		KASSERT(esym != 0);
700
701		memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
702		ehdr.e_ident[EI_CLASS] = ELFCLASS32;
703		ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
704		ehdr.e_ident[EI_VERSION] = EV_CURRENT;
705		ehdr.e_type = ET_EXEC;
706		ehdr.e_machine = EM_386;
707		ehdr.e_version = 1;
708		ehdr.e_ehsize = sizeof(ehdr);
709
710		ksyms_addsyms_explicit((void *)&ehdr,
711		    ms->s_symstart, ms->s_symsize,
712		    ms->s_strstart, ms->s_strsize);
713	}
714
715	return mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS;
716}
717