1 /*- 2 * Copyright (c) 2002, 2005, 2006, 2007 Marcel Moolenaar 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 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/bio.h> 32 #include <sys/diskmbr.h> 33 #include <sys/endian.h> 34 #include <sys/gpt.h> 35 #include <sys/kernel.h> 36 #include <sys/kobj.h> 37 #include <sys/limits.h> 38 #include <sys/lock.h> 39 #include <sys/malloc.h> 40 #include <sys/mutex.h> 41 #include <sys/queue.h> 42 #include <sys/sbuf.h> 43 #include <sys/systm.h> 44 #include <sys/uuid.h> 45 #include <geom/geom.h> 46 #include <geom/part/g_part.h> 47 48 #include "g_part_if.h" 49 50 CTASSERT(offsetof(struct gpt_hdr, padding) == 92); 51 CTASSERT(sizeof(struct gpt_ent) == 128); 52 53 #define EQUUID(a,b) (memcmp(a, b, sizeof(struct uuid)) == 0) 54 55 #define MBRSIZE 512 56 57 enum gpt_elt { 58 GPT_ELT_PRIHDR, 59 GPT_ELT_PRITBL, 60 GPT_ELT_SECHDR, 61 GPT_ELT_SECTBL, 62 GPT_ELT_COUNT 63 }; 64 65 enum gpt_state { 66 GPT_STATE_UNKNOWN, /* Not determined. */ 67 GPT_STATE_MISSING, /* No signature found. */ 68 GPT_STATE_CORRUPT, /* Checksum mismatch. */ 69 GPT_STATE_INVALID, /* Nonconformant/invalid. */ 70 GPT_STATE_OK /* Perfectly fine. */ 71 }; 72 73 struct g_part_gpt_table { 74 struct g_part_table base; 75 u_char mbr[MBRSIZE]; 76 struct gpt_hdr *hdr; 77 quad_t lba[GPT_ELT_COUNT]; 78 enum gpt_state state[GPT_ELT_COUNT]; 79 }; 80 81 struct g_part_gpt_entry { 82 struct g_part_entry base; 83 struct gpt_ent ent; 84 }; 85 86 static void g_gpt_printf_utf16(struct sbuf *, uint16_t *, size_t); 87 static void g_gpt_utf8_to_utf16(const uint8_t *, uint16_t *, size_t); 88 89 static int g_part_gpt_add(struct g_part_table *, struct g_part_entry *, 90 struct g_part_parms *); 91 static int g_part_gpt_bootcode(struct g_part_table *, struct g_part_parms *); 92 static int g_part_gpt_create(struct g_part_table *, struct g_part_parms *); 93 static int g_part_gpt_destroy(struct g_part_table *, struct g_part_parms *); 94 static void g_part_gpt_dumpconf(struct g_part_table *, struct g_part_entry *, 95 struct sbuf *, const char *); 96 static int g_part_gpt_dumpto(struct g_part_table *, struct g_part_entry *); 97 static int g_part_gpt_modify(struct g_part_table *, struct g_part_entry *, 98 struct g_part_parms *); 99 static const char *g_part_gpt_name(struct g_part_table *, struct g_part_entry *, 100 char *, size_t); 101 static int g_part_gpt_probe(struct g_part_table *, struct g_consumer *); 102 static int g_part_gpt_read(struct g_part_table *, struct g_consumer *); 103 static const char *g_part_gpt_type(struct g_part_table *, struct g_part_entry *, 104 char *, size_t); 105 static int g_part_gpt_write(struct g_part_table *, struct g_consumer *); 106 107 static kobj_method_t g_part_gpt_methods[] = { 108 KOBJMETHOD(g_part_add, g_part_gpt_add), 109 KOBJMETHOD(g_part_bootcode, g_part_gpt_bootcode), 110 KOBJMETHOD(g_part_create, g_part_gpt_create), 111 KOBJMETHOD(g_part_destroy, g_part_gpt_destroy), 112 KOBJMETHOD(g_part_dumpconf, g_part_gpt_dumpconf), 113 KOBJMETHOD(g_part_dumpto, g_part_gpt_dumpto), 114 KOBJMETHOD(g_part_modify, g_part_gpt_modify), 115 KOBJMETHOD(g_part_name, g_part_gpt_name), 116 KOBJMETHOD(g_part_probe, g_part_gpt_probe), 117 KOBJMETHOD(g_part_read, g_part_gpt_read), 118 KOBJMETHOD(g_part_type, g_part_gpt_type), 119 KOBJMETHOD(g_part_write, g_part_gpt_write), 120 { 0, 0 } 121 }; 122 123 static struct g_part_scheme g_part_gpt_scheme = { 124 "GPT", 125 g_part_gpt_methods, 126 sizeof(struct g_part_gpt_table), 127 .gps_entrysz = sizeof(struct g_part_gpt_entry), 128 .gps_minent = 128, 129 .gps_maxent = INT_MAX, 130 .gps_bootcodesz = MBRSIZE, 131 }; 132 G_PART_SCHEME_DECLARE(g_part_gpt); 133 134 static struct uuid gpt_uuid_apple_boot = GPT_ENT_TYPE_APPLE_BOOT; 135 static struct uuid gpt_uuid_apple_hfs = GPT_ENT_TYPE_APPLE_HFS; 136 static struct uuid gpt_uuid_apple_label = GPT_ENT_TYPE_APPLE_LABEL; 137 static struct uuid gpt_uuid_apple_raid = GPT_ENT_TYPE_APPLE_RAID; 138 static struct uuid gpt_uuid_apple_raid_offline = GPT_ENT_TYPE_APPLE_RAID_OFFLINE; 139 static struct uuid gpt_uuid_apple_tv_recovery = GPT_ENT_TYPE_APPLE_TV_RECOVERY; 140 static struct uuid gpt_uuid_apple_ufs = GPT_ENT_TYPE_APPLE_UFS; 141 static struct uuid gpt_uuid_efi = GPT_ENT_TYPE_EFI; 142 static struct uuid gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD; 143 static struct uuid gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; 144 static struct uuid gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; 145 static struct uuid gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; 146 static struct uuid gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; 147 static struct uuid gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; 148 static struct uuid gpt_uuid_linux_data = GPT_ENT_TYPE_LINUX_DATA; 149 static struct uuid gpt_uuid_linux_lvm = GPT_ENT_TYPE_LINUX_LVM; 150 static struct uuid gpt_uuid_linux_raid = GPT_ENT_TYPE_LINUX_RAID; 151 static struct uuid gpt_uuid_linux_swap = GPT_ENT_TYPE_LINUX_SWAP; 152 static struct uuid gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; 153 static struct uuid gpt_uuid_ms_reserved = GPT_ENT_TYPE_MS_RESERVED; 154 static struct uuid gpt_uuid_ms_ldm_data = GPT_ENT_TYPE_MS_LDM_DATA; 155 static struct uuid gpt_uuid_ms_ldm_metadata = GPT_ENT_TYPE_MS_LDM_METADATA; 156 static struct uuid gpt_uuid_netbsd_ccd = GPT_ENT_TYPE_NETBSD_CCD; 157 static struct uuid gpt_uuid_netbsd_cgd = GPT_ENT_TYPE_NETBSD_CGD; 158 static struct uuid gpt_uuid_netbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; 159 static struct uuid gpt_uuid_netbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; 160 static struct uuid gpt_uuid_netbsd_raid = GPT_ENT_TYPE_NETBSD_RAID; 161 static struct uuid gpt_uuid_netbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; 162 static struct uuid gpt_uuid_mbr = GPT_ENT_TYPE_MBR; 163 static struct uuid gpt_uuid_unused = GPT_ENT_TYPE_UNUSED; 164 165 static struct g_part_uuid_alias { 166 struct uuid *uuid; 167 int alias; 168 } gpt_uuid_alias_match[] = { 169 { &gpt_uuid_apple_boot, G_PART_ALIAS_APPLE_BOOT }, 170 { &gpt_uuid_apple_hfs, G_PART_ALIAS_APPLE_HFS }, 171 { &gpt_uuid_apple_label, G_PART_ALIAS_APPLE_LABEL }, 172 { &gpt_uuid_apple_raid, G_PART_ALIAS_APPLE_RAID }, 173 { &gpt_uuid_apple_raid_offline, G_PART_ALIAS_APPLE_RAID_OFFLINE }, 174 { &gpt_uuid_apple_tv_recovery, G_PART_ALIAS_APPLE_TV_RECOVERY }, 175 { &gpt_uuid_apple_ufs, G_PART_ALIAS_APPLE_UFS }, 176 { &gpt_uuid_efi, G_PART_ALIAS_EFI }, 177 { &gpt_uuid_freebsd, G_PART_ALIAS_FREEBSD }, 178 { &gpt_uuid_freebsd_boot, G_PART_ALIAS_FREEBSD_BOOT }, 179 { &gpt_uuid_freebsd_swap, G_PART_ALIAS_FREEBSD_SWAP }, 180 { &gpt_uuid_freebsd_ufs, G_PART_ALIAS_FREEBSD_UFS }, 181 { &gpt_uuid_freebsd_vinum, G_PART_ALIAS_FREEBSD_VINUM }, 182 { &gpt_uuid_freebsd_zfs, G_PART_ALIAS_FREEBSD_ZFS }, 183 { &gpt_uuid_linux_data, G_PART_ALIAS_LINUX_DATA }, 184 { &gpt_uuid_linux_lvm, G_PART_ALIAS_LINUX_LVM }, 185 { &gpt_uuid_linux_raid, G_PART_ALIAS_LINUX_RAID }, 186 { &gpt_uuid_linux_swap, G_PART_ALIAS_LINUX_SWAP }, 187 { &gpt_uuid_mbr, G_PART_ALIAS_MBR }, 188 { &gpt_uuid_ms_basic_data, G_PART_ALIAS_MS_BASIC_DATA }, 189 { &gpt_uuid_ms_ldm_data, G_PART_ALIAS_MS_LDM_DATA }, 190 { &gpt_uuid_ms_ldm_metadata, G_PART_ALIAS_MS_LDM_METADATA }, 191 { &gpt_uuid_ms_reserved, G_PART_ALIAS_MS_RESERVED }, 192 { &gpt_uuid_netbsd_ccd, G_PART_ALIAS_NETBSD_CCD }, 193 { &gpt_uuid_netbsd_cgd, G_PART_ALIAS_NETBSD_CGD }, 194 { &gpt_uuid_netbsd_ffs, G_PART_ALIAS_NETBSD_FFS }, 195 { &gpt_uuid_netbsd_lfs, G_PART_ALIAS_NETBSD_LFS }, 196 { &gpt_uuid_netbsd_raid, G_PART_ALIAS_NETBSD_RAID }, 197 { &gpt_uuid_netbsd_swap, G_PART_ALIAS_NETBSD_SWAP }, 198 199 { NULL, 0 } 200 }; 201 202 static struct gpt_hdr * 203 gpt_read_hdr(struct g_part_gpt_table *table, struct g_consumer *cp, 204 enum gpt_elt elt) 205 { 206 struct gpt_hdr *buf, *hdr; 207 struct g_provider *pp; 208 quad_t lba, last; 209 int error; 210 uint32_t crc, sz; 211 212 pp = cp->provider; 213 last = (pp->mediasize / pp->sectorsize) - 1; 214 table->lba[elt] = (elt == GPT_ELT_PRIHDR) ? 1 : last; 215 table->state[elt] = GPT_STATE_MISSING; 216 buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, pp->sectorsize, 217 &error); 218 if (buf == NULL) 219 return (NULL); 220 hdr = NULL; 221 if (memcmp(buf->hdr_sig, GPT_HDR_SIG, sizeof(buf->hdr_sig)) != 0) 222 goto fail; 223 224 table->state[elt] = GPT_STATE_CORRUPT; 225 sz = le32toh(buf->hdr_size); 226 if (sz < 92 || sz > pp->sectorsize) 227 goto fail; 228 229 hdr = g_malloc(sz, M_WAITOK | M_ZERO); 230 bcopy(buf, hdr, sz); 231 hdr->hdr_size = sz; 232 233 crc = le32toh(buf->hdr_crc_self); 234 buf->hdr_crc_self = 0; 235 if (crc32(buf, sz) != crc) 236 goto fail; 237 hdr->hdr_crc_self = crc; 238 239 table->state[elt] = GPT_STATE_INVALID; 240 hdr->hdr_revision = le32toh(buf->hdr_revision); 241 if (hdr->hdr_revision < 0x00010000) 242 goto fail; 243 hdr->hdr_lba_self = le64toh(buf->hdr_lba_self); 244 if (hdr->hdr_lba_self != table->lba[elt]) 245 goto fail; 246 hdr->hdr_lba_alt = le64toh(buf->hdr_lba_alt); 247 248 /* Check the managed area. */ 249 hdr->hdr_lba_start = le64toh(buf->hdr_lba_start); 250 if (hdr->hdr_lba_start < 2 || hdr->hdr_lba_start >= last) 251 goto fail; 252 hdr->hdr_lba_end = le64toh(buf->hdr_lba_end); 253 if (hdr->hdr_lba_end < hdr->hdr_lba_start || hdr->hdr_lba_end >= last) 254 goto fail; 255 256 /* Check the table location and size of the table. */ 257 hdr->hdr_entries = le32toh(buf->hdr_entries); 258 hdr->hdr_entsz = le32toh(buf->hdr_entsz); 259 if (hdr->hdr_entries == 0 || hdr->hdr_entsz < 128 || 260 (hdr->hdr_entsz & 7) != 0) 261 goto fail; 262 hdr->hdr_lba_table = le64toh(buf->hdr_lba_table); 263 if (hdr->hdr_lba_table < 2 || hdr->hdr_lba_table >= last) 264 goto fail; 265 if (hdr->hdr_lba_table >= hdr->hdr_lba_start && 266 hdr->hdr_lba_table <= hdr->hdr_lba_end) 267 goto fail; 268 lba = hdr->hdr_lba_table + 269 (hdr->hdr_entries * hdr->hdr_entsz + pp->sectorsize - 1) / 270 pp->sectorsize - 1; 271 if (lba >= last) 272 goto fail; 273 if (lba >= hdr->hdr_lba_start && lba <= hdr->hdr_lba_end) 274 goto fail; 275 276 table->state[elt] = GPT_STATE_OK; 277 le_uuid_dec(&buf->hdr_uuid, &hdr->hdr_uuid); 278 hdr->hdr_crc_table = le32toh(buf->hdr_crc_table); 279 280 g_free(buf); 281 return (hdr); 282 283 fail: 284 if (hdr != NULL) 285 g_free(hdr); 286 g_free(buf); 287 return (NULL); 288 } 289 290 static struct gpt_ent * 291 gpt_read_tbl(struct g_part_gpt_table *table, struct g_consumer *cp, 292 enum gpt_elt elt, struct gpt_hdr *hdr) 293 { 294 struct g_provider *pp; 295 struct gpt_ent *ent, *tbl; 296 char *buf, *p; 297 unsigned int idx, sectors, tblsz; 298 int error; 299 300 if (hdr == NULL) 301 return (NULL); 302 303 pp = cp->provider; 304 table->lba[elt] = hdr->hdr_lba_table; 305 306 table->state[elt] = GPT_STATE_MISSING; 307 tblsz = hdr->hdr_entries * hdr->hdr_entsz; 308 sectors = (tblsz + pp->sectorsize - 1) / pp->sectorsize; 309 buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, 310 sectors * pp->sectorsize, &error); 311 if (buf == NULL) 312 return (NULL); 313 314 table->state[elt] = GPT_STATE_CORRUPT; 315 if (crc32(buf, tblsz) != hdr->hdr_crc_table) { 316 g_free(buf); 317 return (NULL); 318 } 319 320 table->state[elt] = GPT_STATE_OK; 321 tbl = g_malloc(hdr->hdr_entries * sizeof(struct gpt_ent), 322 M_WAITOK | M_ZERO); 323 324 for (idx = 0, ent = tbl, p = buf; 325 idx < hdr->hdr_entries; 326 idx++, ent++, p += hdr->hdr_entsz) { 327 le_uuid_dec(p, &ent->ent_type); 328 le_uuid_dec(p + 16, &ent->ent_uuid); 329 ent->ent_lba_start = le64dec(p + 32); 330 ent->ent_lba_end = le64dec(p + 40); 331 ent->ent_attr = le64dec(p + 48); 332 /* Keep UTF-16 in little-endian. */ 333 bcopy(p + 56, ent->ent_name, sizeof(ent->ent_name)); 334 } 335 336 g_free(buf); 337 return (tbl); 338 } 339 340 static int 341 gpt_matched_hdrs(struct gpt_hdr *pri, struct gpt_hdr *sec) 342 { 343 344 if (pri == NULL || sec == NULL) 345 return (0); 346 347 if (!EQUUID(&pri->hdr_uuid, &sec->hdr_uuid)) 348 return (0); 349 return ((pri->hdr_revision == sec->hdr_revision && 350 pri->hdr_size == sec->hdr_size && 351 pri->hdr_lba_start == sec->hdr_lba_start && 352 pri->hdr_lba_end == sec->hdr_lba_end && 353 pri->hdr_entries == sec->hdr_entries && 354 pri->hdr_entsz == sec->hdr_entsz && 355 pri->hdr_crc_table == sec->hdr_crc_table) ? 1 : 0); 356 } 357 358 static int 359 gpt_parse_type(const char *type, struct uuid *uuid) 360 { 361 struct uuid tmp; 362 const char *alias; 363 int error; 364 struct g_part_uuid_alias *uap; 365 366 if (type[0] == '!') { 367 error = parse_uuid(type + 1, &tmp); 368 if (error) 369 return (error); 370 if (EQUUID(&tmp, &gpt_uuid_unused)) 371 return (EINVAL); 372 *uuid = tmp; 373 return (0); 374 } 375 for (uap = &gpt_uuid_alias_match[0]; uap->uuid; uap++) { 376 alias = g_part_alias_name(uap->alias); 377 if (!strcasecmp(type, alias)) { 378 *uuid = *uap->uuid; 379 return (0); 380 } 381 } 382 return (EINVAL); 383 } 384 385 static int 386 g_part_gpt_add(struct g_part_table *basetable, struct g_part_entry *baseentry, 387 struct g_part_parms *gpp) 388 { 389 struct g_part_gpt_entry *entry; 390 int error; 391 392 entry = (struct g_part_gpt_entry *)baseentry; 393 error = gpt_parse_type(gpp->gpp_type, &entry->ent.ent_type); 394 if (error) 395 return (error); 396 kern_uuidgen(&entry->ent.ent_uuid, 1); 397 entry->ent.ent_lba_start = baseentry->gpe_start; 398 entry->ent.ent_lba_end = baseentry->gpe_end; 399 if (baseentry->gpe_deleted) { 400 entry->ent.ent_attr = 0; 401 bzero(entry->ent.ent_name, sizeof(entry->ent.ent_name)); 402 } 403 if (gpp->gpp_parms & G_PART_PARM_LABEL) 404 g_gpt_utf8_to_utf16(gpp->gpp_label, entry->ent.ent_name, 405 sizeof(entry->ent.ent_name)); 406 return (0); 407 } 408 409 static int 410 g_part_gpt_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp) 411 { 412 struct g_part_gpt_table *table; 413 size_t codesz; 414 415 codesz = DOSPARTOFF; 416 table = (struct g_part_gpt_table *)basetable; 417 bzero(table->mbr, codesz); 418 codesz = MIN(codesz, gpp->gpp_codesize); 419 if (codesz > 0) 420 bcopy(gpp->gpp_codeptr, table->mbr, codesz); 421 422 /* Mark the PMBR active since some BIOS require it */ 423 table->mbr[DOSPARTOFF] = 0x80; /* status */ 424 return (0); 425 } 426 427 static int 428 g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp) 429 { 430 struct g_provider *pp; 431 struct g_part_gpt_table *table; 432 quad_t last; 433 size_t tblsz; 434 435 /* We don't nest, which means that our depth should be 0. */ 436 if (basetable->gpt_depth != 0) 437 return (ENXIO); 438 439 table = (struct g_part_gpt_table *)basetable; 440 pp = gpp->gpp_provider; 441 tblsz = (basetable->gpt_entries * sizeof(struct gpt_ent) + 442 pp->sectorsize - 1) / pp->sectorsize; 443 if (pp->sectorsize < MBRSIZE || 444 pp->mediasize < (3 + 2 * tblsz + basetable->gpt_entries) * 445 pp->sectorsize) 446 return (ENOSPC); 447 448 last = (pp->mediasize / pp->sectorsize) - 1; 449 450 le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC); 451 table->mbr[DOSPARTOFF + 1] = 0x01; /* shd */ 452 table->mbr[DOSPARTOFF + 2] = 0x01; /* ssect */ 453 table->mbr[DOSPARTOFF + 3] = 0x00; /* scyl */ 454 table->mbr[DOSPARTOFF + 4] = 0xee; /* typ */ 455 table->mbr[DOSPARTOFF + 5] = 0xff; /* ehd */ 456 table->mbr[DOSPARTOFF + 6] = 0xff; /* esect */ 457 table->mbr[DOSPARTOFF + 7] = 0xff; /* ecyl */ 458 le32enc(table->mbr + DOSPARTOFF + 8, 1); /* start */ 459 le32enc(table->mbr + DOSPARTOFF + 12, MIN(last, 0xffffffffLL)); 460 461 table->lba[GPT_ELT_PRIHDR] = 1; 462 table->lba[GPT_ELT_PRITBL] = 2; 463 table->lba[GPT_ELT_SECHDR] = last; 464 table->lba[GPT_ELT_SECTBL] = last - tblsz; 465 466 /* Allocate space for the header */ 467 table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO); 468 469 bcopy(GPT_HDR_SIG, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); 470 table->hdr->hdr_revision = GPT_HDR_REVISION; 471 table->hdr->hdr_size = offsetof(struct gpt_hdr, padding); 472 table->hdr->hdr_lba_start = 2 + tblsz; 473 table->hdr->hdr_lba_end = last - tblsz - 1; 474 kern_uuidgen(&table->hdr->hdr_uuid, 1); 475 table->hdr->hdr_entries = basetable->gpt_entries; 476 table->hdr->hdr_entsz = sizeof(struct gpt_ent); 477 478 basetable->gpt_first = table->hdr->hdr_lba_start; 479 basetable->gpt_last = table->hdr->hdr_lba_end; 480 return (0); 481 } 482 483 static int 484 g_part_gpt_destroy(struct g_part_table *basetable, struct g_part_parms *gpp) 485 { 486 487 /* 488 * Wipe the first 2 sectors as well as the last to clear the 489 * partitioning. 490 */ 491 basetable->gpt_smhead |= 3; 492 basetable->gpt_smtail |= 1; 493 return (0); 494 } 495 496 static void 497 g_part_gpt_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, 498 struct sbuf *sb, const char *indent) 499 { 500 struct g_part_gpt_entry *entry; 501 502 entry = (struct g_part_gpt_entry *)baseentry; 503 if (indent == NULL) { 504 /* conftxt: libdisk compatibility */ 505 sbuf_printf(sb, " xs GPT xt "); 506 sbuf_printf_uuid(sb, &entry->ent.ent_type); 507 } else if (entry != NULL) { 508 /* confxml: partition entry information */ 509 sbuf_printf(sb, "%s<label>", indent); 510 g_gpt_printf_utf16(sb, entry->ent.ent_name, 511 sizeof(entry->ent.ent_name) >> 1); 512 sbuf_printf(sb, "</label>\n"); 513 sbuf_printf(sb, "%s<rawtype>", indent); 514 sbuf_printf_uuid(sb, &entry->ent.ent_type); 515 sbuf_printf(sb, "</rawtype>\n"); 516 sbuf_printf(sb, "%s<rawuuid>", indent); 517 sbuf_printf_uuid(sb, &entry->ent.ent_uuid); 518 sbuf_printf(sb, "</rawuuid>\n"); 519 } else { 520 /* confxml: scheme information */ 521 } 522 } 523 524 static int 525 g_part_gpt_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 526 { 527 struct g_part_gpt_entry *entry; 528 529 entry = (struct g_part_gpt_entry *)baseentry; 530 return ((EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) || 531 EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap)) ? 1 : 0); 532 } 533 534 static int 535 g_part_gpt_modify(struct g_part_table *basetable, 536 struct g_part_entry *baseentry, struct g_part_parms *gpp) 537 { 538 struct g_part_gpt_entry *entry; 539 int error; 540 541 entry = (struct g_part_gpt_entry *)baseentry; 542 if (gpp->gpp_parms & G_PART_PARM_TYPE) { 543 error = gpt_parse_type(gpp->gpp_type, &entry->ent.ent_type); 544 if (error) 545 return (error); 546 } 547 if (gpp->gpp_parms & G_PART_PARM_LABEL) 548 g_gpt_utf8_to_utf16(gpp->gpp_label, entry->ent.ent_name, 549 sizeof(entry->ent.ent_name)); 550 return (0); 551 } 552 553 static const char * 554 g_part_gpt_name(struct g_part_table *table, struct g_part_entry *baseentry, 555 char *buf, size_t bufsz) 556 { 557 struct g_part_gpt_entry *entry; 558 char c; 559 560 entry = (struct g_part_gpt_entry *)baseentry; 561 c = (EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd)) ? 's' : 'p'; 562 snprintf(buf, bufsz, "%c%d", c, baseentry->gpe_index); 563 return (buf); 564 } 565 566 static int 567 g_part_gpt_probe(struct g_part_table *table, struct g_consumer *cp) 568 { 569 struct g_provider *pp; 570 char *buf; 571 int error, res; 572 573 /* We don't nest, which means that our depth should be 0. */ 574 if (table->gpt_depth != 0) 575 return (ENXIO); 576 577 pp = cp->provider; 578 579 /* 580 * Sanity-check the provider. Since the first sector on the provider 581 * must be a PMBR and a PMBR is 512 bytes large, the sector size 582 * must be at least 512 bytes. Also, since the theoretical minimum 583 * number of sectors needed by GPT is 6, any medium that has less 584 * than 6 sectors is never going to be able to hold a GPT. The 585 * number 6 comes from: 586 * 1 sector for the PMBR 587 * 2 sectors for the GPT headers (each 1 sector) 588 * 2 sectors for the GPT tables (each 1 sector) 589 * 1 sector for an actual partition 590 * It's better to catch this pathological case early than behaving 591 * pathologically later on... 592 */ 593 if (pp->sectorsize < MBRSIZE || pp->mediasize < 6 * pp->sectorsize) 594 return (ENOSPC); 595 596 /* Check that there's a MBR. */ 597 buf = g_read_data(cp, 0L, pp->sectorsize, &error); 598 if (buf == NULL) 599 return (error); 600 res = le16dec(buf + DOSMAGICOFFSET); 601 g_free(buf); 602 if (res != DOSMAGIC) 603 return (ENXIO); 604 605 /* Check that there's a primary header. */ 606 buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 607 if (buf == NULL) 608 return (error); 609 res = memcmp(buf, GPT_HDR_SIG, 8); 610 g_free(buf); 611 if (res == 0) 612 return (G_PART_PROBE_PRI_HIGH); 613 614 /* No primary? Check that there's a secondary. */ 615 buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize, 616 &error); 617 if (buf == NULL) 618 return (error); 619 res = memcmp(buf, GPT_HDR_SIG, 8); 620 g_free(buf); 621 return ((res == 0) ? G_PART_PROBE_PRI_HIGH : ENXIO); 622 } 623 624 static int 625 g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp) 626 { 627 struct gpt_hdr *prihdr, *sechdr; 628 struct gpt_ent *tbl, *pritbl, *sectbl; 629 struct g_provider *pp; 630 struct g_part_gpt_table *table; 631 struct g_part_gpt_entry *entry; 632 u_char *buf; 633 int error, index; 634 635 table = (struct g_part_gpt_table *)basetable; 636 pp = cp->provider; 637 638 /* Read the PMBR */ 639 buf = g_read_data(cp, 0, pp->sectorsize, &error); 640 if (buf == NULL) 641 return (error); 642 bcopy(buf, table->mbr, MBRSIZE); 643 g_free(buf); 644 645 /* Read the primary header and table. */ 646 prihdr = gpt_read_hdr(table, cp, GPT_ELT_PRIHDR); 647 if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK) { 648 pritbl = gpt_read_tbl(table, cp, GPT_ELT_PRITBL, prihdr); 649 } else { 650 table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; 651 pritbl = NULL; 652 } 653 654 /* Read the secondary header and table. */ 655 sechdr = gpt_read_hdr(table, cp, GPT_ELT_SECHDR); 656 if (table->state[GPT_ELT_SECHDR] == GPT_STATE_OK) { 657 sectbl = gpt_read_tbl(table, cp, GPT_ELT_SECTBL, sechdr); 658 } else { 659 table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; 660 sectbl = NULL; 661 } 662 663 /* Fail if we haven't got any good tables at all. */ 664 if (table->state[GPT_ELT_PRITBL] != GPT_STATE_OK && 665 table->state[GPT_ELT_SECTBL] != GPT_STATE_OK) { 666 printf("GEOM: %s: corrupt or invalid GPT detected.\n", 667 pp->name); 668 printf("GEOM: %s: GPT rejected -- may not be recoverable.\n", 669 pp->name); 670 return (EINVAL); 671 } 672 673 /* 674 * If both headers are good but they disagree with each other, 675 * then invalidate one. We prefer to keep the primary header, 676 * unless the primary table is corrupt. 677 */ 678 if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK && 679 table->state[GPT_ELT_SECHDR] == GPT_STATE_OK && 680 !gpt_matched_hdrs(prihdr, sechdr)) { 681 if (table->state[GPT_ELT_PRITBL] == GPT_STATE_OK) { 682 table->state[GPT_ELT_SECHDR] = GPT_STATE_INVALID; 683 table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; 684 g_free(sechdr); 685 sechdr = NULL; 686 } else { 687 table->state[GPT_ELT_PRIHDR] = GPT_STATE_INVALID; 688 table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; 689 g_free(prihdr); 690 prihdr = NULL; 691 } 692 } 693 694 if (table->state[GPT_ELT_PRITBL] != GPT_STATE_OK) { 695 printf("GEOM: %s: the primary GPT table is corrupt or " 696 "invalid.\n", pp->name); 697 printf("GEOM: %s: using the secondary instead -- recovery " 698 "strongly advised.\n", pp->name); 699 table->hdr = sechdr; 700 if (prihdr != NULL) 701 g_free(prihdr); 702 tbl = sectbl; 703 if (pritbl != NULL) 704 g_free(pritbl); 705 } else { 706 if (table->state[GPT_ELT_SECTBL] != GPT_STATE_OK) { 707 printf("GEOM: %s: the secondary GPT table is corrupt " 708 "or invalid.\n", pp->name); 709 printf("GEOM: %s: using the primary only -- recovery " 710 "suggested.\n", pp->name); 711 } 712 table->hdr = prihdr; 713 if (sechdr != NULL) 714 g_free(sechdr); 715 tbl = pritbl; 716 if (sectbl != NULL) 717 g_free(sectbl); 718 } 719 720 basetable->gpt_first = table->hdr->hdr_lba_start; 721 basetable->gpt_last = table->hdr->hdr_lba_end; 722 basetable->gpt_entries = table->hdr->hdr_entries; 723 724 for (index = basetable->gpt_entries - 1; index >= 0; index--) { 725 if (EQUUID(&tbl[index].ent_type, &gpt_uuid_unused)) 726 continue; 727 entry = (struct g_part_gpt_entry *)g_part_new_entry(basetable, 728 index+1, tbl[index].ent_lba_start, tbl[index].ent_lba_end); 729 entry->ent = tbl[index]; 730 } 731 732 g_free(tbl); 733 return (0); 734 } 735 736 static const char * 737 g_part_gpt_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 738 char *buf, size_t bufsz) 739 { 740 struct g_part_gpt_entry *entry; 741 struct uuid *type; 742 struct g_part_uuid_alias *uap; 743 744 entry = (struct g_part_gpt_entry *)baseentry; 745 type = &entry->ent.ent_type; 746 for (uap = &gpt_uuid_alias_match[0]; uap->uuid; uap++) 747 if (EQUUID(type, uap->uuid)) 748 return (g_part_alias_name(uap->alias)); 749 buf[0] = '!'; 750 snprintf_uuid(buf + 1, bufsz - 1, type); 751 752 return (buf); 753 } 754 755 static int 756 g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp) 757 { 758 unsigned char *buf, *bp; 759 struct g_provider *pp; 760 struct g_part_entry *baseentry; 761 struct g_part_gpt_entry *entry; 762 struct g_part_gpt_table *table; 763 size_t tlbsz; 764 uint32_t crc; 765 int error, index; 766 767 pp = cp->provider; 768 table = (struct g_part_gpt_table *)basetable; 769 tlbsz = (table->hdr->hdr_entries * table->hdr->hdr_entsz + 770 pp->sectorsize - 1) / pp->sectorsize; 771 772 /* Write the PMBR */ 773 buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 774 bcopy(table->mbr, buf, MBRSIZE); 775 error = g_write_data(cp, 0, buf, pp->sectorsize); 776 g_free(buf); 777 if (error) 778 return (error); 779 780 /* Allocate space for the header and entries. */ 781 buf = g_malloc((tlbsz + 1) * pp->sectorsize, M_WAITOK | M_ZERO); 782 783 memcpy(buf, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); 784 le32enc(buf + 8, table->hdr->hdr_revision); 785 le32enc(buf + 12, table->hdr->hdr_size); 786 le64enc(buf + 40, table->hdr->hdr_lba_start); 787 le64enc(buf + 48, table->hdr->hdr_lba_end); 788 le_uuid_enc(buf + 56, &table->hdr->hdr_uuid); 789 le32enc(buf + 80, table->hdr->hdr_entries); 790 le32enc(buf + 84, table->hdr->hdr_entsz); 791 792 LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { 793 if (baseentry->gpe_deleted) 794 continue; 795 entry = (struct g_part_gpt_entry *)baseentry; 796 index = baseentry->gpe_index - 1; 797 bp = buf + pp->sectorsize + table->hdr->hdr_entsz * index; 798 le_uuid_enc(bp, &entry->ent.ent_type); 799 le_uuid_enc(bp + 16, &entry->ent.ent_uuid); 800 le64enc(bp + 32, entry->ent.ent_lba_start); 801 le64enc(bp + 40, entry->ent.ent_lba_end); 802 le64enc(bp + 48, entry->ent.ent_attr); 803 memcpy(bp + 56, entry->ent.ent_name, 804 sizeof(entry->ent.ent_name)); 805 } 806 807 crc = crc32(buf + pp->sectorsize, 808 table->hdr->hdr_entries * table->hdr->hdr_entsz); 809 le32enc(buf + 88, crc); 810 811 /* Write primary meta-data. */ 812 le32enc(buf + 16, 0); /* hdr_crc_self. */ 813 le64enc(buf + 24, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_self. */ 814 le64enc(buf + 32, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_alt. */ 815 le64enc(buf + 72, table->lba[GPT_ELT_PRITBL]); /* hdr_lba_table. */ 816 crc = crc32(buf, table->hdr->hdr_size); 817 le32enc(buf + 16, crc); 818 819 error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize, 820 buf + pp->sectorsize, tlbsz * pp->sectorsize); 821 if (error) 822 goto out; 823 error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize, 824 buf, pp->sectorsize); 825 if (error) 826 goto out; 827 828 /* Write secondary meta-data. */ 829 le32enc(buf + 16, 0); /* hdr_crc_self. */ 830 le64enc(buf + 24, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_self. */ 831 le64enc(buf + 32, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_alt. */ 832 le64enc(buf + 72, table->lba[GPT_ELT_SECTBL]); /* hdr_lba_table. */ 833 crc = crc32(buf, table->hdr->hdr_size); 834 le32enc(buf + 16, crc); 835 836 error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize, 837 buf + pp->sectorsize, tlbsz * pp->sectorsize); 838 if (error) 839 goto out; 840 error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, 841 buf, pp->sectorsize); 842 843 out: 844 g_free(buf); 845 return (error); 846 } 847 848 static void 849 g_gpt_printf_utf16(struct sbuf *sb, uint16_t *str, size_t len) 850 { 851 u_int bo; 852 uint32_t ch; 853 uint16_t c; 854 855 bo = LITTLE_ENDIAN; /* GPT is little-endian */ 856 while (len > 0 && *str != 0) { 857 ch = (bo == BIG_ENDIAN) ? be16toh(*str) : le16toh(*str); 858 str++, len--; 859 if ((ch & 0xf800) == 0xd800) { 860 if (len > 0) { 861 c = (bo == BIG_ENDIAN) ? be16toh(*str) 862 : le16toh(*str); 863 str++, len--; 864 } else 865 c = 0xfffd; 866 if ((ch & 0x400) == 0 && (c & 0xfc00) == 0xdc00) { 867 ch = ((ch & 0x3ff) << 10) + (c & 0x3ff); 868 ch += 0x10000; 869 } else 870 ch = 0xfffd; 871 } else if (ch == 0xfffe) { /* BOM (U+FEFF) swapped. */ 872 bo = (bo == BIG_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; 873 continue; 874 } else if (ch == 0xfeff) /* BOM (U+FEFF) unswapped. */ 875 continue; 876 877 /* Write the Unicode character in UTF-8 */ 878 if (ch < 0x80) 879 sbuf_printf(sb, "%c", ch); 880 else if (ch < 0x800) 881 sbuf_printf(sb, "%c%c", 0xc0 | (ch >> 6), 882 0x80 | (ch & 0x3f)); 883 else if (ch < 0x10000) 884 sbuf_printf(sb, "%c%c%c", 0xe0 | (ch >> 12), 885 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); 886 else if (ch < 0x200000) 887 sbuf_printf(sb, "%c%c%c%c", 0xf0 | (ch >> 18), 888 0x80 | ((ch >> 12) & 0x3f), 889 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); 890 } 891 } 892 893 static void 894 g_gpt_utf8_to_utf16(const uint8_t *s8, uint16_t *s16, size_t s16len) 895 { 896 size_t s16idx, s8idx; 897 uint32_t utfchar; 898 unsigned int c, utfbytes; 899 900 s8idx = s16idx = 0; 901 utfchar = 0; 902 utfbytes = 0; 903 bzero(s16, s16len << 1); 904 while (s8[s8idx] != 0 && s16idx < s16len) { 905 c = s8[s8idx++]; 906 if ((c & 0xc0) != 0x80) { 907 /* Initial characters. */ 908 if (utfbytes != 0) { 909 /* Incomplete encoding of previous char. */ 910 s16[s16idx++] = htole16(0xfffd); 911 } 912 if ((c & 0xf8) == 0xf0) { 913 utfchar = c & 0x07; 914 utfbytes = 3; 915 } else if ((c & 0xf0) == 0xe0) { 916 utfchar = c & 0x0f; 917 utfbytes = 2; 918 } else if ((c & 0xe0) == 0xc0) { 919 utfchar = c & 0x1f; 920 utfbytes = 1; 921 } else { 922 utfchar = c & 0x7f; 923 utfbytes = 0; 924 } 925 } else { 926 /* Followup characters. */ 927 if (utfbytes > 0) { 928 utfchar = (utfchar << 6) + (c & 0x3f); 929 utfbytes--; 930 } else if (utfbytes == 0) 931 utfbytes = ~0; 932 } 933 /* 934 * Write the complete Unicode character as UTF-16 when we 935 * have all the UTF-8 charactars collected. 936 */ 937 if (utfbytes == 0) { 938 /* 939 * If we need to write 2 UTF-16 characters, but 940 * we only have room for 1, then we truncate the 941 * string by writing a 0 instead. 942 */ 943 if (utfchar >= 0x10000 && s16idx < s16len - 1) { 944 s16[s16idx++] = 945 htole16(0xd800 | ((utfchar >> 10) - 0x40)); 946 s16[s16idx++] = 947 htole16(0xdc00 | (utfchar & 0x3ff)); 948 } else 949 s16[s16idx++] = (utfchar >= 0x10000) ? 0 : 950 htole16(utfchar); 951 } 952 } 953 /* 954 * If our input string was truncated, append an invalid encoding 955 * character to the output string. 956 */ 957 if (utfbytes != 0 && s16idx < s16len) 958 s16[s16idx++] = htole16(0xfffd); 959 } 960