Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/boot/installboot/i386/installboot.c
          +++ new/usr/src/cmd/boot/installboot/i386/installboot.c
↓ open down ↓ 24 lines elided ↑ open up ↑
  25   25   */
  26   26  
  27   27  #include <stdio.h>
  28   28  #include <errno.h>
  29   29  #include <unistd.h>
  30   30  #include <fcntl.h>
  31   31  #include <assert.h>
  32   32  #include <locale.h>
  33   33  #include <strings.h>
  34   34  #include <libfdisk.h>
       35 +#include <libgen.h>
  35   36  
  36   37  #include <sys/dktp/fdisk.h>
  37   38  #include <sys/dkio.h>
  38   39  #include <sys/vtoc.h>
  39   40  #include <sys/multiboot.h>
  40   41  #include <sys/types.h>
  41   42  #include <sys/stat.h>
  42   43  #include <sys/sysmacros.h>
  43   44  #include <sys/efi_partition.h>
  44   45  #include <libfstyp.h>
↓ open down ↓ 41 lines elided ↑ open up ↑
  86   87   * Loader stage2 is created with embedded version, by using fake multiboot (MB)
  87   88   * header within first 32k and EINFO block is at the end of the actual
  88   89   * boot block. MB header load_addr is set to 0 and load_end_addr is set to
  89   90   * actual block end, so the EINFO size is (file size - load_end_addr).
  90   91   * installboot does also store the illumos boot partition LBA to MB space,
  91   92   * starting from bss_end_addr structure member location; stage2 will
  92   93   * detect the partition and file system based on this value.
  93   94   *
  94   95   * Stored location values in MBR/stage2 also mean the bootblocks must be
  95   96   * reinstalled in case the partition content is relocated.
       97 + *
       98 + * EFI boot program installation:
       99 + * EFI boot requires EFI System partition with following directory
      100 + * hierarchy:
      101 + * EFI/VENDOR/file
      102 + * EFI/BOOT/BOOTx64.EFI
      103 + * Where EFI/BOOT is fallback directory. While we have no mechanism to set
      104 + * EFI variable values to define vendor specific boot program location, we
      105 + * will just use EFI/BOOT/BOOTx64.EFI; also this setup is only possible
      106 + * solution for removable media.
      107 + * For now the boot1.efi is used for boot program, boot1.efi is also
      108 + * versioned as is gptzfsboot.
  96  109   */
  97  110  
  98  111  static boolean_t        write_mbr = B_FALSE;
  99  112  static boolean_t        force_mbr = B_FALSE;
 100  113  static boolean_t        force_update = B_FALSE;
 101  114  static boolean_t        do_getinfo = B_FALSE;
 102  115  static boolean_t        do_version = B_FALSE;
 103  116  static boolean_t        do_mirror_bblk = B_FALSE;
 104  117  static boolean_t        strip = B_FALSE;
 105  118  static boolean_t        verbose_dump = B_FALSE;
 106  119  
      120 +#define EFIBOOT64       "bootx64.efi"
      121 +#define EFIBOOT32       "bootia32.efi"
      122 +
 107  123  /* Versioning string, if present. */
 108  124  static char             *update_str;
 109  125  
 110  126  /*
 111  127   * Temporary buffer to store the first 32K of data looking for a multiboot
 112  128   * signature.
 113  129   */
 114  130  char                    mboot_scan[MBOOT_SCAN_SIZE];
 115  131  
 116  132  /* Function prototypes. */
