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 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 |
127gpt_tblsz() |
128{ 129 u_int ents; 130 131 ents = secsz / sizeof(struct gpt_ent); |
132 return ((nparts + ents - 1) / ents); |
133} 134 135static u_int |
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 |
143 secs = gpt_tblsz(); |
144 secs += (where == SCHEME_META_IMG_START) ? 2 : 1; 145 return (secs); 146} 147 148static int |
149gpt_filewrite(int fd, lba_t blk, void *buf, ssize_t bufsz) |
150{ |
151 int error; |
152 |
153 error = mkimg_seek(fd, blk); 154 if (error == 0) { 155 if (write(fd, buf, bufsz) != bufsz) 156 error = errno; 157 } 158 return (error); |
159} 160 161static int |
162gpt_write_pmbr(int fd, lba_t blks, void *bootcode) |
163{ 164 u_char *pmbr; 165 uint32_t secs; 166 int error; 167 |
168 secs = (blks > UINT32_MAX) ? UINT32_MAX : (uint32_t)blks; |
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 * |
192gpt_mktbl(u_int tblsz) |
193{ 194 uuid_t uuid; 195 struct gpt_ent *tbl, *ent; 196 struct part *part; |
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); |
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, |
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); |
233 return (gpt_filewrite(fd, self, hdr, secsz)); |
234} 235 236static int |
237gpt_write(int fd, lba_t imgsz, void *bootcode) |
238{ 239 uuid_t uuid; 240 struct gpt_ent *tbl; 241 struct gpt_hdr *hdr; |
242 uint32_t crc; 243 u_int tblsz; 244 int error; 245 |
246 /* PMBR */ |
247 error = gpt_write_pmbr(fd, imgsz, bootcode); |
248 if (error) 249 return (error); 250 251 /* GPT table(s) */ |
252 tblsz = gpt_tblsz(); 253 tbl = gpt_mktbl(tblsz); |
254 if (tbl == NULL) 255 return (errno); |
256 error = gpt_filewrite(fd, 2, tbl, tblsz * secsz); |
257 if (error) 258 goto out; |
259 error = gpt_filewrite(fd, imgsz - (tblsz + 1), tbl, tblsz * secsz); |
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); |
274 le64enc(&hdr->hdr_lba_end, imgsz - tblsz - 2); |
275 uuidgen(&uuid, 1); 276 uuid_enc_le(&hdr->hdr_uuid, &uuid); |
277 le32enc(&hdr->hdr_entries, nparts); |
278 le32enc(&hdr->hdr_entsz, sizeof(struct gpt_ent)); |
279 crc = crc32(tbl, nparts * sizeof(struct gpt_ent)); |
280 le32enc(&hdr->hdr_crc_table, crc); |
281 error = gpt_write_hdr(fd, hdr, 1, imgsz - 1, 2); |
282 if (!error) |
283 error = gpt_write_hdr(fd, hdr, imgsz - 1, 1, imgsz - tblsz - 1); |
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); |