Пример #1
0
static void
rem(int fd)
{
	uuid_t uuid;
	map_t *gpt, *tpg;
	map_t *tbl, *lbt;
	map_t *m;
	struct gpt_hdr *hdr;
	struct gpt_ent *ent;
	unsigned int i;

	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
	if (gpt == NULL) {
		warnx("%s: error: no primary GPT header; run create or recover",
		    device_name);
		return;
	}

	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
	if (tpg == NULL) {
		warnx("%s: error: no secondary GPT header; run recover",
		    device_name);
		return;
	}

	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
	if (tbl == NULL || lbt == NULL) {
		warnx("%s: error: run recover -- trust me", device_name);
		return;
	}

	/* Remove all matching entries in the map. */
	for (m = map_first(); m != NULL; m = m->map_next) {
		if (m->map_type != MAP_TYPE_GPT_PART || m->map_index == NOENTRY)
			continue;
		if (entry != NOENTRY && entry != m->map_index)
			continue;
		if (block > 0 && block != m->map_start)
			continue;
		if (size > 0 && size != m->map_size)
			continue;

		i = m->map_index;

		hdr = gpt->map_data;
		ent = (void*)((char*)tbl->map_data + i *
		    le32toh(hdr->hdr_entsz));
		le_uuid_dec(&ent->ent_type, &uuid);
		if (!uuid_is_nil(&type, NULL) &&
		    !uuid_equal(&type, &uuid, NULL))
			continue;

		/* Remove the primary entry by clearing the partition type. */
		uuid_create_nil(&ent->ent_type, NULL);

		hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
		hdr->hdr_crc_self = 0;
		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));

		gpt_write(fd, gpt);
		gpt_write(fd, tbl);

		hdr = tpg->map_data;
		ent = (void*)((char*)lbt->map_data + i *
		    le32toh(hdr->hdr_entsz));

		/* Remove the secundary entry. */
		uuid_create_nil(&ent->ent_type, NULL);

		hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
		hdr->hdr_crc_self = 0;
		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));

		gpt_write(fd, lbt);
		gpt_write(fd, tpg);

		printf("%ss%u removed\n", device_name, m->map_index);
	}
}
Пример #2
0
static void
show(int fd __unused)
{
	uuid_t type;
	off_t start;
	map_t *m, *p;
	struct mbr *mbr;
	struct gpt_ent *ent;
	unsigned int i;

	printf("  %*s", lbawidth, "start");
	printf("  %*s", lbawidth, "size");
	printf("  index  contents\n");

	m = map_first();
	while (m != NULL) {
		printf("  %*llu", lbawidth, (long long)m->map_start);
		printf("  %*llu", lbawidth, (long long)m->map_size);
		putchar(' ');
		putchar(' ');
		if (m->map_index > 0)
			printf("%5d", m->map_index);
		else
			printf("     ");
		putchar(' ');
		putchar(' ');
		switch (m->map_type) {
		case MAP_TYPE_MBR:
			if (m->map_start != 0)
				printf("Extended ");
			printf("MBR");
			break;
		case MAP_TYPE_PRI_GPT_HDR:
			printf("Pri GPT header");
			break;
		case MAP_TYPE_SEC_GPT_HDR:
			printf("Sec GPT header");
			break;
		case MAP_TYPE_PRI_GPT_TBL:
			printf("Pri GPT table");
			break;
		case MAP_TYPE_SEC_GPT_TBL:
			printf("Sec GPT table");
			break;
		case MAP_TYPE_MBR_PART:
			p = m->map_data;
			if (p->map_start != 0)
				printf("Extended ");
			printf("MBR part ");
			mbr = p->map_data;
			for (i = 0; i < 4; i++) {
				start = le16toh(mbr->mbr_part[i].part_start_hi);
				start = (start << 16) +
				    le16toh(mbr->mbr_part[i].part_start_lo);
				if (m->map_start == p->map_start + start)
					break;
			}
			printf("%d", mbr->mbr_part[i].part_typ);
			break;
		case MAP_TYPE_GPT_PART:
			printf("GPT part ");
			ent = m->map_data;
			if (show_label) {
				printf("- \"%s\"",
				    utf16_to_utf8(ent->ent_name));
			} else {
				le_uuid_dec(&ent->ent_type, &type);
				printf("- %s", friendly(&type));
			}
			break;
		case MAP_TYPE_PMBR:
			printf("PMBR");
			break;
		}
		putchar('\n');
		m = m->map_next;
	}
}
Пример #3
0
/*
 * Handle GPT on raw disk.  Note that GPTs are not recursive.  The MBR is
 * ignored once a GPT has been detected.
 *
 * GPTs always start at block #1, regardless of how the MBR has been set up.
 * In fact, the MBR's starting block might be pointing to the boot partition
 * in the GPT rather then to the start of the GPT.
 *
 * This routine is called from mbrinit() when a GPT has been detected.
 */
