Print this page
10807 loader fails to boot Dell R510 in UEFI mode
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/boot/sys/boot/common/multiboot2.c
          +++ new/usr/src/boot/sys/boot/common/multiboot2.c
↓ open down ↓ 3 lines elided ↑ open up ↑
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2017 Toomas Soome <tsoome@me.com>
       14 + * Copyright 2019, Joyent, Inc.
  14   15   */
  15   16  
  16   17  /*
  17   18   * This module adds support for loading and booting illumos multiboot2
  18   19   * kernel. This code is only built to support the illumos kernel, it does
  19   20   * not support xen.
  20   21   */
  21   22  
  22   23  #include <sys/cdefs.h>
  23   24  #include <sys/stddef.h>
↓ open down ↓ 768 lines elided ↑ open up ↑
 792  793                          size += sizeof (multiboot_tag_new_acpi_t) +
 793  794                              rsdp->Length;
 794  795                  }
 795  796                  size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 796  797          }
 797  798          size += sizeof (multiboot_tag_t);
 798  799  
 799  800          return (size);
 800  801  }
 801  802  
      803 +#if defined(EFI)
      804 +static bool
      805 +overlaps(uintptr_t start1, size_t size1, uintptr_t start2, size_t size2)
      806 +{
      807 +        if (start1 < start2 + size2 &&
      808 +            start1 + size1 >= start2) {
      809 +                printf("overlaps: %zx-%zx, %zx-%zx\n",
      810 +                    start1, start1 + size1, start2, start2 + size2);
      811 +                return (true);
      812 +        }
      813 +
      814 +        return (false);
      815 +}
      816 +#endif
      817 +
 802  818  static int
 803  819  multiboot2_exec(struct preloaded_file *fp)
 804  820  {
      821 +        multiboot2_info_header_t *mbi = NULL;
 805  822          struct preloaded_file *mfp;
 806      -        multiboot2_info_header_t *mbi;
 807  823          char *cmdline = NULL;
 808  824          struct devdesc *rootdev;
 809  825          struct file_metadata *md;
 810  826          int i, error, num;
 811  827          int rootfs = 0;
 812  828          size_t size;
 813  829          struct bios_smap *smap;
 814  830  #if defined(EFI)
 815  831          multiboot_tag_module_t *module, *mp;
      832 +        struct relocator *relocator = NULL;
 816  833          EFI_MEMORY_DESCRIPTOR *map;
 817  834          UINTN map_size, desc_size;
 818      -        struct relocator *relocator;
 819  835          struct chunk_head *head;
 820  836          struct chunk *chunk;
 821  837          vm_offset_t tmp;
 822  838  
 823  839          efi_getdev((void **)(&rootdev), NULL, NULL);
      840 +
      841 +        /*
      842 +         * We need 5 pages for relocation. We'll allocate from the heap: while
      843 +         * it's possible that our heap got placed low down enough to be in the
      844 +         * way of where we're going to relocate our kernel, it's hopefully not
      845 +         * likely.
      846 +         */
      847 +        if ((relocator = malloc(EFI_PAGE_SIZE * 5)) == NULL) {
      848 +                printf("relocator malloc failed!\n");
      849 +                error = ENOMEM;
      850 +                goto error;
      851 +        }
      852 +
      853 +        if (overlaps((uintptr_t)relocator, EFI_PAGE_SIZE * 5,
      854 +            load_addr, fp->f_size)) {
      855 +                printf("relocator pages overlap the kernel!\n");
      856 +                error = EINVAL;
      857 +                goto error;
      858 +        }
      859 +
 824  860  #else
 825  861          i386_getdev((void **)(&rootdev), NULL, NULL);
 826  862  
 827  863          if (have_framebuffer == false) {
 828  864                  /* make sure we have text mode */
 829  865                  bios_set_text_mode(VGA_TEXT_MODE);
 830  866          }
 831  867  #endif
 832  868  
 833      -        mbi = NULL;
 834  869          error = EINVAL;
 835  870          if (rootdev == NULL) {
 836  871                  printf("can't determine root device\n");
 837  872                  goto error;
 838  873          }
 839  874  
 840  875          /*
 841  876           * Set the image command line.
 842  877           */
 843  878          if (fp->f_args == NULL) {
↓ open down ↓ 324 lines elided ↑ open up ↑
1168 1203                      (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1169 1204                      &desc_size, &tag->mb_descr_vers);
1170 1205                  if (EFI_ERROR(status)) {
1171 1206                          error = EINVAL;
1172 1207                          goto error;
1173 1208                  }
1174 1209                  tag->mb_type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
1175 1210                  tag->mb_size = sizeof (*tag) + map_size;
1176 1211                  tag->mb_descr_size = (uint32_t)desc_size;
1177 1212  
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");
     1213 +                map = (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap;
1197 1214  
1198 1215                  if (keep_bs == 0) {
1199 1216                          status = BS->ExitBootServices(IH, key);
1200 1217                          if (EFI_ERROR(status)) {
1201 1218                                  printf("Call to ExitBootServices failed\n");
1202 1219                                  error = EINVAL;
1203 1220                                  goto error;
1204 1221                          }
1205 1222                  }
1206 1223  
↓ open down ↓ 16 lines elided ↑ open up ↑
1223 1240          mbi->mbi_reserved = 0;
1224 1241  
1225 1242  #if defined(EFI)
1226 1243          /*
1227 1244           * At this point we have load_addr pointing to kernel load
1228 1245           * address, module list in MBI having physical addresses,
1229 1246           * module list in fp having logical addresses and tmp pointing to
1230 1247           * physical address for MBI.
1231 1248           * Now we must move all pieces to place and start the kernel.
1232 1249           */
1233      -        relocator = (struct relocator *)(uintptr_t)map->PhysicalStart;
1234 1250          head = &relocator->rel_chunk_head;
1235 1251          STAILQ_INIT(head);
1236 1252  
1237 1253          i = 0;
1238 1254          chunk = &relocator->rel_chunklist[i++];
1239 1255          chunk->chunk_vaddr = fp->f_addr;
1240 1256          chunk->chunk_paddr = load_addr;
1241 1257          chunk->chunk_size = fp->f_size;
1242 1258  
1243 1259          STAILQ_INSERT_TAIL(head, chunk, chunk_next);
↓ open down ↓ 39 lines elided ↑ open up ↑
1283 1299  
1284 1300          trampoline(MULTIBOOT2_BOOTLOADER_MAGIC, relocator, entry_addr);
1285 1301  #else
1286 1302          dev_cleanup();
1287 1303          __exec((void *)VTOP(multiboot_tramp), MULTIBOOT2_BOOTLOADER_MAGIC,
1288 1304              (void *)entry_addr, (void *)VTOP(mbi));
1289 1305  #endif /* EFI */
1290 1306          panic("exec returned");
1291 1307  
1292 1308  error:
1293      -        if (cmdline != NULL)
1294      -                free(cmdline);
     1309 +        free(cmdline);
     1310 +
1295 1311  #if defined(EFI)
     1312 +        free(relocator);
     1313 +
1296 1314          if (mbi != NULL)
1297 1315                  efi_free_loadaddr((vm_offset_t)mbi, EFI_SIZE_TO_PAGES(size));
1298 1316  #endif
     1317 +
1299 1318          return (error);
1300 1319  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX