diff options
author | Hans Rosenfeld <hans.rosenfeld@nexenta.com> | 2015-01-10 21:16:37 +0100 |
---|---|---|
committer | Gordon Ross <gwr@nexenta.com> | 2015-02-20 18:00:32 -0500 |
commit | 1a902ef8628b0dffd6df5442354ab59bb8530962 (patch) | |
tree | a8f20055af62687834f7818a81d4ebbdf6eb881d /usr/src/cmd/boot/installgrub/installgrub.c | |
parent | 44bc9120699af80bb18366ca474cb2c618608ca9 (diff) | |
download | illumos-joyent-1a902ef8628b0dffd6df5442354ab59bb8530962.tar.gz |
5561 support root pools on EFI/GPT partitioned disks
5125 update zpool/libzfs to manage bootable whole disk pools (EFI/GPT labeled disks)
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/cmd/boot/installgrub/installgrub.c')
-rw-r--r-- | usr/src/cmd/boot/installgrub/installgrub.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/usr/src/cmd/boot/installgrub/installgrub.c b/usr/src/cmd/boot/installgrub/installgrub.c index c27dca802b..4d29d0236e 100644 --- a/usr/src/cmd/boot/installgrub/installgrub.c +++ b/usr/src/cmd/boot/installgrub/installgrub.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Milan Jurik. All rights reserved. - * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ #include <stdio.h> @@ -48,6 +48,10 @@ #include <sys/stat.h> #include <sys/multiboot.h> #include <sys/sysmacros.h> +#include <sys/efi_partition.h> + +#include <libnvpair.h> +#include <libfstyp.h> #include "message.h" #include "installgrub.h" @@ -107,7 +111,7 @@ static void usage(char *); static int read_stage1_from_file(char *, ig_data_t *); static int read_stage2_from_file(char *, ig_data_t *); static int read_stage1_from_disk(int, char *); -static int read_stage2_from_disk(int, ig_stage2_t *); +static int read_stage2_from_disk(int, ig_stage2_t *, int); static int prepare_stage1(ig_data_t *); static int prepare_stage2(ig_data_t *, char *); static void prepare_fake_multiboot(ig_stage2_t *); @@ -389,7 +393,7 @@ handle_getinfo(char *progname, char **argv) goto out_dev; } - ret = read_stage2_from_disk(device->part_fd, stage2); + ret = read_stage2_from_disk(device->part_fd, stage2, device->type); if (ret == BC_ERROR) { (void) fprintf(stderr, gettext("Error reading stage2 from " "%s\n"), device_path); @@ -487,7 +491,8 @@ handle_mirror(char *progname, char **argv) goto out_devs; } - ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr); + ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr, + curr_device->type); if (ret == BC_ERROR) { BOOT_DEBUG("Error reading first stage2 blocks from %s\n", curr_device->path); @@ -623,6 +628,10 @@ propagate_bootblock(ig_data_t *source, ig_data_t *target, char *updt_str) static int init_device(ig_device_t *device, char *path) { + struct dk_gpt *vtoc; + fstyp_handle_t fhdl; + const char *fident; + bzero(device, sizeof (*device)); device->part_fd = -1; device->disk_fd = -1; @@ -655,9 +664,25 @@ init_device(ig_device_t *device, char *path) return (BC_ERROR); } + if (efi_alloc_and_read(device->disk_fd, &vtoc) > 0) { + device->type = IG_DEV_EFI; + efi_free(vtoc); + } + if (get_raw_partition_fd(device) != BC_SUCCESS) return (BC_ERROR); + if (fstyp_init(device->part_fd, 0, NULL, &fhdl) != 0) + return (BC_ERROR); + + if (fstyp_ident(fhdl, "zfs", &fident) != 0) { + fstyp_fini(fhdl); + (void) fprintf(stderr, gettext("Booting of EFI labeled disks " + "is only supported with ZFS\n")); + return (BC_ERROR); + } + fstyp_fini(fhdl); + if (get_start_sector(device) != BC_SUCCESS) return (BC_ERROR); @@ -701,6 +726,21 @@ get_start_sector(ig_device_t *device) struct part_info dkpi; struct extpart_info edkpi; + if (is_efi(device->type)) { + struct dk_gpt *vtoc; + + if (efi_alloc_and_read(device->disk_fd, &vtoc) <= 0) + return (BC_ERROR); + + device->start_sector = vtoc->efi_parts[device->slice].p_start; + /* GPT doesn't use traditional slice letters */ + device->slice = 0xff; + device->partition = 0; + + efi_free(vtoc); + goto found_part; + } + mboot = (struct mboot *)device->boot_sector; if (is_bootpar(device->type)) { @@ -959,7 +999,8 @@ write_stage2(ig_data_t *install) * Note that we use stage2->buf rather than stage2->file, because we * may have extended information after the latter. */ - offset = STAGE2_BLKOFF * SECTOR_SIZE; + offset = STAGE2_BLKOFF(device->type) * SECTOR_SIZE; + if (write_out(device->part_fd, stage2->buf, stage2->buf_size, offset) != BC_SUCCESS) { perror("write"); @@ -968,7 +1009,7 @@ write_stage2(ig_data_t *install) /* Simulate the "old" installgrub output. */ (void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition, - (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF, + (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF(device->type), stage2->first_sector); return (BC_SUCCESS); @@ -1162,7 +1203,7 @@ read_stage1_from_disk(int dev_fd, char *stage1_buf) } static int -read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2) +read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2, int type) { uint32_t size; uint32_t buf_size; @@ -1173,7 +1214,7 @@ read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2) assert(dev_fd != -1); if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan), - STAGE2_BLKOFF * SECTOR_SIZE) != BC_SUCCESS) { + STAGE2_BLKOFF(type) * SECTOR_SIZE) != BC_SUCCESS) { perror(gettext("Error reading stage2 sectors")); return (BC_ERROR); } @@ -1209,7 +1250,7 @@ read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2) } stage2->buf_size = buf_size; - if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF * + if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF(type) * SECTOR_SIZE) != BC_SUCCESS) { perror("read"); free(stage2->buf); @@ -1243,7 +1284,8 @@ is_update_necessary(ig_data_t *data, char *updt_str) bzero(&stage2_disk, sizeof (ig_stage2_t)); /* Gather stage2 (if present) from the target device. */ - if (read_stage2_from_disk(dev_fd, &stage2_disk) != BC_SUCCESS) { + if (read_stage2_from_disk(dev_fd, &stage2_disk, device->type) + != BC_SUCCESS) { BOOT_DEBUG("Unable to read stage2 from %s\n", device->path); BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path); return (B_TRUE); @@ -1367,7 +1409,8 @@ prepare_stage2(ig_data_t *install, char *updt_str) } } else { /* Solaris VTOC */ - stage2->first_sector = device->start_sector + STAGE2_BLKOFF; + stage2->first_sector = device->start_sector + + STAGE2_BLKOFF(device->type); BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector); /* * In a solaris partition, stage2 is written to contiguous @@ -1441,15 +1484,18 @@ get_raw_partition_path(ig_device_t *device) } len = strlen(raw); - if (raw[len - 2] != 's' || raw[len - 1] == '2') { + if (!is_efi(device->type) && + (raw[len - 2] != 's' || raw[len - 1] == '2')) { (void) fprintf(stderr, NOT_ROOT_SLICE); free(raw); return (NULL); } device->slice = atoi(&raw[len - 1]); - raw[len - 2] = 's'; - raw[len - 1] = '2'; + if (!is_efi(device->type)) { + raw[len - 2] = 's'; + raw[len - 1] = '2'; + } return (raw); } |