xref: /freebsd/usr.bin/mkimg/gpt.c (revision 6b1235713e366fa41a69505839d5e7284711544b)
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