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


   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) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2014 Toomas Soome <tsoome@me.com>
  26  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
  27  * Copyright (c) 2018, Joyent, Inc.
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <errno.h>
  33 #include <strings.h>
  34 #include <unistd.h>
  35 #include <smbios.h>
  36 #include <uuid/uuid.h>
  37 #include <libintl.h>
  38 #include <sys/types.h>
  39 #include <sys/dkio.h>
  40 #include <sys/vtoc.h>
  41 #include <sys/mhd.h>
  42 #include <sys/param.h>
  43 #include <sys/dktp/fdisk.h>
  44 #include <sys/efi_partition.h>
  45 #include <sys/byteorder.h>
  46 #include <sys/ddi.h>
  47 


 324                         (void) fprintf(stderr,
 325                             "Bad EFI signature: 0x%llx != 0x%llx\n",
 326                             (long long)efi->efi_gpt_Signature,
 327                             (long long)LE_64(EFI_SIGNATURE));
 328                 return (VT_EINVAL);
 329         }
 330 
 331         /*
 332          * check CRC of the header; the size of the header should
 333          * never be larger than one block
 334          */
 335         crc = efi->efi_gpt_HeaderCRC32;
 336         efi->efi_gpt_HeaderCRC32 = 0;
 337 
 338         if (((len_t)LE_32(efi->efi_gpt_HeaderSize) > dk_ioc->dki_length) ||
 339             crc != LE_32(efi_crc32((unsigned char *)efi,
 340             LE_32(efi->efi_gpt_HeaderSize)))) {
 341                 if (efi_debug)
 342                         (void) fprintf(stderr,
 343                             "Bad EFI CRC: 0x%x != 0x%x\n",
 344                             crc,
 345                             LE_32(efi_crc32((unsigned char *)efi,
 346                             sizeof (struct efi_gpt))));
 347                 return (VT_EINVAL);
 348         }
 349 
 350         return (0);
 351 }
 352 
 353 static int
 354 efi_read(int fd, struct dk_gpt *vtoc)
 355 {
 356         int                     i, j;
 357         int                     label_len;
 358         int                     rval = 0;
 359         int                     vdc_flag = 0;
 360         struct dk_minfo         disk_info;
 361         dk_efi_t                dk_ioc;
 362         efi_gpt_t               *efi;
 363         efi_gpe_t               *efi_parts;
 364         struct dk_cinfo         dki_info;
 365         uint32_t                user_length;
 366         boolean_t               legacy_label = B_FALSE;


 698         (void) fclose(fp);
 699         smbios_close(shp);
 700 }
 701 
 702 /* writes a "protective" MBR */
 703 static int
 704 write_pmbr(int fd, struct dk_gpt *vtoc)
 705 {
 706         dk_efi_t        dk_ioc;
 707         struct mboot    mb;
 708         uchar_t         *cp;
 709         diskaddr_t      size_in_lba;
 710         uchar_t         *buf;
 711         int             len, slot, active;
 712 
 713         slot = active = 0;
 714 
 715         hardware_workarounds(&slot, &active);
 716 
 717         len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize;
 718         buf = calloc(len, 1);
 719 
 720         /*
 721          * Preserve any boot code and disk signature if the first block is
 722          * already an MBR.
 723          */
 724         dk_ioc.dki_lba = 0;
 725         dk_ioc.dki_length = len;
 726         /* LINTED -- always longlong aligned */
 727         dk_ioc.dki_data = (efi_gpt_t *)buf;
 728         if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
 729                 (void) memcpy(&mb, buf, sizeof (mb));
 730                 bzero(&mb, sizeof (mb));
 731                 mb.signature = LE_16(MBB_MAGIC);
 732         } else {
 733                 (void) memcpy(&mb, buf, sizeof (mb));
 734                 if (mb.signature != LE_16(MBB_MAGIC)) {
 735                         bzero(&mb, sizeof (mb));
 736                         mb.signature = LE_16(MBB_MAGIC);
 737                 }
 738         }
 739 
 740         bzero(&mb.parts, sizeof (mb.parts));
 741         cp = (uchar_t *)&mb.parts[slot * sizeof (struct ipart)];
 742         /* bootable or not */
 743         *cp++ = active ? ACTIVE : NOTACTIVE;
 744         /* beginning CHS; 0xffffff if not representable */
 745         *cp++ = 0xff;
 746         *cp++ = 0xff;
 747         *cp++ = 0xff;
 748         /* OS type */
 749         *cp++ = EFI_PMBR;
 750         /* ending CHS; 0xffffff if not representable */
 751         *cp++ = 0xff;
 752         *cp++ = 0xff;
 753         *cp++ = 0xff;
 754         /* starting LBA: 1 (little endian format) by EFI definition */
 755         *cp++ = 0x01;
 756         *cp++ = 0x00;
 757         *cp++ = 0x00;
 758         *cp++ = 0x00;
 759         /* ending LBA: last block on the disk (little endian format) */
 760         size_in_lba = vtoc->efi_last_lba;
 761         if (size_in_lba < 0xffffffff) {
 762                 *cp++ = (size_in_lba & 0x000000ff);
 763                 *cp++ = (size_in_lba & 0x0000ff00) >> 8;
 764                 *cp++ = (size_in_lba & 0x00ff0000) >> 16;
 765                 *cp++ = (size_in_lba & 0xff000000) >> 24;
 766         } else {
 767                 *cp++ = 0xff;


1012 
1013         /*
1014          * the number of blocks occupied by GUID partition entry array
1015          */
1016         nblocks = dk_ioc.dki_length / vtoc->efi_lbasize - 1;
1017 
1018         /*
1019          * Backup GPT header is located on the block after GUID
1020          * partition entry array. Here, we calculate the address
1021          * for backup GPT header.
1022          */
1023         lba_backup_gpt_hdr = vtoc->efi_last_u_lba + 1 + nblocks;
1024         if ((dk_ioc.dki_data = calloc(1, dk_ioc.dki_length)) == NULL)
1025                 return (VT_ERROR);
1026 
1027         efi = dk_ioc.dki_data;
1028 
1029         /* stuff user's input into EFI struct */
1030         efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
1031         efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */
1032         efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt));
1033         efi->efi_gpt_Reserved1 = 0;
1034         efi->efi_gpt_MyLBA = LE_64(1ULL);
1035         efi->efi_gpt_AlternateLBA = LE_64(lba_backup_gpt_hdr);
1036         efi->efi_gpt_FirstUsableLBA = LE_64(vtoc->efi_first_u_lba);
1037         efi->efi_gpt_LastUsableLBA = LE_64(vtoc->efi_last_u_lba);
1038         efi->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
1039         efi->efi_gpt_NumberOfPartitionEntries = LE_32(vtoc->efi_nparts);
1040         efi->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (struct efi_gpe));
1041         UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid);
1042 
1043         /* LINTED -- always longlong aligned */
1044         efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + vtoc->efi_lbasize);
1045 
1046         for (i = 0; i < vtoc->efi_nparts; i++) {
1047                 for (j = 0;
1048                     j < sizeof (conversion_array) /
1049                     sizeof (struct uuid_to_ptag); j++) {
1050 
1051                         if (vtoc->efi_parts[i].p_tag ==
1052                             conversion_array[j].p_tag) {


1077                     LE_64(vtoc->efi_parts[i].p_start +
1078                     vtoc->efi_parts[i].p_size - 1);
1079                 efi_parts[i].efi_gpe_Attributes.PartitionAttrs =
1080                     LE_16(vtoc->efi_parts[i].p_flag);
1081                 for (j = 0; j < EFI_PART_NAME_LEN; j++) {
1082                         efi_parts[i].efi_gpe_PartitionName[j] =
1083                             LE_16((ushort_t)vtoc->efi_parts[i].p_name[j]);
1084                 }
1085                 if ((vtoc->efi_parts[i].p_tag != V_UNASSIGNED) &&
1086                     uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_uguid)) {
1087                         (void) uuid_generate((uchar_t *)
1088                             &vtoc->efi_parts[i].p_uguid);
1089                 }
1090                 bcopy(&vtoc->efi_parts[i].p_uguid,
1091                     &efi_parts[i].efi_gpe_UniquePartitionGUID,
1092                     sizeof (uuid_t));
1093         }
1094         efi->efi_gpt_PartitionEntryArrayCRC32 =
1095             LE_32(efi_crc32((unsigned char *)efi_parts,
1096             vtoc->efi_nparts * (int)sizeof (struct efi_gpe)));
1097         efi->efi_gpt_HeaderCRC32 =
1098             LE_32(efi_crc32((unsigned char *)efi, sizeof (struct efi_gpt)));
1099 
1100         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1101                 free(dk_ioc.dki_data);
1102                 switch (errno) {
1103                 case EIO:
1104                         return (VT_EIO);
1105                 case EINVAL:
1106                         return (VT_EINVAL);
1107                 default:
1108                         return (VT_ERROR);
1109                 }
1110         }
1111 
1112         /* write backup partition array */
1113         dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1;
1114         dk_ioc.dki_length -= vtoc->efi_lbasize;
1115         /* LINTED */
1116         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data +
1117             vtoc->efi_lbasize);
1118 


