Beispiel #1
0
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);
}
Beispiel #2
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);
}
Beispiel #3
0
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);
}
Beispiel #4
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
static int
dskread(void *buf, daddr_t lba, unsigned nblk)
{

	return drvread(&dsk, buf, lba + dsk.start, nblk);
}
Beispiel #7
0
/*
 * 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);
}
Beispiel #8
0
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
}