Ejemplo n.º 1
0
/* pi_gpt_ctor() - GPT iterator specific initialization */
static int pi_gpt_ctor(struct part_iter *iter,
	const struct disk_info *di, int flags,
	const struct disk_gpt_header *gpth, const struct disk_gpt_part_entry *gptl
)
{
    uint64_t siz;

    if (pi_ctor(iter, di, flags))
	return -1;

    siz = (uint64_t)gpth->part_count * gpth->part_size;

    if (!(iter->data = malloc((size_t)siz))) {
	critm();
	goto bail;
    }

    memcpy(iter->data, gptl, (size_t)siz);

    iter->gpt.pe_count = (int)gpth->part_count;
    iter->gpt.pe_size = (int)gpth->part_size;
    iter->gpt.ufirst = gpth->lba_first_usable;
    iter->gpt.ulast = gpth->lba_last_usable;

    memcpy(&iter->gpt.disk_guid, &gpth->disk_guid, sizeof gpth->disk_guid);
    memcpy(&iter->gpt.part_guid, &gpth->disk_guid, sizeof gpth->disk_guid);

    iter->type = typegpt;
    return 0;
bail:
    pi_dtor_(iter);
    return -1;
}
Ejemplo n.º 2
0
/* pi_dos_ctor() - MBR/EBR iterator specific initialization */
static int pi_dos_ctor(struct part_iter *iter,
	const struct disk_info *di, int flags,
	const struct disk_dos_mbr *mbr
)
{
    if (pi_ctor(iter, di, flags))
	return -1;

    if (!(iter->data = malloc(sizeof *mbr))) {
	critm();
	goto bail;
    }

    memcpy(iter->data, mbr, sizeof *mbr);

    iter->dos.bebr_index0 = -1;
    iter->dos.disk_sig = mbr->disk_sig;

    iter->type = typedos;
    return 0;
bail:
    pi_dtor_(iter);
    return -1;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}