summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
authorHans Rosenfeld <hans.rosenfeld@nexenta.com>2015-01-10 21:16:37 +0100
committerGordon Ross <gwr@nexenta.com>2015-02-20 18:00:32 -0500
commit1a902ef8628b0dffd6df5442354ab59bb8530962 (patch)
treea8f20055af62687834f7818a81d4ebbdf6eb881d /usr/src/cmd
parent44bc9120699af80bb18366ca474cb2c618608ca9 (diff)
downloadillumos-gate-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')
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm.c34
-rw-r--r--usr/src/cmd/boot/installgrub/Makefile3
-rw-r--r--usr/src/cmd/boot/installgrub/installgrub.c74
-rw-r--r--usr/src/cmd/boot/installgrub/installgrub.h9
4 files changed, 94 insertions, 26 deletions
diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c
index c9466725f5..454b266d45 100644
--- a/usr/src/cmd/boot/bootadm/bootadm.c
+++ b/usr/src/cmd/boot/bootadm/bootadm.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -116,6 +116,9 @@ typedef struct {
#define ENTRY_INIT -1 /* entryNum initial value */
#define ALL_ENTRIES -2 /* selects all boot entries */
+#define PARTNO_NOTFOUND -1 /* Solaris partition not found */
+#define PARTNO_EFI -2 /* EFI partition table found */
+
#define GRUB_DIR "/boot/grub"
#define GRUB_STAGE2 GRUB_DIR "/stage2"
#define GRUB_MENU "/boot/grub/menu.lst"
@@ -4916,14 +4919,14 @@ create_diskmap(char *osroot)
static int
get_partition(char *device)
{
- int i, fd, is_pcfs, partno = -1;
+ int i, fd, is_pcfs, partno = PARTNO_NOTFOUND;
struct mboot *mboot;
char boot_sect[SECTOR_SIZE];
char *wholedisk, *slice;
#ifdef i386
ext_part_t *epp;
uint32_t secnum, numsec;
- int rval, pno, ext_partno = -1;
+ int rval, pno, ext_partno = PARTNO_NOTFOUND;
#endif
/* form whole disk (p0) */
@@ -4979,6 +4982,11 @@ get_partition(char *device)
break;
}
} else { /* look for solaris partition, old and new */
+ if (part->systid == EFI_PMBR) {
+ partno = PARTNO_EFI;
+ break;
+ }
+
#ifdef i386
if ((part->systid == SUNIXOS &&
(fdisk_is_linux_swap(epp, part->relsect,
@@ -4999,7 +5007,7 @@ get_partition(char *device)
}
#ifdef i386
/* If no primary solaris partition, check extended partition */
- if ((partno == -1) && (ext_partno != -1)) {
+ if ((partno == PARTNO_NOTFOUND) && (ext_partno != PARTNO_NOTFOUND)) {
rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
if (rval == FDISK_SUCCESS) {
partno = pno - 1;
@@ -5072,13 +5080,18 @@ get_grubroot(char *osroot, char *osdev, char *menu_root)
}
fdiskpart = get_partition(osdev);
- INJECT_ERROR1("GRUBROOT_FDISK_FAIL", fdiskpart = -1);
- if (fdiskpart == -1) {
+ INJECT_ERROR1("GRUBROOT_FDISK_FAIL", fdiskpart = PARTNO_NOTFOUND);
+ if (fdiskpart == PARTNO_NOTFOUND) {
bam_error(FDISKPART_FAIL, osdev);
return (NULL);
}
grubroot = s_calloc(1, 10);
+ if (fdiskpart == PARTNO_EFI) {
+ fdiskpart = atoi(&slice[1]);
+ slice = NULL;
+ }
+
if (slice) {
(void) snprintf(grubroot, 10, "(hd%s,%d,%c)",
grubhd, fdiskpart, slice[1] + 'a' - '0');
@@ -7103,8 +7116,8 @@ get_grubsign(char *osroot, char *osdev)
bam_print(GRUBSIGN_FOUND_OR_CREATED, sign, osdev);
fdiskpart = get_partition(osdev);
- INJECT_ERROR1("GET_GRUBSIGN_FDISK", fdiskpart = -1);
- if (fdiskpart == -1) {
+ INJECT_ERROR1("GET_GRUBSIGN_FDISK", fdiskpart = PARTNO_NOTFOUND);
+ if (fdiskpart == PARTNO_NOTFOUND) {
bam_error(FDISKPART_FAIL, osdev);
free(sign);
return (NULL);
@@ -7112,6 +7125,11 @@ get_grubsign(char *osroot, char *osdev)
slice = strrchr(osdev, 's');
+ if (fdiskpart == PARTNO_EFI) {
+ fdiskpart = atoi(&slice[1]);
+ slice = NULL;
+ }
+
grubsign = s_calloc(1, MAXNAMELEN + 10);
if (slice) {
(void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d,%c)",
diff --git a/usr/src/cmd/boot/installgrub/Makefile b/usr/src/cmd/boot/installgrub/Makefile
index 4cc69eccd5..aecf0f7096 100644
--- a/usr/src/cmd/boot/installgrub/Makefile
+++ b/usr/src/cmd/boot/installgrub/Makefile
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2015, Nexenta Systems, Inc.
#
PROG= installgrub
@@ -45,7 +46,7 @@ LDLIBS += -lmd5
i386_CFLAGS += -D_LARGEFILE64_SOURCE
i386_CFLAGS += -D_FILE_OFFSET_BITS=64
-LDLIBS += -lfdisk
+LDLIBS += -lfdisk -lefi -lfstyp
LINTFLAGS += \
-erroff=E_BAD_PTR_CAST_ALIGN \
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);
}
diff --git a/usr/src/cmd/boot/installgrub/installgrub.h b/usr/src/cmd/boot/installgrub/installgrub.h
index af6e60b973..037ffad4ce 100644
--- a/usr/src/cmd/boot/installgrub/installgrub.h
+++ b/usr/src/cmd/boot/installgrub/installgrub.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _INSTALLGRUB_H
@@ -68,10 +68,12 @@ typedef struct _ig_data {
enum ig_devtype_t {
IG_DEV_X86BOOTPAR = 1,
- IG_DEV_SOLVTOC
+ IG_DEV_SOLVTOC,
+ IG_DEV_EFI
};
#define is_bootpar(type) (type == IG_DEV_X86BOOTPAR)
+#define is_efi(type) (type == IG_DEV_EFI)
#define STAGE2_MEMADDR (0x8000) /* loading addr of stage2 */
@@ -86,7 +88,8 @@ enum ig_devtype_t {
#define STAGE2_BLOCKLIST (SECTOR_SIZE - 0x8)
#define STAGE2_INSTALLPART (SECTOR_SIZE + 0x8)
#define STAGE2_FORCE_LBA (SECTOR_SIZE + 0x11)
-#define STAGE2_BLKOFF (50) /* offset from start of fdisk part */
+#define STAGE2_BLKOFF(type) \
+ (is_efi(type) ? 1024 : 50) /* offset from start of part */
#ifdef __cplusplus
}