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 --- 11 unchanged lines hidden (view full) --- 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 --- 11 unchanged lines hidden (view full) --- 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> --- 82 unchanged lines hidden (view full) --- 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> --- 82 unchanged lines hidden (view full) --- 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 --- 7 unchanged lines hidden (view full) --- 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 --- 7 unchanged lines hidden (view full) --- 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); |