static int gptread_hdr(const char *which, struct dsk *dskp, struct gpt_hdr *hdr, uint64_t hdrlba) { uint32_t crc; if (drvread(dskp, secbuf, hdrlba, 1)) { printf("%s: unable to read %s GPT header\n", BOOTPROG, which); return (-1); } bcopy(secbuf, hdr, sizeof(*hdr)); if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 || hdr->hdr_lba_self != hdrlba || hdr->hdr_revision < 0x00010000 || hdr->hdr_entsz < sizeof(struct gpt_ent) || hdr->hdr_entries > MAXTBLENTS || DEV_BSIZE % hdr->hdr_entsz != 0) { printf("%s: invalid %s GPT header\n", BOOTPROG, which); return (-1); } crc = hdr->hdr_crc_self; hdr->hdr_crc_self = 0; if (crc32(hdr, hdr->hdr_size) != crc) { printf("%s: %s GPT header checksum mismatch\n", BOOTPROG, which); return (-1); } hdr->hdr_crc_self = crc; return (0); }
static int dskread(void *buf, unsigned lba, unsigned nblk) { struct dos_partition *dp; struct disklabel *d; char *sec; int i; if (!dsk_meta) { sec = dmadat->secbuf; dsk_start = 0; if (drvread(sec, DOSBBSECTOR, 1)) return -1; dp = (void *)(sec + DOSPARTOFF); for (i = 0; i < NDOSPART; i++) { if (dp[i].dp_typ == DOSPTYP_386BSD) break; } if (i == NDOSPART) return -1; /* * Although dp_start is aligned within the disk * partition structure, DOSPARTOFF is 446, which is * only word (2) aligned, not longword (4) aligned. * Cope by using memcpy to fetch the start of this * partition. */ memcpy(&dsk_start, &dp[1].dp_start, 4); if (drvread(sec, dsk_start + LABELSECTOR, 1)) return -1; d = (void *)(sec + LABELOFFSET); if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { printf("Invalid %s\n", "label"); return -1; } if (!d->d_partitions[0].p_size) { printf("Invalid %s\n", "partition"); return -1; } dsk_start += d->d_partitions[0].p_offset; dsk_start -= d->d_partitions[RAW_PART].p_offset; dsk_meta++; } return drvread(buf, dsk_start + lba, nblk); }
static int gptread_table(const char *which, const uuid_t *uuid, struct dsk *dskp, struct gpt_hdr *hdr, struct gpt_ent *table) { struct gpt_ent *ent; int entries_per_sec; int part, nent; daddr_t slba; if (hdr->hdr_entries == 0) return (0); entries_per_sec = DEV_BSIZE / hdr->hdr_entsz; slba = hdr->hdr_lba_table; nent = 0; for (;;) { if (drvread(dskp, secbuf, slba, 1)) { printf("%s: unable to read %s GPT partition table\n", BOOTPROG, which); return (-1); } ent = (struct gpt_ent *)secbuf; for (part = 0; part < entries_per_sec; part++, ent++) { bcopy(ent, &table[nent], sizeof(table[nent])); if (++nent >= hdr->hdr_entries) break; } if (nent >= hdr->hdr_entries) break; slba++; } if (crc32(table, nent * hdr->hdr_entsz) != hdr->hdr_crc_table) { printf("%s: %s GPT table checksum mismatch\n", BOOTPROG, which); return (-1); } return (0); }
static int dskread(void *buf, unsigned lba, unsigned nblk) { struct dos_partition *dp; struct disklabel *d; char *sec; unsigned sl, i; if (!dsk_meta) { sec = dmadat->secbuf; dsk.start = 0; if (drvread(sec, DOSBBSECTOR, 1)) return -1; dp = (void *)(sec + DOSPARTOFF); sl = dsk.slice; if (sl < BASE_SLICE) { for (i = 0; i < NDOSPART; i++) if (dp[i].dp_typ == DOSPTYP_386BSD && (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { sl = BASE_SLICE + i; if (dp[i].dp_flag & 0x80 || dsk.slice == COMPATIBILITY_SLICE) break; } if (dsk.slice == WHOLE_DISK_SLICE) dsk.slice = sl; } if (sl != WHOLE_DISK_SLICE) { if (sl != COMPATIBILITY_SLICE) dp += sl - BASE_SLICE; if (dp->dp_typ != DOSPTYP_386BSD) { printf("Invalid %s\n", "slice"); return -1; } dsk.start = dp->dp_start; } if (drvread(sec, dsk.start + LABELSECTOR, 1)) return -1; d = (void *)(sec + LABELOFFSET); if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { if (dsk.part != RAW_PART) { printf("Invalid %s\n", "label"); return -1; } } else { if (!dsk.init) { if (d->d_type == DTYPE_SCSI) dsk.type = TYPE_DA; dsk.init++; } if (dsk.part >= d->d_npartitions || !d->d_partitions[dsk.part].p_size) { printf("Invalid %s\n", "partition"); return -1; } dsk.start += d->d_partitions[dsk.part].p_offset; dsk.start -= d->d_partitions[RAW_PART].p_offset; } } return drvread(buf, dsk.start + lba, nblk); }
static int dskread(void *buf, daddr_t lba, unsigned nblk) { struct gpt_hdr hdr; struct gpt_ent *ent; char *sec; daddr_t slba, elba; int part, entries_per_sec; if (!dsk_meta) { /* Read and verify GPT. */ sec = dmadat->secbuf; dsk.start = 0; if (drvread(sec, 1, 1)) return -1; memcpy(&hdr, sec, sizeof(hdr)); if (bcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 || hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { printf("Invalid GPT header\n"); return -1; } /* XXX: CRC check? */ /* * If the partition isn't specified, then search for the first UFS * partition and hope it is /. Perhaps we should be using an OS * flag in the GPT entry to mark / partitions. * * If the partition is specified, then figure out the LBA for the * sector containing that partition index and load it. */ entries_per_sec = DEV_BSIZE / hdr.hdr_entsz; if (dsk.part == -1) { slba = hdr.hdr_lba_table; elba = slba + hdr.hdr_entries / entries_per_sec; while (slba < elba && dsk.part == -1) { if (drvread(sec, slba, 1)) return -1; for (part = 0; part < entries_per_sec; part++) { ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz); if (bcmp(&ent->ent_type, &freebsd_ufs_uuid, sizeof(uuid_t)) == 0) { dsk.part = (slba - hdr.hdr_lba_table) * entries_per_sec + part + 1; dsk.start = ent->ent_lba_start; break; } } slba++; } if (dsk.part == -1) { printf("No UFS partition was found\n"); return -1; } } else { if (dsk.part > hdr.hdr_entries) { printf("Invalid partition index\n"); return -1; } slba = hdr.hdr_lba_table + (dsk.part - 1) / entries_per_sec; if (drvread(sec, slba, 1)) return -1; part = (dsk.part - 1) % entries_per_sec; ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz); if (bcmp(&ent->ent_type, &freebsd_ufs_uuid, sizeof(uuid_t)) != 0) { printf("Specified partition is not UFS\n"); return -1; } dsk.start = ent->ent_lba_start; } /* * XXX: No way to detect SCSI vs. ATA currently. */ #if 0 if (!dsk.init) { if (d->d_type == DTYPE_SCSI) dsk.type = TYPE_DA; dsk.init++; } #endif } return drvread(buf, dsk.start + lba, nblk); }
static int dskread(void *buf, daddr_t lba, unsigned nblk) { return drvread(&dsk, buf, lba + dsk.start, nblk); }
/* * Read from the probed disk. We have established the slice and partition * base sector. */ int dskread(void *buf, unsigned lba, unsigned nblk) { return drvread(buf, dsk.start + lba, nblk); }
static int dskprobe(void) { struct dos_partition *dp; #ifdef DISKLABEL64 struct disklabel64 *d; #else struct disklabel32 *d; #endif char *sec; unsigned i; uint8_t sl; /* * Probe slice table */ sec = boot2_dmadat->secbuf; dsk.start = 0; if (drvread(sec, DOSBBSECTOR, 1)) return -1; dp = (void *)(sec + DOSPARTOFF); sl = dsk.slice; if (sl < BASE_SLICE) { for (i = 0; i < NDOSPART; i++) if (dp[i].dp_typ == DOSPTYP_386BSD && (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { sl = BASE_SLICE + i; if (dp[i].dp_flag & 0x80 || dsk.slice == COMPATIBILITY_SLICE) break; } if (dsk.slice == WHOLE_DISK_SLICE) dsk.slice = sl; } if (sl != WHOLE_DISK_SLICE) { if (sl != COMPATIBILITY_SLICE) dp += sl - BASE_SLICE; if (dp->dp_typ != DOSPTYP_386BSD) { printf(INVALID_S, "slice"); return -1; } dsk.start = dp->dp_start; } /* * Probe label and partition table */ #ifdef DISKLABEL64 if (drvread(sec, dsk.start, (sizeof(struct disklabel64) + 511) / 512)) return -1; d = (void *)sec; if (d->d_magic != DISKMAGIC64) { printf(INVALID_S, "label"); return -1; } else { if (dsk.part >= d->d_npartitions || d->d_partitions[dsk.part].p_bsize == 0) { printf(INVALID_S, "partition"); return -1; } dsk.start += d->d_partitions[dsk.part].p_boffset / 512; } #else if (drvread(sec, dsk.start + LABELSECTOR32, 1)) return -1; d = (void *)(sec + LABELOFFSET32); if (d->d_magic != DISKMAGIC32 || d->d_magic2 != DISKMAGIC32) { if (dsk.part != RAW_PART) { printf(INVALID_S, "label"); return -1; } } else { if (!dsk.init) { if (d->d_type == DTYPE_SCSI) dsk.type = TYPE_DA; dsk.init++; } if (dsk.part >= d->d_npartitions || !d->d_partitions[dsk.part].p_size) { printf(INVALID_S, "partition"); return -1; } dsk.start += d->d_partitions[dsk.part].p_offset; dsk.start -= d->d_partitions[RAW_PART].p_offset; } #endif /* * Probe filesystem */ #if defined(UFS) && defined(HAMMERFS) if (boot2_hammer_api.fsinit() == 0) { fsapi = &boot2_hammer_api; } else if (boot2_ufs_api.fsinit() == 0) { fsapi = &boot2_ufs_api; } else { printf("fs probe failed\n"); fsapi = &boot2_ufs_api; return -1; } return 0; #else return fsapi->fsinit(); #endif }