Ejemplo n.º 1
0
static int
read_label(struct biosdisk *d)
{
	struct disklabel dflt_lbl;
	struct mbr_partition mbr[MBR_PART_COUNT];
	struct partition *p;
	uint32_t sector;
	int i;
	int error;
	int typ;
	uint32_t ext_base, this_ext, next_ext;
#ifdef COMPAT_386BSD_MBRPART
	int sector_386bsd = -1;
#endif

	memset(&dflt_lbl, 0, sizeof(dflt_lbl));
	dflt_lbl.d_npartitions = 8;

	d->boff = 0;

	if (d->ll.type != BIOSDISK_TYPE_HD)
		/* No label on floppy and CD */
		return -1;

	/*
	 * find NetBSD Partition in DOS partition table
	 * XXX check magic???
	 */
	ext_base = 0;
	next_ext = 0;
	for (;;) {
		this_ext = ext_base + next_ext;
		next_ext = 0;
		if (readsects(&d->ll, this_ext, 1, d->buf, 0)) {
#ifdef DISK_DEBUG
			printf("error reading MBR sector %u\n", this_ext);
#endif
			return EIO;
		}
		memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr));
		/* Look for NetBSD partition ID */
		for (i = 0; i < MBR_PART_COUNT; i++) {
			typ = mbr[i].mbrp_type;
			if (typ == 0)
				continue;
			sector = this_ext + mbr[i].mbrp_start;
#ifdef DISK_DEBUG
			printf("ptn type %d in sector %u\n", typ, sector);
#endif
                        if (typ == MBR_PTYPE_MINIX_14B) {
				if (!read_minix_subp(d, &dflt_lbl,
						   this_ext, sector)) {
					/* Don't add "container" partition */
					continue;
				}
			}
			if (typ == MBR_PTYPE_NETBSD) {
				error = check_label(d, sector);
				if (error >= 0)
					return error;
			}
			if (MBR_IS_EXTENDED(typ)) {
				next_ext = mbr[i].mbrp_start;
				continue;
			}
#ifdef COMPAT_386BSD_MBRPART
			if (this_ext == 0 && typ == MBR_PTYPE_386BSD)
				sector_386bsd = sector;
#endif
			if (this_ext != 0) {
				if (dflt_lbl.d_npartitions >= MAXPARTITIONS)
					continue;
				p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++];
			} else
				p = &dflt_lbl.d_partitions[i];
			p->p_offset = sector;
			p->p_size = mbr[i].mbrp_size;
			p->p_fstype = xlat_mbr_fstype(typ);
		}
		if (next_ext == 0)
			break;
		if (ext_base == 0) {
			ext_base = next_ext;
			next_ext = 0;
		}
	}

	sector = 0;
#ifdef COMPAT_386BSD_MBRPART
	if (sector_386bsd != -1) {
		printf("old BSD partition ID!\n");
		sector = sector_386bsd;
	}
