From 7e934d3acc051b7ee3ef0d11571fd1225800a607 Mon Sep 17 00:00:00 2001 From: Andy Fiddaman Date: Sun, 11 Feb 2018 14:39:52 +0000 Subject: [PATCH] 9067 Support PMBR customisation with EFI label 9116 fdisk limits heads to 254 (mostly) Reviewed by: Toomas Soome Reviewed by: Jorge Schrauwen Reviewed by: Dominik Hassler Approved by: Robert Mustacchi --- exception_lists/copyright | 3 + usr/src/cmd/fdisk/fdisk.c | 128 ++++++++++++++------- usr/src/data/hwdata/Makefile | 12 +- .../data/hwdata/THIRDPARTYLICENSE.efifixes.descrip | 1 + .../data/hwdata/THIRDPARTYLICENSE.efifixes.tmpl | 30 +++++ usr/src/data/hwdata/efi.fixes | 72 ++++++++++++ usr/src/lib/libefi/Makefile.com | 5 +- usr/src/lib/libefi/common/rdwr_efi.c | 112 +++++++++++++++++- usr/src/man/man1m/fdisk.1m | 46 ++++++-- usr/src/man/man3ext/efi_alloc_and_init.3ext | 20 +++- .../pkg/manifests/system-data-hardware-registry.mf | 4 + 11 files changed, 369 insertions(+), 64 deletions(-) create mode 100644 usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.descrip create mode 100644 usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.tmpl create mode 100644 usr/src/data/hwdata/efi.fixes diff --git a/exception_lists/copyright b/exception_lists/copyright index f4888837fa..9c0ad7bbae 100644 --- a/exception_lists/copyright +++ b/exception_lists/copyright @@ -23,6 +23,7 @@ # Copyright 2015 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011 by Delphix. All rights reserved. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # syntax: glob @@ -99,6 +100,8 @@ usr/src/common/bzip2/decompress.c usr/src/common/bzip2/bzlib_private.h usr/src/common/bzip2/huffman.c usr/src/common/ficl/* +usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.descrip +usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.tmpl usr/src/grub/grub-0.97/stage2/Makefile.am usr/src/grub/grub-0.97/stage2/builtins.c usr/src/grub/grub-0.97/stage2/disk_io.c diff --git a/usr/src/cmd/fdisk/fdisk.c b/usr/src/cmd/fdisk/fdisk.c index efd7313e7c..466a608bc2 100644 --- a/usr/src/cmd/fdisk/fdisk.c +++ b/usr/src/cmd/fdisk/fdisk.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ @@ -87,20 +88,6 @@ #define DEFAULT_PATH "/dev/rdsk/" -/* XXX - should be in fdisk.h, used by sd as well */ - -/* - * the MAX values are the maximum usable values for BIOS chs values - * The MAX_CYL value of 1022 is the maximum usable value - * the value of 1023 is a fence value, - * indicating no CHS geometry exists for the corresponding LBA value. - * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1) - * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT) - */ -#define MAX_SECT (63) -#define MAX_CYL (1022) -#define MAX_HEAD (254) - #define DK_MAX_2TB UINT32_MAX /* Max # of sectors in 2TB */ /* for clear_vtoc() */ @@ -159,9 +146,10 @@ static char Usage[] = "Usage: fdisk\n" "[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n" "[ -b masterboot ]\n" "[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n" +"[ -E [slot:active] ]\n" "[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n" "[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n" -"[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice"; +"[ -w | r | d | n | I | B | g | G | R | t | T ] rdevice"; static char Usage1[] = " Partition options:\n" " -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n" @@ -180,9 +168,10 @@ static char Usage1[] = " Partition options:\n" " -b master_boot\n" " Use master_boot as the master boot file.\n" " -B Create one Solaris partition that uses the entire disk.\n" -" -E Create one EFI partition that uses the entire disk.\n" " -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n" " Delete a partition. See attribute definitions for -A.\n" +" -E [slot:active]\n" +" Create an EFI partition that uses the entire disk.\n" " -F fdisk_file\n" " Use fdisk_file to initialize on-line fdisk table.\n" " -I Forego device checks. Generate a file image of what would go\n" @@ -303,6 +292,8 @@ static struct mboot BootCod; /* buffer for master boot record */ static int io_wholedisk = 0; /* use whole disk for Solaris (-B) */ static int io_EFIdisk = 0; /* use whole disk for EFI (-E) */ +static int io_EFIslot = 0; /* slot in which to place EFI entry */ +static int io_EFIactive = 0; /* mark EFI entry as active */ static int io_debug = 0; /* activate verbose mode (-d) */ static int io_image = 0; /* create image using geometry (-I) */ @@ -687,6 +678,7 @@ static void clear_vtoc(int table, int part); static int lecture_and_query(char *warning, char *devname); static void sanity_check_provided_device(char *devname, int fd); static char *get_node(char *devname); +static int efi_create(void); #ifdef i386 static void id_to_name(uchar_t sysid, char *buffer); @@ -714,7 +706,7 @@ static void ext_print_logdrive_layout_debug(); * This function is called only during the non-interactive mode. * It is touchy and does not tolerate any errors. If there are * mounted logical drives, changes to the partition table - * is disallowed. + * are disallowed. */ static void update_disk_and_exit(boolean_t table_changed) @@ -778,7 +770,7 @@ main(int argc, char *argv[]) setbuf(stdout, 0); /* Process the options. */ - while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE")) + while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE:")) != EOF) { switch (c) { @@ -816,7 +808,7 @@ main(int argc, char *argv[]) continue; case 'T': io_ADJT++; - /* FALLTHRU */ + /* FALLTHROUGH */ case 't': io_adjt++; continue; @@ -825,6 +817,11 @@ main(int argc, char *argv[]) io_fdisk++; continue; case 'E': + if (sscanf(optarg, "%d:%d", + &io_EFIslot, &io_EFIactive) != 2) { + io_EFIslot = io_EFIactive = 0; + optind--; + } io_EFIdisk++; io_fdisk++; continue; @@ -871,7 +868,7 @@ main(int argc, char *argv[]) (void) fprintf(stderr, "%s\n", Usage); (void) fprintf(stderr, "%s\n", Usage1); exit(0); - /* FALLTHRU */ + /* FALLTHROUGH */ case 'v': v_flag = 1; continue; @@ -905,7 +902,6 @@ main(int argc, char *argv[]) exit(2); } - /* Figure out the correct device node to open */ Dfltdev = get_node(argv[optind]); @@ -1012,7 +1008,7 @@ main(int argc, char *argv[]) disk_geom.dkg_nhead == 0 || disk_geom.dkg_nsect == 0 || disk_geom.dkg_ncyl > MAX_CYL || - disk_geom.dkg_nhead > MAX_HEAD || + disk_geom.dkg_nhead > MAX_HEAD + 1 || disk_geom.dkg_nsect > MAX_SECT) { /* @@ -1150,7 +1146,6 @@ main(int argc, char *argv[]) fill_patt(); /* will not return */ } - /* This is the fdisk edit, the real reason for the program. */ sanity_check_provided_device(Dfltdev, Dev); @@ -1268,17 +1263,14 @@ main(int argc, char *argv[]) Set_Table_CHS_Values(0); update_disk_and_exit(B_TRUE); } else if (io_EFIdisk) { - /* create an EFI partition for the whole disk */ - nulltbl(); - i = insert_tbl(EFI_PMBR, 0, 0, 0, 0, 0, 0, 0, 1, - (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB : - (dev_capacity - 1), 0); - if (i != 0) { + if (efi_create() == 0) { (void) fprintf(stderr, "Error creating EFI partition\n"); exit(1); } - update_disk_and_exit(B_TRUE); + (void) close(Dev); + exit(0); + /* NOTREACHED */ } } } @@ -1463,7 +1455,6 @@ dev_mboot_write(off_t sect, char *buff, int bootsiz) } } - /* see if the old table had EFI */ for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) { if (Old_Table[old_pt].systid == EFI_PMBR) { @@ -1481,8 +1472,14 @@ dev_mboot_write(off_t sect, char *buff, int bootsiz) (Old_Table[old_pt].relsect == Table[new_pt].relsect) && (Old_Table[old_pt].numsect == - Table[new_pt].numsect)) + Table[new_pt].numsect)) { + /* + * New EFI guard partition matches old. + * Do not clear EFI labels in this case. + */ + clr_efi = -1; break; + } } /* @@ -2079,7 +2076,7 @@ load(int funct, char *file) " \"%s\"\n", file); exit(1); - /* FALLTHRU */ + /* FALLTHROUGH */ case LOADADD: @@ -2251,7 +2248,7 @@ Set_Table_CHS_Values(int ti) * so store the maximum CHS field values in the CHS fields. */ cy = MAX_CYL + 1; - hd = MAX_HEAD; + hd = MAX_HEAD + 1; sc = MAX_SECT; } else { cy = lba / hba_sectors / hba_heads; @@ -2269,7 +2266,7 @@ Set_Table_CHS_Values(int ti) lba = (uint32_t)(Table[ti].relsect + Table[ti].numsect - 1); if (lba >= hba_heads * hba_sectors * MAX_CYL) { cy = MAX_CYL + 1; - hd = MAX_HEAD; + hd = MAX_HEAD + 1; sc = MAX_SECT; } else { cy = lba / hba_sectors / hba_heads; @@ -2315,7 +2312,6 @@ insert_tbl( return (-1); } - Table[i].systid = (uchar_t)id; Table[i].bootid = (uchar_t)act; Table[i].numsect = LE_32(numsect); @@ -2324,18 +2320,30 @@ insert_tbl( if (id == UNUSED) { (void) memset(&Table[i], 0, sizeof (struct ipart)); } else if (0 < bsect && bsect <= MAX_SECT && - 0 <= bhead && bhead <= MAX_HEAD && + 0 <= bhead && bhead <= MAX_HEAD + 1 && 0 < esect && esect <= MAX_SECT && - 0 <= ehead && ehead <= MAX_HEAD) { + 0 <= ehead && ehead <= MAX_HEAD + 1) { /* * If we have been called with a valid geometry, use it * valid means non-zero values that fit in the BIOS fields */ - if (bcyl > MAX_CYL) + if (bcyl > MAX_CYL) { + /* + * bcyl is set to the special fence value indicating + * that the geometry is not representable for the + * start LBA. + * Set all fields to the maximum values. + */ bcyl = MAX_CYL + 1; - if (ecyl > MAX_CYL) + bhead = MAX_HEAD + 1; + bsect = MAX_SECT; + } + if (ecyl > MAX_CYL) { ecyl = MAX_CYL + 1; + ehead = MAX_HEAD + 1; + esect = MAX_SECT; + } Table[i].begcyl = bcyl & 0xff; Table[i].endcyl = ecyl & 0xff; Table[i].beghead = (uchar_t)bhead; @@ -2764,7 +2772,7 @@ stage0(void) } (void) close(Dev); exit(0); - /* FALLTHRU */ + /* FALLTHROUGH */ #endif #ifdef i386 case '7': @@ -2780,7 +2788,7 @@ stage0(void) } (void) close(Dev); exit(0); - /* FALLTHRU */ + /* FALLTHROUGH */ default: break; } @@ -5625,3 +5633,39 @@ nopartdefined() return (0); return (1); } + +/* create an EFI partition for the whole disk */ +static int +efi_create() +{ + if (io_EFIslot < 0 || io_EFIslot > 3) { + (void) fprintf(stderr, + "EFI partition slot must be between 0 and 3 inclusive.\n"); + return (0); + } + if (io_EFIactive != 0 && io_EFIactive != 1) { + (void) fprintf(stderr, + "EFI partition active flag must be 0 or 1.\n"); + return (0); + } + + nulltbl(); + /* + * In the following call, start and end cylinder values are set to one + * above the maximum number of cylinders. This is a special fence + * value which indicates that the geometry for the corresponding LBA + * is not representable. This results in a protective MBR which + * is the same as that created by libefi. + */ + if (insert_tbl(EFI_PMBR, + io_EFIactive ? ACTIVE : NOTACTIVE, + MAX_HEAD + 1, MAX_SECT, MAX_CYL + 1, + MAX_HEAD + 1, MAX_SECT, MAX_CYL + 1, + 1, + (dev_capacity > DK_MAX_2TB) ? DK_MAX_2TB : (dev_capacity - 1), + io_EFIslot) != io_EFIslot) + return (0); + copy_Table_to_Bootblk(); + dev_mboot_write(0, Bootsect, sectsiz); + return (1); +} diff --git a/usr/src/data/hwdata/Makefile b/usr/src/data/hwdata/Makefile index 881c051214..13c724f2a2 100644 --- a/usr/src/data/hwdata/Makefile +++ b/usr/src/data/hwdata/Makefile @@ -22,25 +22,31 @@ # # Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # include $(SRC)/data/Makefile.data -HWDATA= pci.ids usb.ids +HWDATA= pci.ids usb.ids efi.fixes HWDATADIR= $(ROOT)/usr/share/hwdata ROOTHWDATA= $(HWDATA:%=$(HWDATADIR)/%) -CLOBBERFILES= THIRDPARTYLICENSE.pciids +CLOBBERFILES= THIRDPARTYLICENSE.pciids THIRDPARTYLICENSE.efifixes $(ROOTHWDATA):= FILEMODE = 444 -all install: THIRDPARTYLICENSE.pciids +all install: THIRDPARTYLICENSE.pciids THIRDPARTYLICENSE.efifixes THIRDPARTYLICENSE.pciids: pci.ids THIRDPARTYLICENSE.pciids.tmpl $(RM) $@ $(SED) -e '/^$$/,$$ d' < pci.ids > $@ $(CAT) THIRDPARTYLICENSE.pciids.tmpl >> $@ +THIRDPARTYLICENSE.efifixes: efi.fixes THIRDPARTYLICENSE.efifixes.tmpl + $(RM) $@ + $(SED) -e '/^$$/,$$ d' < efi.fixes > $@ + $(CAT) THIRDPARTYLICENSE.efifixes.tmpl >> $@ + install: $(ROOTHWDATA) $(HWDATADIR)/%: % diff --git a/usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.descrip b/usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.descrip new file mode 100644 index 0000000000..cb9ab21a43 --- /dev/null +++ b/usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.descrip @@ -0,0 +1 @@ +EFIFIXES diff --git a/usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.tmpl b/usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.tmpl new file mode 100644 index 0000000000..fd6569e9bb --- /dev/null +++ b/usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes.tmpl @@ -0,0 +1,30 @@ + +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) [year] [your name] + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * [id for your version control system, if any] + */ diff --git a/usr/src/data/hwdata/efi.fixes b/usr/src/data/hwdata/efi.fixes new file mode 100644 index 0000000000..1f1c4dca2f --- /dev/null +++ b/usr/src/data/hwdata/efi.fixes @@ -0,0 +1,72 @@ +# This file contains definitions of systems which are known to have problems +# booting from an EFI/GPT partitioned disk, and the workaround. It is used +# by libefi to change the way in which the protective master-boot-record (PMBR) +# is written to the disk when the EFI label changes. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +# Copyright (c) 2016 Allan Jude +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. + +# Each line consists of a number of whitespace delimited name=value pairs +# which define conditions for the host system which are matched against values +# in SMBIOS tables. These are followed by actions to take if the host system +# matches; more than one action can be specified. +# +# Conditions: +# From the SMB_TYPE_SYSTEM table (`smbios -t SMB_TYPE_SYSTEM`) +# sys.manufacturer +# sys.product +# sys.version +# From the SMB_TYPE_BASEBOARD table (`smbios -t SMB_TYPE_BASEBOARD`) +# mb.manufacturer +# mb.product +# mb.version +# +# Actions: +# pmbr_slot=n 0 <= n <= 3 (default 0) +# Place the EFI partition entry into slot n in the PMBR +# pmbr_active=n 0 <= n <= 1 (default 0) +# Mark the EFI partition as active within the PMBR + +# References: +# https://lists.freebsd.org/pipermail/freebsd-i386/2013-March/010437.html +# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=194359 + +sys.manufacturer="Lenovo" sys.version="ThinkPad X220" pmbr_slot=1 +sys.manufacturer="Lenovo" sys.version="ThinkPad T420" pmbr_slot=1 +sys.manufacturer="Lenovo" sys.version="ThinkPad T520" pmbr_slot=1 +sys.manufacturer="Lenovo" sys.version="ThinkPad W520" pmbr_slot=1 +sys.manufacturer="Lenovo" sys.version="ThinkPad X1" pmbr_slot=1 + +sys.manufacturer="Dell Inc." sys.product="Latitude E6330" pmbr_active=1 +sys.manufacturer="Dell Inc." sys.product="Latitude E7440" pmbr_active=1 +sys.manufacturer="Dell Inc." sys.product="Latitude E7240" pmbr_active=1 +sys.manufacturer="Dell Inc." sys.product="Precision Tower 5810" pmbr_active=1 + +sys.manufacturer="Hewlett-Packard" sys.product="HP ProBook 4330s" pmbr_active=1 + +mb.manufacturer="Intel Corporation" mb.product="DP965LT" pmbr_active=1 +mb.manufacturer="Intel Corporation" mb.product="D510MO" pmbr_active=1 + +mb.manufacturer="Acer" mb.product="Veriton M6630G" pmbr_active=1 + diff --git a/usr/src/lib/libefi/Makefile.com b/usr/src/lib/libefi/Makefile.com index 4b8c5d1277..3fc915acdd 100644 --- a/usr/src/lib/libefi/Makefile.com +++ b/usr/src/lib/libefi/Makefile.com @@ -20,10 +20,9 @@ # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# LIBRARY = libefi.a VERS = .1 @@ -37,7 +36,7 @@ include ../../Makefile.rootfs SRCDIR = ../common LIBS = $(DYNLIB) $(LINTLIB) -LDLIBS += -luuid -lc +LDLIBS += -luuid -lsmbios -lc $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CFLAGS += $(CCVERBOSE) diff --git a/usr/src/lib/libefi/common/rdwr_efi.c b/usr/src/lib/libefi/common/rdwr_efi.c index 60eeb1c422..e40f4f9b38 100644 --- a/usr/src/lib/libefi/common/rdwr_efi.c +++ b/usr/src/lib/libefi/common/rdwr_efi.c @@ -23,6 +23,7 @@ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright 2014 Toomas Soome + * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +117,8 @@ int efi_debug = 1; int efi_debug = 0; #endif +#define EFI_FIXES_DB "/usr/share/hwdata/efi.fixes" + extern unsigned int efi_crc32(const unsigned char *, unsigned int); static int efi_read(int, struct dk_gpt *); @@ -555,6 +559,104 @@ efi_read(int fd, struct dk_gpt *vtoc) return (dki_info.dki_partition); } +static void +hardware_workarounds(int *slot, int *active) +{ + smbios_struct_t s_sys, s_mb; + smbios_info_t sys, mb; + smbios_hdl_t *shp; + char buf[0x400]; + FILE *fp; + int err; + + if ((fp = fopen(EFI_FIXES_DB, "rF")) == NULL) + return; + + if ((shp = smbios_open(NULL, SMB_VERSION, 0, &err)) == NULL) { + if (efi_debug) + (void) fprintf(stderr, + "libefi failed to load SMBIOS: %s\n", + smbios_errmsg(err)); + (void) fclose(fp); + return; + } + + if (smbios_lookup_type(shp, SMB_TYPE_SYSTEM, &s_sys) == SMB_ERR || + smbios_info_common(shp, s_sys.smbstr_id, &sys) == SMB_ERR) + (void) memset(&sys, '\0', sizeof (sys)); + if (smbios_lookup_type(shp, SMB_TYPE_BASEBOARD, &s_mb) == SMB_ERR || + smbios_info_common(shp, s_mb.smbstr_id, &mb) == SMB_ERR) + (void) memset(&mb, '\0', sizeof (mb)); + + while (fgets(buf, sizeof (buf), fp) != NULL) { + char *tok, *val, *end; + + tok = buf + strspn(buf, " \t"); + if (*tok == '#') + continue; + while (*tok != '\0') { + tok += strspn(tok, " \t"); + if ((val = strchr(tok, '=')) == NULL) + break; + *val++ = '\0'; + if (*val == '"') + end = strchr(++val, '"'); + else + end = strpbrk(val, " \t\n"); + if (end == NULL) + break; + *end++ = '\0'; + + if (strcmp(tok, "sys.manufacturer") == 0 && + (sys.smbi_manufacturer == NULL || + strcasecmp(val, sys.smbi_manufacturer))) + break; + if (strcmp(tok, "sys.product") == 0 && + (sys.smbi_product == NULL || + strcasecmp(val, sys.smbi_product))) + break; + if (strcmp(tok, "sys.version") == 0 && + (sys.smbi_version == NULL || + strcasecmp(val, sys.smbi_version))) + break; + if (strcmp(tok, "mb.manufacturer") == 0 && + (mb.smbi_manufacturer == NULL || + strcasecmp(val, mb.smbi_manufacturer))) + break; + if (strcmp(tok, "mb.product") == 0 && + (mb.smbi_product == NULL || + strcasecmp(val, mb.smbi_product))) + break; + if (strcmp(tok, "mb.version") == 0 && + (mb.smbi_version == NULL || + strcasecmp(val, mb.smbi_version))) + break; + + if (strcmp(tok, "pmbr_slot") == 0) { + *slot = atoi(val); + if (*slot < 0 || *slot > 3) + *slot = 0; + if (efi_debug) + (void) fprintf(stderr, + "Using slot %d\n", *slot); + } + + if (strcmp(tok, "pmbr_active") == 0) { + *active = atoi(val); + if (*active < 0 || *active > 1) + *active = 0; + if (efi_debug) + (void) fprintf(stderr, + "Using active %d\n", *active); + } + + tok = end; + } + } + (void) fclose(fp); + smbios_close(shp); +} + /* writes a "protective" MBR */ static int write_pmbr(int fd, struct dk_gpt *vtoc) @@ -564,7 +666,11 @@ write_pmbr(int fd, struct dk_gpt *vtoc) uchar_t *cp; diskaddr_t size_in_lba; uchar_t *buf; - int len; + int len, slot, active; + + slot = active = 0; + + hardware_workarounds(&slot, &active); len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize; buf = calloc(len, 1); @@ -590,9 +696,9 @@ write_pmbr(int fd, struct dk_gpt *vtoc) } bzero(&mb.parts, sizeof (mb.parts)); - cp = (uchar_t *)&mb.parts[0]; + cp = (uchar_t *)&mb.parts[slot * sizeof (struct ipart)]; /* bootable or not */ - *cp++ = 0; + *cp++ = active ? ACTIVE : NOTACTIVE; /* beginning CHS; 0xffffff if not representable */ *cp++ = 0xff; *cp++ = 0xff; diff --git a/usr/src/man/man1m/fdisk.1m b/usr/src/man/man1m/fdisk.1m index a07d94b8cb..db5a8b5536 100644 --- a/usr/src/man/man1m/fdisk.1m +++ b/usr/src/man/man1m/fdisk.1m @@ -1,26 +1,28 @@ '\" te .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved +.\" Copyright 2018 OmniOS Community Edition (OmniOSce) Association. .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. .\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with .\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH FDISK 1M "Sep 10, 2013" +.TH FDISK 1M "Feb 11, 2018" .SH NAME fdisk \- create or modify fixed disk partition table .SH SYNOPSIS .LP .nf \fBfdisk\fR [\fB-o\fR \fIoffset\fR] [\fB-s\fR \fIsize\fR] [\fB-P\fR \fIfill_patt\fR] [\fB-S\fR \fIgeom_file\fR] - [\fB-w\fR | \fB-r\fR | \fB-d\fR | \fB-n\fR | \fB-I\fR | \fB-B\fR | \fB-t\fR | \fB-T\fR | \fB-g\fR | \fB-G\fR | \fB-R\fR | \fB-E\fR] + [\fB-w\fR | \fB-r\fR | \fB-d\fR | \fB-n\fR | \fB-I\fR | \fB-B\fR | \fB-t\fR | \fB-T\fR | \fB-g\fR | \fB-G\fR | \fB-R\fR] [-\fB-F\fR \fIfdisk_file\fR] [ [\fB-v\fR] \fB-W\fR {\fIfdisk_file\fR | \(mi}] [\fB-h\fR] [\fB-b\fR \fImasterboot\fR] [\fB-A\fR \fIid\fR : \fIact\fR : \fIbhead\fR : \fIbsect\fR : \fIbcyl\fR : \fIehead\fR : \fIesect\fR : \fIecyl\fR : \fIrsect\fR : \fInumsect\fR] [\fB-D\fR \fIid\fR : \fIact\fR : \fIbhead:\fR \fIbsect\fR : \fIbcyl\fR : \fIehead:\fR \fIesect\fR : \fIecyl\fR : \fIrsect\fR : \fInumsect\fR] \fIrdevice\fR + [\fB-E\fR [\fIslot\fR : \fIactive\fR]] + \fIrdevice\fR .fi .SH DESCRIPTION -.sp .LP This command is used to do the following: .RS +4 @@ -97,7 +99,6 @@ partition table, but the allocated disk space is not initialized. partition, and \fBformat\fR(1M) is required to write the VTOC or EFI/GPT metadata. .SS "Menu Options" -.sp .LP The menu options for interactive mode given by the \fBfdisk\fR program are: .sp @@ -270,7 +271,6 @@ This option exits without modifying the partition table. .RE .SH OPTIONS -.sp .LP The following options apply to \fBfdisk\fR: .sp @@ -336,11 +336,41 @@ Solaris partition if the \fBfdisk\fR table changes. .sp .ne 2 .na -\fB\fB-E\fR\fR +\fB-E\fR [\fIslot\fR:\fIactive\fR] .ad .sp .6 .RS 4n Create an \fBEFI\fR partition that uses the entire disk. +.sp +By default this partition entry will be placed into the first slot within the +partition table and will not be marked active. The remaining slots within the +table will be zeroed out. +.sp +Some broken firmware implementations have issues booting in CSM/Legacy/BIOS +mode from EFI partitions that are not set active. Others have issues with +booting from EFI partitions without UEFI if the protective partition table +entry is in the first slot. To work around these problems, the \fB-E\fR +option takes an optional argument which can be used to override the defaults +described above. + +.sp +.ne 2 +.na +\fB\fIslot\fR\fR +.ad +.RS 11n +Specify the MBR slot into which the EFI partition should be placed. This accepts a value in the range 0 to 3 with the default being 0. +.RE + +.sp +.ne 2 +.na +\fB\fIactive\fR\fR +.ad +.RS 11n +Specify whether the EFI partition entry should be marked active; \fB0\fR specifies not active (the default) and \fB1\fR means active. +.RE + .RE .sp @@ -737,7 +767,6 @@ with the \fB-F\fR option below. .RE .SH FILES -.sp .ne 2 .na \fB\fB/dev/rdsk/c0t0d0p0\fR\fR @@ -756,7 +785,6 @@ Default master boot program. .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -772,12 +800,10 @@ Architecture x86 and SPARC .TE .SH SEE ALSO -.sp .LP \fBuname\fR(1), \fBfmthard\fR(1M), \fBformat\fR(1M), \fBnewfs\fR(1M), \fBprtvtoc\fR(1M), \fBattributes\fR(5) .SH DIAGNOSTICS -.sp .LP Most messages will be self-explanatory. The following may appear immediately after starting the program: diff --git a/usr/src/man/man3ext/efi_alloc_and_init.3ext b/usr/src/man/man3ext/efi_alloc_and_init.3ext index ad82078869..2f201b5846 100644 --- a/usr/src/man/man3ext/efi_alloc_and_init.3ext +++ b/usr/src/man/man3ext/efi_alloc_and_init.3ext @@ -1,9 +1,10 @@ '\" te .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved. +.\" Copyright 2018 OmniOS Community Edition (OmniOSce) Association. .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH EFI_ALLOC_AND_INIT 3EXT "April 9, 2016" +.TH EFI_ALLOC_AND_INIT 3EXT "February 6, 2018" .SH NAME efi_alloc_and_init, efi_alloc_and_read, efi_free, efi_write, efi_use_whole_disk \- manipulate a disk's EFI Partition Table @@ -55,7 +56,8 @@ The \fBefi_free()\fR function frees the memory allocated by \fBefi_alloc_and_init()\fR and \fBefi_alloc_and_read()\fR. .sp .LP -The \fBefi_write()\fR function writes the EFI partition table. +The \fBefi_write()\fR function writes the EFI partition table and creates a +Protective Master Boot Record (PMBR); see below. .sp .LP The \fBefi_use_whole_disk()\fR function takes any space that is not contained @@ -76,7 +78,7 @@ partition table and contains at least the following members: .in +2 .nf uint_t efi_version; /* set to EFI_VERSION_CURRENT */ -uint_t efi_nparts; /* number of partitions in efi_parts */ +uint_t efi_nparts; /* no. of partitions in efi_parts */ uint_t efi_lbasize; /* size of block in bytes */ diskaddr_t efi_last_lba; /* last block on the disk */ diskaddr_t efi_first_u_lba; /* first block after labels */ @@ -85,6 +87,18 @@ struct dk_part efi_parts[]; /* array of partitions */ .fi .in -2 +.SS "Protective Master Boot Record" +.LP +When a disk receives an EFI label, a protective MBR (\fBPMBR\fR) is also +written containing a single partiton of type \fBEEh\fR and spanning the +entire disk (up to the limit of what can be represented in an MBR). By +default that partition is placed in slot 0 of the PMBR and not marked as +active. Some BIOS implementations contain bugs that require the entry to be +placed into a different slot or to be made active in order for the system +to boot successfully. The default behaviour is modified for systems with known +firmware bugs, refer to \fB/usr/share/hwdata/efi.fixes\fR for more +information. + .SH RETURN VALUES .LP Upon successful completion, \fBefi_alloc_and_init()\fR returns 0. Otherwise it diff --git a/usr/src/pkg/manifests/system-data-hardware-registry.mf b/usr/src/pkg/manifests/system-data-hardware-registry.mf index f57f6dd80a..66c1791c7d 100644 --- a/usr/src/pkg/manifests/system-data-hardware-registry.mf +++ b/usr/src/pkg/manifests/system-data-hardware-registry.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # set name=pkg.fmri value=pkg:/system/data/hardware-registry@$(PKGVERS) @@ -33,10 +34,13 @@ set name=variant.arch value=$(ARCH) dir path=usr group=sys dir path=usr/share dir path=usr/share/hwdata group=sys +file path=usr/share/hwdata/efi.fixes preserve=renamenew file path=usr/share/hwdata/pci.ids file path=usr/share/hwdata/usb.ids legacy pkg=SUNWhwdata \ desc="ASCII databases describing various PCI, USB and other hardware" \ name="Hardware data files" +license usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes \ + license=usr/src/data/hwdata/THIRDPARTYLICENSE.efifixes license usr/src/data/hwdata/THIRDPARTYLICENSE.pciids \ license=usr/src/data/hwdata/THIRDPARTYLICENSE.pciids -- 2.11.4.GIT