1125                             "write of backup partitions to block %llu "
1126                             "failed, errno %d\n",
1127                             vtoc->efi_last_u_lba + 1,
1128                             errno);
1129                 }
1130         }
1131         /*
1132          * now swap MyLBA and AlternateLBA fields and write backup
1133          * partition table header
1134          */
1135         dk_ioc.dki_lba = lba_backup_gpt_hdr;
1136         dk_ioc.dki_length = vtoc->efi_lbasize;
1137         /* LINTED */
1138         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data -
1139             vtoc->efi_lbasize);
1140         efi->efi_gpt_AlternateLBA = LE_64(1ULL);
1141         efi->efi_gpt_MyLBA = LE_64(lba_backup_gpt_hdr);
1142         efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1);
1143         efi->efi_gpt_HeaderCRC32 = 0;
1144         efi->efi_gpt_HeaderCRC32 =
1145             LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data,
1146             sizeof (struct efi_gpt)));
1147 
1148         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1149                 if (efi_debug) {
1150                         (void) fprintf(stderr,
1151                             "write of backup header to block %llu failed, "
1152                             "errno %d\n",
1153                             lba_backup_gpt_hdr,
1154                             errno);
1155                 }
1156         }
1157         /* write the PMBR */
1158         (void) write_pmbr(fd, vtoc);
1159         free(dk_ioc.dki_data);
1160         return (0);
1161 }
1162 
1163 void
1164 efi_free(struct dk_gpt *ptr)
1165 {
1166         free(ptr);




   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) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2014 Toomas Soome <tsoome@me.com>
  26  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
  27  * Copyright 2019 Joyent, Inc.
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <errno.h>
  33 #include <strings.h>
  34 #include <unistd.h>
  35 #include <smbios.h>
  36 #include <uuid/uuid.h>
  37 #include <libintl.h>
  38 #include <sys/types.h>
  39 #include <sys/dkio.h>
  40 #include <sys/vtoc.h>
  41 #include <sys/mhd.h>
  42 #include <sys/param.h>
  43 #include <sys/dktp/fdisk.h>
  44 #include <sys/efi_partition.h>
  45 #include <sys/byteorder.h>
  46 #include <sys/ddi.h>
  47 


 324                         (void) fprintf(stderr,
 325                             "Bad EFI signature: 0x%llx != 0x%llx\n",
 326                             (long long)efi->efi_gpt_Signature,
 327                             (long long)LE_64(EFI_SIGNATURE));
 328                 return (VT_EINVAL);
 329         }
 330 
 331         /*
 332          * check CRC of the header; the size of the header should
 333          * never be larger than one block
 334          */
 335         crc = efi->efi_gpt_HeaderCRC32;
 336         efi->efi_gpt_HeaderCRC32 = 0;
 337 
 338         if (((len_t)LE_32(efi->efi_gpt_HeaderSize) > dk_ioc->dki_length) ||
 339             crc != LE_32(efi_crc32((unsigned char *)efi,
 340             LE_32(efi->efi_gpt_HeaderSize)))) {
 341                 if (efi_debug)
 342                         (void) fprintf(stderr,
 343                             "Bad EFI CRC: 0x%x != 0x%x\n",
 344                             crc, LE_32(efi_crc32((unsigned char *)efi,
 345                             LE_32(efi->efi_gpt_HeaderSize))));

 346                 return (VT_EINVAL);
 347         }
 348 
 349         return (0);
 350 }
 351 
 352 static int
 353 efi_read(int fd, struct dk_gpt *vtoc)
 354 {
 355         int                     i, j;
 356         int                     label_len;
 357         int                     rval = 0;
 358         int                     vdc_flag = 0;
 359         struct dk_minfo         disk_info;
 360         dk_efi_t                dk_ioc;
 361         efi_gpt_t               *efi;
 362         efi_gpe_t               *efi_parts;
 363         struct dk_cinfo         dki_info;
 364         uint32_t                user_length;
 365         boolean_t               legacy_label = B_FALSE;


 697         (void) fclose(fp);
 698         smbios_close(shp);
 699 }
 700 
 701 /* writes a "protective" MBR */
 702 static int
 703 write_pmbr(int fd, struct dk_gpt *vtoc)
 704 {
 705         dk_efi_t        dk_ioc;
 706         struct mboot    mb;
 707         uchar_t         *cp;
 708         diskaddr_t      size_in_lba;
 709         uchar_t         *buf;
 710         int             len, slot, active;
 711 
 712         slot = active = 0;
 713 
 714         hardware_workarounds(&slot, &active);
 715 
 716         len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize;
 717         buf = calloc(1, len);
 718 
 719         /*
 720          * Preserve any boot code and disk signature if the first block is
 721          * already an MBR.
 722          */
 723         dk_ioc.dki_lba = 0;
 724         dk_ioc.dki_length = len;
 725         /* LINTED -- always longlong aligned */
 726         dk_ioc.dki_data = (efi_gpt_t *)buf;
 727         if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
 728                 (void) memcpy(&mb, buf, sizeof (mb));
 729                 bzero(&mb, sizeof (mb));
 730                 mb.signature = LE_16(MBB_MAGIC);
 731         } else {
 732                 (void) memcpy(&mb, buf, sizeof (mb));
 733                 if (mb.signature != LE_16(MBB_MAGIC)) {
 734                         bzero(&mb, sizeof (mb));
 735                         mb.signature = LE_16(MBB_MAGIC);
 736                 }
 737         }
 738 
 739         bzero(&mb.parts, sizeof (mb.parts));
 740         cp = (uchar_t *)&mb.parts[slot * sizeof (struct ipart)];
 741         /* bootable or not */
 742         *cp++ = active ? ACTIVE : NOTACTIVE;
 743         /* beginning CHS; same as starting LBA (but one-based) */
 744         *cp++ = 0x0;
 745         *cp++ = 0x2;
 746         *cp++ = 0x0;
 747         /* OS type */
 748         *cp++ = EFI_PMBR;
 749         /* ending CHS; 0xffffff if not representable */
 750         *cp++ = 0xff;
 751         *cp++ = 0xff;
 752         *cp++ = 0xff;
 753         /* starting LBA: 1 (little endian format) by EFI definition */
 754         *cp++ = 0x01;
 755         *cp++ = 0x00;
 756         *cp++ = 0x00;
 757         *cp++ = 0x00;
 758         /* ending LBA: last block on the disk (little endian format) */
 759         size_in_lba = vtoc->efi_last_lba;
 760         if (size_in_lba < 0xffffffff) {
 761                 *cp++ = (size_in_lba & 0x000000ff);
 762                 *cp++ = (size_in_lba & 0x0000ff00) >> 8;
 763                 *cp++ = (size_in_lba & 0x00ff0000) >> 16;
 764                 *cp++ = (size_in_lba & 0xff000000) >> 24;
 765         } else {
 766                 *cp++ = 0xff;


1011 
1012         /*
1013          * the number of blocks occupied by GUID partition entry array
1014          */
1015         nblocks = dk_ioc.dki_length / vtoc->efi_lbasize - 1;
1016 
1017         /*
1018          * Backup GPT header is located on the block after GUID
1019          * partition entry array. Here, we calculate the address
1020          * for backup GPT header.
1021          */
1022         lba_backup_gpt_hdr = vtoc->efi_last_u_lba + 1 + nblocks;
1023         if ((dk_ioc.dki_data = calloc(1, dk_ioc.dki_length)) == NULL)
1024                 return (VT_ERROR);
1025 
1026         efi = dk_ioc.dki_data;
1027 
1028         /* stuff user's input into EFI struct */
1029         efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
1030         efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */
1031         efi->efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE);
1032         efi->efi_gpt_Reserved1 = 0;
1033         efi->efi_gpt_MyLBA = LE_64(1ULL);
1034         efi->efi_gpt_AlternateLBA = LE_64(lba_backup_gpt_hdr);
1035         efi->efi_gpt_FirstUsableLBA = LE_64(vtoc->efi_first_u_lba);
1036         efi->efi_gpt_LastUsableLBA = LE_64(vtoc->efi_last_u_lba);
1037         efi->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
1038         efi->efi_gpt_NumberOfPartitionEntries = LE_32(vtoc->efi_nparts);
1039         efi->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (struct efi_gpe));
1040         UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid);
1041 
1042         /* LINTED -- always longlong aligned */
1043         efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + vtoc->efi_lbasize);
1044 
1045         for (i = 0; i < vtoc->efi_nparts; i++) {
1046                 for (j = 0;
1047                     j < sizeof (conversion_array) /
1048                     sizeof (struct uuid_to_ptag); j++) {
1049 
1050                         if (vtoc->efi_parts[i].p_tag ==
1051                             conversion_array[j].p_tag) {


1076                     LE_64(vtoc->efi_parts[i].p_start +
1077                     vtoc->efi_parts[i].p_size - 1);
1078                 efi_parts[i].efi_gpe_Attributes.PartitionAttrs =
1079                     LE_16(vtoc->efi_parts[i].p_flag);
1080                 for (j = 0; j < EFI_PART_NAME_LEN; j++) {
1081                         efi_parts[i].efi_gpe_PartitionName[j] =
1082                             LE_16((ushort_t)vtoc->efi_parts[i].p_name[j]);
1083                 }
1084                 if ((vtoc->efi_parts[i].p_tag != V_UNASSIGNED) &&
1085                     uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_uguid)) {
1086                         (void) uuid_generate((uchar_t *)
1087                             &vtoc->efi_parts[i].p_uguid);
1088                 }
1089                 bcopy(&vtoc->efi_parts[i].p_uguid,
1090                     &efi_parts[i].efi_gpe_UniquePartitionGUID,
1091                     sizeof (uuid_t));
1092         }
1093         efi->efi_gpt_PartitionEntryArrayCRC32 =
1094             LE_32(efi_crc32((unsigned char *)efi_parts,
1095             vtoc->efi_nparts * (int)sizeof (struct efi_gpe)));
1096         efi->efi_gpt_HeaderCRC32 = LE_32(efi_crc32((unsigned char *)efi,
1097             EFI_HEADER_SIZE));
1098 
1099         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1100                 free(dk_ioc.dki_data);
1101                 switch (errno) {
1102                 case EIO:
1103                         return (VT_EIO);
1104                 case EINVAL:
1105                         return (VT_EINVAL);
1106                 default:
1107                         return (VT_ERROR);
1108                 }
1109         }
1110 
1111         /* write backup partition array */
1112         dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1;
1113         dk_ioc.dki_length -= vtoc->efi_lbasize;
1114         /* LINTED */
1115         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data +
1116             vtoc->efi_lbasize);
1117 