int
gptinit(cdev_t dev, struct disk_info *info, struct diskslices **sspp)
{
	struct buf *bp1 = NULL;
	struct buf *bp2 = NULL;
	struct gpt_hdr *gpt;
	struct gpt_ent *ent;
	struct diskslice *sp;
	struct diskslices *ssp;
	cdev_t wdev;
	int error;
	uint32_t len;
	uint32_t entries;
	uint32_t entsz;
	uint32_t crc;
	uint32_t table_lba;
	uint32_t table_blocks;
	int i = 0, j;
	const char *dname;

	/*
	 * The GPT starts in sector 1.
	 */
	wdev = dev;
	dname = dev_dname(wdev);
	bp1 = geteblk((int)info->d_media_blksize);
	bp1->b_bio1.bio_offset = info->d_media_blksize;
	bp1->b_bio1.bio_done = biodone_sync;
	bp1->b_bio1.bio_flags |= BIO_SYNC;
	bp1->b_bcount = info->d_media_blksize;
	bp1->b_cmd = BUF_CMD_READ;
	dev_dstrategy(wdev, &bp1->b_bio1);
	if (biowait(&bp1->b_bio1, "gptrd") != 0) {
		kprintf("%s: reading GPT @ block 1: error %d\n",
			dname, bp1->b_error);
		error = EIO;
		goto done;
	}

	/*
	 * Header sanity check
	 */
	gpt = (void *)bp1->b_data;
	len = le32toh(gpt->hdr_size);
	if (len < GPT_MIN_HDR_SIZE || len > info->d_media_blksize) {
		kprintf("%s: Illegal GPT header size %d\n", dname, len);
		error = EINVAL;
		goto done;
	}

	crc = le32toh(gpt->hdr_crc_self);
	gpt->hdr_crc_self = 0;
	if (crc32(gpt, len) != crc) {
		kprintf("%s: GPT CRC32 did not match\n", dname);
		error = EINVAL;
		goto done;
	}

	/*
	 * Validate the partition table and its location, then read it
	 * into a buffer.
	 */
	entries = le32toh(gpt->hdr_entries);
	entsz = le32toh(gpt->hdr_entsz);
	table_lba = le32toh(gpt->hdr_lba_table);
	table_blocks = (entries * entsz + info->d_media_blksize - 1) /
		       info->d_media_blksize;
	if (entries < 1 || entries > 128 ||
	    entsz < 128 || (entsz & 7) || entsz > MAXBSIZE / entries ||
	    table_lba < 2 || table_lba + table_blocks > info->d_media_blocks) {
		kprintf("%s: GPT partition table is out of bounds\n", dname);
		error = EINVAL;
		goto done;
	}

	/*
	 * XXX subject to device dma size limitations
	 */
	bp2 = geteblk((int)(table_blocks * info->d_media_blksize));
	bp2->b_bio1.bio_offset = (off_t)table_lba * info->d_media_blksize;
	bp2->b_bio1.bio_done = biodone_sync;
	bp2->b_bio1.bio_flags |= BIO_SYNC;
	bp2->b_bcount = table_blocks * info->d_media_blksize;
	bp2->b_cmd = BUF_CMD_READ;
	dev_dstrategy(wdev, &bp2->b_bio1);
	if (biowait(&bp2->b_bio1, "gptrd") != 0) {
		kprintf("%s: reading GPT partition table @ %lld: error %d\n",
			dname,
			(long long)bp2->b_bio1.bio_offset,
			bp2->b_error);
		error = EIO;
		goto done;
	}

	/*
	 * We are passed a pointer to a minimal slices struct.  Replace
	 * it with a maximal one (128 slices + special slices).  Well,
	 * really there is only one special slice (the WHOLE_DISK_SLICE)
	 * since we use the compatibility slice for s0, but don't quibble.
	 * 
	 */
	kfree(*sspp, M_DEVBUF);
	ssp = *sspp = dsmakeslicestruct(BASE_SLICE+128, info);

	/*
	 * Create a slice for each partition.
	 */
	for (i = 0; i < (int)entries && i < 128; ++i) {
		struct gpt_ent sent;
		char partname[2];
		char *sname;

		ent = (void *)((char *)bp2->b_data + i * entsz);
		le_uuid_dec(&ent->ent_type, &sent.ent_type);
		le_uuid_dec(&ent->ent_uuid, &sent.ent_uuid);
		sent.ent_lba_start = le64toh(ent->ent_lba_start);
		sent.ent_lba_end = le64toh(ent->ent_lba_end);
		sent.ent_attr = le64toh(ent->ent_attr);

		for (j = 0; j < NELEM(ent->ent_name); ++j)
			sent.ent_name[j] = le16toh(ent->ent_name[j]);

		/*
		 * The COMPATIBILITY_SLICE is actually slice 0 (s0).  This
		 * is a bit weird becaue the whole-disk slice is #1, so
		 * slice 1 (s1) starts at BASE_SLICE.
		 */
		if (i == 0)
			sp = &ssp->dss_slices[COMPATIBILITY_SLICE];
		else
			sp = &ssp->dss_slices[BASE_SLICE+i-1];
		sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE,
			       WHOLE_SLICE_PART, partname);

		if (kuuid_is_nil(&sent.ent_type))
			continue;

		if (sent.ent_lba_start < table_lba + table_blocks ||
		    sent.ent_lba_end >= info->d_media_blocks ||
		    sent.ent_lba_start >= sent.ent_lba_end) {
			kprintf("%s part %d: unavailable, bad start or "
				"ending lba\n",
				sname, i);
		} else {
			gpt_setslice(sname, info, sp, &sent);
		}
	}
	ssp->dss_nslices = BASE_SLICE + i;

	error = 0;
done:
	if (bp1) {
		bp1->b_flags |= B_INVAL | B_AGE;
		brelse(bp1);
	}
	if (bp2) {
		bp2->b_flags |= B_INVAL | B_AGE;
		brelse(bp2);
	}
	if (error == EINVAL)
		error = 0;
	return (error);
}