Print this page
10570 Need workaround to EFI boot on AMI BIOS


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*
  27  * Virtual disk server
  28  */
  29 
  30 
  31 #include <sys/types.h>
  32 #include <sys/conf.h>
  33 #include <sys/crc32.h>
  34 #include <sys/ddi.h>
  35 #include <sys/dkio.h>
  36 #include <sys/file.h>
  37 #include <sys/fs/hsfs_isospec.h>
  38 #include <sys/mdeg.h>
  39 #include <sys/mhd.h>
  40 #include <sys/modhash.h>
  41 #include <sys/note.h>
  42 #include <sys/pathname.h>
  43 #include <sys/sdt.h>


5815          * The minimum size for the label is 16K (EFI_MIN_ARRAY_SIZE)
5816          * for GPEs plus one block for the GPT and one for PMBR.
5817          */
5818         first_u_lba = (EFI_MIN_ARRAY_SIZE / bsize) + 2;
5819         vd->flabel_limit = (uint_t)first_u_lba;
5820         vd->flabel_size = VD_LABEL_EFI_SIZE(bsize);
5821         vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP);
5822         gpt = VD_LABEL_EFI_GPT(vd, bsize);
5823         gpe = VD_LABEL_EFI_GPE(vd, bsize);
5824 
5825         /*
5826          * Adjust the vdisk_size, we emulate the first few blocks
5827          * for the disk label.
5828          */
5829         vd->vdisk_size += first_u_lba;
5830         s0_start = first_u_lba;
5831         s0_end = vd->vdisk_size - 1;
5832 
5833         gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
5834         gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
5835         gpt->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t));
5836         gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba);
5837         gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
5838         gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
5839 
5840         UUID_LE_CONVERT(gpe[0].efi_gpe_PartitionTypeGUID, uuid);
5841         gpe[0].efi_gpe_StartingLBA = LE_64(s0_start);
5842         gpe[0].efi_gpe_EndingLBA = LE_64(s0_end);
5843 
5844         if (vd_slice_single_slice) {
5845                 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(1);
5846         } else {
5847                 /* adjust the number of slices */
5848                 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(VD_MAXPART);
5849                 vd->nslices = V_NUMPAR;
5850 
5851                 /* define a fake reserved partition */
5852                 UUID_LE_CONVERT(gpe[VD_MAXPART - 1].efi_gpe_PartitionTypeGUID,
5853                     efi_reserved);
5854                 gpe[VD_MAXPART - 1].efi_gpe_StartingLBA =
5855                     LE_64(s0_end + 1);
5856                 gpe[VD_MAXPART - 1].efi_gpe_EndingLBA =
5857                     LE_64(s0_end + EFI_MIN_RESV_SIZE);
5858 
5859                 /* adjust the vdisk_size to include the reserved slice */
5860                 vd->vdisk_size += EFI_MIN_RESV_SIZE;
5861         }
5862 
5863         gpt->efi_gpt_LastUsableLBA = LE_64(vd->vdisk_size - 1);
5864 
5865         /* adjust the vdisk size for the backup GPT and GPE */
5866         vd->vdisk_size += (EFI_MIN_ARRAY_SIZE / bsize) + 1;
5867         gpt->efi_gpt_AlternateLBA = LE_64(vd->vdisk_size - 1);
5868 
5869         CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table);
5870         gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
5871 
5872         CRC32(crc, gpt, sizeof (efi_gpt_t), -1U, crc32_table);
5873         gpt->efi_gpt_HeaderCRC32 = LE_32(~crc);
5874 
5875         return (0);
5876 }
5877 
5878 /*
5879  * Setup for a virtual disk whose backend is a file (exported as a single slice
5880  * or as a full disk). In that case, the backend is accessed using the vnode
5881  * interface.
5882  */
5883 static int
5884 vd_setup_backend_vnode(vd_t *vd)
5885 {
5886         int             rval, status;
5887         dev_t           dev;
5888         char            *file_path = vd->device_path;
5889         ldi_handle_t    lhandle;
5890         struct dk_cinfo dk_cinfo;
5891 
5892         ASSERT(!vd->volume);




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2019, Joyent, Inc.
  25  */
  26 
  27 /*
  28  * Virtual disk server
  29  */
  30 
  31 
  32 #include <sys/types.h>
  33 #include <sys/conf.h>
  34 #include <sys/crc32.h>
  35 #include <sys/ddi.h>
  36 #include <sys/dkio.h>
  37 #include <sys/file.h>
  38 #include <sys/fs/hsfs_isospec.h>
  39 #include <sys/mdeg.h>
  40 #include <sys/mhd.h>
  41 #include <sys/modhash.h>
  42 #include <sys/note.h>
  43 #include <sys/pathname.h>
  44 #include <sys/sdt.h>


5816          * The minimum size for the label is 16K (EFI_MIN_ARRAY_SIZE)
5817          * for GPEs plus one block for the GPT and one for PMBR.
5818          */
5819         first_u_lba = (EFI_MIN_ARRAY_SIZE / bsize) + 2;
5820         vd->flabel_limit = (uint_t)first_u_lba;
5821         vd->flabel_size = VD_LABEL_EFI_SIZE(bsize);
5822         vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP);
5823         gpt = VD_LABEL_EFI_GPT(vd, bsize);
5824         gpe = VD_LABEL_EFI_GPE(vd, bsize);
5825 
5826         /*
5827          * Adjust the vdisk_size, we emulate the first few blocks
5828          * for the disk label.
5829          */
5830         vd->vdisk_size += first_u_lba;
5831         s0_start = first_u_lba;
5832         s0_end = vd->vdisk_size - 1;
5833 
5834         gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
5835         gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
5836         gpt->efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE);
5837         gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba);
5838         gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
5839         gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
5840 
5841         UUID_LE_CONVERT(gpe[0].efi_gpe_PartitionTypeGUID, uuid);
5842         gpe[0].efi_gpe_StartingLBA = LE_64(s0_start);
5843         gpe[0].efi_gpe_EndingLBA = LE_64(s0_end);
5844 
5845         if (vd_slice_single_slice) {
5846                 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(1);
5847         } else {
5848                 /* adjust the number of slices */
5849                 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(VD_MAXPART);
5850                 vd->nslices = V_NUMPAR;
5851 
5852                 /* define a fake reserved partition */
5853                 UUID_LE_CONVERT(gpe[VD_MAXPART - 1].efi_gpe_PartitionTypeGUID,
5854                     efi_reserved);
5855                 gpe[VD_MAXPART - 1].efi_gpe_StartingLBA =
5856                     LE_64(s0_end + 1);
5857                 gpe[VD_MAXPART - 1].efi_gpe_EndingLBA =
5858                     LE_64(s0_end + EFI_MIN_RESV_SIZE);
5859 
5860                 /* adjust the vdisk_size to include the reserved slice */
5861                 vd->vdisk_size += EFI_MIN_RESV_SIZE;
5862         }
5863 
5864         gpt->efi_gpt_LastUsableLBA = LE_64(vd->vdisk_size - 1);
5865 
5866         /* adjust the vdisk size for the backup GPT and GPE */
5867         vd->vdisk_size += (EFI_MIN_ARRAY_SIZE / bsize) + 1;
5868         gpt->efi_gpt_AlternateLBA = LE_64(vd->vdisk_size - 1);
5869 
5870         CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table);
5871         gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
5872 
5873         CRC32(crc, gpt, EFI_HEADER_SIZE, -1U, crc32_table);
5874         gpt->efi_gpt_HeaderCRC32 = LE_32(~crc);
5875 
5876         return (0);
5877 }
5878 
5879 /*
5880  * Setup for a virtual disk whose backend is a file (exported as a single slice
5881  * or as a full disk). In that case, the backend is accessed using the vnode
5882  * interface.
5883  */
5884 static int
5885 vd_setup_backend_vnode(vd_t *vd)
5886 {
5887         int             rval, status;
5888         dev_t           dev;
5889         char            *file_path = vd->device_path;
5890         ldi_handle_t    lhandle;
5891         struct dk_cinfo dk_cinfo;
5892 
5893         ASSERT(!vd->volume);