コード例 #1
0
ファイル: vdmtool.c プロジェクト: bradla/OpenBSD-Hammer2
void
report(int fd)
{
	uint8_t *vdit, *vdit2, *tmpvdit;
	size_t vditsize, vditsize2;
	struct vdm_label *dl;
	struct vdm_boot_info *bi;
	struct disklabel *lp;
	uint8_t sector[VDM_BLOCK_SIZE];
	struct vdit_block_header *hdr;

	read_sector(fd, VDM_LABEL_SECTOR, sector);
	analyze_label_sector(sector, &dl, &bi);

	if (dl == NULL)
		return;

	printf("label version %04x\n", betoh16(dl->version));

	if (bi != NULL)
		printf("disk boot info: start %08x size %08x version %08x\n",
		    betoh32(bi->boot_start),
		    betoh32(bi->boot_size), betoh32(bi->version));

	read_sector(fd, VDIT_SECTOR, sector);
	hdr = (struct vdit_block_header *)sector;
	if (VDM_ID_KIND(&hdr->id) != VDIT_BLOCK_HEAD_BE) {
		lp = (struct disklabel *)(sector + LABELOFFSET);
		if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC) {
			if (verbose)
				printf("no VDIT but a native OpenBSD label\n");
			return;
		}
		errx(3, "unexpected block kind on sector %08x: %02x",
		    1, VDM_ID_KIND(&hdr->id));
	}

	vdit = read_vdit(fd, 1, &vditsize);
	if (vdit != NULL) {
		tmpvdit = vdit;
		while (tmpvdit != NULL)
			tmpvdit = print_vdit_entry(tmpvdit);

		vdit2 = read_vdit(fd, betoh32(hdr->secondary_vdit), &vditsize2);
		if (vdit2 == NULL)
			printf("can't read backup VDIT\n");
		else {
			if (vditsize2 < vditsize) {
				printf("WARNING: backup VDIT is smaller "
				    "than main VDIT!\n");
				vditsize = vditsize2;
			}
			if (memcmp(vdit, vdit2, vditsize) != 0)
				printf("VDIT and backup VDIT differ!\n");
			free(vdit2);
		}

		free(vdit);
	}
}
コード例 #2
0
ファイル: vdmtool.c プロジェクト: bradla/OpenBSD-Hammer2
uint8_t *
append_vdit_portion(int fd, uint32_t secno, uint8_t *buf, uint8_t *sector,
    int kind)
{
	struct vdit_block_header *hdr;
	u_int chunksz;

	hdr = (struct vdit_block_header *)sector;
	if (VDM_ID_KIND(&hdr->id) != kind) {
		printf("unexpected block kind on sector %08x: %02x\n",
		    secno, VDM_ID_KIND(&hdr->id));
		return NULL;
	}

	/* store first sector of the portion */
	chunksz = betoh16(hdr->chunksz);
	buf = append_vdit_sector(secno, buf, sector, kind);
	chunksz--;
	secno++;

	/* do the others */
	while (chunksz-- != 0) {
		read_sector(fd, secno, sector);
		buf = append_vdit_sector(secno, buf, sector, VDIT_BLOCK);
		if (buf == NULL)
			return NULL;
		secno++;
	}

	return buf;
}
コード例 #3
0
ファイル: vdmtool.c プロジェクト: bradla/OpenBSD-Hammer2
uint32_t
get_vdit_size(int fd, uint32_t secno)
{
	uint8_t sector[VDM_BLOCK_SIZE];
	struct vdit_block_header *hdr;
	uint32_t cursize = 0;
	int kind = VDIT_BLOCK_HEAD_BE;

	for (;;) {
		read_sector(fd, secno, sector);
		hdr = (struct vdit_block_header *)sector;
		if (VDM_ID_KIND(&hdr->id) != kind) {
			printf("unexpected VDIT block kind "
			    "on sector %08x: %02x\n",
			    secno, VDM_ID_KIND(&hdr->id));
			return 0;
		}

		if (verbose)
			printf("sector %08x: vdit frag type %02x, length %04x, "
			    "next frag at %08x\n",
			    secno, VDM_ID_KIND(&hdr->id),
			    betoh16(hdr->chunksz), secno);

		cursize += betoh16(hdr->chunksz);
		if (betoh32(hdr->nextblk) == VDM_NO_BLK_NUMBER)
			break;

		secno = betoh32(hdr->nextblk);
		kind = VDIT_PORTION_HEADER_BLOCK;
	}

	return cursize;
}
コード例 #4
0
ファイル: vdmtool.c プロジェクト: bradla/OpenBSD-Hammer2
uint8_t *
append_vdit_sector(uint32_t secno, uint8_t *buf, uint8_t *sector, int kind)
{
	struct vdit_block_header *hdr;

	hdr = (struct vdit_block_header *)sector;
	if (VDM_ID_KIND(&hdr->id) != kind) {
		printf("unexpected block kind on sector %08x: %02x\n",
		    secno, VDM_ID_KIND(&hdr->id));
		return NULL;
	}

#ifdef DEBUG
	printf("sector %08x: vdit block %08x\n",
	    secno, VDM_ID_BLKNO(&hdr->id));
#endif

	memcpy(buf, sector + sizeof *hdr, VDM_BLOCK_SIZE - (sizeof *hdr));
	return buf + VDM_BLOCK_SIZE - (sizeof *hdr);
}
コード例 #5
0
ファイル: disksubr.c プロジェクト: orumin/openbsd-efivars
/*
 * Process a contiguous chunk of VDIT, verifying and removing each block header
 * as we go.
 */
