示例#1
0
static int
read_sector(mbr_args_t *a, uint sector, int count)
{
	int error;

	error = disk_read_sectors(a->strat, a->lp, a->bp, sector, count);
	if (error != 0)
		a->error = error;
	return error;
}
示例#2
0
static struct disk_gpt_header *try_gpt_hdr(const struct disk_info *di, int sec)
{
    const char *desc = sec ? "backup" : "primary";
    uint64_t gpt_cur = sec ? di->lbacnt - 1 : 1;
    struct disk_gpt_header *gpth;
    char errbuf[64];

    gpth = disk_read_sectors(di, gpt_cur, 1);
    if (!gpth) {
	sprintf(errbuf, "Unable to read %s GPT header.", desc);
	try_gpt_we(errbuf, sec);
	return NULL;
    }
    if(!valid_crc_hdr(gpth)) {
	sprintf(errbuf, "Invalid checksum of %s GPT header.", desc);
	try_gpt_we(errbuf, sec);
	free(gpth);
	return NULL;
    }
    return gpth;
}
示例#3
0
static struct disk_gpt_part_entry *try_gpt_list(const struct disk_info *di, const struct disk_gpt_header *gpth, int alt)
{
    int pri = gpth->lba_cur < gpth->lba_alt;
    const char *desc = alt ? "alternative" : "main";
    struct disk_gpt_part_entry *gptl;
    char errbuf[64];
    uint64_t gpt_lsiz;	    /* size of GPT partition list in bytes */
    uint64_t gpt_lcnt;	    /* size of GPT partition in sectors */
    uint64_t gpt_loff;	    /* offset to GPT partition list in sectors */

    gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count;
    gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps;
    if (!alt) {
	/* prefer header value for partition table if not asking for alternative */
	gpt_loff = gpth->lba_table;
    } else {
	/* try to read alternative, we have to calculate its position */
	if (!pri)
	    gpt_loff = gpth->lba_alt + 1;
	else
	    gpt_loff = gpth->lba_alt - gpt_lcnt;
    }

    gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt);
    if (!gptl) {
	sprintf(errbuf, "Unable to read %s GPT partition list.", desc);
	try_gpt_we(errbuf, alt);
	return NULL;
    }
    if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) {
	sprintf(errbuf, "Invalid checksum of %s GPT partition list.", desc);
	try_gpt_we(errbuf, alt);
	free(gptl);
	return NULL;
    }
    return gptl;
}
示例#4
0
/**
 * pi_begin() - check disk, validate, and get proper iterator
 * @di:	    diskinfo struct pointer
 *
 * This function checks the disk for GPT or legacy partition table and allocates
 * an appropriate iterator.
 **/
struct part_iter *pi_begin(const struct disk_info *di, int stepall)
{
    int setraw = 0;
    struct part_iter *iter = NULL;
    struct disk_dos_mbr *mbr = NULL;
    struct disk_gpt_header *gpth = NULL;
    struct disk_gpt_part_entry *gptl = NULL;

    /* Read MBR */
    if (!(mbr = disk_read_sectors(di, 0, 1))) {
	error("Couldn't read first disk sector.\n");
	goto bail;
    }

    setraw = -1;

    /* Check for MBR magic*/
    if (mbr->sig != disk_mbr_sig_magic) {
	error("No MBR magic.\n");
	goto bail;
    }

    /* Check for GPT protective MBR */
    if (mbr->table[0].ostype == 0xEE) {
	if (!(gpth = disk_read_sectors(di, 1, 1))) {
	    error("Couldn't read potential GPT header.\n");
	    goto bail;
	}
    }

