UINTN gptsync(VOID) { UINTN status = 0; UINTN status_gpt, status_mbr; BOOLEAN proceed = FALSE; Print(L"gptsync version %s\ncopyright (c) 2006-2007 Christoph Pfisterer & 2013 Roderick W. Smith\n", VERSION); // get full information from disk status_gpt = read_gpt(); status_mbr = read_mbr(); if (status_gpt != 0 || status_mbr != 0) return (status_gpt || status_mbr); // cross-check current situation Print(L"\n"); status = check_gpt(); // check GPT for consistency if (status != 0) return status; status = check_mbr(); // check MBR for consistency if (status != 0) return status; status = analyze(); // analyze the situation & compose new MBR table if (status != 0) return status; if (new_mbr_part_count == 0) return status; // offer user the choice what to do status = input_boolean(STR("\nMay I update the MBR as printed above? [y/N] "), &proceed); if (status != 0 || proceed != TRUE) return status; // adjust the MBR and write it back status = write_mbr(); if (status != 0) return status; return status; }
UINTN gptsync(int optind, int argc, char **argv) { UINTN status = 0; UINTN status_gpt, status_mbr; BOOLEAN proceed = FALSE; // get full information from disk status_gpt = read_gpt(); status_mbr = read_mbr(); if (status_gpt != 0 || status_mbr != 0) return (status_gpt || status_mbr); // cross-check current situation Print(L"\n"); status = check_gpt(); // check GPT for consistency if (status != 0) return status; status = check_mbr(); // check MBR for consistency if (status != 0) return status; status = analyze(optind, argc, argv); // analyze the situation & compose new MBR table if (status != 0) return status; // offer user the choice what to do status = input_boolean(STR("\nMay I update the MBR as printed above? [y/N] "), &proceed); if (status != 0 || proceed != TRUE) return status; // adjust the MBR and write it back status = write_mbr(); if (status != 0) return status; return status; }
static bool guid_is_nil(const struct uuid *u) { static const struct uuid nil = { .time_low = 0 }; return (memcmp(u, &nil, sizeof(*u)) == 0 ? true : false); } static bool guid_is_equal(const struct uuid *a, const struct uuid *b) { return (memcmp(a, b, sizeof(*a)) == 0 ? true : false); } static int check_gpt(struct biosdisk *d, daddr_t sector) { struct gpt_hdr gpth; const struct gpt_ent *ep; const struct uuid *u; daddr_t entblk; size_t size; uint32_t crc; int sectors; int entries; int entry; int i, j; /* read in gpt_hdr sector */ if (readsects(&d->ll, sector, 1, d->buf, 1)) { #ifdef DISK_DEBUG printf("Error reading GPT header at %"PRId64"\n", sector); #endif return EIO; } memcpy(&gpth, d->buf, sizeof(gpth)); if (memcmp(GPT_HDR_SIG, gpth.hdr_sig, sizeof(gpth.hdr_sig))) return -1; crc = gpth.hdr_crc_self; gpth.hdr_crc_self = 0; gpth.hdr_crc_self = crc32(0, (const void *)&gpth, GPT_HDR_SIZE); if (gpth.hdr_crc_self != crc) { return -1; } if (gpth.hdr_lba_self != sector) return -1; #ifdef _STANDALONE bi_wedge.matchblk = sector; bi_wedge.matchnblks = 1; md5(bi_wedge.matchhash, d->buf, d->ll.secsize); #endif sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */ entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */ entblk = gpth.hdr_lba_table; crc = crc32(0, NULL, 0); j = 0; ep = (const struct gpt_ent *)d->buf; for (entry = 0; entry < gpth.hdr_entries; entry += entries) { size = MIN(sizeof(d->buf), (gpth.hdr_entries - entry) * gpth.hdr_entsz); entries = size / gpth.hdr_entsz; sectors = roundup(size, d->ll.secsize) / d->ll.secsize; if (readsects(&d->ll, entblk, sectors, d->buf, 1)) return -1; entblk += sectors; crc = crc32(crc, (const void *)d->buf, size); for (i = 0; j < BIOSDISKNPART && i < entries; i++, j++) { u = (const struct uuid *)ep[i].ent_type; if (!guid_is_nil(u)) { d->part[j].offset = ep[i].ent_lba_start; d->part[j].size = ep[i].ent_lba_end - ep[i].ent_lba_start + 1; if (guid_is_equal(u, &GET_nbsd_ffs)) d->part[j].fstype = FS_BSDFFS; else if (guid_is_equal(u, &GET_nbsd_lfs)) d->part[j].fstype = FS_BSDLFS; else if (guid_is_equal(u, &GET_nbsd_raid)) d->part[j].fstype = FS_RAID; else if (guid_is_equal(u, &GET_nbsd_swap)) d->part[j].fstype = FS_SWAP; else d->part[j].fstype = FS_OTHER; } } } if (crc != gpth.hdr_crc_table) { #ifdef DISK_DEBUG printf("GPT table CRC invalid\n"); #endif return -1; } return 0; } static int read_gpt(struct biosdisk *d) { struct biosdisk_extinfo ed; daddr_t gptsector[2]; int i, error; if (d->ll.type != BIOSDISK_TYPE_HD) /* No GPT on floppy and CD */ return -1; gptsector[0] = GPT_HDR_BLKNO; if (set_geometry(&d->ll, &ed) == 0 && d->ll.flags & BIOSDISK_INT13EXT) { gptsector[1] = ed.totsec - 1; /* Sanity check values returned from BIOS */ if (ed.sbytes >= 512 && (ed.sbytes & (ed.sbytes - 1)) == 0) d->ll.secsize = ed.sbytes; } else { #ifdef DISK_DEBUG printf("Unable to determine extended disk geometry - " "using CHS\n"); #endif /* at least try some other reasonable values then */ gptsector[1] = d->ll.chs_sectors - 1; } /* * Use any valid GPT available, do not require both GPTs to be valid */ for (i = 0; i < __arraycount(gptsector); i++) { error = check_gpt(d, gptsector[i]); if (error == 0) break; } if (i >= __arraycount(gptsector)) { memset(d->part, 0, sizeof(d->part)); return -1; } #ifdef DISK_DEBUG printf("using %s GPT\n", (i == 0) ? "primary" : "secondary"); #endif return 0; } #endif /* !NO_GPT */ #ifndef NO_DISKLABEL static void ingest_label(struct biosdisk *d, struct disklabel *lp) { int part; memset(d->part, 0, sizeof(d->part)); for (part = 0; part < lp->d_npartitions; part++) { if (lp->d_partitions[part].p_size == 0) continue; if (lp->d_partitions[part].p_fstype == FS_UNUSED) continue; d->part[part].fstype = lp->d_partitions[part].p_fstype; d->part[part].offset = lp->d_partitions[part].p_offset; d->part[part].size = lp->d_partitions[part].p_size; } }