↓ open down ↓ 820 lines elided ↑ open up ↑
 937  953          return (BC_SUCCESS);
 938  954  }
 939  955  
 940  956  static int
 941  957  get_boot_slice(ib_device_t *device, struct dk_gpt *vtoc)
 942  958  {
 943  959          uint_t i;
 944  960          char *path, *ptr;
 945  961  
 946  962          for (i = 0; i < vtoc->efi_nparts; i++) {
 947      -                if (vtoc->efi_parts[i].p_tag == V_BOOT) {
      963 +                if (vtoc->efi_parts[i].p_tag == V_SYSTEM) {
 948  964                          if ((path = strdup(device->target.path)) == NULL) {
 949  965                                  perror(gettext("Memory allocation failure"));
 950  966                                  return (BC_ERROR);
 951  967                          }
 952  968                          ptr = strrchr(path, 's');
 953  969                          ptr++;
 954  970                          *ptr = '\0';
 955  971                          (void) asprintf(&ptr, "%s%d", path, i);
 956  972                          free(path);
 957  973                          if (ptr == NULL) {
 958  974                                  perror(gettext("Memory allocation failure"));
 959  975                                  return (BC_ERROR);
 960  976                          }
      977 +                        device->system.path = ptr;
      978 +                        device->system.fd = open_device(ptr);
      979 +                        device->system.id = i;
      980 +                        device->system.devtype = IG_DEV_EFI;
      981 +                        device->system.fstype = IG_FS_PCFS;
      982 +                        device->system.start = vtoc->efi_parts[i].p_start;
      983 +                        device->system.size = vtoc->efi_parts[i].p_size;
      984 +                        device->system.offset = 0;
      985 +                } else if (vtoc->efi_parts[i].p_tag == V_BOOT) {
      986 +                        if ((path = strdup(device->target.path)) == NULL) {
      987 +                                perror(gettext("Memory allocation failure"));
      988 +                                return (BC_ERROR);
      989 +                        }
      990 +                        ptr = strrchr(path, 's');
      991 +                        ptr++;
      992 +                        *ptr = '\0';
      993 +                        (void) asprintf(&ptr, "%s%d", path, i);
      994 +                        free(path);
      995 +                        if (ptr == NULL) {
      996 +                                perror(gettext("Memory allocation failure"));
      997 +                                return (BC_ERROR);
      998 +                        }
 961  999                          device->stage.path = ptr;
 962 1000                          device->stage.fd = open_device(ptr);
 963 1001                          device->stage.id = i;
 964 1002                          device->stage.devtype = IG_DEV_EFI;
 965 1003                          device->stage.fstype = IG_FS_NONE;
 966 1004                          device->stage.start = vtoc->efi_parts[i].p_start;
 967 1005                          device->stage.size = vtoc->efi_parts[i].p_size;
 968 1006                          device->stage.offset = 1; /* leave sector 0 for VBR */
 969      -                        return (BC_SUCCESS);
 970 1007                  }
 971 1008          }
 972 1009          return (BC_SUCCESS);
 973 1010  }
 974 1011  
 975 1012  static int
 976 1013  init_device(ib_device_t *device, char *path)
 977 1014  {
 978 1015          struct dk_gpt *vtoc;
 979 1016          fstyp_handle_t fhdl;
 980 1017          const char *fident;
 981 1018          char *p;
 982 1019          int pathlen = strlen(path);
 983 1020          int ret;
 984 1021  
 985 1022          bzero(device, sizeof (*device));
 986 1023          device->fd = -1;        /* whole disk fd */
 987 1024          device->stage.fd = -1;  /* bootblock partition fd */
     1025 +        device->system.fd = -1; /* efi system partition fd */
 988 1026          device->target.fd = -1; /* target fs partition fd */
 989 1027  
 990 1028          /* basic check, whole disk is not allowed */
 991 1029          if ((p = strrchr(path, '/')) == NULL)
 992 1030                  p = path;
 993 1031          if ((strrchr(p, 'p') == NULL && strrchr(p, 's') == NULL) ||
 994 1032              (path[pathlen-2] == 'p' && path[pathlen-1] == '0')) {
 995 1033                  (void) fprintf(stderr, gettext("installing loader to "
 996 1034                      "whole disk device is not supported\n"));
 997 1035          }
↓ open down ↓ 137 lines elided ↑ open up ↑
1135 1173          return (get_start_sector(device));
1136 1174  }
1137 1175  
1138 1176  static void
1139 1177  cleanup_device(ib_device_t *device)
1140 1178  {
1141 1179          if (device->path)
1142 1180                  free(device->path);
1143 1181          if (device->stage.path)
1144 1182                  free(device->stage.path);
     1183 +        if (device->system.path)
     1184 +                free(device->system.path);
1145 1185          if (device->target.path)
1146 1186                  free(device->target.path);
1147 1187  
1148 1188          if (device->fd != -1)
1149 1189                  (void) close(device->fd);
1150 1190          if (device->stage.fd != -1)
1151 1191                  (void) close(device->stage.fd);
     1192 +        if (device->system.fd != -1)
     1193 +                (void) close(device->system.fd);
1152 1194          if (device->target.fd != -1)
1153 1195                  (void) close(device->target.fd);
1154 1196          bzero(device, sizeof (*device));
1155 1197  }
1156 1198  
1157 1199  static void
1158 1200  cleanup_bootblock(ib_bootblock_t *bblock)
1159 1201  {
1160 1202          free(bblock->buf);
1161 1203          bzero(bblock, sizeof (ib_bootblock_t));
↓ open down ↓ 83 lines elided ↑ open up ↑
1245 1287   *              BC_NOUPDT  - if no installation was performed because the
1246 1288   *                           version currently installed is more recent than the
1247 1289   *                           supplied one.
1248 1290   *
1249 1291   */
1250 1292  static int
1251 1293  handle_install(char *progname, char **argv)
1252 1294  {
1253 1295          ib_data_t       install_data;
1254 1296          ib_bootblock_t  *bblock = &install_data.bootblock;
     1297 +        ib_bootblock_t  *eblock = &install_data.efiblock;
1255 1298          char            *stage1 = NULL;
1256 1299          char            *bootblock = NULL;
     1300 +        char            *efiboot = NULL;
1257 1301          char            *device_path = NULL;
     1302 +        char            *tmp;
1258 1303          int             ret = BC_ERROR;
1259 1304  
1260 1305          stage1 = strdup(argv[0]);
1261 1306          bootblock = strdup(argv[1]);
1262 1307          device_path = strdup(argv[2]);
1263 1308  
1264 1309          if (!device_path || !bootblock || !stage1) {
1265 1310                  (void) fprintf(stderr, gettext("Missing parameter"));
1266 1311                  usage(progname);
1267 1312                  goto out;
1268 1313          }
1269 1314  
     1315 +        tmp = strdup(argv[1]);
     1316 +        if (tmp == NULL) {
     1317 +                perror(gettext("Memory allocation failure"));
     1318 +                goto out;
     1319 +        }
     1320 +        (void) asprintf(&efiboot, "%s/" EFIBOOT64, dirname(tmp));
     1321 +        free(tmp);
     1322 +        if (efiboot == NULL) {
     1323 +                perror(gettext("Memory allocation failure"));
     1324 +                goto out;
     1325 +        }
     1326 +
1270 1327          BOOT_DEBUG("device path: %s, stage1 path: %s bootblock path: %s\n",
1271 1328              device_path, stage1, bootblock);
1272 1329          bzero(&install_data, sizeof (ib_data_t));
1273 1330  
1274 1331          if (init_device(&install_data.device, device_path) != BC_SUCCESS) {
1275 1332                  (void) fprintf(stderr, gettext("Unable to open device %s\n"),
1276 1333                      device_path);
1277 1334                  goto out;
1278 1335          }
1279 1336  
↓ open down ↓ 1 lines elided ↑ open up ↑
1281 1338                  (void) fprintf(stderr, gettext("Error opening %s\n"), stage1);
1282 1339                  goto out_dev;
1283 1340          }
1284 1341  
1285 1342          if (read_bootblock_from_file(bootblock, bblock) != BC_SUCCESS) {
1286 1343                  (void) fprintf(stderr, gettext("Error reading %s\n"),
1287 1344                      bootblock);
1288 1345                  goto out_dev;
1289 1346          }
1290 1347  
     1348 +        /* only read EFI boot program if there is system partition */
     1349 +        if (install_data.device.system.fd != -1) {
     1350 +                if (read_bootblock_from_file(efiboot, eblock) != BC_SUCCESS) {
     1351 +                        (void) fprintf(stderr, gettext("Error reading %s\n"),
     1352 +                            efiboot);
     1353 +                        goto out_dev;
     1354 +                }
     1355 +        }
     1356 +
1291 1357          /*
1292 1358           * is_update_necessary() will take care of checking if versioning and/or
1293 1359           * forcing the update have been specified. It will also emit a warning
1294 1360           * if a non-versioned update is attempted over a versioned bootblock.
1295 1361           */
1296 1362          if (!is_update_necessary(&install_data, update_str)) {
1297 1363                  (void) fprintf(stderr, gettext("bootblock version installed "
1298 1364                      "on %s is more recent or identical\n"
1299 1365                      "Use -F to override or install without the -u option\n"),
1300 1366                      device_path);
1301 1367                  ret = BC_NOUPDT;
1302 1368                  goto out_dev;
1303 1369          }
1304 1370  
1305 1371          BOOT_DEBUG("Ready to commit to disk\n");
1306 1372          ret = commit_to_disk(&install_data, update_str);
1307 1373  
1308 1374  out_dev:
1309 1375          cleanup_device(&install_data.device);
1310 1376  out:
     1377 +        free(efiboot);
1311 1378          free(stage1);
1312 1379          free(bootblock);
1313 1380          free(device_path);
1314 1381          return (ret);
1315 1382  }
1316 1383  
1317 1384  /*
1318 1385   * Retrieves from a device the extended information (einfo) associated to the
1319 1386   * file or installed stage2.
1320 1387   * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0
↓ open down ↓ 320 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX