xref: /illumos-gate/usr/src/boot/common/multiboot2.c (revision 0a14cabd9bf525ab0f2b78c8550e855b8a97c1f2)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2017 Toomas Soome <tsoome@me.com>
14  * Copyright 2019, Joyent, Inc.
15  */
16 
17 /*
18  * This module adds support for loading and booting illumos multiboot2
19  * kernel. This code is only built to support the illumos kernel, it does
20  * not support xen.
21  */
22 
23 #include <sys/cdefs.h>
24 #include <sys/stddef.h>
25 
26 #include <sys/param.h>
27 #include <sys/exec.h>
28 #include <sys/linker.h>
29 #include <sys/module.h>
30 #include <sys/stdint.h>
31 #include <sys/multiboot2.h>
32 #include <stand.h>
33 #include <stdbool.h>
34 #include <machine/elf.h>
35 #include "libzfs.h"
36 
37 #include "bootstrap.h"
38 #include <sys/consplat.h>
39 
40 #include <machine/metadata.h>
41 #include <machine/pc/bios.h>
42 
43 #define	SUPPORT_DHCP
44 #include <bootp.h>
45 
46 #include <gfx_fb.h>
47 
48 #if !defined(EFI)
49 #include "../i386/btx/lib/btxv86.h"
50 #include "libi386.h"
51 #include "vbe.h"
52 
53 #else
54 #include <efi.h>
55 #include <efilib.h>
56 #include "loader_efi.h"
57 
58 static void (*trampoline)(uint32_t, struct relocator *, uint64_t);
59 static UINTN efi_map_size;		/* size of efi memory map */
60 #endif
61 
62 #include "platform/acfreebsd.h"
63 #include "acconfig.h"
64 #define	ACPI_SYSTEM_XFACE
65 #include "actypes.h"
66 #include "actbl.h"
67 
68 extern ACPI_TABLE_RSDP *rsdp;
69 
70 /* MB data heap pointer. */
71 static vm_offset_t last_addr;
72 
73 static int multiboot2_loadfile(char *, uint64_t, struct preloaded_file **);
74 static int multiboot2_exec(struct preloaded_file *);
75 
76 struct file_format multiboot2 = { multiboot2_loadfile, multiboot2_exec };
77 static bool keep_bs = false;
78 static vm_offset_t load_addr;
79 static vm_offset_t entry_addr;
80 
81 /*
82  * Validate tags in info request. This function is provided just to
83  * recognize the current tag list and only serves as a limited
84  * safe guard against possibly corrupt information.
85  */
86 static bool
87 is_info_request_valid(multiboot_header_tag_information_request_t *rtag)
88 {
89 	int i;
90 
91 	/*
92 	 * If the tag is optional and we do not support it, we do not
93 	 * have to do anything special, so we skip optional tags.
94 	 */
95 	if (rtag->mbh_flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
96 		return (true);
97 
98 	for (i = 0; i < (rtag->mbh_size - sizeof (*rtag)) /
99 	    sizeof (rtag->mbh_requests[0]); i++)
100 		switch (rtag->mbh_requests[i]) {
101 		case MULTIBOOT_TAG_TYPE_END:
102 		case MULTIBOOT_TAG_TYPE_CMDLINE:
103 		case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
104 		case MULTIBOOT_TAG_TYPE_MODULE:
105 		case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
106 		case MULTIBOOT_TAG_TYPE_BOOTDEV:
107 		case MULTIBOOT_TAG_TYPE_MMAP:
108 		case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
109 		case MULTIBOOT_TAG_TYPE_VBE:
110 		case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
111 		case MULTIBOOT_TAG_TYPE_APM:
112 		case MULTIBOOT_TAG_TYPE_EFI32:
113 		case MULTIBOOT_TAG_TYPE_EFI64:
114 		case MULTIBOOT_TAG_TYPE_ACPI_OLD:
115 		case MULTIBOOT_TAG_TYPE_ACPI_NEW:
116 		case MULTIBOOT_TAG_TYPE_NETWORK:
117 		case MULTIBOOT_TAG_TYPE_EFI_MMAP:
118 		case MULTIBOOT_TAG_TYPE_EFI_BS:
119 		case MULTIBOOT_TAG_TYPE_EFI32_IH:
120 		case MULTIBOOT_TAG_TYPE_EFI64_IH:
121 		case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
122 			break;
123 		default:
124 			printf("unsupported information tag: 0x%x\n",
125 			    rtag->mbh_requests[i]);
126 			return (false);
127 		}
128 	return (true);
129 }
130 
131 static int
132 multiboot2_loadfile(char *filename, uint64_t dest,
133     struct preloaded_file **result)
134 {
135 	int fd, error;
136 	uint32_t i;
137 	struct stat st;
138 	caddr_t header_search;
139 	multiboot2_header_t *header;
140 	multiboot_header_tag_t *tag;
141 	multiboot_header_tag_address_t *addr_tag = NULL;
142 	multiboot_header_tag_entry_address_t *entry_tag = NULL;
143 	struct preloaded_file *fp;
144 
145 	/* This allows to check other file formats from file_formats array. */
146 	error = EFTYPE;
147 	if (filename == NULL)
148 		return (error);
149 
150 	/* is kernel already loaded? */
151 	fp = file_findfile(NULL, NULL);
152 	if (fp != NULL)
153 		return (error);
154 
155 	if ((fd = open(filename, O_RDONLY)) == -1)
156 		return (errno);
157 
158 	/*
159 	 * Read MULTIBOOT_SEARCH size in order to search for the
160 	 * multiboot magic header.
161 	 */
162 	header_search = malloc(MULTIBOOT_SEARCH);
163 	if (header_search == NULL) {
164 		close(fd);
165 		return (ENOMEM);
166 	}
167 
168 	if (read(fd, header_search, MULTIBOOT_SEARCH) != MULTIBOOT_SEARCH)
169 		goto out;
170 
171 	header = NULL;
172 	for (i = 0; i <= (MULTIBOOT_SEARCH - sizeof (multiboot2_header_t));
173 	    i += MULTIBOOT_HEADER_ALIGN) {
174 		header = (multiboot2_header_t *)(header_search + i);
175 
176 		/* Do we have match on magic? */
177 		if (header->mb2_magic != MULTIBOOT2_HEADER_MAGIC) {
178 			header = NULL;
179 			continue;
180 		}
181 		/*
182 		 * Validate checksum, the sum of magic + architecture +
183 		 * header_length + checksum must equal 0.
184 		 */
185 		if (header->mb2_magic + header->mb2_architecture +
186 		    header->mb2_header_length + header->mb2_checksum != 0) {
187 			header = NULL;
188 			continue;
189 		}
190 		/*
191 		 * Finally, the entire header must fit within MULTIBOOT_SEARCH.
192 		 */
193 		if (i + header->mb2_header_length > MULTIBOOT_SEARCH) {
194 			header = NULL;
195 			continue;
196 		}
197 		break;
198 	}
199 
200 	if (header == NULL)
201 		goto out;
202 
203 	for (tag = header->mb2_tags; tag->mbh_type != MULTIBOOT_TAG_TYPE_END;
204 	    tag = (multiboot_header_tag_t *)((uintptr_t)tag +
205 	    roundup2(tag->mbh_size, MULTIBOOT_TAG_ALIGN))) {
206 		switch (tag->mbh_type) {
207 		case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
208 			if (is_info_request_valid((void*)tag) == false)
209 				goto out;
210 			break;
211 		case MULTIBOOT_HEADER_TAG_ADDRESS:
212 			addr_tag = (multiboot_header_tag_address_t *)tag;
213 			break;
214 		case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
215 			entry_tag =
216 			    (multiboot_header_tag_entry_address_t *)tag;
217 			break;
218 		case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
219 			break;
220 		case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
221 			break;
222 		case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
223 			/* we always align modules */
224 			break;
225 		case MULTIBOOT_HEADER_TAG_EFI_BS:
226 			keep_bs = true;
227 			break;
228 		default:
229 			if (!(tag->mbh_flags & MULTIBOOT_HEADER_TAG_OPTIONAL)) {
230 				printf("unsupported tag: 0x%x\n",
231 				    tag->mbh_type);
232 				goto out;
233 			}
234 		}
235 	}
236 
237 	/*
238 	 * We must have addr_tag and entry_tag to load a 64-bit kernel.
239 	 * If these tags are missing, we either have a 32-bit kernel, or
240 	 * this is not our kernel at all.
241 	 */
242 	if (addr_tag != NULL && entry_tag != NULL) {
243 		fp = file_alloc();
244 		if (fp == NULL) {
245 			error = ENOMEM;
246 			goto out;
247 		}
248 		if (lseek(fd, 0, SEEK_SET) == -1) {
249 			printf("lseek failed\n");
250 			error = EIO;
251 			file_discard(fp);
252 			goto out;
253 		}
254 		if (fstat(fd, &st) < 0) {
255 			printf("fstat failed\n");
256 			error = EIO;
257 			file_discard(fp);
258 			goto out;
259 		}
260 
261 		load_addr = addr_tag->mbh_load_addr;
262 		entry_addr = entry_tag->mbh_entry_addr;
263 		fp->f_addr = archsw.arch_loadaddr(LOAD_KERN, filename,
264 		    addr_tag->mbh_load_addr);
265 		if (fp->f_addr == 0) {
266 			error = ENOMEM;
267 			file_discard(fp);
268 			goto out;
269 		}
270 		fp->f_size = archsw.arch_readin(fd, fp->f_addr, st.st_size);
271 
272 		if (fp->f_size != st.st_size) {
273 			printf("error reading %s: %s\n", filename,
274 			    strerror(errno));
275 			file_discard(fp);
276 			error = EIO;
277 			goto out;
278 		}
279 
280 		fp->f_name = strdup(filename);
281 		fp->f_type = strdup("aout multiboot2 kernel");
282 		if (fp->f_name == NULL || fp->f_type == NULL) {
283 			error = ENOMEM;
284 			file_discard(fp);
285 			goto out;
286 		}
287 
288 		fp->f_metadata = NULL;
289 		error = 0;
290 	} else {
291 #if defined(EFI)
292 		/* 32-bit kernel is not yet supported for EFI */
293 		printf("32-bit kernel is not supported by UEFI loader\n");
294 		error = ENOTSUP;
295 		goto out;
296 #endif
297 		/* elf32_loadfile_raw will fill the attributes in fp. */
298 		error = elf32_loadfile_raw(filename, dest, &fp, 2);
299 		if (error != 0) {
300 			printf("elf32_loadfile_raw failed: %d unable to "
301 			    "load multiboot2 kernel\n", error);
302 			goto out;
303 		}
304 		entry_addr = fp->f_addr;
305 		/*
306 		 * We want the load_addr to have some legal value,
307 		 * so we set it same as the entry_addr.
308 		 * The distinction is important with UEFI, but not
309 		 * with BIOS version, because BIOS version does not use
310 		 * staging area.
311 		 */
312 		load_addr = fp->f_addr;
313 	}
314 
315 	setenv("kernelname", fp->f_name, 1);
316 #if defined(EFI)
317 	efi_addsmapdata(fp);
318 #else
319 	bios_addsmapdata(fp);
320 #endif
321 	*result = fp;
322 out:
323 	free(header_search);
324 	close(fd);
325 	return (error);
326 }
327 
328 /*
329  * Search the command line for named property.
330  *
331  * Return codes:
332  *	0	The name is found, we return the data in value and len.
333  *	ENOENT	The name is not found.
334  *	EINVAL	The provided command line is badly formed.
335  */
336 static int
337 find_property_value(const char *cmd, const char *name, const char **value,
338     size_t *len)
339 {
340 	const char *namep, *valuep;
341 	size_t name_len, value_len;
342 	int quoted;
343 
344 	*value = NULL;
345 	*len = 0;
346 
347 	if (cmd == NULL)
348 		return (ENOENT);
349 
350 	while (*cmd != '\0') {
351 		if (cmd[0] != '-' || cmd[1] != 'B') {
352 			cmd++;
353 			continue;
354 		}
355 		cmd += 2;	/* Skip -B */
356 		while (cmd[0] == ' ' || cmd[0] == '\t')
357 			cmd++;	/* Skip whitespaces. */
358 		while (*cmd != '\0' && cmd[0] != ' ' && cmd[0] != '\t') {
359 			namep = cmd;
360 			valuep = strchr(cmd, '=');
361 			if (valuep == NULL)
362 				break;
363 			name_len = valuep - namep;
364 			valuep++;
365 			value_len = 0;
366 			quoted = 0;
367 			for (;; ++value_len) {
368 				if (valuep[value_len] == '\0')
369 					break;
370 
371 				/* Is this value quoted? */
372 				if (value_len == 0 &&
373 				    (valuep[0] == '\'' || valuep[0] == '"')) {
374 					quoted = valuep[0];
375 					++value_len;
376 				}
377 
378 				/*
379 				 * In the quote accept any character,
380 				 * but look for ending quote.
381 				 */
382 				if (quoted != 0) {
383 					if (valuep[value_len] == quoted)
384 						quoted = 0;
385 					continue;
386 				}
387 
388 				/* A comma or white space ends the value. */
389 				if (valuep[value_len] == ',' ||
390 				    valuep[value_len] == ' ' ||
391 				    valuep[value_len] == '\t')
392 					break;
393 			}
394 			if (quoted != 0) {
395 				printf("Missing closing '%c' in \"%s\"\n",
396 				    quoted, valuep);
397 				return (EINVAL);
398 			}
399 			if (value_len != 0) {
400 				if (strncmp(namep, name, name_len) == 0) {
401 					*value = valuep;
402 					*len = value_len;
403 					return (0);
404 				}
405 			}
406 			cmd = valuep + value_len;
407 			while (*cmd == ',')
408 				cmd++;
409 		}
410 	}
411 	return (ENOENT);
412 }
413 
414 /*
415  * If command line has " -B ", insert property after "-B ", otherwise
416  * append to command line.
417  */
418 static char *
419 insert_cmdline(const char *head, const char *prop)
420 {
421 	const char *prop_opt = " -B ";
422 	char *cmdline, *tail;
423 	int len = 0;
424 
425 	tail = strstr(head, prop_opt);
426 	if (tail != NULL) {
427 		ptrdiff_t diff;
428 		tail += strlen(prop_opt);
429 		diff = tail - head;
430 		if (diff >= INT_MAX)
431 			return (NULL);
432 		len = (int)diff;
433 	}
434 
435 	if (tail == NULL)
436 		asprintf(&cmdline, "%s%s%s", head, prop_opt, prop);
437 	else
438 		asprintf(&cmdline, "%.*s%s,%s", len, head, prop, tail);
439 
440 	return (cmdline);
441 }
442 
443 /*
444  * Since we have no way to pass the environment to the mb1 kernel other than
445  * through arguments, we need to take care of console setup.
446  *
447  * If the console is in mirror mode, set the kernel console from $os_console.
448  * If it's unset, use first item from $console.
449  * If $console is "ttyX", also pass $ttyX-mode, since it may have been set by
450  * the user.
451  *
452  * In case of memory allocation errors, just return the original command line
453  * so we have a chance of booting.
454  *
455  * On success, cl will be freed and a new, allocated command line string is
456  * returned.
457  *
458  * For the mb2 kernel, we only set command line console if os_console is set.
459  * We can not overwrite console in the environment, as it can disrupt the
460  * loader console messages, and we do not want to deal with the os_console
461  * in the kernel.
462  */
463 static char *
464 update_cmdline(char *cl, bool mb2)
465 {
466 	char *os_console = getenv("os_console");
467 	char *ttymode = NULL;
468 	char mode[10];
469 	char *tmp;
470 	const char *prop;
471 	size_t plen;
472 	int rv;
473 
474 	if (mb2 == true && os_console == NULL)
475 		return (cl);
476 
477 	if (os_console == NULL) {
478 		tmp = strdup(getenv("console"));
479 		os_console = strsep(&tmp, ", ");
480 	} else {
481 		os_console = strdup(os_console);
482 	}
483 
484 	if (os_console == NULL)
485 		return (cl);
486 
487 	if (mb2 == false && strncmp(os_console, "tty", 3) == 0) {
488 		snprintf(mode, sizeof (mode), "%s-mode", os_console);
489 		/*
490 		 * The ttyX-mode variable is set by our serial console
491 		 * driver for ttya-ttyd. However, since the os_console
492 		 * values are not verified, it is possible we get bogus
493 		 * name and no mode variable. If so, we do not set console
494 		 * property and let the kernel use defaults.
495 		 */
496 		if ((ttymode = getenv(mode)) == NULL)
497 			return (cl);
498 	}
499 
500 	rv = find_property_value(cl, "console", &prop, &plen);
501 	if (rv != 0 && rv != ENOENT) {
502 		free(os_console);
503 		return (cl);
504 	}
505 
506 	/* If console is set and this is MB2 boot, we are done. */
507 	if (rv == 0 && mb2 == true) {
508 		free(os_console);
509 		return (cl);
510 	}
511 
512 	/* If console is set, do we need to set tty mode? */
513 	if (rv == 0) {
514 		const char *ttyp = NULL;
515 		size_t ttylen;
516 
517 		free(os_console);
518 		os_console = NULL;
519 		*mode = '\0';
520 		if (strncmp(prop, "tty", 3) == 0 && plen == 4) {
521 			strncpy(mode, prop, plen);
522 			mode[plen] = '\0';
523 			strncat(mode, "-mode", 5);
524 			find_property_value(cl, mode, &ttyp, &ttylen);
525 		}
526 
527 		if (*mode != '\0' && ttyp == NULL)
528 			ttymode = getenv(mode);
529 		else
530 			return (cl);
531 	}
532 
533 	/* Build updated command line. */
534 	if (os_console != NULL) {
535 		char *propstr;
536 
537 		asprintf(&propstr, "console=%s", os_console);
538 		free(os_console);
539 		if (propstr == NULL) {
540 			return (cl);
541 		}
542 
543 		tmp = insert_cmdline(cl, propstr);
544 		free(propstr);
545 		if (tmp == NULL)
546 			return (cl);
547 
548 		free(cl);
549 		cl = tmp;
550 	}
551 	if (ttymode != NULL) {
552 		char *propstr;
553 
554 		asprintf(&propstr, "%s=\"%s\"", mode, ttymode);
555 		if (propstr == NULL)
556 			return (cl);
557 
558 		tmp = insert_cmdline(cl, propstr);
559 		free(propstr);
560 		if (tmp == NULL)
561 			return (cl);
562 		free(cl);
563 		cl = tmp;
564 	}
565 
566 	return (cl);
567 }
568 
569 /*
570  * Build the kernel command line. Shared function between MB1 and MB2.
571  *
572  * In both cases, if fstype is set and is not zfs, we do not set up
573  * zfs-bootfs property. But we set kernel file name and options.
574  *
575  * For the MB1, we only can pass properties on command line, so
576  * we will set console, ttyX-mode (for serial console) and zfs-bootfs.
577  *
578  * For the MB2, we can pass properties in environment, but if os_console
579  * is set in environment, we need to add console property on the kernel
580  * command line.
581  *
582  * The console properties are managed in update_cmdline().
583  */
584 int
585 mb_kernel_cmdline(struct preloaded_file *fp, struct devdesc *rootdev,
586     char **line)
587 {
588 	const char *fs = getenv("fstype");
589 	char *cmdline;
590 	size_t len;
591 	bool zfs_root = false;
592 	bool mb2;
593 	int rv;
594 
595 	/*
596 	 * With multiple console devices and "os_console" variable not
597 	 * set, set os_console to last input device.
598 	 */
599 	rv = cons_inputdev();
600 	if (rv != -1)
601 		(void) setenv("os_console", consoles[rv]->c_name, 0);
602 
603 	/*
604 	 * 64-bit kernel has aout header, 32-bit kernel is elf, and the
605 	 * type strings are different. Lets just search for "multiboot2".
606 	 */
607 	if (strstr(fp->f_type, "multiboot2") == NULL)
608 		mb2 = false;
609 	else
610 		mb2 = true;
611 
612 	if (rootdev->d_dev->dv_type == DEVT_ZFS)
613 		zfs_root = true;
614 
615 	/* If we have fstype set in env, reset zfs_root if needed. */
616 	if (fs != NULL && strcmp(fs, "zfs") != 0)
617 		zfs_root = false;
618 
619 	/*
620 	 * If we have fstype set on the command line,
621 	 * reset zfs_root if needed.
622 	 */
623 	rv = find_property_value(fp->f_args, "fstype", &fs, &len);
624 	if (rv != 0 && rv != ENOENT)
625 		return (rv);
626 
627 	if (fs != NULL && strncmp(fs, "zfs", len) != 0)
628 		zfs_root = false;
629 
630 	/* zfs_bootfs() will set the environment, it must be called. */
631 	if (zfs_root == true)
632 		fs = zfs_bootfs(rootdev);
633 
634 	if (fp->f_args == NULL)
635 		cmdline = strdup(fp->f_name);
636 	else
637 		asprintf(&cmdline, "%s %s", fp->f_name, fp->f_args);
638 
639 	if (cmdline == NULL)
640 		return (ENOMEM);
641 
642 	/* Append zfs-bootfs for MB1 command line. */
643 	if (mb2 == false && zfs_root == true) {
644 		char *tmp;
645 
646 		tmp = insert_cmdline(cmdline, fs);
647 		free(cmdline);
648 		if (tmp == NULL)
649 			return (ENOMEM);
650 		cmdline = tmp;
651 	}
652 
653 	*line = update_cmdline(cmdline, mb2);
654 	return (0);
655 }
656 
657 /*
658  * Returns allocated virtual address from MB info area.
659  */
660 static vm_offset_t
661 mb_malloc(size_t n)
662 {
663 	vm_offset_t ptr = last_addr;
664 	last_addr = roundup(last_addr + n, MULTIBOOT_TAG_ALIGN);
665 	return (ptr);
666 }
667 
668 /*
669  * Calculate size for module tag list.
670  */
671 static size_t
672 module_size(struct preloaded_file *fp)
673 {
674 	size_t len, size;
675 	struct preloaded_file *mfp;
676 
677 	size = 0;
678 	for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) {
679 		len = strlen(mfp->f_name) + 1;
680 		len += strlen(mfp->f_type) + 5 + 1; /* 5 is for "type=" */
681 		if (mfp->f_args != NULL)
682 			len += strlen(mfp->f_args) + 1;
683 		size += sizeof (multiboot_tag_module_t) + len;
684 		size = roundup(size, MULTIBOOT_TAG_ALIGN);
685 	}
686 	return (size);
687 }
688 
689 #if defined(EFI)
690 /*
691  * Calculate size for UEFI memory map tag.
692  */
693 #define	EFI_EXTRA_PAGES	3
694 
695 static int
696 efimemmap_size(void)
697 {
698 	UINTN size, cur_size, desc_size;
699 	EFI_MEMORY_DESCRIPTOR *mmap;
700 	EFI_STATUS ret;
701 
702 	size = EFI_PAGE_SIZE;		/* Start with 4k. */
703 	while (1) {
704 		cur_size = size;
705 		mmap = malloc(cur_size);
706 		if (mmap == NULL)
707 			return (0);
708 		ret = BS->GetMemoryMap(&cur_size, mmap, NULL, &desc_size, NULL);
709 		free(mmap);
710 		if (ret == EFI_SUCCESS)
711 			break;
712 		if (ret == EFI_BUFFER_TOO_SMALL) {
713 			if (size < cur_size)
714 				size = cur_size;
715 			size += (EFI_PAGE_SIZE);
716 		} else
717 			return (0);
718 	}
719 
720 	/* EFI MMAP will grow when we allocate MBI, set some buffer. */
721 	size += (EFI_EXTRA_PAGES << EFI_PAGE_SHIFT);
722 	size = roundup2(size, EFI_PAGE_SIZE);
723 	efi_map_size = size;	/* Record the calculated size. */
724 	return (sizeof (multiboot_tag_efi_mmap_t) + size);
725 }
726 #endif
727 
728 /*
729  * Calculate size for bios smap tag.
730  */
731 static size_t
732 biossmap_size(struct preloaded_file *fp)
733 {
734 	int num;
735 	struct file_metadata *md;
736 
737 	md = file_findmetadata(fp, MODINFOMD_SMAP);
738 	if (md == NULL)
739 		return (0);
740 
741 	num = md->md_size / sizeof (struct bios_smap); /* number of entries */
742 	return (sizeof (multiboot_tag_mmap_t) +
743 	    num * sizeof (multiboot_mmap_entry_t));
744 }
745 
746 static size_t
747 mbi_size(struct preloaded_file *fp, char *cmdline)
748 {
749 	size_t size;
750 
751 	size = sizeof (uint32_t) * 2; /* first 2 fields from MBI header */
752 	size += sizeof (multiboot_tag_string_t) + strlen(cmdline) + 1;
753 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
754 	size += sizeof (multiboot_tag_string_t) + strlen(bootprog_info) + 1;
755 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
756 #if !defined(EFI)
757 	size += sizeof (multiboot_tag_basic_meminfo_t);
758 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
759 #endif
760 	size += module_size(fp);
761 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
762 #if defined(EFI)
763 	size += sizeof (multiboot_tag_efi64_t);
764 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
765 	size += efimemmap_size();
766 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
767 #endif
768 
769 	size += biossmap_size(fp);
770 	size = roundup2(size, MULTIBOOT_TAG_ALIGN);
771 
772 	if (has_framebuffer) {
773 		if (gfx_fb.framebuffer_common.framebuffer_type ==
774 		    MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) {
775 			uint16_t nc;
776 			nc = gfx_fb.u.fb1.framebuffer_palette_num_colors;
777 			size +=
778 			    sizeof (struct multiboot_tag_framebuffer_common);
779 			size += sizeof (uint16_t);
780 			size += nc * sizeof (multiboot_color_t);
781 		} else {
782 			size += sizeof (multiboot_tag_framebuffer_t);
783 		}
784 		size = roundup2(size, MULTIBOOT_TAG_ALIGN);
785 	}
786 
787 	if (bootp_response != NULL) {
788 		size += sizeof (multiboot_tag_network_t) + bootp_response_size;
789 		size = roundup2(size, MULTIBOOT_TAG_ALIGN);
790 	}
791 
792 	if (rsdp != NULL) {
793 		if (rsdp->Revision == 0) {
794 			size += sizeof (multiboot_tag_old_acpi_t) +
795 			    sizeof (ACPI_RSDP_COMMON);
796 		} else {
797 			size += sizeof (multiboot_tag_new_acpi_t) +
798 			    rsdp->Length;
799 		}
800 		size = roundup2(size, MULTIBOOT_TAG_ALIGN);
801 	}
802 	size += sizeof (multiboot_tag_t);
803 
804 	return (size);
805 }
806 
807 #if defined(EFI)
808 static bool
809 overlaps(uintptr_t start1, size_t size1, uintptr_t start2, size_t size2)
810 {
811 	if (start1 < start2 + size2 &&
812 	    start1 + size1 >= start2) {
813 		printf("overlaps: %zx-%zx, %zx-%zx\n",
814 		    start1, start1 + size1, start2, start2 + size2);
815 		return (true);
816 	}
817 
818 	return (false);
819 }
820 #endif
821 
822 static int
823 multiboot2_exec(struct preloaded_file *fp)
824 {
825 	multiboot2_info_header_t *mbi = NULL;
826 	struct preloaded_file *mfp;
827 	char *cmdline = NULL;
828 	struct devdesc *rootdev;
829 	struct file_metadata *md;
830 	int i, error, num;
831 	int rootfs = 0;
832 	size_t size;
833 	struct bios_smap *smap;
834 #if defined(EFI)
835 	multiboot_tag_module_t *module, *mp;
836 	struct relocator *relocator = NULL;
837 	EFI_MEMORY_DESCRIPTOR *map;
838 	UINTN map_size, desc_size;
839 	struct chunk_head *head;
840 	struct chunk *chunk;
841 	vm_offset_t tmp;
842 
843 	efi_getdev((void **)(&rootdev), NULL, NULL);
844 
845 	/*
846 	 * We need 5 pages for relocation. We'll allocate from the heap: while
847 	 * it's possible that our heap got placed low down enough to be in the
848 	 * way of where we're going to relocate our kernel, it's hopefully not
849 	 * likely.
850 	 */
851 	if ((relocator = malloc(EFI_PAGE_SIZE * 5)) == NULL) {
852 		printf("relocator malloc failed!\n");
853 		error = ENOMEM;
854 		goto error;
855 	}
856 
857 	if (overlaps((uintptr_t)relocator, EFI_PAGE_SIZE * 5,
858 	    load_addr, fp->f_size)) {
859 		printf("relocator pages overlap the kernel!\n");
860 		error = EINVAL;
861 		goto error;
862 	}
863 
864 #else
865 	i386_getdev((void **)(&rootdev), NULL, NULL);
866 #endif
867 
868 	error = EINVAL;
869 	if (rootdev == NULL) {
870 		printf("can't determine root device\n");
871 		goto error;
872 	}
873 
874 	/*
875 	 * Set the image command line.
876 	 */
877 	if (fp->f_args == NULL) {
878 		cmdline = getenv("boot-args");
879 		if (cmdline != NULL) {
880 			fp->f_args = strdup(cmdline);
881 			if (fp->f_args == NULL) {
882 				error = ENOMEM;
883 				goto error;
884 			}
885 		}
886 	}
887 
888 	error = mb_kernel_cmdline(fp, rootdev, &cmdline);
889 	if (error != 0)
890 		goto error;
891 
892 	/* mb_kernel_cmdline() updates the environment. */
893 	build_environment_module();
894 
895 	/* Pass the loaded console font for kernel. */
896 	build_font_module();
897 
898 	size = mbi_size(fp, cmdline);	/* Get the size for MBI. */
899 
900 	/* Set up the base for mb_malloc. */
901 	i = 0;
902 	for (mfp = fp; mfp->f_next != NULL; mfp = mfp->f_next)
903 		i++;
904 
905 #if defined(EFI)
906 	/* We need space for kernel + MBI + # modules */
907 	num = (EFI_PAGE_SIZE - offsetof(struct relocator, rel_chunklist)) /
908 	    sizeof (struct chunk);
909 	if (i + 2 >= num) {
910 		printf("Too many modules, do not have space for relocator.\n");
911 		error = ENOMEM;
912 		goto error;
913 	}
914 
915 	last_addr = efi_loadaddr(LOAD_MEM, &size, mfp->f_addr + mfp->f_size);
916 	mbi = (multiboot2_info_header_t *)last_addr;
917 	if (mbi == NULL) {
918 		error = ENOMEM;
919 		goto error;
920 	}
921 	last_addr = (vm_offset_t)mbi->mbi_tags;
922 #else
923 	/* Start info block from the new page. */
924 	last_addr = i386_loadaddr(LOAD_MEM, &size, mfp->f_addr + mfp->f_size);
925 
926 	/* Do we have space for multiboot info? */
927 	if (last_addr + size >= memtop_copyin) {
928 		error = ENOMEM;
929 		goto error;
930 	}
931 
932 	mbi = (multiboot2_info_header_t *)PTOV(last_addr);
933 	last_addr = (vm_offset_t)mbi->mbi_tags;
934 #endif	/* EFI */
935 
936 	{
937 		multiboot_tag_string_t *tag;
938 		i = sizeof (multiboot_tag_string_t) + strlen(cmdline) + 1;
939 		tag = (multiboot_tag_string_t *)mb_malloc(i);
940 
941 		tag->mb_type = MULTIBOOT_TAG_TYPE_CMDLINE;
942 		tag->mb_size = i;
943 		memcpy(tag->mb_string, cmdline, strlen(cmdline) + 1);
944 		free(cmdline);
945 		cmdline = NULL;
946 	}
947 
948 	{
949 		multiboot_tag_string_t *tag;
950 		i = sizeof (multiboot_tag_string_t) + strlen(bootprog_info) + 1;
951 		tag = (multiboot_tag_string_t *)mb_malloc(i);
952 
953 		tag->mb_type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
954 		tag->mb_size = i;
955 		memcpy(tag->mb_string, bootprog_info,
956 		    strlen(bootprog_info) + 1);
957 	}
958 
959 #if !defined(EFI)
960 	/* Only set in case of BIOS. */
961 	{
962 		multiboot_tag_basic_meminfo_t *tag;
963 		tag = (multiboot_tag_basic_meminfo_t *)
964 		    mb_malloc(sizeof (*tag));
965 
966 		tag->mb_type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
967 		tag->mb_size = sizeof (*tag);
968 		tag->mb_mem_lower = bios_basemem / 1024;
969 		tag->mb_mem_upper = bios_extmem / 1024;
970 	}
971 #endif
972 
973 	num = 0;
974 	for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) {
975 		num++;
976 		if (mfp->f_type != NULL && strcmp(mfp->f_type, "rootfs") == 0)
977 			rootfs++;
978 	}
979 
980 	if (num == 0 || rootfs == 0) {
981 		/* We need at least one module - rootfs. */
982 		printf("No rootfs module provided, aborting\n");
983 		error = EINVAL;
984 		goto error;
985 	}
986 
987 	/*
988 	 * Set the stage for physical memory layout:
989 	 * - We have kernel at load_addr.
990 	 * - Modules are aligned to page boundary.
991 	 * - MBI is aligned to page boundary.
992 	 * - Set the tmp to point to physical address of the first module.
993 	 * - tmp != mfp->f_addr only in case of EFI.
994 	 */
995 #if defined(EFI)
996 	tmp = roundup2(load_addr + fp->f_size + 1, MULTIBOOT_MOD_ALIGN);
997 	module = (multiboot_tag_module_t *)last_addr;
998 #endif
999 
1000 	for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) {
1001 		multiboot_tag_module_t *tag;
1002 
1003 		num = strlen(mfp->f_name) + 1;
1004 		num += strlen(mfp->f_type) + 5 + 1;
1005 		if (mfp->f_args != NULL) {
1006 			num += strlen(mfp->f_args) + 1;
1007 		}
1008 		cmdline = malloc(num);
1009 		if (cmdline == NULL) {
1010 			error = ENOMEM;
1011 			goto error;
1012 		}
1013 
1014 		if (mfp->f_args != NULL)
1015 			snprintf(cmdline, num, "%s type=%s %s",
1016 			    mfp->f_name, mfp->f_type, mfp->f_args);
1017 		else
1018 			snprintf(cmdline, num, "%s type=%s",
1019 			    mfp->f_name, mfp->f_type);
1020 
1021 		tag = (multiboot_tag_module_t *)mb_malloc(sizeof (*tag) + num);
1022 
1023 		tag->mb_type = MULTIBOOT_TAG_TYPE_MODULE;
1024 		tag->mb_size = sizeof (*tag) + num;
1025 #if defined(EFI)
1026 		/*
1027 		 * We can assign module addresses only after BS have been
1028 		 * switched off.
1029 		 */
1030 		tag->mb_mod_start = 0;
1031 		tag->mb_mod_end = mfp->f_size;
1032 #else
1033 		tag->mb_mod_start = mfp->f_addr;
1034 		tag->mb_mod_end = mfp->f_addr + mfp->f_size;
1035 #endif
1036 		memcpy(tag->mb_cmdline, cmdline, num);
1037 		free(cmdline);
1038 		cmdline = NULL;
1039 	}
1040 
1041 	md = file_findmetadata(fp, MODINFOMD_SMAP);
1042 	if (md == NULL) {
1043 		printf("no memory smap\n");
1044 		error = EINVAL;
1045 		goto error;
1046 	}
1047 
1048 	smap = (struct bios_smap *)md->md_data;
1049 	num = md->md_size / sizeof (struct bios_smap); /* number of entries */
1050 
1051 	{
1052 		multiboot_tag_mmap_t *tag;
1053 		multiboot_mmap_entry_t *mmap_entry;
1054 
1055 		tag = (multiboot_tag_mmap_t *)
1056 		    mb_malloc(sizeof (*tag) +
1057 		    num * sizeof (multiboot_mmap_entry_t));
1058 
1059 		tag->mb_type = MULTIBOOT_TAG_TYPE_MMAP;
1060 		tag->mb_size = sizeof (*tag) +
1061 		    num * sizeof (multiboot_mmap_entry_t);
1062 		tag->mb_entry_size = sizeof (multiboot_mmap_entry_t);
1063 		tag->mb_entry_version = 0;
1064 		mmap_entry = (multiboot_mmap_entry_t *)tag->mb_entries;
1065 
1066 		for (i = 0; i < num; i++) {
1067 			mmap_entry[i].mmap_addr = smap[i].base;
1068 			mmap_entry[i].mmap_len = smap[i].length;
1069 			mmap_entry[i].mmap_type = smap[i].type;
1070 			mmap_entry[i].mmap_reserved = 0;
1071 		}
1072 	}
1073 
1074 	if (bootp_response != NULL) {
1075 		multiboot_tag_network_t *tag;
1076 		tag = (multiboot_tag_network_t *)
1077 		    mb_malloc(sizeof (*tag) + bootp_response_size);
1078 
1079 		tag->mb_type = MULTIBOOT_TAG_TYPE_NETWORK;
1080 		tag->mb_size = sizeof (*tag) + bootp_response_size;
1081 		memcpy(tag->mb_dhcpack, bootp_response, bootp_response_size);
1082 	}
1083 
1084 	if (rsdp != NULL) {
1085 		multiboot_tag_new_acpi_t *ntag;
1086 		multiboot_tag_old_acpi_t *otag;
1087 		uint32_t tsize;
1088 
1089 		if (rsdp->Revision == 0) {
1090 			tsize = sizeof (*otag) + sizeof (ACPI_RSDP_COMMON);
1091 			otag = (multiboot_tag_old_acpi_t *)mb_malloc(tsize);
1092 			otag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
1093 			otag->mb_size = tsize;
1094 			memcpy(otag->mb_rsdp, rsdp, sizeof (ACPI_RSDP_COMMON));
1095 		} else {
1096 			tsize = sizeof (*ntag) + rsdp->Length;
1097 			ntag = (multiboot_tag_new_acpi_t *)mb_malloc(tsize);
1098 			ntag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
1099 			ntag->mb_size = tsize;
1100 			memcpy(ntag->mb_rsdp, rsdp, rsdp->Length);
1101 		}
1102 	}
1103 
1104 #if defined(EFI)
1105 #ifdef  __LP64__
1106 	{
1107 		multiboot_tag_efi64_t *tag;
1108 		tag = (multiboot_tag_efi64_t *)
1109 		    mb_malloc(sizeof (*tag));
1110 
1111 		tag->mb_type = MULTIBOOT_TAG_TYPE_EFI64;
1112 		tag->mb_size = sizeof (*tag);
1113 		tag->mb_pointer = (uint64_t)(uintptr_t)ST;
1114 	}
1115 #else
1116 	{
1117 		multiboot_tag_efi32_t *tag;
1118 		tag = (multiboot_tag_efi32_t *)
1119 		    mb_malloc(sizeof (*tag));
1120 
1121 		tag->mb_type = MULTIBOOT_TAG_TYPE_EFI32;
1122 		tag->mb_size = sizeof (*tag);
1123 		tag->mb_pointer = (uint32_t)ST;
1124 	}
1125 #endif /* __LP64__ */
1126 #endif /* EFI */
1127 
1128 	if (has_framebuffer) {
1129 		multiboot_tag_framebuffer_t *tag;
1130 		uint32_t size;
1131 
1132 		if (gfx_fb.framebuffer_common.framebuffer_type ==
1133 		    MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) {
1134 			uint16_t nc;
1135 			nc = gfx_fb.u.fb1.framebuffer_palette_num_colors;
1136 			size = sizeof (struct multiboot_tag_framebuffer_common)
1137 			    + sizeof (nc)
1138 			    + nc * sizeof (multiboot_color_t);
1139 		} else {
1140 			size = sizeof (*tag);
1141 		}
1142 
1143 		tag = (multiboot_tag_framebuffer_t *)mb_malloc(size);
1144 		memcpy(tag, &gfx_fb, sizeof (*tag));
1145 		tag->framebuffer_common.mb_type =
1146 		    MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
1147 		tag->framebuffer_common.mb_size = size;
1148 
1149 #if !defined(EFI)
1150 		extern multiboot_color_t *cmap;
1151 
1152 		if (gfx_fb.framebuffer_common.framebuffer_type ==
1153 		    MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) {
1154 			uint16_t nc;
1155 			nc = gfx_fb.u.fb1.framebuffer_palette_num_colors;
1156 			memcpy(tag->u.fb1.framebuffer_palette, cmap,
1157 			    sizeof (multiboot_color_t) * nc);
1158 		}
1159 #endif /* !EFI */
1160 	}
1161 
1162 #if defined(EFI)
1163 	/* Leave EFI memmap last as we will also switch off the BS. */
1164 	{
1165 		multiboot_tag_efi_mmap_t *tag;
1166 		UINTN key;
1167 		EFI_STATUS status;
1168 
1169 		tag = (multiboot_tag_efi_mmap_t *)
1170 		    mb_malloc(sizeof (*tag));
1171 
1172 		map_size = 0;
1173 		status = BS->GetMemoryMap(&map_size,
1174 		    (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1175 		    &desc_size, &tag->mb_descr_vers);
1176 		if (status != EFI_BUFFER_TOO_SMALL) {
1177 			error = EINVAL;
1178 			goto error;
1179 		}
1180 		map_size = roundup2(map_size, EFI_PAGE_SIZE);
1181 
1182 		i = 2;	/* Attempts to ExitBootServices() */
1183 		while (map_size <= efi_map_size && i > 0) {
1184 			status = BS->GetMemoryMap(&map_size,
1185 			    (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1186 			    &desc_size, &tag->mb_descr_vers);
1187 			if (status == EFI_BUFFER_TOO_SMALL) {
1188 				/* Still too small? */
1189 				map_size += EFI_PAGE_SIZE;
1190 				continue;
1191 			}
1192 			if (EFI_ERROR(status)) {
1193 				error = EINVAL;
1194 				goto error;
1195 			}
1196 
1197 			if (keep_bs != 0)
1198 				break;
1199 
1200 			status = BS->ExitBootServices(IH, key);
1201 			if (status == EFI_SUCCESS) {
1202 				has_boot_services = false;
1203 				break;
1204 			}
1205 			i--;
1206 		}
1207 		if (status != EFI_SUCCESS) {
1208 			error = EINVAL;
1209 			goto error;
1210 		}
1211 
1212 		tag->mb_type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
1213 		tag->mb_size = sizeof (*tag) + map_size;
1214 		tag->mb_descr_size = (uint32_t)desc_size;
1215 
1216 		map = (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap;
1217 
1218 		last_addr += map_size;
1219 		last_addr = roundup2(last_addr, MULTIBOOT_TAG_ALIGN);
1220 	}
1221 #endif /* EFI */
1222 
1223 	/*
1224 	 * MB tag list end marker.
1225 	 */
1226 	{
1227 		multiboot_tag_t *tag = (multiboot_tag_t *)
1228 		    mb_malloc(sizeof (*tag));
1229 		tag->mb_type = MULTIBOOT_TAG_TYPE_END;
1230 		tag->mb_size = sizeof (*tag);
1231 	}
1232 
1233 	mbi->mbi_total_size = last_addr - (vm_offset_t)mbi;
1234 	mbi->mbi_reserved = 0;
1235 
1236 #if defined(EFI)
1237 	/*
1238 	 * At this point we have load_addr pointing to kernel load
1239 	 * address, module list in MBI having physical addresses,
1240 	 * module list in fp having logical addresses and tmp pointing to
1241 	 * physical address for MBI.
1242 	 * Now we must move all pieces to place and start the kernel.
1243 	 */
1244 	head = &relocator->rel_chunk_head;
1245 	STAILQ_INIT(head);
1246 
1247 	i = 0;
1248 	chunk = &relocator->rel_chunklist[i++];
1249 	chunk->chunk_vaddr = fp->f_addr;
1250 	chunk->chunk_paddr = load_addr;
1251 	chunk->chunk_size = fp->f_size;
1252 
1253 	STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1254 
1255 	mp = module;
1256 	for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) {
1257 		chunk = &relocator->rel_chunklist[i++];
1258 		chunk->chunk_vaddr = mfp->f_addr;
1259 
1260 		/*
1261 		 * fix the mb_mod_start and mb_mod_end.
1262 		 */
1263 		mp->mb_mod_start = efi_physaddr(module, tmp, map,
1264 		    map_size / desc_size, desc_size, mfp->f_addr,
1265 		    mp->mb_mod_end);
1266 		if (mp->mb_mod_start == 0)
1267 			panic("Could not find memory for module");
1268 
1269 		mp->mb_mod_end += mp->mb_mod_start;
1270 		chunk->chunk_paddr = mp->mb_mod_start;
1271 		chunk->chunk_size = mfp->f_size;
1272 		STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1273 
1274 		mp = (multiboot_tag_module_t *)
1275 		    roundup2((uintptr_t)mp + mp->mb_size,
1276 		    MULTIBOOT_TAG_ALIGN);
1277 	}
1278 	chunk = &relocator->rel_chunklist[i++];
1279 	chunk->chunk_vaddr = (EFI_VIRTUAL_ADDRESS)(uintptr_t)mbi;
1280 	chunk->chunk_paddr = efi_physaddr(module, tmp, map,
1281 	    map_size / desc_size, desc_size, (uintptr_t)mbi,
1282 	    mbi->mbi_total_size);
1283 	chunk->chunk_size = mbi->mbi_total_size;
1284 	STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1285 
1286 	trampoline = (void *)(uintptr_t)relocator + EFI_PAGE_SIZE;
1287 	memmove(trampoline, multiboot_tramp, EFI_PAGE_SIZE);
1288 
1289 	relocator->rel_copy = (uintptr_t)trampoline + EFI_PAGE_SIZE;
1290 	memmove((void *)relocator->rel_copy, efi_copy_finish, EFI_PAGE_SIZE);
1291 
1292 	relocator->rel_memmove = (uintptr_t)relocator->rel_copy + EFI_PAGE_SIZE;
1293 	memmove((void *)relocator->rel_memmove, memmove, EFI_PAGE_SIZE);
1294 	relocator->rel_stack = relocator->rel_memmove + EFI_PAGE_SIZE - 8;
1295 
1296 	trampoline(MULTIBOOT2_BOOTLOADER_MAGIC, relocator, entry_addr);
1297 #else
1298 	dev_cleanup();
1299 	__exec((void *)VTOP(multiboot_tramp), MULTIBOOT2_BOOTLOADER_MAGIC,
1300 	    (void *)entry_addr, (void *)VTOP(mbi));
1301 #endif /* EFI */
1302 	panic("exec returned");
1303 
1304 error:
1305 	free(cmdline);
1306 
1307 #if defined(EFI)
1308 	free(relocator);
1309 
1310 	if (mbi != NULL)
1311 		efi_free_loadaddr((vm_offset_t)mbi, EFI_SIZE_TO_PAGES(size));
1312 #endif
1313 
1314 	return (error);
1315 }
1316