static int read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl, int this_ext, daddr_t sector) { struct mbr_partition mbr[MBR_PART_COUNT]; int i; int typ; struct partition *p; if (readsects(&d->ll, sector, 1, d->buf, 0)) { #ifdef DISK_DEBUG printf("Error reading MFS sector %"PRId64"\n", sector); #endif return EIO; } if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) { return -1; } memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr)); for (i = 0; i < MBR_PART_COUNT; i++) { typ = mbr[i].mbrp_type; if (typ == 0) continue; sector = this_ext + mbr[i].mbrp_start; if (dflt_lbl->d_npartitions >= MAXPARTITIONS) continue; p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++]; p->p_offset = sector; p->p_size = mbr[i].mbrp_size; p->p_fstype = xlat_mbr_fstype(typ); } return 0; }
static int look_netbsd_part(mbr_args_t *a, mbr_partition_t *dp, int slot, uint ext_base) { struct partition *pp; int ptn_base = ext_base + le32toh(dp->mbrp_start); int rval; if ( #ifdef COMPAT_386BSD_MBRPART dp->mbrp_type == MBR_PTYPE_386BSD || #endif dp->mbrp_type == MBR_PTYPE_NETBSD) { rval = validate_label(a, ptn_base); #if RAW_PART == 3 /* Put actual location where we found the label into ptn 2 */ if (rval == SCAN_FOUND || a->lp->d_partitions[2].p_size == 0) { a->lp->d_partitions[2].p_size = le32toh(dp->mbrp_size); a->lp->d_partitions[2].p_offset = ptn_base; } #endif /* If we got a netbsd label look no further */ if (rval == SCAN_FOUND) return rval; } /* Install main partitions into e..h and extended into i+ */ if (ext_base == 0) slot += 4; else { slot = 4 + MBR_PART_COUNT; pp = &a->lp->d_partitions[slot]; for (; slot < MAXPARTITIONS; pp++, slot++) { /* This gets called twice - avoid duplicates */ if (pp->p_offset == ptn_base && pp->p_size == le32toh(dp->mbrp_size)) break; if (pp->p_size == 0) break; } } if (slot < MAXPARTITIONS) { /* Stop 'a' being the entire disk */ a->lp->d_partitions[0].p_size = 0; a->lp->d_partitions[0].p_fstype = 0; /* save partition info */ pp = &a->lp->d_partitions[slot]; pp->p_offset = ptn_base; pp->p_size = le32toh(dp->mbrp_size); pp->p_fstype = xlat_mbr_fstype(dp->mbrp_type); if (slot >= a->lp->d_npartitions) a->lp->d_npartitions = slot + 1; } return SCAN_CONTINUE; }
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; }