xref: /freebsd/usr.bin/mkimg/gpt.c (revision 835adc6898cfb0725e60e5279acdb822280acd76)
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 
3642997114SMarcel Moolenaar #include <gpt.h>
3742997114SMarcel Moolenaar #include <mbr.h>
386b123571SMarcel Moolenaar 
395aad7d9aSMarcel Moolenaar #include "endian.h"
40f0e9dcedSMarcel Moolenaar #include "image.h"
41a5eb4ea3SMarcel Moolenaar #include "mkimg.h"
42a5eb4ea3SMarcel Moolenaar #include "scheme.h"
43a5eb4ea3SMarcel Moolenaar 
4442997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_efi = GPT_ENT_TYPE_EFI;
4542997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD;
4642997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
4742997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS;
4842997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
4942997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
5042997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
5142997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
5242997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_mbr = GPT_ENT_TYPE_MBR;
5342997114SMarcel Moolenaar static mkimg_uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
54a5eb4ea3SMarcel Moolenaar 
55a5eb4ea3SMarcel Moolenaar static struct mkimg_alias gpt_aliases[] = {
56a5eb4ea3SMarcel Moolenaar     {	ALIAS_EFI, ALIAS_PTR2TYPE(&gpt_uuid_efi) },
57a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD, ALIAS_PTR2TYPE(&gpt_uuid_freebsd) },
58a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_boot) },
59a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_nandfs) },
60a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_swap) },
61a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_ufs) },
62a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_vinum) },
63a5eb4ea3SMarcel Moolenaar     {	ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_zfs) },
64a5eb4ea3SMarcel Moolenaar     {	ALIAS_MBR, ALIAS_PTR2TYPE(&gpt_uuid_mbr) },
658adccff3SMarcel Moolenaar     {	ALIAS_NTFS, ALIAS_PTR2TYPE(&gpt_uuid_ms_basic_data) },
66a5eb4ea3SMarcel Moolenaar     {	ALIAS_NONE, 0 }		/* Keep last! */
67a5eb4ea3SMarcel Moolenaar };
68a5eb4ea3SMarcel Moolenaar 
69a5eb4ea3SMarcel Moolenaar /* CRC32 code derived from work by Gary S. Brown. */
70a5eb4ea3SMarcel Moolenaar static const uint32_t crc32_tab[] = {
71a5eb4ea3SMarcel Moolenaar 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
72a5eb4ea3SMarcel Moolenaar 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
73a5eb4ea3SMarcel Moolenaar 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
74a5eb4ea3SMarcel Moolenaar 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
75a5eb4ea3SMarcel Moolenaar 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
76a5eb4ea3SMarcel Moolenaar 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
77a5eb4ea3SMarcel Moolenaar 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
78a5eb4ea3SMarcel Moolenaar 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
79a5eb4ea3SMarcel Moolenaar 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
80a5eb4ea3SMarcel Moolenaar 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
81a5eb4ea3SMarcel Moolenaar 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
82a5eb4ea3SMarcel Moolenaar 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
83a5eb4ea3SMarcel Moolenaar 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
84a5eb4ea3SMarcel Moolenaar 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
85a5eb4ea3SMarcel Moolenaar 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
86a5eb4ea3SMarcel Moolenaar 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
87a5eb4ea3SMarcel Moolenaar 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
88a5eb4ea3SMarcel Moolenaar 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
89a5eb4ea3SMarcel Moolenaar 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
90a5eb4ea3SMarcel Moolenaar 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
91a5eb4ea3SMarcel Moolenaar 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
92a5eb4ea3SMarcel Moolenaar 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
93a5eb4ea3SMarcel Moolenaar 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
94a5eb4ea3SMarcel Moolenaar 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
95a5eb4ea3SMarcel Moolenaar 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
96a5eb4ea3SMarcel Moolenaar 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
97a5eb4ea3SMarcel Moolenaar 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
98a5eb4ea3SMarcel Moolenaar 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
99a5eb4ea3SMarcel Moolenaar 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
100a5eb4ea3SMarcel Moolenaar 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
101a5eb4ea3SMarcel Moolenaar 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
102a5eb4ea3SMarcel Moolenaar 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
103a5eb4ea3SMarcel Moolenaar 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
104a5eb4ea3SMarcel Moolenaar 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
105a5eb4ea3SMarcel Moolenaar 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
106a5eb4ea3SMarcel Moolenaar 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
107a5eb4ea3SMarcel Moolenaar 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
108a5eb4ea3SMarcel Moolenaar 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
109a5eb4ea3SMarcel Moolenaar 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
110a5eb4ea3SMarcel Moolenaar 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
111a5eb4ea3SMarcel Moolenaar 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
112a5eb4ea3SMarcel Moolenaar 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
113a5eb4ea3SMarcel Moolenaar 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
114a5eb4ea3SMarcel Moolenaar };
115a5eb4ea3SMarcel Moolenaar 
116a5eb4ea3SMarcel Moolenaar static uint32_t
117a5eb4ea3SMarcel Moolenaar crc32(const void *buf, size_t sz)
118a5eb4ea3SMarcel Moolenaar {
119a5eb4ea3SMarcel Moolenaar 	const uint8_t *p = (const uint8_t *)buf;
120a5eb4ea3SMarcel Moolenaar 	uint32_t crc = ~0U;
121a5eb4ea3SMarcel Moolenaar 
122a5eb4ea3SMarcel Moolenaar 	while (sz--)
123a5eb4ea3SMarcel Moolenaar 		crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
124a5eb4ea3SMarcel Moolenaar 	return (crc ^ ~0U);
125a5eb4ea3SMarcel Moolenaar }
126a5eb4ea3SMarcel Moolenaar 
127a5eb4ea3SMarcel Moolenaar static u_int
128a5eb4ea3SMarcel Moolenaar gpt_tblsz(void)
129a5eb4ea3SMarcel Moolenaar {
130a5eb4ea3SMarcel Moolenaar 	u_int ents;
131a5eb4ea3SMarcel Moolenaar 
132a5eb4ea3SMarcel Moolenaar 	ents = secsz / sizeof(struct gpt_ent);
133a5eb4ea3SMarcel Moolenaar 	return ((nparts + ents - 1) / ents);
134a5eb4ea3SMarcel Moolenaar }
135a5eb4ea3SMarcel Moolenaar 
13653fcdb2dSMarcel Moolenaar static lba_t
13753fcdb2dSMarcel Moolenaar gpt_metadata(u_int where, lba_t blk)
138a5eb4ea3SMarcel Moolenaar {
139a5eb4ea3SMarcel Moolenaar 
14053fcdb2dSMarcel Moolenaar 	if (where == SCHEME_META_IMG_START || where == SCHEME_META_IMG_END) {
14153fcdb2dSMarcel Moolenaar 		blk += gpt_tblsz();
14253fcdb2dSMarcel Moolenaar 		blk += (where == SCHEME_META_IMG_START) ? 2 : 1;
14353fcdb2dSMarcel Moolenaar 	}
14453fcdb2dSMarcel Moolenaar 	return (round_block(blk));
145a5eb4ea3SMarcel Moolenaar }
146a5eb4ea3SMarcel Moolenaar 
147a5eb4ea3SMarcel Moolenaar static int
148f0e9dcedSMarcel Moolenaar gpt_write_pmbr(lba_t blks, void *bootcode)
149a5eb4ea3SMarcel Moolenaar {
150a5eb4ea3SMarcel Moolenaar 	u_char *pmbr;
151a5eb4ea3SMarcel Moolenaar 	uint32_t secs;
152a5eb4ea3SMarcel Moolenaar 	int error;
153a5eb4ea3SMarcel Moolenaar 
1546b14aecaSEmmanuel Vadot 	secs = (blks > UINT32_MAX) ? UINT32_MAX : (uint32_t)blks - 1;
155a5eb4ea3SMarcel Moolenaar 
156a5eb4ea3SMarcel Moolenaar 	pmbr = malloc(secsz);
157a5eb4ea3SMarcel Moolenaar 	if (pmbr == NULL)
158a5eb4ea3SMarcel Moolenaar 		return (errno);
159a5eb4ea3SMarcel Moolenaar 	if (bootcode != NULL) {
160a5eb4ea3SMarcel Moolenaar 		memcpy(pmbr, bootcode, DOSPARTOFF);
161a5eb4ea3SMarcel Moolenaar 		memset(pmbr + DOSPARTOFF, 0, secsz - DOSPARTOFF);
162a5eb4ea3SMarcel Moolenaar 	} else
163a5eb4ea3SMarcel Moolenaar 		memset(pmbr, 0, secsz);
164a5eb4ea3SMarcel Moolenaar 	pmbr[DOSPARTOFF + 2] = 2;
165a5eb4ea3SMarcel Moolenaar 	pmbr[DOSPARTOFF + 4] = 0xee;
166a5eb4ea3SMarcel Moolenaar 	pmbr[DOSPARTOFF + 5] = 0xff;
167a5eb4ea3SMarcel Moolenaar 	pmbr[DOSPARTOFF + 6] = 0xff;
168a5eb4ea3SMarcel Moolenaar 	pmbr[DOSPARTOFF + 7] = 0xff;
169a5eb4ea3SMarcel Moolenaar 	le32enc(pmbr + DOSPARTOFF + 8, 1);
170a5eb4ea3SMarcel Moolenaar 	le32enc(pmbr + DOSPARTOFF + 12, secs);
171a5eb4ea3SMarcel Moolenaar 	le16enc(pmbr + DOSMAGICOFFSET, DOSMAGIC);
172f0e9dcedSMarcel Moolenaar 	error = image_write(0, pmbr, 1);
173a5eb4ea3SMarcel Moolenaar 	free(pmbr);
174a5eb4ea3SMarcel Moolenaar 	return (error);
175a5eb4ea3SMarcel Moolenaar }
176a5eb4ea3SMarcel Moolenaar 
177a5eb4ea3SMarcel Moolenaar static struct gpt_ent *
178a5eb4ea3SMarcel Moolenaar gpt_mktbl(u_int tblsz)
179a5eb4ea3SMarcel Moolenaar {
18042997114SMarcel Moolenaar 	mkimg_uuid_t uuid;
181a5eb4ea3SMarcel Moolenaar 	struct gpt_ent *tbl, *ent;
182a5eb4ea3SMarcel Moolenaar 	struct part *part;
183a5eb4ea3SMarcel Moolenaar 	int c, idx;
184a5eb4ea3SMarcel Moolenaar 
185a5eb4ea3SMarcel Moolenaar 	tbl = calloc(tblsz, secsz);
186a5eb4ea3SMarcel Moolenaar 	if (tbl == NULL)
187a5eb4ea3SMarcel Moolenaar 		return (NULL);
188a5eb4ea3SMarcel Moolenaar 
1891080fb19SMarcel Moolenaar 	TAILQ_FOREACH(part, &partlist, link) {
190a5eb4ea3SMarcel Moolenaar 		ent = tbl + part->index;
19142997114SMarcel Moolenaar 		mkimg_uuid_enc(&ent->ent_type, ALIAS_TYPE2PTR(part->type));
192f3582a72SMarcel Moolenaar 		mkimg_uuid(&uuid);
19342997114SMarcel Moolenaar 		mkimg_uuid_enc(&ent->ent_uuid, &uuid);
194a5eb4ea3SMarcel Moolenaar 		le64enc(&ent->ent_lba_start, part->block);
195a5eb4ea3SMarcel Moolenaar 		le64enc(&ent->ent_lba_end, part->block + part->size - 1);
196a5eb4ea3SMarcel Moolenaar 		if (part->label != NULL) {
197a5eb4ea3SMarcel Moolenaar 			idx = 0;
198a5eb4ea3SMarcel Moolenaar 			while ((c = part->label[idx]) != '\0') {
199a5eb4ea3SMarcel Moolenaar 				le16enc(ent->ent_name + idx, c);
200a5eb4ea3SMarcel Moolenaar 				idx++;
201a5eb4ea3SMarcel Moolenaar 			}
202a5eb4ea3SMarcel Moolenaar 		}
203a5eb4ea3SMarcel Moolenaar 	}
204a5eb4ea3SMarcel Moolenaar 	return (tbl);
205a5eb4ea3SMarcel Moolenaar }
206a5eb4ea3SMarcel Moolenaar 
207a5eb4ea3SMarcel Moolenaar static int
208f0e9dcedSMarcel Moolenaar gpt_write_hdr(struct gpt_hdr *hdr, uint64_t self, uint64_t alt, uint64_t tbl)
209a5eb4ea3SMarcel Moolenaar {
210a5eb4ea3SMarcel Moolenaar 	uint32_t crc;
211a5eb4ea3SMarcel Moolenaar 
212a5eb4ea3SMarcel Moolenaar 	le64enc(&hdr->hdr_lba_self, self);
213a5eb4ea3SMarcel Moolenaar 	le64enc(&hdr->hdr_lba_alt, alt);
214a5eb4ea3SMarcel Moolenaar 	le64enc(&hdr->hdr_lba_table, tbl);
215a5eb4ea3SMarcel Moolenaar 	hdr->hdr_crc_self = 0;
216a5eb4ea3SMarcel Moolenaar 	crc = crc32(hdr, offsetof(struct gpt_hdr, padding));
217a5eb4ea3SMarcel Moolenaar 	le64enc(&hdr->hdr_crc_self, crc);
218f0e9dcedSMarcel Moolenaar 	return (image_write(self, hdr, 1));
219a5eb4ea3SMarcel Moolenaar }
220a5eb4ea3SMarcel Moolenaar 
221a5eb4ea3SMarcel Moolenaar static int
222f0e9dcedSMarcel Moolenaar gpt_write(lba_t imgsz, void *bootcode)
223a5eb4ea3SMarcel Moolenaar {
22442997114SMarcel Moolenaar 	mkimg_uuid_t uuid;
225a5eb4ea3SMarcel Moolenaar 	struct gpt_ent *tbl;
226a5eb4ea3SMarcel Moolenaar 	struct gpt_hdr *hdr;
227a5eb4ea3SMarcel Moolenaar 	uint32_t crc;
228a5eb4ea3SMarcel Moolenaar 	u_int tblsz;
229a5eb4ea3SMarcel Moolenaar 	int error;
230a5eb4ea3SMarcel Moolenaar 
231a5eb4ea3SMarcel Moolenaar 	/* PMBR */
232f0e9dcedSMarcel Moolenaar 	error = gpt_write_pmbr(imgsz, bootcode);
233a5eb4ea3SMarcel Moolenaar 	if (error)
234a5eb4ea3SMarcel Moolenaar 		return (error);
235a5eb4ea3SMarcel Moolenaar 
236a5eb4ea3SMarcel Moolenaar 	/* GPT table(s) */
237a5eb4ea3SMarcel Moolenaar 	tblsz = gpt_tblsz();
238a5eb4ea3SMarcel Moolenaar 	tbl = gpt_mktbl(tblsz);
239a5eb4ea3SMarcel Moolenaar 	if (tbl == NULL)
240a5eb4ea3SMarcel Moolenaar 		return (errno);
241f0e9dcedSMarcel Moolenaar 	error = image_write(2, tbl, tblsz);
242a5eb4ea3SMarcel Moolenaar 	if (error)
243a5eb4ea3SMarcel Moolenaar 		goto out;
244f0e9dcedSMarcel Moolenaar 	error = image_write(imgsz - (tblsz + 1), tbl, tblsz);
245a5eb4ea3SMarcel Moolenaar 	if (error)
246a5eb4ea3SMarcel Moolenaar 		goto out;
247a5eb4ea3SMarcel Moolenaar 
248a5eb4ea3SMarcel Moolenaar 	/* GPT header(s) */
249a5eb4ea3SMarcel Moolenaar 	hdr = malloc(secsz);
250a5eb4ea3SMarcel Moolenaar 	if (hdr == NULL) {
251a5eb4ea3SMarcel Moolenaar 		error = errno;
252a5eb4ea3SMarcel Moolenaar 		goto out;
253a5eb4ea3SMarcel Moolenaar 	}
254a5eb4ea3SMarcel Moolenaar 	memset(hdr, 0, secsz);
255a5eb4ea3SMarcel Moolenaar 	memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
256a5eb4ea3SMarcel Moolenaar 	le32enc(&hdr->hdr_revision, GPT_HDR_REVISION);
257a5eb4ea3SMarcel Moolenaar 	le32enc(&hdr->hdr_size, offsetof(struct gpt_hdr, padding));
258a5eb4ea3SMarcel Moolenaar 	le64enc(&hdr->hdr_lba_start, 2 + tblsz);
259a5eb4ea3SMarcel Moolenaar 	le64enc(&hdr->hdr_lba_end, imgsz - tblsz - 2);
260f3582a72SMarcel Moolenaar 	mkimg_uuid(&uuid);
26142997114SMarcel Moolenaar 	mkimg_uuid_enc(&hdr->hdr_uuid, &uuid);
262*835adc68SMarcel Moolenaar 	le32enc(&hdr->hdr_entries, tblsz * secsz / sizeof(struct gpt_ent));
263a5eb4ea3SMarcel Moolenaar 	le32enc(&hdr->hdr_entsz, sizeof(struct gpt_ent));
264*835adc68SMarcel Moolenaar 	crc = crc32(tbl, tblsz * secsz);
265a5eb4ea3SMarcel Moolenaar 	le32enc(&hdr->hdr_crc_table, crc);
266f0e9dcedSMarcel Moolenaar 	error = gpt_write_hdr(hdr, 1, imgsz - 1, 2);
267a5eb4ea3SMarcel Moolenaar 	if (!error)
268f0e9dcedSMarcel Moolenaar 		error = gpt_write_hdr(hdr, imgsz - 1, 1, imgsz - tblsz - 1);
269a5eb4ea3SMarcel Moolenaar 	free(hdr);
270a5eb4ea3SMarcel Moolenaar 
271a5eb4ea3SMarcel Moolenaar  out:
272a5eb4ea3SMarcel Moolenaar 	free(tbl);
273a5eb4ea3SMarcel Moolenaar 	return (error);
274a5eb4ea3SMarcel Moolenaar }
275a5eb4ea3SMarcel Moolenaar 
276a5eb4ea3SMarcel Moolenaar static struct mkimg_scheme gpt_scheme = {
277a5eb4ea3SMarcel Moolenaar 	.name = "gpt",
278a5eb4ea3SMarcel Moolenaar 	.description = "GUID Partition Table",
279a5eb4ea3SMarcel Moolenaar 	.aliases = gpt_aliases,
280a5eb4ea3SMarcel Moolenaar 	.metadata = gpt_metadata,
281a5eb4ea3SMarcel Moolenaar 	.write = gpt_write,
282a5eb4ea3SMarcel Moolenaar 	.nparts = 4096,
283a5eb4ea3SMarcel Moolenaar 	.labellen = 36,
284a5eb4ea3SMarcel Moolenaar 	.bootcode = 512,
285a5eb4ea3SMarcel Moolenaar 	.maxsecsz = 4096
286a5eb4ea3SMarcel Moolenaar };
287a5eb4ea3SMarcel Moolenaar 
288a5eb4ea3SMarcel Moolenaar SCHEME_DEFINE(gpt_scheme);
289