1124                             "write of backup partitions to block %llu "
1125                             "failed, errno %d\n",
1126                             vtoc->efi_last_u_lba + 1,
1127                             errno);
1128                 }
1129         }
1130         /*
1131          * now swap MyLBA and AlternateLBA fields and write backup
1132          * partition table header
1133          */
1134         dk_ioc.dki_lba = lba_backup_gpt_hdr;
1135         dk_ioc.dki_length = vtoc->efi_lbasize;
1136         /* LINTED */
1137         dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data -
1138             vtoc->efi_lbasize);
1139         efi->efi_gpt_AlternateLBA = LE_64(1ULL);
1140         efi->efi_gpt_MyLBA = LE_64(lba_backup_gpt_hdr);
1141         efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1);
1142         efi->efi_gpt_HeaderCRC32 = 0;
1143         efi->efi_gpt_HeaderCRC32 =
1144             LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data, EFI_HEADER_SIZE));

1145 
1146         if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
1147                 if (efi_debug) {
1148                         (void) fprintf(stderr,
1149                             "write of backup header to block %llu failed, "
1150                             "errno %d\n",
1151                             lba_backup_gpt_hdr,
1152                             errno);
1153                 }
1154         }
1155         /* write the PMBR */
1156         (void) write_pmbr(fd, vtoc);
1157         free(dk_ioc.dki_data);
1158         return (0);
1159 }
1160 
1161 void
1162 efi_free(struct dk_gpt *ptr)
1163 {
1164         free(ptr);