Deleted Added
sdiff udiff text old ( 263537 ) new ( 263653 )
full compact
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);