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/types.h> 31a5eb4ea3SMarcel Moolenaar #include <sys/diskmbr.h> 32a5eb4ea3SMarcel Moolenaar #include <sys/endian.h> 33a5eb4ea3SMarcel Moolenaar #include <sys/errno.h> 34a5eb4ea3SMarcel Moolenaar #include <sys/gpt.h> 35a5eb4ea3SMarcel Moolenaar #include <stddef.h> 36a5eb4ea3SMarcel Moolenaar #include <stdint.h> 37a5eb4ea3SMarcel Moolenaar #include <stdlib.h> 38a5eb4ea3SMarcel Moolenaar #include <string.h> 39a5eb4ea3SMarcel Moolenaar #include <unistd.h> 40a5eb4ea3SMarcel Moolenaar #include <uuid.h> 41a5eb4ea3SMarcel Moolenaar 42*f0e9dcedSMarcel 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; 60a5eb4ea3SMarcel Moolenaar 61a5eb4ea3SMarcel Moolenaar static struct mkimg_alias gpt_aliases[] = { 62a5eb4ea3SMarcel Moolenaar { ALIAS_EFI, ALIAS_PTR2TYPE(&gpt_uuid_efi) }, 63a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD, ALIAS_PTR2TYPE(&gpt_uuid_freebsd) }, 64a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_boot) }, 65a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_nandfs) }, 66a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_swap) }, 67a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_ufs) }, 68a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_vinum) }, 69a5eb4ea3SMarcel Moolenaar { ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_zfs) }, 70a5eb4ea3SMarcel Moolenaar { ALIAS_MBR, ALIAS_PTR2TYPE(&gpt_uuid_mbr) }, 71a5eb4ea3SMarcel Moolenaar { ALIAS_NONE, 0 } /* Keep last! */ 72a5eb4ea3SMarcel Moolenaar }; 73a5eb4ea3SMarcel Moolenaar 74a5eb4ea3SMarcel Moolenaar /* CRC32 code derived from work by Gary S. Brown. */ 75a5eb4ea3SMarcel Moolenaar static const uint32_t crc32_tab[] = { 76a5eb4ea3SMarcel Moolenaar 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 77a5eb4ea3SMarcel Moolenaar 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 78a5eb4ea3SMarcel Moolenaar 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 79a5eb4ea3SMarcel Moolenaar 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 80a5eb4ea3SMarcel Moolenaar 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 81a5eb4ea3SMarcel Moolenaar 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 82a5eb4ea3SMarcel Moolenaar 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 83a5eb4ea3SMarcel Moolenaar 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 84a5eb4ea3SMarcel Moolenaar 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 85a5eb4ea3SMarcel Moolenaar 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 86a5eb4ea3SMarcel Moolenaar 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 87a5eb4ea3SMarcel Moolenaar 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 88a5eb4ea3SMarcel Moolenaar 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 89a5eb4ea3SMarcel Moolenaar 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 90a5eb4ea3SMarcel Moolenaar 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 91a5eb4ea3SMarcel Moolenaar 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 92a5eb4ea3SMarcel Moolenaar 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 93a5eb4ea3SMarcel Moolenaar 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 94a5eb4ea3SMarcel Moolenaar 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 95a5eb4ea3SMarcel Moolenaar 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 96a5eb4ea3SMarcel Moolenaar 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 97a5eb4ea3SMarcel Moolenaar 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 98a5eb4ea3SMarcel Moolenaar 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 99a5eb4ea3SMarcel Moolenaar 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 100a5eb4ea3SMarcel Moolenaar 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 101a5eb4ea3SMarcel Moolenaar 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 102a5eb4ea3SMarcel Moolenaar 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 103a5eb4ea3SMarcel Moolenaar 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 104a5eb4ea3SMarcel Moolenaar 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 105a5eb4ea3SMarcel Moolenaar 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 106a5eb4ea3SMarcel Moolenaar 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 107a5eb4ea3SMarcel Moolenaar 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 108a5eb4ea3SMarcel Moolenaar 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 109a5eb4ea3SMarcel Moolenaar 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 110a5eb4ea3SMarcel Moolenaar 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 111a5eb4ea3SMarcel Moolenaar 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 112a5eb4ea3SMarcel Moolenaar 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 113a5eb4ea3SMarcel Moolenaar 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 114a5eb4ea3SMarcel Moolenaar 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 115a5eb4ea3SMarcel Moolenaar 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 116a5eb4ea3SMarcel Moolenaar 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 117a5eb4ea3SMarcel Moolenaar 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 118a5eb4ea3SMarcel Moolenaar 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 119a5eb4ea3SMarcel Moolenaar }; 120a5eb4ea3SMarcel Moolenaar 121a5eb4ea3SMarcel Moolenaar static uint32_t 122a5eb4ea3SMarcel Moolenaar crc32(const void *buf, size_t sz) 123a5eb4ea3SMarcel Moolenaar { 124a5eb4ea3SMarcel Moolenaar const uint8_t *p = (const uint8_t *)buf; 125a5eb4ea3SMarcel Moolenaar uint32_t crc = ~0U; 126a5eb4ea3SMarcel Moolenaar 127a5eb4ea3SMarcel Moolenaar while (sz--) 128a5eb4ea3SMarcel Moolenaar crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8); 129a5eb4ea3SMarcel Moolenaar return (crc ^ ~0U); 130a5eb4ea3SMarcel Moolenaar } 131a5eb4ea3SMarcel Moolenaar 1329e410826SMarcel Moolenaar static void 1339e410826SMarcel Moolenaar gpt_uuid_enc(void *buf, const uuid_t *uuid) 1349e410826SMarcel Moolenaar { 1359e410826SMarcel Moolenaar uint8_t *p = buf; 1369e410826SMarcel Moolenaar int i; 1379e410826SMarcel Moolenaar 1389e410826SMarcel Moolenaar le32enc(p, uuid->time_low); 1399e410826SMarcel Moolenaar le16enc(p + 4, uuid->time_mid); 1409e410826SMarcel Moolenaar le16enc(p + 6, uuid->time_hi_and_version); 1419e410826SMarcel Moolenaar p[8] = uuid->clock_seq_hi_and_reserved; 1429e410826SMarcel Moolenaar p[9] = uuid->clock_seq_low; 1439e410826SMarcel Moolenaar for (i = 0; i < _UUID_NODE_LEN; i++) 1449e410826SMarcel Moolenaar p[10 + i] = uuid->node[i]; 1459e410826SMarcel Moolenaar } 1469e410826SMarcel Moolenaar 147a5eb4ea3SMarcel Moolenaar static u_int 148a5eb4ea3SMarcel Moolenaar gpt_tblsz(void) 149a5eb4ea3SMarcel Moolenaar { 150a5eb4ea3SMarcel Moolenaar u_int ents; 151a5eb4ea3SMarcel Moolenaar 152a5eb4ea3SMarcel Moolenaar ents = secsz / sizeof(struct gpt_ent); 153a5eb4ea3SMarcel Moolenaar return ((nparts + ents - 1) / ents); 154a5eb4ea3SMarcel Moolenaar } 155a5eb4ea3SMarcel Moolenaar 156a5eb4ea3SMarcel Moolenaar static u_int 157a5eb4ea3SMarcel Moolenaar gpt_metadata(u_int where) 158a5eb4ea3SMarcel Moolenaar { 159a5eb4ea3SMarcel Moolenaar u_int secs; 160a5eb4ea3SMarcel Moolenaar 161a5eb4ea3SMarcel Moolenaar if (where != SCHEME_META_IMG_START && where != SCHEME_META_IMG_END) 162a5eb4ea3SMarcel Moolenaar return (0); 163a5eb4ea3SMarcel Moolenaar 164a5eb4ea3SMarcel Moolenaar secs = gpt_tblsz(); 165a5eb4ea3SMarcel Moolenaar secs += (where == SCHEME_META_IMG_START) ? 2 : 1; 166a5eb4ea3SMarcel Moolenaar return (secs); 167a5eb4ea3SMarcel Moolenaar } 168a5eb4ea3SMarcel Moolenaar 169a5eb4ea3SMarcel Moolenaar static int 170*f0e9dcedSMarcel 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); 194*f0e9dcedSMarcel 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 211a5eb4ea3SMarcel Moolenaar STAILQ_FOREACH(part, &partlist, link) { 212a5eb4ea3SMarcel Moolenaar ent = tbl + part->index; 2139e410826SMarcel Moolenaar gpt_uuid_enc(&ent->ent_type, ALIAS_TYPE2PTR(part->type)); 214a5eb4ea3SMarcel Moolenaar uuidgen(&uuid, 1); 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 230*f0e9dcedSMarcel 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); 240*f0e9dcedSMarcel Moolenaar return (image_write(self, hdr, 1)); 241a5eb4ea3SMarcel Moolenaar } 242a5eb4ea3SMarcel Moolenaar 243a5eb4ea3SMarcel Moolenaar static int 244*f0e9dcedSMarcel 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 */ 254*f0e9dcedSMarcel 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); 263*f0e9dcedSMarcel Moolenaar error = image_write(2, tbl, tblsz); 264a5eb4ea3SMarcel Moolenaar if (error) 265a5eb4ea3SMarcel Moolenaar goto out; 266*f0e9dcedSMarcel 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); 282a5eb4ea3SMarcel Moolenaar uuidgen(&uuid, 1); 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); 288*f0e9dcedSMarcel Moolenaar error = gpt_write_hdr(hdr, 1, imgsz - 1, 2); 289a5eb4ea3SMarcel Moolenaar if (!error) 290*f0e9dcedSMarcel 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