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 } else { 517 /* confxml: scheme information */ 518 } 519 } 520 521 static int 522 g_part_gpt_dumpto(struct g_part_table *table, struct g_part_entry *baseentry) 523 { 524 struct g_part_gpt_entry *entry; 525 526 entry = (struct g_part_gpt_entry *)baseentry; 527 return ((EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) || 528 EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap)) ? 1 : 0); 529 } 530 531 static int 532 g_part_gpt_modify(struct g_part_table *basetable, 533 struct g_part_entry *baseentry, struct g_part_parms *gpp) 534 { 535 struct g_part_gpt_entry *entry; 536 int error; 537 538 entry = (struct g_part_gpt_entry *)baseentry; 539 if (gpp->gpp_parms & G_PART_PARM_TYPE) { 540 error = gpt_parse_type(gpp->gpp_type, &entry->ent.ent_type); 541 if (error) 542 return (error); 543 } 544 if (gpp->gpp_parms & G_PART_PARM_LABEL) 545 g_gpt_utf8_to_utf16(gpp->gpp_label, entry->ent.ent_name, 546 sizeof(entry->ent.ent_name)); 547 return (0); 548 } 549 550 static const char * 551 g_part_gpt_name(struct g_part_table *table, struct g_part_entry *baseentry, 552 char *buf, size_t bufsz) 553 { 554 struct g_part_gpt_entry *entry; 555 char c; 556 557 entry = (struct g_part_gpt_entry *)baseentry; 558 c = (EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd)) ? 's' : 'p'; 559 snprintf(buf, bufsz, "%c%d", c, baseentry->gpe_index); 560 return (buf); 561 } 562 563 static int 564 g_part_gpt_probe(struct g_part_table *table, struct g_consumer *cp) 565 { 566 struct g_provider *pp; 567 char *buf; 568 int error, res; 569 570 /* We don't nest, which means that our depth should be 0. */ 571 if (table->gpt_depth != 0) 572 return (ENXIO); 573 574 pp = cp->provider; 575 576 /* 577 * Sanity-check the provider. Since the first sector on the provider 578 * must be a PMBR and a PMBR is 512 bytes large, the sector size 579 * must be at least 512 bytes. Also, since the theoretical minimum 580 * number of sectors needed by GPT is 6, any medium that has less 581 * than 6 sectors is never going to be able to hold a GPT. The 582 * number 6 comes from: 583 * 1 sector for the PMBR 584 * 2 sectors for the GPT headers (each 1 sector) 585 * 2 sectors for the GPT tables (each 1 sector) 586 * 1 sector for an actual partition 587 * It's better to catch this pathological case early than behaving 588 * pathologically later on... 589 */ 590 if (pp->sectorsize < MBRSIZE || pp->mediasize < 6 * pp->sectorsize) 591 return (ENOSPC); 592 593 /* Check that there's a MBR. */ 594 buf = g_read_data(cp, 0L, pp->sectorsize, &error); 595 if (buf == NULL) 596 return (error); 597 res = le16dec(buf + DOSMAGICOFFSET); 598 g_free(buf); 599 if (res != DOSMAGIC) 600 return (ENXIO); 601 602 /* Check that there's a primary header. */ 603 buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error); 604 if (buf == NULL) 605 return (error); 606 res = memcmp(buf, GPT_HDR_SIG, 8); 607 g_free(buf); 608 if (res == 0) 609 return (G_PART_PROBE_PRI_HIGH); 610 611 /* No primary? Check that there's a secondary. */ 612 buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize, 613 &error); 614 if (buf == NULL) 615 return (error); 616 res = memcmp(buf, GPT_HDR_SIG, 8); 617 g_free(buf); 618 return ((res == 0) ? G_PART_PROBE_PRI_HIGH : ENXIO); 619 } 620 621 static int 622 g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp) 623 { 624 struct gpt_hdr *prihdr, *sechdr; 625 struct gpt_ent *tbl, *pritbl, *sectbl; 626 struct g_provider *pp; 627 struct g_part_gpt_table *table; 628 struct g_part_gpt_entry *entry; 629 u_char *buf; 630 int error, index; 631 632 table = (struct g_part_gpt_table *)basetable; 633 pp = cp->provider; 634 635 /* Read the PMBR */ 636 buf = g_read_data(cp, 0, pp->sectorsize, &error); 637 if (buf == NULL) 638 return (error); 639 bcopy(buf, table->mbr, MBRSIZE); 640 g_free(buf); 641 642 /* Read the primary header and table. */ 643 prihdr = gpt_read_hdr(table, cp, GPT_ELT_PRIHDR); 644 if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK) { 645 pritbl = gpt_read_tbl(table, cp, GPT_ELT_PRITBL, prihdr); 646 } else { 647 table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; 648 pritbl = NULL; 649 } 650 651 /* Read the secondary header and table. */ 652 sechdr = gpt_read_hdr(table, cp, GPT_ELT_SECHDR); 653 if (table->state[GPT_ELT_SECHDR] == GPT_STATE_OK) { 654 sectbl = gpt_read_tbl(table, cp, GPT_ELT_SECTBL, sechdr); 655 } else { 656 table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; 657 sectbl = NULL; 658 } 659 660 /* Fail if we haven't got any good tables at all. */ 661 if (table->state[GPT_ELT_PRITBL] != GPT_STATE_OK && 662 table->state[GPT_ELT_SECTBL] != GPT_STATE_OK) { 663 printf("GEOM: %s: corrupt or invalid GPT detected.\n", 664 pp->name); 665 printf("GEOM: %s: GPT rejected -- may not be recoverable.\n", 666 pp->name); 667 return (EINVAL); 668 } 669 670 /* 671 * If both headers are good but they disagree with each other, 672 * then invalidate one. We prefer to keep the primary header, 673 * unless the primary table is corrupt. 674 */ 675 if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK && 676 table->state[GPT_ELT_SECHDR] == GPT_STATE_OK && 677 !gpt_matched_hdrs(prihdr, sechdr)) { 678 if (table->state[GPT_ELT_PRITBL] == GPT_STATE_OK) { 679 table->state[GPT_ELT_SECHDR] = GPT_STATE_INVALID; 680 table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; 681 g_free(sechdr); 682 sechdr = NULL; 683 } else { 684 table->state[GPT_ELT_PRIHDR] = GPT_STATE_INVALID; 685 table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; 686 g_free(prihdr); 687 prihdr = NULL; 688 } 689 } 690 691 if (table->state[GPT_ELT_PRITBL] != GPT_STATE_OK) { 692 printf("GEOM: %s: the primary GPT table is corrupt or " 693 "invalid.\n", pp->name); 694 printf("GEOM: %s: using the secondary instead -- recovery " 695 "strongly advised.\n", pp->name); 696 table->hdr = sechdr; 697 if (prihdr != NULL) 698 g_free(prihdr); 699 tbl = sectbl; 700 if (pritbl != NULL) 701 g_free(pritbl); 702 } else { 703 if (table->state[GPT_ELT_SECTBL] != GPT_STATE_OK) { 704 printf("GEOM: %s: the secondary GPT table is corrupt " 705 "or invalid.\n", pp->name); 706 printf("GEOM: %s: using the primary only -- recovery " 707 "suggested.\n", pp->name); 708 } 709 table->hdr = prihdr; 710 if (sechdr != NULL) 711 g_free(sechdr); 712 tbl = pritbl; 713 if (sectbl != NULL) 714 g_free(sectbl); 715 } 716 717 basetable->gpt_first = table->hdr->hdr_lba_start; 718 basetable->gpt_last = table->hdr->hdr_lba_end; 719 basetable->gpt_entries = table->hdr->hdr_entries; 720 721 for (index = basetable->gpt_entries - 1; index >= 0; index--) { 722 if (EQUUID(&tbl[index].ent_type, &gpt_uuid_unused)) 723 continue; 724 entry = (struct g_part_gpt_entry *)g_part_new_entry(basetable, 725 index+1, tbl[index].ent_lba_start, tbl[index].ent_lba_end); 726 entry->ent = tbl[index]; 727 } 728 729 g_free(tbl); 730 return (0); 731 } 732 733 static const char * 734 g_part_gpt_type(struct g_part_table *basetable, struct g_part_entry *baseentry, 735 char *buf, size_t bufsz) 736 { 737 struct g_part_gpt_entry *entry; 738 struct uuid *type; 739 struct g_part_uuid_alias *uap; 740 741 entry = (struct g_part_gpt_entry *)baseentry; 742 type = &entry->ent.ent_type; 743 for (uap = &gpt_uuid_alias_match[0]; uap->uuid; uap++) 744 if (EQUUID(type, uap->uuid)) 745 return (g_part_alias_name(uap->alias)); 746 buf[0] = '!'; 747 snprintf_uuid(buf + 1, bufsz - 1, type); 748 749 return (buf); 750 } 751 752 static int 753 g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp) 754 { 755 unsigned char *buf, *bp; 756 struct g_provider *pp; 757 struct g_part_entry *baseentry; 758 struct g_part_gpt_entry *entry; 759 struct g_part_gpt_table *table; 760 size_t tlbsz; 761 uint32_t crc; 762 int error, index; 763 764 pp = cp->provider; 765 table = (struct g_part_gpt_table *)basetable; 766 tlbsz = (table->hdr->hdr_entries * table->hdr->hdr_entsz + 767 pp->sectorsize - 1) / pp->sectorsize; 768 769 /* Write the PMBR */ 770 buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); 771 bcopy(table->mbr, buf, MBRSIZE); 772 error = g_write_data(cp, 0, buf, pp->sectorsize); 773 g_free(buf); 774 if (error) 775 return (error); 776 777 /* Allocate space for the header and entries. */ 778 buf = g_malloc((tlbsz + 1) * pp->sectorsize, M_WAITOK | M_ZERO); 779 780 memcpy(buf, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); 781 le32enc(buf + 8, table->hdr->hdr_revision); 782 le32enc(buf + 12, table->hdr->hdr_size); 783 le64enc(buf + 40, table->hdr->hdr_lba_start); 784 le64enc(buf + 48, table->hdr->hdr_lba_end); 785 le_uuid_enc(buf + 56, &table->hdr->hdr_uuid); 786 le32enc(buf + 80, table->hdr->hdr_entries); 787 le32enc(buf + 84, table->hdr->hdr_entsz); 788 789 LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { 790 if (baseentry->gpe_deleted) 791 continue; 792 entry = (struct g_part_gpt_entry *)baseentry; 793 index = baseentry->gpe_index - 1; 794 bp = buf + pp->sectorsize + table->hdr->hdr_entsz * index; 795 le_uuid_enc(bp, &entry->ent.ent_type); 796 le_uuid_enc(bp + 16, &entry->ent.ent_uuid); 797 le64enc(bp + 32, entry->ent.ent_lba_start); 798 le64enc(bp + 40, entry->ent.ent_lba_end); 799 le64enc(bp + 48, entry->ent.ent_attr); 800 memcpy(bp + 56, entry->ent.ent_name, 801 sizeof(entry->ent.ent_name)); 802 } 803 804 crc = crc32(buf + pp->sectorsize, 805 table->hdr->hdr_entries * table->hdr->hdr_entsz); 806 le32enc(buf + 88, crc); 807 808 /* Write primary meta-data. */ 809 le32enc(buf + 16, 0); /* hdr_crc_self. */ 810 le64enc(buf + 24, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_self. */ 811 le64enc(buf + 32, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_alt. */ 812 le64enc(buf + 72, table->lba[GPT_ELT_PRITBL]); /* hdr_lba_table. */ 813 crc = crc32(buf, table->hdr->hdr_size); 814 le32enc(buf + 16, crc); 815 816 error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize, 817 buf + pp->sectorsize, tlbsz * pp->sectorsize); 818 if (error) 819 goto out; 820 error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize, 821 buf, pp->sectorsize); 822 if (error) 823 goto out; 824 825 /* Write secondary meta-data. */ 826 le32enc(buf + 16, 0); /* hdr_crc_self. */ 827 le64enc(buf + 24, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_self. */ 828 le64enc(buf + 32, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_alt. */ 829 le64enc(buf + 72, table->lba[GPT_ELT_SECTBL]); /* hdr_lba_table. */ 830 crc = crc32(buf, table->hdr->hdr_size); 831 le32enc(buf + 16, crc); 832 833 error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize, 834 buf + pp->sectorsize, tlbsz * pp->sectorsize); 835 if (error) 836 goto out; 837 error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, 838 buf, pp->sectorsize); 839 840 out: 841 g_free(buf); 842 return (error); 843 } 844 845 static void 846 g_gpt_printf_utf16(struct sbuf *sb, uint16_t *str, size_t len) 847 { 848 u_int bo; 849 uint32_t ch; 850 uint16_t c; 851 852 bo = LITTLE_ENDIAN; /* GPT is little-endian */ 853 while (len > 0 && *str != 0) { 854 ch = (bo == BIG_ENDIAN) ? be16toh(*str) : le16toh(*str); 855 str++, len--; 856 if ((ch & 0xf800) == 0xd800) { 857 if (len > 0) { 858 c = (bo == BIG_ENDIAN) ? be16toh(*str) 859 : le16toh(*str); 860 str++, len--; 861 } else 862 c = 0xfffd; 863 if ((ch & 0x400) == 0 && (c & 0xfc00) == 0xdc00) { 864 ch = ((ch & 0x3ff) << 10) + (c & 0x3ff); 865 ch += 0x10000; 866 } else 867 ch = 0xfffd; 868 } else if (ch == 0xfffe) { /* BOM (U+FEFF) swapped. */ 869 bo = (bo == BIG_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; 870 continue; 871 } else if (ch == 0xfeff) /* BOM (U+FEFF) unswapped. */ 872 continue; 873 874 /* Write the Unicode character in UTF-8 */ 875 if (ch < 0x80) 876 sbuf_printf(sb, "%c", ch); 877 else if (ch < 0x800) 878 sbuf_printf(sb, "%c%c", 0xc0 | (ch >> 6), 879 0x80 | (ch & 0x3f)); 880 else if (ch < 0x10000) 881 sbuf_printf(sb, "%c%c%c", 0xe0 | (ch >> 12), 882 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); 883 else if (ch < 0x200000) 884 sbuf_printf(sb, "%c%c%c%c", 0xf0 | (ch >> 18), 885 0x80 | ((ch >> 12) & 0x3f), 886 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); 887 } 888 } 889 890 static void 891 g_gpt_utf8_to_utf16(const uint8_t *s8, uint16_t *s16, size_t s16len) 892 { 893 size_t s16idx, s8idx; 894 uint32_t utfchar; 895 unsigned int c, utfbytes; 896 897 s8idx = s16idx = 0; 898 utfchar = 0; 899 utfbytes = 0; 900 bzero(s16, s16len << 1); 901 while (s8[s8idx] != 0 && s16idx < s16len) { 902 c = s8[s8idx++]; 903 if ((c & 0xc0) != 0x80) { 904 /* Initial characters. */ 905 if (utfbytes != 0) { 906 /* Incomplete encoding of previous char. */ 907 s16[s16idx++] = htole16(0xfffd); 908 } 909 if ((c & 0xf8) == 0xf0) { 910 utfchar = c & 0x07; 911 utfbytes = 3; 912 } else if ((c & 0xf0) == 0xe0) { 913 utfchar = c & 0x0f; 914 utfbytes = 2; 915 } else if ((c & 0xe0) == 0xc0) { 916 utfchar = c & 0x1f; 917 utfbytes = 1; 918 } else { 919 utfchar = c & 0x7f; 920 utfbytes = 0; 921 } 922 } else { 923 /* Followup characters. */ 924 if (utfbytes > 0) { 925 utfchar = (utfchar << 6) + (c & 0x3f); 926 utfbytes--; 927 } else if (utfbytes == 0) 928 utfbytes = ~0; 929 } 930 /* 931 * Write the complete Unicode character as UTF-16 when we 932 * have all the UTF-8 charactars collected. 933 */ 934 if (utfbytes == 0) { 935 /* 936 * If we need to write 2 UTF-16 characters, but 937 * we only have room for 1, then we truncate the 938 * string by writing a 0 instead. 939 */ 940 if (utfchar >= 0x10000 && s16idx < s16len - 1) { 941 s16[s16idx++] = 942 htole16(0xd800 | ((utfchar >> 10) - 0x40)); 943 s16[s16idx++] = 944 htole16(0xdc00 | (utfchar & 0x3ff)); 945 } else 946 s16[s16idx++] = (utfchar >= 0x10000) ? 0 : 947 htole16(utfchar); 948 } 949 } 950 /* 951 * If our input string was truncated, append an invalid encoding 952 * character to the output string. 953 */ 954 if (utfbytes != 0 && s16idx < s16len) 955 s16[s16idx++] = htole16(0xfffd); 956 } 957