char *
extract_vdit_portion(char *dst, const char *src, unsigned int nsec,
    unsigned int vdit_blkno, int kind)
{
	struct vdit_block_header *vbh;

	for (; nsec != 0; nsec--) {
		vbh = (struct vdit_block_header *)src;
		if (VDM_ID_KIND(&vbh->id) != kind ||
		    VDM_ID_BLKNO(&vbh->id) != vdit_blkno ||
		    vbh->id.node_number != VDM_NO_NODE_NUMBER)
			return NULL;
		kind = VDIT_BLOCK;

		memcpy(dst, src + sizeof *vbh, dbtob(1) - sizeof *vbh);
		dst += dbtob(1) - sizeof *vbh;
		src += dbtob(1);
		vdit_blkno++;
	}

	return dst;
}
コード例 #6
0
ファイル: disksubr.c プロジェクト: orumin/openbsd-efivars
/*
 * Search for a VDIT volume information. If one is found, search for a
 * vdmpart instance of name "OpenBSD". If one is found, set the disklabel
 * bounds to the area it spans, and attempt to read a native label within
 * it.
 */
int
readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp,
    daddr_t *partoffp, int spoofonly, struct vdm_boot_info *vbi)
{
	struct buf *sbp = NULL;
	struct vdit_block_header *vbh;
	struct vdit_entry_header *veh;
	char *vdit_storage = NULL, *vdit_end;
	size_t vdit_size;
	unsigned int largest_chunk, vdit_blkno;
	int expected_kind;
	daddr_t blkno;
	int error = 0;
	vdit_id_t *vdmpart_id;
	struct vdit_vdmpart_instance *bsd_vdmpart;

	/*
	 * Figure out the size of the first VDIT.
	 */

	vdit_size = largest_chunk = 0;
	expected_kind = VDIT_BLOCK_HEAD_BE;
	blkno = VDIT_SECTOR;
	for (;;) {
		error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, blkno));
		if (error)
			return (error);

		vbh = (struct vdit_block_header *)bp->b_data;
		if (VDM_ID_KIND(&vbh->id) != expected_kind ||
		    VDM_ID_BLKNO(&vbh->id) != vdit_size ||
		    vbh->id.node_number != VDM_NO_NODE_NUMBER)
			return EINVAL;

		if (vbi != NULL) {
			if ((blkno >= vbi->boot_start &&
			     blkno < vbi->boot_start + vbi->boot_size) ||
			    (blkno + vbh->chunksz - 1 >= vbi->boot_start &&
			     blkno + vbh->chunksz - 1 <
			     vbi->boot_start + vbi->boot_size))
			return EINVAL;
		}

		if (vbh->chunksz > largest_chunk)
			largest_chunk = vbh->chunksz;
		vdit_size += vbh->chunksz;
		if (vbh->nextblk == VDM_NO_BLK_NUMBER)
			break;
		blkno = vbh->nextblk;
		if (blkno >= DL_GETDSIZE(lp))
			return EINVAL;
		expected_kind = VDIT_PORTION_HEADER_BLOCK;
	}

	/*
	 * Now read the first VDIT.
	 */

	vdit_size *= dbtob(1) - sizeof(struct vdit_block_header);
	vdit_storage = malloc(vdit_size, M_DEVBUF, M_WAITOK);
	largest_chunk = dbtob(largest_chunk);
	sbp = geteblk(largest_chunk);
	sbp->b_dev = bp->b_dev;

	vdit_end = vdit_storage;
	expected_kind = VDIT_BLOCK_HEAD_BE;
	blkno = VDIT_SECTOR;
	vdit_blkno = 0;
	for (;;) {
		sbp->b_blkno = blkno;
		sbp->b_bcount = largest_chunk;
		CLR(sbp->b_flags, B_READ | B_WRITE | B_DONE);
		SET(sbp->b_flags, B_BUSY | B_READ | B_RAW);
		(*strat)(sbp);
		if ((error = biowait(sbp)) != 0)
			goto done;

		vbh = (struct vdit_block_header *)sbp->b_data;
		if (VDM_ID_KIND(&vbh->id) != expected_kind) {
			error = EINVAL;
			goto done;
		}

		vdit_end = extract_vdit_portion(vdit_end, sbp->b_data,
		    vbh->chunksz, vdit_blkno, expected_kind);
		if (vdit_end == NULL) {
			error = EINVAL;
			goto done;
		}
		if (vbh->nextblk == VDM_NO_BLK_NUMBER)
			break;
		vdit_blkno += vbh->chunksz;
		blkno = vbh->nextblk;
		expected_kind = VDIT_PORTION_HEADER_BLOCK;
	}

	/*
	 * Walk the VDIT entries.
	 *
	 * If we find an OpenBSD vdmpart, we'll set our disk area bounds to
	 * its area, and will read a label from there.
	 */

	vdmpart_id = NULL;
	bsd_vdmpart = NULL;

	veh = (struct vdit_entry_header *)vdit_storage;
	while ((caddr_t)veh < vdit_end) {
		switch (veh->type) {
		case VDIT_ENTRY_SUBDRIVER_INFO:
		    {
			struct vdit_subdriver_entry *vse;

			vse = (struct vdit_subdriver_entry *)(veh + 1);
			if (strcmp(vse->name, VDM_SUBDRIVER_VDMPART) == 0)
				vdmpart_id = &vse->subdriver_id;
		    }
			break;
		case VDIT_ENTRY_INSTANCE:
		    {
			struct vdit_instance_entry *vie;

			vie = (struct vdit_instance_entry *)(veh + 1);
			if (strcmp(vie->name, VDM_INSTANCE_OPENBSD) == 0) {
				if (vdmpart_id != NULL &&
				    memcmp(vdmpart_id, &vie->subdriver_id,
				      sizeof(vdit_id_t)) == 0) {
					/* found it! */
					if (bsd_vdmpart != NULL) {
						bsd_vdmpart = NULL;
						veh->type = VDIT_ENTRY_SENTINEL;
					} else
						bsd_vdmpart = (struct
						    vdit_vdmpart_instance *)vie;
				}
			}
		    }
			break;
		}
		if (veh->type == VDIT_ENTRY_SENTINEL)
			break;
		veh = (struct vdit_entry_header *)((char *)veh + veh->size);
	}

	if (bsd_vdmpart != NULL) {
		uint32_t start, size;

		memcpy(&start, &bsd_vdmpart->start_blkno, sizeof(uint32_t));
		memcpy(&size, &bsd_vdmpart->size, sizeof(uint32_t));

		if (start >= DL_GETDSIZE(lp) ||
		    start + size > DL_GETDSIZE(lp)) {
			error = EINVAL;
			goto done;
		}

		if (partoffp != NULL) {
			*partoffp = start;
			goto done;
		} else {
			DL_SETBSTART(lp, start);
			DL_SETBEND(lp, start + size);
		}

		/*
		 * Now read the native label.
		 */

		if (spoofonly == 0) {
			error = readdisksector(bp, strat, lp,
			    DL_BLKTOSEC(lp, start + LABELSECTOR));
			if (error)
				goto done;

			error = checkdisklabel(bp->b_data + LABELOFFSET, lp,
			    start, start + size);
		}
	} else {
		/*
		 * VDM label, but no OpenBSD vdmpart partition found.
		 * XXX is it worth registering the whole disk as a
		 * XXX `don't touch' vendor partition in that case?
		 */
		error = ENOENT;
		goto done;
	}

done:
	free(vdit_storage, M_DEVBUF, vdit_size);
	if (sbp != NULL) {
		sbp->b_flags |= B_INVAL;
		brelse(sbp);
	}

	return error;
}