#endif

	/*
	 * One of two things:
	 * 	1. no MBR
	 *	2. no NetBSD partition in MBR
	 *
	 * We simply default to "start of disk" in this case and
	 * press on.
	 */
	error = check_label(d, sector);
	if (error >= 0)
		return error;

	/*
	 * Nothing at start of disk, return info from mbr partitions.
	 */
	/* XXX fill it to make checksum match kernel one */
	dflt_lbl.d_checksum = dkcksum(&dflt_lbl);
	ingest_label(d, &dflt_lbl);
	return 0;
}
Ejemplo n.º 2
0
static void
getparts(mbr_args_t *a, uint32_t off, uint32_t extoff)
{
	struct dkwedge_info dkw;
	struct mbr_partition *dp;
	struct mbr_sector *mbr;
	const char *ptype;
	int i, error;

	error = dkwedge_read(a->pdk, a->vp, off, a->buf, a->secsize);
	if (error) {
		aprint_error("%s: unable to read MBR @ %u/%u, "
		    "error = %d\n", a->pdk->dk_name, off, a->secsize, a->error);
		a->error = error;
		return;
	}

	mbr = a->buf;
	if (mbr->mbr_magic != htole16(MBR_MAGIC))
		return;

	dp = mbr->mbr_parts;

	for (i = 0; i < MBR_PART_COUNT; i++) {
		/* Extended partitions are handled below. */
		if (dp[i].mbrp_type == 0 ||
		    MBR_IS_EXTENDED(dp[i].mbrp_type))
		    	continue;

		if ((ptype = mbr_ptype_to_str(dp[i].mbrp_type)) == NULL) {
			/*
			 * XXX Should probably just add these...
			 * XXX maybe just have an empty ptype?
			 */
			aprint_verbose("%s: skipping partition %d, "
			    "type 0x%02x\n", a->pdk->dk_name, i,
			    dp[i].mbrp_type);
			continue;
		}
		strcpy(dkw.dkw_ptype, ptype);

		strcpy(dkw.dkw_parent, a->pdk->dk_name);
		dkw.dkw_offset = le32toh(dp[i].mbrp_start);
		dkw.dkw_size = le32toh(dp[i].mbrp_size);

		/*
		 * These get historical disk naming style
		 * wedge names.  We start at 'e', and reserve
		 * 4 slots for each MBR we parse.
		 *
		 * XXX For FAT, we should extract the FAT volume
		 * XXX name.
		 */
		snprintf(dkw.dkw_wname, sizeof(dkw.dkw_wname),
		    "%s%c", a->pdk->dk_name,
		    'e' + (a->mbr_count * MBR_PART_COUNT) + i);

		error = dkwedge_add(&dkw);
		if (error == EEXIST)
			aprint_error("%s: wedge named '%s' already "
			    "exists, manual intervention required\n",
			    a->pdk->dk_name, dkw.dkw_wname);
		else if (error)
			aprint_error("%s: error %d adding partition "
			    "%d type 0x%02x\n", a->pdk->dk_name, error,
			    (a->mbr_count * MBR_PART_COUNT) + i,
			    dp[i].mbrp_type);
	}

	/* We've parsed one MBR. */
	a->mbr_count++;

	/* Recursively scan extended partitions. */
	for (i = 0; i < MBR_PART_COUNT; i++) {
		uint32_t poff;

		if (MBR_IS_EXTENDED(dp[i].mbrp_type)) {
			poff = le32toh(dp[i].mbrp_start) + extoff;
			getparts(a, poff, extoff ? extoff : poff);
		}
	}
}
Ejemplo n.º 3
0
static int
scan_mbr(mbr_args_t *a, int (*actn)(mbr_args_t *, mbr_partition_t *, int, uint))
{
	mbr_partition_t ptns[MBR_PART_COUNT];
	mbr_partition_t *dp;
	struct mbr_sector *mbr;
	uint ext_base, this_ext, next_ext;
	int rval;
	int i;
	int j;
#ifdef COMPAT_386BSD_MBRPART
	int dp_386bsd = -1;
	int ap_386bsd = -1;
#endif

	ext_base = 0;
	this_ext = 0;
	for (;;) {
		if (read_sector(a, this_ext, 1)) {
			a->msg = "dos partition I/O error";
			return SCAN_ERROR;
		}

		/* Note: Magic number is little-endian. */
		mbr = (void *)a->bp->b_data;
		if (mbr->mbr_magic != htole16(MBR_MAGIC))
			return SCAN_CONTINUE;

		/* Copy data out of buffer so action can use bp */
		memcpy(ptns, &mbr->mbr_parts, sizeof ptns);

		/* Look for drivers and skip them */
		if (ext_base == 0 && ptns[0].mbrp_type == MBR_PTYPE_DM6_DDO) {
			/* We've found a DM6 DDO partition type (used by
			 * the Ontrack Disk Manager drivers).
			 *
			 * Ensure that there are no other partitions in the
			 * MBR and jump to the real partition table (stored
			 * in the first sector of the second track). */
			bool ok = true;

			for (i = 1; i < MBR_PART_COUNT; i++)
				if (ptns[i].mbrp_type != MBR_PTYPE_UNUSED)
					ok = false;

			if (ok) {
				this_ext = le32toh(a->lp->d_secpercyl /
				    a->lp->d_ntracks);
				continue;
			}
		}

		/* look for NetBSD partition */
		next_ext = 0;
		dp = ptns;
		j = 0;
		for (i = 0; i < MBR_PART_COUNT; i++, dp++) {
			if (dp->mbrp_type == MBR_PTYPE_UNUSED)
				continue;
			/* Check end of partition is inside disk limits */
			if ((uint64_t)ext_base + le32toh(dp->mbrp_start) +
			    le32toh(dp->mbrp_size) > a->lp->d_secperunit) {
				/* This mbr doesn't look good.... */
				a->msg = "mbr partition exceeds disk size";
				/* ...but don't report this as an error (yet) */
				return SCAN_CONTINUE;
			}
			a->found_mbr = 1;
			if (MBR_IS_EXTENDED(dp->mbrp_type)) {
				next_ext = le32toh(dp->mbrp_start);
				continue;
			}
#ifdef COMPAT_386BSD_MBRPART
			if (dp->mbrp_type == MBR_PTYPE_386BSD) {
				/*
				 * If more than one matches, take last,
				 * as NetBSD install tool does.
				 */
				if (this_ext == 0) {
					dp_386bsd = i;
					ap_386bsd = j;
				}
				continue;
			}
#endif
			rval = (*actn)(a, dp, j, this_ext);
			if (rval != SCAN_CONTINUE)
				return rval;
			j++;
		}
		if (next_ext == 0)
			break;
		if (ext_base == 0) {
			ext_base = next_ext;
			next_ext = 0;
		}
		next_ext += ext_base;
		if (next_ext <= this_ext)
			break;
		this_ext = next_ext;
	}
#ifdef COMPAT_386BSD_MBRPART
	if (this_ext == 0 && dp_386bsd != -1)
		return (*actn)(a, &ptns[dp_386bsd], ap_386bsd, 0);
#endif
	return SCAN_CONTINUE;
}
Ejemplo n.º 4
0
static int
scan_mbr(mbr_args_t *a, int (*actn)(mbr_args_t *, struct mbr_partition *,
				    int, u_int))
{
	struct mbr_partition ptns[MBR_PART_COUNT];
	struct mbr_partition *dp;
	struct mbr_sector *mbr;
	u_int ext_base, this_ext, next_ext;
	int i, rval;
#ifdef COMPAT_386BSD_MBRPART
	int dp_386bsd = -1;
#endif

	ext_base = 0;
	this_ext = 0;
	for (;;) {
		a->error = dkwedge_read(a->pdk, a->vp, this_ext, a->buf,
					DEV_BSIZE);
		if (a->error) {
			aprint_error("%s: unable to read MBR @ %u, "
			    "error = %d\n", a->pdk->dk_name, this_ext,
			    a->error);
			return (SCAN_ERROR);
		}

		mbr = a->buf;
		if (mbr->mbr_magic != htole16(MBR_MAGIC))
			return (SCAN_CONTINUE);

		/* Copy data out of buffer so action can use the buffer. */
		memcpy(ptns, &mbr->mbr_parts, sizeof(ptns));

		/* Looks for NetBSD partition. */
		next_ext = 0;
		dp = ptns;
		for (i = 0; i < MBR_PART_COUNT; i++, dp++) {
			if (dp->mbrp_type == 0)
				continue;
			if (MBR_IS_EXTENDED(dp->mbrp_type)) {
				next_ext = le32toh(dp->mbrp_start);
				continue;
			}
#ifdef COMPAT_386BSD_MBRPART
			if (dp->mbrp_type == MBR_PTYPE_386BSD) {
				/*
				 * If more than one matches, take last,
				 * as NetBSD install tool does.
				 */
				if (this_ext == 0)
					dp_386bsd = i;
				continue;
			}
#endif
			rval = (*actn)(a, dp, i, this_ext);
			if (rval != SCAN_CONTINUE)
				return (rval);
		}
		if (next_ext == 0)
			break;
		if (ext_base == 0) {
			ext_base = next_ext;
			next_ext = 0;
		}
		next_ext += ext_base;
		if (next_ext <= this_ext)
			break;
		this_ext = next_ext;
	}
#ifdef COMPAT_386BSD_MBRPART
	if (this_ext == 0 && dp_386bsd != -1)
		return ((*actn)(a, &ptns[dp_386bsd], dp_386bsd, 0));
#endif
	return (SCAN_CONTINUE);
}