    if (gpth && gpth->rev.uint32 == 0x00010000 &&
	    !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof(disk_gpt_sig_magic))) {
	/* looks like GPT v1.0 */
	uint64_t gpt_loff;	    /* offset to GPT partition list in sectors */
	uint64_t gpt_lsiz;	    /* size of GPT partition list in bytes */
	uint64_t gpt_lcnt;	    /* size of GPT partition in sectors */
#ifdef DEBUG
	puts("Looks like a GPT v1.0 disk.");
	disk_gpt_header_dump(gpth);
#endif
	/* Verify checksum, fallback to backup, then bail if invalid */
	if (gpt_check_hdr_crc(di, &gpth))
	    goto bail;

	gpt_loff = gpth->lba_table;
	gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count;
	gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps;

	/*
	 * disk_read_sectors allows reading of max 255 sectors, so we use
	 * it as a sanity check base. EFI doesn't specify max (AFAIK).
	 * Apart from that, some extensive sanity checks.
	 */
	if (!gpt_loff || !gpt_lsiz || gpt_lcnt > 255u ||
		gpth->lba_first_usable > gpth->lba_last_usable ||
		!sane(gpt_loff, gpt_lcnt) ||
		gpt_loff + gpt_lcnt > gpth->lba_first_usable ||
		!sane(gpth->lba_last_usable, gpt_lcnt) ||
		gpth->lba_last_usable + gpt_lcnt >= gpth->lba_alt ||
		gpth->lba_alt >= di->lbacnt ||
		gpth->part_size < sizeof(struct disk_gpt_part_entry)) {
	    error("Invalid GPT header's values.\n");
	    goto bail;
	}
	if (!(gptl = disk_read_sectors(di, gpt_loff, (uint8_t)gpt_lcnt))) {
	    error("Couldn't read GPT partition list.\n");
	    goto bail;
	}
	/* Check array checksum(s). */
	if (check_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) {
	    error("WARNING: GPT partition list checksum invalid, trying backup.\n");
	    free(gptl);
	    /* secondary array directly precedes secondary header */
	    if (!(gptl = disk_read_sectors(di, gpth->lba_alt - gpt_lcnt, (uint8_t)gpt_lcnt))) {
		error("Couldn't read backup GPT partition list.\n");
		goto bail;
	    }
	    if (check_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) {
		error("Backup GPT partition list checksum invalid.\n");
		goto bail;
	    }
	}
	/* allocate iterator and exit */
	iter = pi_new(typegpt, di, stepall, gpth, gptl);
    } else {
	/* looks like MBR */
	iter = pi_new(typedos, di, stepall, mbr);
    }

    setraw = 0;
bail:
    if (setraw) {
	error("WARNING: treating disk as raw.\n");
	iter = pi_new(typeraw, di, stepall);
    }
    free(mbr);
    free(gpth);
    free(gptl);

    return iter;
}
示例#5
0
const char *
convertdisklabel(struct disklabel *lp, void (*strat)(struct buf *),
    struct buf *bp, uint32_t secperunit)
{
	struct partition rp, *altp, *p;
	int geom_ok;
	const char *str;

	memset(&rp, 0, sizeof(rp));
	rp.p_size = secperunit;
	rp.p_fstype = FS_UNUSED;

	/* If we can seek to d_secperunit - 1, believe the disk geometry. */
	if (secperunit != 0 &&
	    disk_read_sectors(strat, lp, bp, secperunit - 1, 1) == 0)
		geom_ok = 1;
	else
		geom_ok = 0;

#if 0
	printf("%s: secperunit (%" PRIu32 ") %s\n", __func__,
	    secperunit, geom_ok ? "ok" : "not ok");
#endif

	p = &lp->d_partitions[RAW_PART];
	if (RAW_PART == 'c' - 'a')
		altp = &lp->d_partitions['d' - 'a'];
	else
		altp = &lp->d_partitions['c' - 'a'];

	if (lp->d_npartitions > RAW_PART && p->p_offset == 0 && p->p_size != 0)
		return NULL;	/* already a raw partition */
	else if (lp->d_npartitions > MAX('c', 'd') - 'a' &&
		 altp->p_offset == 0 && altp->p_size != 0) {
		/* alternate partition ('c' or 'd') is suitable for raw slot,
		 * swap with 'd' or 'c'.
		 */
		rp = *p;
		*p = *altp;
		*altp = rp;
		return NULL;
	} else if (lp->d_npartitions <= RAW_PART &&
	           lp->d_npartitions > 'c' - 'a') {
		/* No raw partition is present, but the alternate is present.
		 * Copy alternate to raw partition.
		 */
		lp->d_npartitions = RAW_PART + 1;
		*p = *altp;
		return NULL;
	} else if (!geom_ok)
		str = "no raw partition and disk reports bad geometry";
	else if (lp->d_npartitions <= RAW_PART) {
		memset(&lp->d_partitions[lp->d_npartitions], 0,
		    sizeof(struct partition) * (RAW_PART - lp->d_npartitions));
		*p = rp;
		lp->d_npartitions = RAW_PART + 1;
		return NULL;
	} else if (lp->d_npartitions < MAXPARTITIONS) {
		memmove(p + 1, p,
		    sizeof(struct partition) * (lp->d_npartitions - RAW_PART));
		*p = rp;
		lp->d_npartitions++;
		return NULL;
	} else
		str = "no raw partition and partition table is full";
#ifdef DIAGNOSTIC
	printf("Bad partition: %s\n", str);
	printf("type = %u, subtype = %u, typename = %s\n",
	    lp->d_type, lp->d_subtype, lp->d_typename);
	printf("secsize = %u, nsectors = %u, ntracks = %u\n",
	    lp->d_secsize, lp->d_nsectors, lp->d_ntracks);
	printf("ncylinders = %u, secpercyl = %u, secperunit = %u\n",
	    lp->d_ncylinders, lp->d_secpercyl, lp->d_secperunit);
	printf("npartitions = %u\n", lp->d_npartitions);

	for (size_t i = 0; i < MIN(lp->d_npartitions, MAXPARTITIONS); i++) {
		p = &lp->d_partitions[i];
		printf("\t%c: offset = %u size = %u fstype = %u\n",
		    (char)(i + 'a'), p->p_offset, p->p_size, p->p_fstype);
	}
#endif			
	return str;
}
示例#6
0
文件: chain.c 项目: Celelibi/syslinux
int main(int argc, char *argv[])
{
    struct part_iter *iter = NULL;
    void *sbck = NULL;
    struct data_area fdat, hdat, sdat, data[3];
    int ndata = 0;

    console_ansi_raw();

    memset(&fdat, 0, sizeof fdat);
    memset(&hdat, 0, sizeof hdat);
    memset(&sdat, 0, sizeof sdat);

    opt_set_defs();
    if (opt_parse_args(argc, argv))
	goto bail;

#if 0
    /* Get max fixed disk number */
    fixed_cnt = *(uint8_t *)(0x475);

    /*
     * hmm, looks like we can't do that -
     * some bioses/vms just set it to 1
     * and go on living happily
     * any better options than hardcoded 0x80 - 0xFF ?
     */
#endif

    /* Get disk/part iterator matching user supplied options */
    if (find_dp(&iter))
	goto bail;

    /* Perform initial partition entry mangling */
    if (manglepe_fixchs(iter))
	goto bail;
    if (manglepe_hide(iter))
	goto bail;

    /* Load the boot file */
    if (opt.file) {
	fdat.base = (opt.fseg << 4) + opt.foff;

	if (loadfile(opt.file, &fdat.data, &fdat.size)) {
	    error("Couldn't read the boot file.");
	    goto bail;
	}
	if (fdat.base + fdat.size > dosmax) {
	    error("The boot file is too big to load at this address.");
	    goto bail;
	}
    }

    /* Load the sector */
    if (opt.sect) {
	sdat.base = (opt.sseg << 4) + opt.soff;
	sdat.size = iter->di.bps;

	if (sdat.base + sdat.size > dosmax) {
	    error("The sector cannot be loaded at such high address.");
	    goto bail;
	}
	if (!(sdat.data = disk_read_sectors(&iter->di, iter->abs_lba, 1))) {
	    error("Couldn't read the sector.");
	    goto bail;
	}
	if (opt.save) {
	    if (!(sbck = malloc(sdat.size))) {
		critm();
		goto bail;
	    }
	    memcpy(sbck, sdat.data, sdat.size);
	}
	if (opt.file && opt.maps && overlap(&fdat, &sdat)) {
	    warn("The sector won't be mmapped, as it would conflict with the boot file.");
	    opt.maps = false;
	}
    }

    /* Prep the handover */
    if (opt.hand) {
	if (setup_handover(iter, &hdat))
	    goto bail;
	/* Verify possible conflicts */
	if ( ( opt.file && overlap(&fdat, &hdat)) ||
	     ( opt.maps && overlap(&sdat, &hdat)) ) {
	    warn("Handover area won't be prepared,\n"
		  "as it would conflict with the boot file and/or the sector.");
	    opt.hand = false;
	}
    }

    /* Adjust registers */

    mangler_init(iter);
    mangler_handover(iter, &hdat);
    mangler_grldr(iter);

    /* Patching functions */

    if (manglef_isolinux(&fdat))
	goto bail;

    if (manglef_grub(iter, &fdat))
	goto bail;
#if 0
    if (manglef_drmk(&fdat))
	goto bail;
#endif
    if (manglef_bpb(iter, &fdat))
	goto bail;

    if (mangles_bpb(iter, &sdat))
	goto bail;

    if (mangles_save(iter, &sdat, sbck))
	goto bail;

    if (manglesf_bss(&sdat, &fdat))
	goto bail;

    /* This *must* be after BPB saving or copying */
    if (mangles_cmldr(&sdat))
	goto bail;

    /*
     * Prepare boot-time mmap data. We should to it here, as manglers could
     * potentially alter some of the data.
     */

    if (opt.file)
	memcpy(data + ndata++, &fdat, sizeof fdat);
    if (opt.maps)
	memcpy(data + ndata++, &sdat, sizeof sdat);
    if (opt.hand)
	memcpy(data + ndata++, &hdat, sizeof hdat);

#ifdef DEBUG
    dprintf("iter->di dsk, bps: %X, %u\niter->di lbacnt, C*H*S: %"PRIu64", %u\n"
	   "iter->di C, H, S: %u, %u, %u\n",
	iter->di.disk, iter->di.bps,
	iter->di.lbacnt, iter->di.cyl * iter->di.head * iter->di.spt,
	iter->di.cyl, iter->di.head, iter->di.spt);
    dprintf("iter idx: %d\n", iter->index);
    dprintf("iter lba: %"PRIu64"\n", iter->abs_lba);
    if (opt.hand)
	dprintf("hand lba: %u\n",
		((struct disk_dos_part_entry *)hdat.data)->start_lba);
#endif

    if (opt.warn) {
	puts("Press any key to continue booting...");
	wait_key();
    }

    if (ndata && !opt.brkchain) /* boot only if we actually chainload */
	do_boot(data, ndata);
    else
	puts("Service-only run completed, exiting.");
bail:
    pi_del(&iter);
    /* Free allocated areas */
    free(fdat.data);
    free(sdat.data);
    free(hdat.data);
    free(sbck);
    return 255;
}
示例#7
0
/* pi_begin() - validate and and get proper iterator for a disk described by di */
struct part_iter *pi_begin(const struct disk_info *di, int flags)
{
    int gptprot, ret = -1;
    struct part_iter *iter;
    struct disk_dos_mbr *mbr = NULL;
    struct disk_gpt_header *gpth = NULL;
    struct disk_gpt_part_entry *gptl = NULL;

    /* Preallocate iterator */
    if (!(iter = pi_alloc()))
	goto bail;

    /* Read MBR */
    if (!(mbr = disk_read_sectors(di, 0, 1))) {
	error("Couldn't read the first disk sector.");
	goto bail;
    }

    /* Check for MBR magic */
    if (mbr->sig != disk_mbr_sig_magic) {
	warn("No MBR magic, treating disk as raw.");
	/* looks like RAW */
	ret = pi_ctor(iter, di, flags);
	goto bail;
    }

    /* Check for GPT protective MBR */
    gptprot = 0;
    for (size_t i = 0; i < 4; i++)
	gptprot |= (mbr->table[i].ostype == 0xEE);
    if (gptprot && !(flags & PIF_PREFMBR)) {
	if (!(gpth = disk_read_sectors(di, 1, 1))) {
	    error("Couldn't read potential GPT header.");
	    goto bail;
	}
    }

    if (gpth && gpth->rev.uint32 == 0x00010000 &&
	    !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) {
	/* looks like GPT v1.0 */
	uint64_t gpt_loff;	    /* offset to GPT partition list in sectors */
	uint64_t gpt_lsiz;	    /* size of GPT partition list in bytes */
	uint64_t gpt_lcnt;	    /* size of GPT partition in sectors */
#ifdef DEBUG
	dprintf("Looks like a GPT v1.0 disk.\n");
	disk_gpt_header_dump(gpth);
#endif
	/* Verify checksum, fallback to backup, then bail if invalid */
	if (gpt_check_hdr_crc(di, &gpth))
	    goto bail;

	gpt_loff = gpth->lba_table;
	gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count;
	gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps;

	/*
	 * disk_read_sectors allows reading of max 255 sectors, so we use
	 * it as a sanity check base. EFI doesn't specify max (AFAIK).
	 * Apart from that, some extensive sanity checks.
	 */
	if (!(flags & PIF_RELAX) && (
		!gpt_loff || !gpt_lsiz || gpt_lcnt > 255u ||
		gpth->lba_first_usable > gpth->lba_last_usable ||
		!sane(gpt_loff, gpt_lcnt) ||
		gpt_loff + gpt_lcnt > gpth->lba_first_usable ||
		!sane(gpth->lba_last_usable, gpt_lcnt) ||
		gpth->lba_last_usable + gpt_lcnt >= gpth->lba_alt ||
		gpth->lba_alt >= di->lbacnt ||
		gpth->part_size < sizeof *gptl)) {
	    error("Invalid GPT header's values.");
	    goto bail;
	}
	if (!(gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt))) {
	    error("Couldn't read GPT partition list.");
	    goto bail;
	}
	/* Check array checksum(s). */
	if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) {
	    warn("Checksum of the main GPT partition list is invalid, trying backup.");
	    free(gptl);
	    /* secondary array directly precedes secondary header */
	    if (!(gptl = disk_read_sectors(di, gpth->lba_alt - gpt_lcnt, gpt_lcnt))) {
		error("Couldn't read backup GPT partition list.");
		goto bail;
	    }
	    if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) {
		error("Checksum of the backup GPT partition list is invalid, giving up.");
		goto bail;
	    }
	}
	/* looks like GPT */
	ret = pi_gpt_ctor(iter, di, flags, gpth, gptl);
    } else {
	/* looks like MBR */
	ret = pi_dos_ctor(iter, di, flags, mbr);
    }
bail:
    if (ret < 0)
	free(iter);
    free(mbr);
    free(gpth);
    free(gptl);

    return iter;
}
示例#8
0
/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl and anything required in the strategy routine
 * (e.g., sector size) must be filled in before calling us.
 * Returns null on success and an error string on failure.
 */
const char *
readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
    struct cpu_disklabel *clp)
{
	struct buf *bp;
	struct disklabel *dlp;
	struct dkbad *bdp;
	const char *msg = NULL;
	uint32_t secperunit;
	int i;

	/* minimal requirements for archtypal disk label */
	if (lp->d_secsize == 0)
		lp->d_secsize = DEV_BSIZE;
	if (lp->d_secperunit == 0)
		lp->d_secperunit = 0x1fffffff;
	lp->d_npartitions = RAW_PART + 1;
	if (lp->d_partitions[RAW_PART].p_size == 0)
		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
	lp->d_partitions[RAW_PART].p_offset = 0;

	secperunit = lp->d_secperunit;

	/* obtain buffer to probe drive with */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	/* Next, dig out disk label.  If successful, locate disk
	 * label within block and validate.
	 */
	if (disk_read_sectors(strat, lp, bp, LABELSECTOR, 1) != 0) {
		msg = "disk label read error";
		goto done;
	}

	for (dlp = (struct disklabel *)bp->b_data;
	    dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize -
	     sizeof(*dlp));
	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
			if (msg == NULL)
				msg = "no disk label";
		} else if (dlp->d_npartitions > MAXPARTITIONS ||
			   dkcksum(dlp) != 0)
			msg = "disk label corrupted";
		else {
			*lp = *dlp;
			msg = NULL;
			break;
		}
	}

	if (msg)
		goto done;

	if ((msg = convertdisklabel(lp, strat, bp, secperunit)) != NULL)
		goto done;

	/* obtain bad sector table if requested and present */
	if (clp && (bdp = &clp->bad) != NULL && (lp->d_flags & D_BADSECT)) {
		struct dkbad *db;

		i = 0;
		do {
			/* read a bad sector table */
			bp->b_oflags &= ~(BO_DONE);
			bp->b_flags |= B_READ;
			bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
			if (lp->d_secsize > DEV_BSIZE)
				bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
			else
				bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
			bp->b_bcount = lp->d_secsize;
			bp->b_cylinder = lp->d_ncylinders - 1;
			(*strat)(bp);

			/* if successful, validate, otherwise try another */
			if (biowait(bp)) {
				msg = "bad sector table I/O error";
			} else {
				db = (struct dkbad *)(bp->b_data);
#define DKBAD_MAGIC 0x4321
				if (db->bt_mbz == 0
					&& db->bt_flag == DKBAD_MAGIC) {
					msg = NULL;
					*bdp = *db;
					break;
				} else
					msg = "bad sector table corrupted";
			}
		} while (bp->b_error != 0 && (i += 2) < 10 &&
			i < lp->d_nsectors);
	}

done:
	brelse(bp, 0);
	return (msg);
}
示例#9
0
/* pi_begin() - validate and and get proper iterator for a disk described by di */
struct part_iter *pi_begin(const struct disk_info *di, int flags)
{
    int isgpt = 0, ret = -1;
    struct part_iter *iter;
    struct disk_dos_mbr *mbr = NULL;
    struct disk_gpt_header *gpth = NULL;
    struct disk_gpt_part_entry *gptl = NULL;

    /* Preallocate iterator */
    if (!(iter = pi_alloc()))
	goto out;

    /* Read MBR */
    if (!(mbr = disk_read_sectors(di, 0, 1))) {
	error("Unable to read the first disk sector.");
	goto out;
    }

    /* Check for MBR magic */
    if (mbr->sig != disk_mbr_sig_magic) {
	warn("No MBR magic, treating disk as raw.");
	/* looks like RAW */
	ret = pi_ctor(iter, di, flags);
	goto out;
    }

    /* Check for GPT protective MBR */
    for (size_t i = 0; i < 4; i++)
	isgpt |= (mbr->table[i].ostype == 0xEE);
    isgpt = isgpt && !(flags & PIF_PREFMBR);

    /* Try to read GPT header */
    if (isgpt) {
	gpth = try_gpt_hdr(di, 0);
	if (!gpth)
	    /*
	     * this read might fail if bios reports different disk size (different vm/pc)
	     * not much we can do here to avoid it
	     */
	    gpth = try_gpt_hdr(di, 1);
	if (!gpth)
	    goto out;
    }

    if (gpth && gpth->rev.uint32 == 0x00010000 &&
	    !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) {
	/* looks like GPT v1.0 */
#ifdef DEBUG
	dprintf("Looks like a GPT v1.0 disk.\n");
	disk_gpt_header_dump(gpth);
#endif
	if (notsane_gpt_hdr(di, gpth, flags)) {
	    error("GPT header values are corrupted.");
	    goto out;
	}

	gptl = try_gpt_list(di, gpth, 0);
	if (!gptl)
	    gptl = try_gpt_list(di, gpth, 1);
	if (!gptl)
	    goto out;

	/* looks like GPT */
	ret = pi_gpt_ctor(iter, di, flags, gpth, gptl);
    } else {
	/* looks like MBR */
	ret = pi_dos_ctor(iter, di, flags, mbr);
    }
out:
    if (ret < 0) {
	free(iter);
	iter = NULL;
    }
    free(mbr);
    free(gpth);
    free(gptl);

    return iter;
}
示例#10
0
const char *
convertdisklabel(struct disklabel *lp, void (*strat)(struct buf *),
    struct buf *bp, uint32_t secperunit)
{
	struct partition rp, *altp, *p;
	int geom_ok;

	memset(&rp, 0, sizeof(rp));
	rp.p_size = secperunit;
	rp.p_fstype = FS_UNUSED;

	/* If we can seek to d_secperunit - 1, believe the disk geometry. */
	if (secperunit != 0 &&
	    disk_read_sectors(strat, lp, bp, secperunit - 1, 1) == 0)
		geom_ok = 1;
	else
		geom_ok = 0;

#if 0
	printf("%s: secperunit (%" PRIu32 ") %s\n", __func__,
	    secperunit, geom_ok ? "ok" : "not ok");
#endif

	p = &lp->d_partitions[RAW_PART];
	if (RAW_PART == 'c' - 'a')
		altp = &lp->d_partitions['d' - 'a'];
	else
		altp = &lp->d_partitions['c' - 'a'];

	if (lp->d_npartitions > RAW_PART && p->p_offset == 0 && p->p_size != 0)
		;	/* already a raw partition */
	else if (lp->d_npartitions > MAX('c', 'd') - 'a' &&
		 altp->p_offset == 0 && altp->p_size != 0) {
		/* alternate partition ('c' or 'd') is suitable for raw slot,
		 * swap with 'd' or 'c'.
		 */
		rp = *p;
		*p = *altp;
		*altp = rp;
	} else if (lp->d_npartitions <= RAW_PART &&
	           lp->d_npartitions > 'c' - 'a') {
		/* No raw partition is present, but the alternate is present.
		 * Copy alternate to raw partition.
		 */
		lp->d_npartitions = RAW_PART + 1;
		*p = *altp;
	} else if (!geom_ok)
		return "no raw partition and disk reports bad geometry";
	else if (lp->d_npartitions <= RAW_PART) {
		memset(&lp->d_partitions[lp->d_npartitions], 0,
		    sizeof(struct partition) * (RAW_PART - lp->d_npartitions));
		*p = rp;
		lp->d_npartitions = RAW_PART + 1;
	} else if (lp->d_npartitions < MAXPARTITIONS) {
		memmove(p + 1, p,
		    sizeof(struct partition) * (lp->d_npartitions - RAW_PART));
		*p = rp;
		lp->d_npartitions++;
	} else
		return "no raw partition and partition table is full";
	return NULL;
}
示例#11
0
ssize_t hd_read(minor_t minor, lbaint_t lba_start, lbaint_t count, void* buffer)
{
    ssize_t read = 0;
    CHS_t chs_addr_start;

    chs_disk_geometry_t* dev_info = (chs_disk_geometry_t*) hd_getinfo(minor);
    assert(dev_info != NULL);
    // check that the number of sectors per track is not greated than what I can write in a real mode segment
    assert(dev_info->NS <= (SEGMENT_SIZE_16bit_MODE / SECTOR_SIZE));
    // check parameters
    assert(lba_start < dev_info->Nlba);
    assert(lba_start + count <= dev_info->Nlba);

    uint16_t buf_rm_segment;
    uint16_t buf_rm_offset;
#ifdef BOOTLOADER_PROTECTED_MODE_ENABLED
    buf_rm_segment = SEGMENT_EXTRA_DATA_RM;
    buf_rm_offset = 0x0000;
#else
    reg_get_data_segment(&buf_rm_segment);
    buf_rm_offset = (uint16_t)(uint32_t)buffer;
#endif

    uint8_t nb_sectors_to_read = count;
    while (count > 0) {
        // convert LBA address to CHS address
        lbatochs(dev_info, lba_start, &chs_addr_start);
#ifdef DEBUG_HD_DRIVER 
        debug_printf("hd(%u,%u): req READ (lba_start = %u <=> CHS=(%u,%u,%u), count = %u)\r\n",
                HARD_DISK_DRIVER, minor, lba_start,
                chs_addr_start.C, chs_addr_start.H, chs_addr_start.S, count);
#endif


        // check track bounds
        if (count > dev_info->NS) {
            nb_sectors_to_read = dev_info->NS - chs_addr_start.S + 1;
#ifdef DEBUG_HD_DRIVER 
            debug_printf("hd(%u,%u): resize req to (lba_start = %u, count = %u)\r\n",
                    HARD_DISK_DRIVER, minor, lba_start, nb_sectors_to_read);
#endif
        }

#ifdef DEBUG_HD_DRIVER 
        debug_printf("hd(%u,%u): [bios] disk %#02x, attempt to read %u sectors",
                HARD_DISK_DRIVER, minor, BIOS_HD_DRIVE_BASE_NB + minor, nb_sectors_to_read);
#endif
        uint8_t nb_read_sectors = 0;
        for (uint8_t i=0; i<5 && (nb_read_sectors != nb_sectors_to_read); i++) {
            nb_read_sectors = disk_read_sectors(BIOS_HD_DRIVE_BASE_NB + minor, buf_rm_segment, buf_rm_offset, &chs_addr_start, nb_sectors_to_read);
        }

#ifdef DEBUG_HD_DRIVER 
        if (nb_read_sectors != nb_sectors_to_read) {
            debug_printf(", read %u sectors [NOK]\r\n", nb_read_sectors);
        } else {
            debug_printf(" [OK]\r\n");
        }
#endif

        size_t nb_read_bytes = nb_read_sectors * SECTOR_SIZE;

#ifdef BOOTLOADER_PROTECTED_MODE_ENABLED
        // copy data to buffer
        memcpy(buffer, (void*)(buf_rm_segment << 4 | buf_rm_offset), nb_read_bytes);
        buf_rm_offset = 0x0000;
#else
        buf_rm_offset += nb_read_bytes;
#endif

        read += nb_read_bytes;
        count -= nb_read_sectors;
        lba_start += nb_read_sectors;
    }

    return read;
}