diff --git a/sys/sys/disk/gpt.h b/sys/sys/disk/gpt.h index e48b13684814..596a5cba1681 100644 --- a/sys/sys/disk/gpt.h +++ b/sys/sys/disk/gpt.h @@ -1,261 +1,268 @@ /*- * Copyright (c) 2002 Marcel Moolenaar * 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 ``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 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. */ #ifndef _SYS_DISK_GPT_H_ #define _SYS_DISK_GPT_H_ #include /* * Applications can define GPT_UUID_TYPE if they want the GPT structures * to use a particular type definition for UUIDs/GUIDs. This header uses * a generic (DCE 1.1 compatible) definition otherwise. */ #ifndef GPT_UUID_TYPE struct gpt_uuid { uint32_t time_low; uint16_t time_mid; uint16_t time_hi_and_version; uint8_t clock_seq_hi_and_reserved; uint8_t clock_seq_low; uint8_t node[6]; }; #define GPT_UUID_TYPE struct gpt_uuid #endif /* !GPT_UUID_TYPE */ typedef GPT_UUID_TYPE gpt_uuid_t; #ifdef CTASSERT CTASSERT(sizeof(gpt_uuid_t) == 16); #endif struct gpt_hdr { char hdr_sig[8]; #define GPT_HDR_SIG "EFI PART" uint32_t hdr_revision; #define GPT_HDR_REVISION 0x00010000 uint32_t hdr_size; uint32_t hdr_crc_self; uint32_t __reserved; uint64_t hdr_lba_self; uint64_t hdr_lba_alt; uint64_t hdr_lba_start; uint64_t hdr_lba_end; gpt_uuid_t hdr_uuid; uint64_t hdr_lba_table; uint32_t hdr_entries; uint32_t hdr_entsz; uint32_t hdr_crc_table; /* * The header as defined in the EFI spec is not a multiple of 8 bytes * and given that the alignment requirement is on an 8 byte boundary, * padding will happen. We make the padding explicit so that we can * correct the value returned by sizeof() when we put the size of the * header in field hdr_size, or otherwise use offsetof(). */ uint32_t padding; }; #ifdef CTASSERT CTASSERT(offsetof(struct gpt_hdr, padding) == 92); #endif +/* + * The GPT standard (section 5.3 of UEFI standard version 2.10) requires + * we reserve at least 16k after the PMBR and the GPT header for the GPT + * Array Entries. + */ +#define GPT_MIN_RESERVED 16384 + struct gpt_ent { gpt_uuid_t ent_type; gpt_uuid_t ent_uuid; uint64_t ent_lba_start; uint64_t ent_lba_end; uint64_t ent_attr; #define GPT_ENT_ATTR_PLATFORM (1ULL << 0) #define GPT_ENT_ATTR_BOOTME (1ULL << 59) #define GPT_ENT_ATTR_BOOTONCE (1ULL << 58) #define GPT_ENT_ATTR_BOOTFAILED (1ULL << 57) uint16_t ent_name[36]; /* UTF-16. */ }; #ifdef CTASSERT CTASSERT(sizeof(struct gpt_ent) == 128); #endif /* CTASSERT */ #define GPT_ENT_TYPE_UNUSED \ {0x00000000,0x0000,0x0000,0x00,0x00,{0x00,0x00,0x00,0x00,0x00,0x00}} #define GPT_ENT_TYPE_EFI \ {0xc12a7328,0xf81f,0x11d2,0xba,0x4b,{0x00,0xa0,0xc9,0x3e,0xc9,0x3b}} #define GPT_ENT_TYPE_MBR \ {0x024dee41,0x33e7,0x11d3,0x9d,0x69,{0x00,0x08,0xc7,0x81,0xf3,0x9f}} #define GPT_ENT_TYPE_FREEBSD \ {0x516e7cb4,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}} #define GPT_ENT_TYPE_FREEBSD_BOOT \ {0x83bd6b9d,0x7f41,0x11dc,0xbe,0x0b,{0x00,0x15,0x60,0xb8,0x4f,0x0f}} #define GPT_ENT_TYPE_FREEBSD_NANDFS \ {0x74ba7dd9,0xa689,0x11e1,0xbd,0x04,{0x00,0xe0,0x81,0x28,0x6a,0xcf}} #define GPT_ENT_TYPE_FREEBSD_SWAP \ {0x516e7cb5,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}} #define GPT_ENT_TYPE_FREEBSD_UFS \ {0x516e7cb6,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}} #define GPT_ENT_TYPE_FREEBSD_VINUM \ {0x516e7cb8,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}} #define GPT_ENT_TYPE_FREEBSD_ZFS \ {0x516e7cba,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}} #define GPT_ENT_TYPE_PREP_BOOT \ {0x9e1a2d38,0xc612,0x4316,0xaa,0x26,{0x8b,0x49,0x52,0x1e,0x5a,0x8b}} /* * The following are unused but documented here to avoid reuse. * * GPT_ENT_TYPE_FREEBSD_UFS2 \ * {0x516e7cb7,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}} */ /* * Foreign partition types that we're likely to encounter. Note that Linux * apparently choose to share data partitions with MS. I don't what the * advantage might be. I can see how sharing swap partitions is advantageous * though. */ #define GPT_ENT_TYPE_MS_BASIC_DATA \ {0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}} #define GPT_ENT_TYPE_MS_LDM_DATA \ {0xaf9b60a0,0x1431,0x4f62,0xbc,0x68,{0x33,0x11,0x71,0x4a,0x69,0xad}} #define GPT_ENT_TYPE_MS_LDM_METADATA \ {0x5808c8aa,0x7e8f,0x42e0,0x85,0xd2,{0xe1,0xe9,0x04,0x34,0xcf,0xb3}} #define GPT_ENT_TYPE_MS_RECOVERY \ {0xde94bba4,0x06d1,0x4d40,0xa1,0x6a,{0xbf,0xd5,0x01,0x79,0xd6,0xac}} #define GPT_ENT_TYPE_MS_RESERVED \ {0xe3c9e316,0x0b5c,0x4db8,0x81,0x7d,{0xf9,0x2d,0xf0,0x02,0x15,0xae}} #define GPT_ENT_TYPE_MS_SPACES \ {0xe75caf8f,0xf680,0x4cee,0xaf,0xa3,{0xb0,0x01,0xe5,0x6e,0xfc,0x2d}} #define GPT_ENT_TYPE_LINUX_DATA \ {0x0fc63daf,0x8483,0x4772,0x8e,0x79,{0x3d,0x69,0xd8,0x47,0x7d,0xe4}} #define GPT_ENT_TYPE_LINUX_RAID \ {0xa19d880f,0x05fc,0x4d3b,0xa0,0x06,{0x74,0x3f,0x0f,0x84,0x91,0x1e}} #define GPT_ENT_TYPE_LINUX_SWAP \ {0x0657fd6d,0xa4ab,0x43c4,0x84,0xe5,{0x09,0x33,0xc8,0x4b,0x4f,0x4f}} #define GPT_ENT_TYPE_LINUX_LVM \ {0xe6d6d379,0xf507,0x44c2,0xa2,0x3c,{0x23,0x8f,0x2a,0x3d,0xf9,0x28}} #define GPT_ENT_TYPE_VMFS \ {0xaa31e02a,0x400f,0x11db,0x95,0x90,{0x00,0x0c,0x29,0x11,0xd1,0xb8}} #define GPT_ENT_TYPE_VMKDIAG \ {0x9d275380,0x40ad,0x11db,0xbf,0x97,{0x00,0x0c,0x29,0x11,0xd1,0xb8}} #define GPT_ENT_TYPE_VMRESERVED \ {0x9198effc,0x31c0,0x11db,0x8f,0x78,{0x00,0x0c,0x29,0x11,0xd1,0xb8}} #define GPT_ENT_TYPE_VMVSANHDR \ {0x381cfccc,0x7288,0x11e0,0x92,0xee,{0x00,0x0c,0x29,0x11,0xd0,0xb2}} #define GPT_ENT_TYPE_APPLE_BOOT \ {0x426F6F74,0x0000,0x11aa,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_HFS \ {0x48465300,0x0000,0x11aa,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_UFS \ {0x55465300,0x0000,0x11aa,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_ZFS \ {0x6a898cc3,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_APPLE_RAID \ {0x52414944,0x0000,0x11aa,0xaa,0x22,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_RAID_OFFLINE \ {0x52414944,0x5f4f,0x11aa,0xaa,0x22,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_LABEL \ {0x4C616265,0x6c00,0x11aa,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_TV_RECOVERY \ {0x5265636f,0x7665,0x11AA,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_CORE_STORAGE \ {0x53746f72,0x6167,0x11AA,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_APPLE_APFS \ {0x7c3457ef,0x0000,0x11aa,0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}} #define GPT_ENT_TYPE_NETBSD_FFS \ {0x49f48d5a,0xb10e,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} #define GPT_ENT_TYPE_NETBSD_LFS \ {0x49f48d82,0xb10e,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} #define GPT_ENT_TYPE_NETBSD_SWAP \ {0x49f48d32,0xb10e,0x11dc,0xB9,0x9B,{0x00,0x19,0xd1,0x87,0x96,0x48}} #define GPT_ENT_TYPE_NETBSD_RAID \ {0x49f48daa,0xb10e,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} #define GPT_ENT_TYPE_NETBSD_CCD \ {0x2db519c4,0xb10f,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} #define GPT_ENT_TYPE_NETBSD_CGD \ {0x2db519ec,0xb10f,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} #define GPT_ENT_TYPE_DRAGONFLY_LABEL32 \ {0x9d087404,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_SWAP \ {0x9d58fdbd,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_UFS1 \ {0x9d94ce7c,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_VINUM \ {0x9dd4478f,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_CCD \ {0xdbd5211b,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_LABEL64 \ {0x3d48ce54,0x1d16,0x11dc,0x86,0x96,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_LEGACY \ {0xbd215ab2,0x1d16,0x11dc,0x86,0x96,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_HAMMER \ {0x61dc63ac,0x6e38,0x11dc,0x85,0x13,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_DRAGONFLY_HAMMER2 \ {0x5cbb9ad1,0x862d,0x11dc,0xa9,0x4d,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} #define GPT_ENT_TYPE_CHROMEOS_FIRMWARE \ {0xcab6e88e,0xabf3,0x4102,0xa0,0x7a,{0xd4,0xbb,0x9b,0xe3,0xc1,0xd3}} #define GPT_ENT_TYPE_CHROMEOS_KERNEL \ {0xfe3a2a5d,0x4f32,0x41a7,0xb7,0x25,{0xac,0xcc,0x32,0x85,0xa3,0x09}} #define GPT_ENT_TYPE_CHROMEOS_RESERVED \ {0x2e0a753d,0x9e48,0x43b0,0x83,0x37,{0xb1,0x51,0x92,0xcb,0x1b,0x5e}} #define GPT_ENT_TYPE_CHROMEOS_ROOT \ {0x3cb8e202,0x3b7e,0x47dd,0x8a,0x3c,{0x7f,0xf2,0xa1,0x3c,0xfc,0xec}} #define GPT_ENT_TYPE_OPENBSD_DATA \ {0x824cc7a0,0x36a8,0x11e3,0x89,0x0a,{0x95,0x25,0x19,0xad,0x3f,0x61}} #define GPT_ENT_TYPE_SOLARIS_BOOT \ {0x6a82cb45,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_ROOT \ {0x6a85cf4d,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_SWAP \ {0x6a87c46f,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_BACKUP \ {0x6a8b642b,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_VAR \ {0x6a8ef2e9,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_HOME \ {0x6a90ba39,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_ALTSEC \ {0x6a9283a5,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_SOLARIS_RESERVED \ {0x6a945a3b,0x1dd2,0x11b2,0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}} #define GPT_ENT_TYPE_HIFIVE_FSBL \ {0x5b193300,0xfc78,0x40cd,0x80,0x02,{0xe8,0x6c,0x45,0x58,0x0b,0x47}} #define GPT_ENT_TYPE_HIFIVE_BBL \ {0x2e54b353,0x1271,0x4842,0x80,0x6f,{0xe4,0x36,0xd6,0xaf,0x69,0x85}} /* * Boot partition used by GRUB 2. */ #define GPT_ENT_TYPE_BIOS_BOOT \ {0x21686148,0x6449,0x6e6f,0x74,0x4e,{0x65,0x65,0x64,0x45,0x46,0x49}} #endif /* _SYS_DISK_GPT_H_ */ diff --git a/usr.bin/mkimg/gpt.c b/usr.bin/mkimg/gpt.c index 59c51a6a177b..ed3f008c394f 100644 --- a/usr.bin/mkimg/gpt.c +++ b/usr.bin/mkimg/gpt.c @@ -1,288 +1,296 @@ /*- * Copyright (c) 2014 Juniper Networks, Inc. * 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. */ -#include +#include #include #include #include #include #include #include #include #include "endian.h" #include "image.h" #include "mkimg.h" #include "scheme.h" static mkimg_uuid_t gpt_uuid_efi = GPT_ENT_TYPE_EFI; static mkimg_uuid_t gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD; static mkimg_uuid_t gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; static mkimg_uuid_t gpt_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS; static mkimg_uuid_t gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; static mkimg_uuid_t gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; static mkimg_uuid_t gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; static mkimg_uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; static mkimg_uuid_t gpt_uuid_mbr = GPT_ENT_TYPE_MBR; static mkimg_uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; static mkimg_uuid_t gpt_uuid_prep_boot = GPT_ENT_TYPE_PREP_BOOT; static struct mkimg_alias gpt_aliases[] = { { ALIAS_EFI, ALIAS_PTR2TYPE(&gpt_uuid_efi) }, { ALIAS_FREEBSD, ALIAS_PTR2TYPE(&gpt_uuid_freebsd) }, { ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_boot) }, { ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_nandfs) }, { ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_swap) }, { ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_ufs) }, { ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_vinum) }, { ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_zfs) }, { ALIAS_MBR, ALIAS_PTR2TYPE(&gpt_uuid_mbr) }, { ALIAS_NTFS, ALIAS_PTR2TYPE(&gpt_uuid_ms_basic_data) }, { ALIAS_PPCBOOT, ALIAS_PTR2TYPE(&gpt_uuid_prep_boot) }, { ALIAS_NONE, 0 } /* Keep last! */ }; /* CRC32 code derived from work by Gary S. Brown. */ static const uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; static uint32_t crc32(const void *buf, size_t sz) { const uint8_t *p = (const uint8_t *)buf; uint32_t crc = ~0U; while (sz--) crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8); return (crc ^ ~0U); } +/* + * Return the number of sectors needed to store the partition table. + */ static u_int gpt_tblsz(void) { - u_int ents; + u_int eps; /* Entries per Sector */ - ents = secsz / sizeof(struct gpt_ent); - return ((nparts + ents - 1) / ents); + /* + * Count the number of sectors needed for the GPT Entry Array to store + * the number of partitions defined for this image. Enforce the 16kB + * minimum space for the GPT Entry Array per UEFI v2.10 Section 5.3. + */ + eps = secsz / sizeof(struct gpt_ent); + return (MAX(howmany(GPT_MIN_RESERVED, secsz), howmany(nparts, eps))); } static lba_t gpt_metadata(u_int where, lba_t blk) { if (where == SCHEME_META_IMG_START || where == SCHEME_META_IMG_END) { blk += gpt_tblsz(); blk += (where == SCHEME_META_IMG_START) ? 2 : 1; } return (round_block(blk)); } static int gpt_write_pmbr(lba_t blks, void *bootcode) { u_char *pmbr; uint32_t secs; int error; secs = (blks > UINT32_MAX) ? UINT32_MAX : (uint32_t)blks - 1; pmbr = malloc(secsz); if (pmbr == NULL) return (errno); if (bootcode != NULL) { memcpy(pmbr, bootcode, DOSPARTOFF); memset(pmbr + DOSPARTOFF, 0, secsz - DOSPARTOFF); } else memset(pmbr, 0, secsz); pmbr[DOSPARTOFF + 2] = 2; pmbr[DOSPARTOFF + 4] = 0xee; pmbr[DOSPARTOFF + 5] = 0xff; pmbr[DOSPARTOFF + 6] = 0xff; pmbr[DOSPARTOFF + 7] = 0xff; le32enc(pmbr + DOSPARTOFF + 8, 1); le32enc(pmbr + DOSPARTOFF + 12, secs); le16enc(pmbr + DOSMAGICOFFSET, DOSMAGIC); error = image_write(0, pmbr, 1); free(pmbr); return (error); } static struct gpt_ent * gpt_mktbl(u_int tblsz) { mkimg_uuid_t uuid; struct gpt_ent *tbl, *ent; struct part *part; int c, idx; tbl = calloc(tblsz, secsz); if (tbl == NULL) return (NULL); TAILQ_FOREACH(part, &partlist, link) { ent = tbl + part->index; mkimg_uuid_enc(&ent->ent_type, ALIAS_TYPE2PTR(part->type)); mkimg_uuid(&uuid); mkimg_uuid_enc(&ent->ent_uuid, &uuid); le64enc(&ent->ent_lba_start, part->block); le64enc(&ent->ent_lba_end, part->block + part->size - 1); if (part->label != NULL) { idx = 0; while ((c = part->label[idx]) != '\0') { le16enc(ent->ent_name + idx, c); idx++; } } } return (tbl); } static int gpt_write_hdr(struct gpt_hdr *hdr, uint64_t self, uint64_t alt, uint64_t tbl) { uint32_t crc; le64enc(&hdr->hdr_lba_self, self); le64enc(&hdr->hdr_lba_alt, alt); le64enc(&hdr->hdr_lba_table, tbl); hdr->hdr_crc_self = 0; crc = crc32(hdr, offsetof(struct gpt_hdr, padding)); le64enc(&hdr->hdr_crc_self, crc); return (image_write(self, hdr, 1)); } static int gpt_write(lba_t imgsz, void *bootcode) { mkimg_uuid_t uuid; struct gpt_ent *tbl; struct gpt_hdr *hdr; uint32_t crc; u_int tblsz; int error; /* PMBR */ error = gpt_write_pmbr(imgsz, bootcode); if (error) return (error); /* GPT table(s) */ tblsz = gpt_tblsz(); tbl = gpt_mktbl(tblsz); if (tbl == NULL) return (errno); error = image_write(2, tbl, tblsz); if (error) goto out; error = image_write(imgsz - (tblsz + 1), tbl, tblsz); if (error) goto out; /* GPT header(s) */ hdr = malloc(secsz); if (hdr == NULL) { error = errno; goto out; } memset(hdr, 0, secsz); memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)); le32enc(&hdr->hdr_revision, GPT_HDR_REVISION); le32enc(&hdr->hdr_size, offsetof(struct gpt_hdr, padding)); le64enc(&hdr->hdr_lba_start, 2 + tblsz); le64enc(&hdr->hdr_lba_end, imgsz - tblsz - 2); mkimg_uuid(&uuid); mkimg_uuid_enc(&hdr->hdr_uuid, &uuid); le32enc(&hdr->hdr_entries, tblsz * secsz / sizeof(struct gpt_ent)); le32enc(&hdr->hdr_entsz, sizeof(struct gpt_ent)); crc = crc32(tbl, tblsz * secsz); le32enc(&hdr->hdr_crc_table, crc); error = gpt_write_hdr(hdr, 1, imgsz - 1, 2); if (!error) error = gpt_write_hdr(hdr, imgsz - 1, 1, imgsz - tblsz - 1); free(hdr); out: free(tbl); return (error); } static struct mkimg_scheme gpt_scheme = { .name = "gpt", .description = "GUID Partition Table", .aliases = gpt_aliases, .metadata = gpt_metadata, .write = gpt_write, .nparts = 4096, .labellen = 36, .bootcode = 512, .maxsecsz = 4096 }; SCHEME_DEFINE(gpt_scheme);