1a5eb4ea3SMarcel Moolenaar /*- 2a5eb4ea3SMarcel Moolenaar * Copyright (c) 2014 Juniper Networks, Inc. 3a5eb4ea3SMarcel Moolenaar * All rights reserved. 4a5eb4ea3SMarcel Moolenaar * 5a5eb4ea3SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 6a5eb4ea3SMarcel Moolenaar * modification, are permitted provided that the following conditions 7a5eb4ea3SMarcel Moolenaar * are met: 8a5eb4ea3SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 9a5eb4ea3SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 10a5eb4ea3SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 11a5eb4ea3SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 12a5eb4ea3SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 13a5eb4ea3SMarcel Moolenaar * 14a5eb4ea3SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15a5eb4ea3SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16a5eb4ea3SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17a5eb4ea3SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18a5eb4ea3SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19a5eb4ea3SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20a5eb4ea3SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21a5eb4ea3SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22a5eb4ea3SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23a5eb4ea3SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24a5eb4ea3SMarcel Moolenaar * SUCH DAMAGE. 25a5eb4ea3SMarcel Moolenaar */ 26a5eb4ea3SMarcel Moolenaar 27a5eb4ea3SMarcel Moolenaar #include <sys/cdefs.h> 28a5eb4ea3SMarcel Moolenaar __FBSDID("$FreeBSD$"); 29a5eb4ea3SMarcel Moolenaar 30a5eb4ea3SMarcel Moolenaar #include <sys/errno.h> 31a5eb4ea3SMarcel Moolenaar #include <stddef.h> 32a5eb4ea3SMarcel Moolenaar #include <stdint.h> 33a5eb4ea3SMarcel Moolenaar #include <stdlib.h> 34a5eb4ea3SMarcel Moolenaar #include <string.h> 35a5eb4ea3SMarcel Moolenaar #include <unistd.h> 36a5eb4ea3SMarcel Moolenaar #include <uuid.h> 37a5eb4ea3SMarcel Moolenaar 38*6b123571SMarcel Moolenaar #include <sys/diskmbr.h> 39*6b123571SMarcel Moolenaar #include <sys/gpt.h> 40*6b123571SMarcel Moolenaar 415aad7d9aSMarcel Moolenaar #include "endian.h" 42f0e9dcedSMarcel Moolenaar #include "image.h" 43a5eb4ea3SMarcel Moolenaar #include "mkimg.h" 44a5eb4ea3SMarcel Moolenaar #include "scheme.h" 45a5eb4ea3SMarcel Moolenaar 46f529e2e0SMarcel Moolenaar #ifndef GPT_ENT_TYPE_FREEBSD_NANDFS 47f529e2e0SMarcel Moolenaar #define GPT_ENT_TYPE_FREEBSD_NANDFS \ 48f529e2e0SMarcel Moolenaar {0x74ba7dd9,0xa689,0x11e1,0xbd,0x04,{0x00,0xe0,0x81,0x28,0x6a,0xcf}} 49f529e2e0SMarcel Moolenaar #endif 50f529e2e0SMarcel Moolenaar 51a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_efi = GPT_ENT_TYPE_EFI; 52a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD; 53a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; 54a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS; 55a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; 56a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; 57a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; 58a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; 59a5eb4ea3SMarcel Moolenaar static uuid_t gpt_uuid_mbr = GPT_ENT_TYPE_MBR; 608adccff3SMarcel Moolenaar static uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; 61a5eb4ea3SMarcel Moolenaar 62a5eb4ea3SMarcel Moolenaar static struct mkimg_alias gpt_aliases[] = { 63a5eb4ea3SMarcel Moolenaar { ALIAS_EFI, ALIAS_PTR2TYPE(&gpt_uuid_efi) }, 64a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD, ALIAS_PTR2TYPE(&gpt_uuid_freebsd) }, 65a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_boot) }, 66a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_nandfs) }, 67a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_swap) }, 68a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_ufs) }, 69a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_vinum) }, 70a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_zfs) }, 71a5eb4ea3SMarcel Moolenaar { ALIAS_MBR, ALIAS_PTR2TYPE(&gpt_uuid_mbr) }, 728adccff3SMarcel Moolenaar { ALIAS_NTFS, ALIAS_PTR2TYPE(&gpt_uuid_ms_basic_data) }, 73a5eb4ea3SMarcel Moolenaar { ALIAS_NONE, 0 } /* Keep last! */ 74a5eb4ea3SMarcel Moolenaar }; 75a5eb4ea3SMarcel Moolenaar 76a5eb4ea3SMarcel Moolenaar /* CRC32 code derived from work by Gary S. Brown. */ 77a5eb4ea3SMarcel Moolenaar static const uint32_t crc32_tab[] = { 78a5eb4ea3SMarcel Moolenaar 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 79a5eb4ea3SMarcel Moolenaar 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 80a5eb4ea3SMarcel Moolenaar 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 81a5eb4ea3SMarcel Moolenaar 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 82a5eb4ea3SMarcel Moolenaar 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 83a5eb4ea3SMarcel Moolenaar 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 84a5eb4ea3SMarcel Moolenaar 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 85a5eb4ea3SMarcel Moolenaar 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 86a5eb4ea3SMarcel Moolenaar 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 87a5eb4ea3SMarcel Moolenaar 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 88a5eb4ea3SMarcel Moolenaar 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 89a5eb4ea3SMarcel Moolenaar 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 90a5eb4ea3SMarcel Moolenaar 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 91a5eb4ea3SMarcel Moolenaar 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 92a5eb4ea3SMarcel Moolenaar 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 93a5eb4ea3SMarcel Moolenaar 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 94a5eb4ea3SMarcel Moolenaar 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 95a5eb4ea3SMarcel Moolenaar 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 96a5eb4ea3SMarcel Moolenaar 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 97a5eb4ea3SMarcel Moolenaar 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 98a5eb4ea3SMarcel Moolenaar 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 99a5eb4ea3SMarcel Moolenaar 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 100a5eb4ea3SMarcel Moolenaar 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 101a5eb4ea3SMarcel Moolenaar 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 102a5eb4ea3SMarcel Moolenaar 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 103a5eb4ea3SMarcel Moolenaar 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 104a5eb4ea3SMarcel Moolenaar 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 105a5eb4ea3SMarcel Moolenaar 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 106a5eb4ea3SMarcel Moolenaar 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 107a5eb4ea3SMarcel Moolenaar 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 108a5eb4ea3SMarcel Moolenaar 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 109a5eb4ea3SMarcel Moolenaar 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 110a5eb4ea3SMarcel Moolenaar 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 111a5eb4ea3SMarcel Moolenaar 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 112a5eb4ea3SMarcel Moolenaar 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 113a5eb4ea3SMarcel Moolenaar 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 114a5eb4ea3SMarcel Moolenaar 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 115a5eb4ea3SMarcel Moolenaar 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 116a5eb4ea3SMarcel Moolenaar 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 117a5eb4ea3SMarcel Moolenaar 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 118a5eb4ea3SMarcel Moolenaar 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 119a5eb4ea3SMarcel Moolenaar 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 120a5eb4ea3SMarcel Moolenaar 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 121a5eb4ea3SMarcel Moolenaar }; 122a5eb4ea3SMarcel Moolenaar 123a5eb4ea3SMarcel Moolenaar static uint32_t 124a5eb4ea3SMarcel Moolenaar crc32(const void *buf, size_t sz) 125a5eb4ea3SMarcel Moolenaar { 126a5eb4ea3SMarcel Moolenaar const uint8_t *p = (const uint8_t *)buf; 127a5eb4ea3SMarcel Moolenaar uint32_t crc = ~0U; 128a5eb4ea3SMarcel Moolenaar 129a5eb4ea3SMarcel Moolenaar while (sz--) 130a5eb4ea3SMarcel Moolenaar crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8); 131a5eb4ea3SMarcel Moolenaar return (crc ^ ~0U); 132a5eb4ea3SMarcel Moolenaar } 133a5eb4ea3SMarcel Moolenaar 1349e410826SMarcel Moolenaar static void 1359e410826SMarcel Moolenaar gpt_uuid_enc(void *buf, const uuid_t *uuid) 1369e410826SMarcel Moolenaar { 1379e410826SMarcel Moolenaar uint8_t *p = buf; 1389e410826SMarcel Moolenaar int i; 1399e410826SMarcel Moolenaar 1409e410826SMarcel Moolenaar le32enc(p, uuid->time_low); 1419e410826SMarcel Moolenaar le16enc(p + 4, uuid->time_mid); 1429e410826SMarcel Moolenaar le16enc(p + 6, uuid->time_hi_and_version); 1439e410826SMarcel Moolenaar p[8] = uuid->clock_seq_hi_and_reserved; 1449e410826SMarcel Moolenaar p[9] = uuid->clock_seq_low; 1459e410826SMarcel Moolenaar for (i = 0; i < _UUID_NODE_LEN; i++) 1469e410826SMarcel Moolenaar p[10 + i] = uuid->node[i]; 1479e410826SMarcel Moolenaar } 1489e410826SMarcel Moolenaar 149a5eb4ea3SMarcel Moolenaar static u_int 150a5eb4ea3SMarcel Moolenaar gpt_tblsz(void) 151a5eb4ea3SMarcel Moolenaar { 152a5eb4ea3SMarcel Moolenaar u_int ents; 153a5eb4ea3SMarcel Moolenaar 154a5eb4ea3SMarcel Moolenaar ents = secsz / sizeof(struct gpt_ent); 155a5eb4ea3SMarcel Moolenaar return ((nparts + ents - 1) / ents); 156a5eb4ea3SMarcel Moolenaar } 157a5eb4ea3SMarcel Moolenaar 15853fcdb2dSMarcel Moolenaar static lba_t 15953fcdb2dSMarcel Moolenaar gpt_metadata(u_int where, lba_t blk) 160a5eb4ea3SMarcel Moolenaar { 161a5eb4ea3SMarcel Moolenaar 16253fcdb2dSMarcel Moolenaar if (where == SCHEME_META_IMG_START || where == SCHEME_META_IMG_END) { 16353fcdb2dSMarcel Moolenaar blk += gpt_tblsz(); 16453fcdb2dSMarcel Moolenaar blk += (where == SCHEME_META_IMG_START) ? 2 : 1; 16553fcdb2dSMarcel Moolenaar } 16653fcdb2dSMarcel Moolenaar return (round_block(blk)); 167a5eb4ea3SMarcel Moolenaar } 168a5eb4ea3SMarcel Moolenaar 169a5eb4ea3SMarcel Moolenaar static int 170f0e9dcedSMarcel Moolenaar gpt_write_pmbr(lba_t blks, void *bootcode) 171a5eb4ea3SMarcel Moolenaar { 172a5eb4ea3SMarcel Moolenaar u_char *pmbr; 173a5eb4ea3SMarcel Moolenaar uint32_t secs; 174a5eb4ea3SMarcel Moolenaar int error; 175a5eb4ea3SMarcel Moolenaar 176a5eb4ea3SMarcel Moolenaar secs = (blks > UINT32_MAX) ? UINT32_MAX : (uint32_t)blks; 177a5eb4ea3SMarcel Moolenaar 178a5eb4ea3SMarcel Moolenaar pmbr = malloc(secsz); 179a5eb4ea3SMarcel Moolenaar if (pmbr == NULL) 180a5eb4ea3SMarcel Moolenaar return (errno); 181a5eb4ea3SMarcel Moolenaar if (bootcode != NULL) { 182a5eb4ea3SMarcel Moolenaar memcpy(pmbr, bootcode, DOSPARTOFF); 183a5eb4ea3SMarcel Moolenaar memset(pmbr + DOSPARTOFF, 0, secsz - DOSPARTOFF); 184a5eb4ea3SMarcel Moolenaar } else 185a5eb4ea3SMarcel Moolenaar memset(pmbr, 0, secsz); 186a5eb4ea3SMarcel Moolenaar pmbr[DOSPARTOFF + 2] = 2; 187a5eb4ea3SMarcel Moolenaar pmbr[DOSPARTOFF + 4] = 0xee; 188a5eb4ea3SMarcel Moolenaar pmbr[DOSPARTOFF + 5] = 0xff; 189a5eb4ea3SMarcel Moolenaar pmbr[DOSPARTOFF + 6] = 0xff; 190a5eb4ea3SMarcel Moolenaar pmbr[DOSPARTOFF + 7] = 0xff; 191a5eb4ea3SMarcel Moolenaar le32enc(pmbr + DOSPARTOFF + 8, 1); 192a5eb4ea3SMarcel Moolenaar le32enc(pmbr + DOSPARTOFF + 12, secs); 193a5eb4ea3SMarcel Moolenaar le16enc(pmbr + DOSMAGICOFFSET, DOSMAGIC); 194f0e9dcedSMarcel Moolenaar error = image_write(0, pmbr, 1); 195a5eb4ea3SMarcel Moolenaar free(pmbr); 196a5eb4ea3SMarcel Moolenaar return (error); 197a5eb4ea3SMarcel Moolenaar } 198a5eb4ea3SMarcel Moolenaar 199a5eb4ea3SMarcel Moolenaar static struct gpt_ent * 200a5eb4ea3SMarcel Moolenaar gpt_mktbl(u_int tblsz) 201a5eb4ea3SMarcel Moolenaar { 202a5eb4ea3SMarcel Moolenaar uuid_t uuid; 203a5eb4ea3SMarcel Moolenaar struct gpt_ent *tbl, *ent; 204a5eb4ea3SMarcel Moolenaar struct part *part; 205a5eb4ea3SMarcel Moolenaar int c, idx; 206a5eb4ea3SMarcel Moolenaar 207a5eb4ea3SMarcel Moolenaar tbl = calloc(tblsz, secsz); 208a5eb4ea3SMarcel Moolenaar if (tbl == NULL) 209a5eb4ea3SMarcel Moolenaar return (NULL); 210a5eb4ea3SMarcel Moolenaar 2111080fb19SMarcel Moolenaar TAILQ_FOREACH(part, &partlist, link) { 212a5eb4ea3SMarcel Moolenaar ent = tbl + part->index; 2139e410826SMarcel Moolenaar gpt_uuid_enc(&ent->ent_type, ALIAS_TYPE2PTR(part->type)); 214f3582a72SMarcel Moolenaar mkimg_uuid(&uuid); 2159e410826SMarcel Moolenaar gpt_uuid_enc(&ent->ent_uuid, &uuid); 216a5eb4ea3SMarcel Moolenaar le64enc(&ent->ent_lba_start, part->block); 217a5eb4ea3SMarcel Moolenaar le64enc(&ent->ent_lba_end, part->block + part->size - 1); 218a5eb4ea3SMarcel Moolenaar if (part->label != NULL) { 219a5eb4ea3SMarcel Moolenaar idx = 0; 220a5eb4ea3SMarcel Moolenaar while ((c = part->label[idx]) != '\0') { 221a5eb4ea3SMarcel Moolenaar le16enc(ent->ent_name + idx, c); 222a5eb4ea3SMarcel Moolenaar idx++; 223a5eb4ea3SMarcel Moolenaar } 224a5eb4ea3SMarcel Moolenaar } 225a5eb4ea3SMarcel Moolenaar } 226a5eb4ea3SMarcel Moolenaar return (tbl); 227a5eb4ea3SMarcel Moolenaar } 228a5eb4ea3SMarcel Moolenaar 229a5eb4ea3SMarcel Moolenaar static int 230f0e9dcedSMarcel Moolenaar gpt_write_hdr(struct gpt_hdr *hdr, uint64_t self, uint64_t alt, uint64_t tbl) 231a5eb4ea3SMarcel Moolenaar { 232a5eb4ea3SMarcel Moolenaar uint32_t crc; 233a5eb4ea3SMarcel Moolenaar 234a5eb4ea3SMarcel Moolenaar le64enc(&hdr->hdr_lba_self, self); 235a5eb4ea3SMarcel Moolenaar le64enc(&hdr->hdr_lba_alt, alt); 236a5eb4ea3SMarcel Moolenaar le64enc(&hdr->hdr_lba_table, tbl); 237a5eb4ea3SMarcel Moolenaar hdr->hdr_crc_self = 0; 238a5eb4ea3SMarcel Moolenaar crc = crc32(hdr, offsetof(struct gpt_hdr, padding)); 239a5eb4ea3SMarcel Moolenaar le64enc(&hdr->hdr_crc_self, crc); 240f0e9dcedSMarcel Moolenaar return (image_write(self, hdr, 1)); 241a5eb4ea3SMarcel Moolenaar } 242a5eb4ea3SMarcel Moolenaar 243a5eb4ea3SMarcel Moolenaar static int 244f0e9dcedSMarcel Moolenaar gpt_write(lba_t imgsz, void *bootcode) 245a5eb4ea3SMarcel Moolenaar { 246a5eb4ea3SMarcel Moolenaar uuid_t uuid; 247a5eb4ea3SMarcel Moolenaar struct gpt_ent *tbl; 248a5eb4ea3SMarcel Moolenaar struct gpt_hdr *hdr; 249a5eb4ea3SMarcel Moolenaar uint32_t crc; 250a5eb4ea3SMarcel Moolenaar u_int tblsz; 251a5eb4ea3SMarcel Moolenaar int error; 252a5eb4ea3SMarcel Moolenaar 253a5eb4ea3SMarcel Moolenaar /* PMBR */ 254f0e9dcedSMarcel Moolenaar error = gpt_write_pmbr(imgsz, bootcode); 255a5eb4ea3SMarcel Moolenaar if (error) 256a5eb4ea3SMarcel Moolenaar return (error); 257a5eb4ea3SMarcel Moolenaar 258a5eb4ea3SMarcel Moolenaar /* GPT table(s) */ 259a5eb4ea3SMarcel Moolenaar tblsz = gpt_tblsz(); 260a5eb4ea3SMarcel Moolenaar tbl = gpt_mktbl(tblsz); 261a5eb4ea3SMarcel Moolenaar if (tbl == NULL) 262a5eb4ea3SMarcel Moolenaar return (errno); 263f0e9dcedSMarcel Moolenaar error = image_write(2, tbl, tblsz); 264a5eb4ea3SMarcel Moolenaar if (error) 265a5eb4ea3SMarcel Moolenaar goto out; 266f0e9dcedSMarcel Moolenaar error = image_write(imgsz - (tblsz + 1), tbl, tblsz); 267a5eb4ea3SMarcel Moolenaar if (error) 268a5eb4ea3SMarcel Moolenaar goto out; 269a5eb4ea3SMarcel Moolenaar 270a5eb4ea3SMarcel Moolenaar /* GPT header(s) */ 271a5eb4ea3SMarcel Moolenaar hdr = malloc(secsz); 272a5eb4ea3SMarcel Moolenaar if (hdr == NULL) { 273a5eb4ea3SMarcel Moolenaar error = errno; 274a5eb4ea3SMarcel Moolenaar goto out; 275a5eb4ea3SMarcel Moolenaar } 276a5eb4ea3SMarcel Moolenaar memset(hdr, 0, secsz); 277a5eb4ea3SMarcel Moolenaar memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)); 278a5eb4ea3SMarcel Moolenaar le32enc(&hdr->hdr_revision, GPT_HDR_REVISION); 279a5eb4ea3SMarcel Moolenaar le32enc(&hdr->hdr_size, offsetof(struct gpt_hdr, padding)); 280a5eb4ea3SMarcel Moolenaar le64enc(&hdr->hdr_lba_start, 2 + tblsz); 281a5eb4ea3SMarcel Moolenaar le64enc(&hdr->hdr_lba_end, imgsz - tblsz - 2); 282f3582a72SMarcel Moolenaar mkimg_uuid(&uuid); 2839e410826SMarcel Moolenaar gpt_uuid_enc(&hdr->hdr_uuid, &uuid); 284a5eb4ea3SMarcel Moolenaar le32enc(&hdr->hdr_entries, nparts); 285a5eb4ea3SMarcel Moolenaar le32enc(&hdr->hdr_entsz, sizeof(struct gpt_ent)); 286a5eb4ea3SMarcel Moolenaar crc = crc32(tbl, nparts * sizeof(struct gpt_ent)); 287a5eb4ea3SMarcel Moolenaar le32enc(&hdr->hdr_crc_table, crc); 288f0e9dcedSMarcel Moolenaar error = gpt_write_hdr(hdr, 1, imgsz - 1, 2); 289a5eb4ea3SMarcel Moolenaar if (!error) 290f0e9dcedSMarcel Moolenaar error = gpt_write_hdr(hdr, imgsz - 1, 1, imgsz - tblsz - 1); 291a5eb4ea3SMarcel Moolenaar free(hdr); 292a5eb4ea3SMarcel Moolenaar 293a5eb4ea3SMarcel Moolenaar out: 294a5eb4ea3SMarcel Moolenaar free(tbl); 295a5eb4ea3SMarcel Moolenaar return (error); 296a5eb4ea3SMarcel Moolenaar } 297a5eb4ea3SMarcel Moolenaar 298a5eb4ea3SMarcel Moolenaar static struct mkimg_scheme gpt_scheme = { 299a5eb4ea3SMarcel Moolenaar .name = "gpt", 300a5eb4ea3SMarcel Moolenaar .description = "GUID Partition Table", 301a5eb4ea3SMarcel Moolenaar .aliases = gpt_aliases, 302a5eb4ea3SMarcel Moolenaar .metadata = gpt_metadata, 303a5eb4ea3SMarcel Moolenaar .write = gpt_write, 304a5eb4ea3SMarcel Moolenaar .nparts = 4096, 305a5eb4ea3SMarcel Moolenaar .labellen = 36, 306a5eb4ea3SMarcel Moolenaar .bootcode = 512, 307a5eb4ea3SMarcel Moolenaar .maxsecsz = 4096 308a5eb4ea3SMarcel Moolenaar }; 309a5eb4ea3SMarcel Moolenaar 310a5eb4ea3SMarcel Moolenaar SCHEME_DEFINE(gpt_scheme); 311