Ejemplo n.º 1
0
int msdos_partition(struct parsed_partitions *state)
{
	sector_t sector_size = bdev_logical_block_size(state->bdev) / 512;
	Sector sect;
	unsigned char *data;
	struct partition *p;
	struct fat_boot_sector *fb;
	int slot;

	data = read_part_sector(state, 0, &sect);
	if (!data)
		return -1;
	if (!msdos_magic_present(data + 510)) {
		put_dev_sector(sect);
		return 0;
	}

	if (aix_magic_present(state, data)) {
		put_dev_sector(sect);
		printk( " [AIX]");
		return 0;
	}

	/*
	 * Now that the 55aa signature is present, this is probably
	 * either the boot sector of a FAT filesystem or a DOS-type
	 * partition table. Reject this in case the boot indicator
	 * is not 0 or 0x80.
	 */
	p = (struct partition *) (data + 0x1be);
	for (slot = 1; slot <= 4; slot++, p++) {
		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
			/*
			 * Even without a valid boot inidicator value
			 * its still possible this is valid FAT filesystem
			 * without a partition table.
			 */
			fb = (struct fat_boot_sector *) data;
			if (slot == 1 && fb->reserved && fb->fats
				&& fat_valid_media(fb->media)) {
				printk("\n");
				put_dev_sector(sect);
				return 1;
			} else {
				put_dev_sector(sect);
				return 0;
			}
		}
	}

#ifdef CONFIG_EFI_PARTITION
	p = (struct partition *) (data + 0x1be);
	for (slot = 1 ; slot <= 4 ; slot++, p++) {
		/* If this is an EFI GPT disk, msdos should ignore it. */
		if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
			put_dev_sector(sect);
			return 0;
		}
	}
#endif
	p = (struct partition *) (data + 0x1be);

	/*
	 * Look for partitions in two passes:
	 * First find the primary and DOS-type extended partitions.
	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
	 */

	state->next = 5;
	for (slot = 1 ; slot <= 4 ; slot++, p++) {
		sector_t start = start_sect(p)*sector_size;
		sector_t size = nr_sects(p)*sector_size;
		if (!size)
			continue;
		if (is_extended_partition(p)) {
			/*
			 * prevent someone doing mkfs or mkswap on an
			 * extended partition, but leave room for LILO
			 * FIXME: this uses one logical sector for > 512b
			 * sector, although it may not be enough/proper.
			 */
			sector_t n = 2;
			n = min(size, max(sector_size, n));
			put_partition(state, slot, start, n);

			printk(" <");
			parse_extended(state, start, size);
			printk(" >");
			continue;
		}
		put_partition(state, slot, start, size);
		if (SYS_IND(p) == LINUX_RAID_PARTITION)
			state->parts[slot].flags = ADDPART_FLAG_RAID;
		if (SYS_IND(p) == DM6_PARTITION)
			printk("[DM]");
		if (SYS_IND(p) == EZD_PARTITION)
			printk("[EZD]");
	}

	printk("\n");

	/* second pass - output for each on a separate line */
	p = (struct partition *) (0x1be + data);
	for (slot = 1 ; slot <= 4 ; slot++, p++) {
		unsigned char id = SYS_IND(p);
		int n;

		if (!nr_sects(p))
			continue;

		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
			;

		if (!subtypes[n].parse)
			continue;
		subtypes[n].parse(state, start_sect(p) * sector_size,
				  nr_sects(p) * sector_size, slot);
	}
	put_dev_sector(sect);
	return 1;
}
int blkdev_refresh(blkdev_t *blk)
{
    int fd = 0;
    char *devpath = NULL;
    unsigned char *block = NULL;
    int i, rc;

    if (!(block = malloc(512)))
        goto out;

    /*
     * Get the device size
     */
    devpath = blkdev_get_devpath(blk);

    if ((fd = open(devpath, O_RDONLY)) < 0) {
        LOGE("Unable to open device '%s' (%s)", devpath, strerror(errno));
        return -errno;
    }

    if (ioctl(fd, BLKGETSIZE, &blk->nr_sec)) {
        LOGE("Unable to get device size (%m)");
        return -errno;
    }
    close(fd);
    free(devpath);

    /*
     * Open the disk partition table
     */
    devpath = blkdev_get_devpath(blk->disk);
    if ((fd = open(devpath, O_RDONLY)) < 0) {
        LOGE("Unable to open device '%s' (%s)", devpath,
             strerror(errno));
        free(devpath);
        return -errno;
    }

    free(devpath);

    if ((rc = read(fd, block, 512)) != 512) {
        LOGE("Unable to read device partition table (%d, %s)",
             rc, strerror(errno));
        goto out;
    }

    /*
     * If we're a disk, then process the partition table. Otherwise we're
     * a partition so get the partition type
     */

    if (blk->type == blkdev_disk) {
        blk->nr_parts = 0;

        if ((block[0x1fe] != 0x55) || (block[0x1ff] != 0xAA)) {
            LOGI("Disk %d:%d does not contain a partition table",
                 blk->major, blk->minor);
            goto out;
        }

        for (i = 0; i < 4; i++) {
            struct dos_partition part;

            dos_partition_dec(block + DOSPARTOFF + i * sizeof(struct dos_partition), &part);
            if (part.dp_flag != 0 && part.dp_flag != 0x80) {
                struct fat_boot_sector *fb = (struct fat_boot_sector *) &block[0];
             
                if (!i && fb->reserved && fb->fats && fat_valid_media(fb->media)) {
                    LOGI("Detected FAT filesystem in partition table");
                    break;
                } else {
                    LOGI("Partition table looks corrupt");
                    break;
                }
            }
            if (part.dp_size != 0 && part.dp_typ != 0)
                blk->nr_parts++;
        }
    } else if (blk->type == blkdev_partition) {
        struct dos_partition part;
        int part_no = blk->minor -1;

        if (part_no < 4) {
            dos_partition_dec(block + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part);
            blk->part_type = part.dp_typ;
        } else {
            LOGW("Skipping partition %d", part_no);
        }
    }

 out:

    if (block)
        free(block);

    char tmp[255];
    char tmp2[32];
    sprintf(tmp, "%s (blkdev %d:%d), %u secs (%u MB)",
                 (blk->type == blkdev_disk ? "Disk" : "Partition"),
                 blk->major, blk->minor,
                 blk->nr_sec,
                 (uint32_t) (((uint64_t) blk->nr_sec * 512) / 1024) / 1024);

    if (blk->type == blkdev_disk) 
        sprintf(tmp2, " %d partitions", blk->nr_parts);
    else
        sprintf(tmp2, " type 0x%x", blk->part_type);

    strcat(tmp, tmp2);
    LOGI(tmp);

    close(fd);

    return 0;
}