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