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