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