Ejemplo n.º 1
0
/* Scans The partitions */
int scan_partitions(struct disk_info *dsk)
{
    static unsigned char sector[SECTOR_SIZE];
    struct MBRpartition *part;
    struct partition_info *current = NULL;
    int sector_size;
    int ret, i;

    ret = read_disk(dsk->fd, sector, 0, 1, dsk->sector_size);
    if(ret < 0)
        return ret;

    if(ret < sector_size)
    {
        LOG_INFO("Error Reading the MBR on %s \n", path);
        return -1;
    }

    if(!valid_part_table_flag(sector))
    {
        LOG_INFO("Partition Table Error on %s\n", dsk->device_file);
        LOG_INFO("Invalid End of sector marker");
        return -INVALID_TABLE;
    }

    /* First Scan primary Partitions */
    for(i = 0; i < 4; i++)
    {
        part = pt_offset(sector, i);
        if((part->sys_ind != 0x00) || (get_nr_sects(part) != 0x00))
        {
            LOG_INFO("index %d ID %X size %Ld \n", i, part->sys_ind, get_nr_sects(part));

            if(!dsk->partition) {
                current = malloc(sizeof(struct partition_info));
                memset(current, 0, sizeof(struct partition_info));
                dsk->partition = current;
            } else {
                current->next = malloc(sizeof(struct partition_info));
                memset(current->next, 0, sizeof(struct partition_info));
                current = current->next;
            }
            current->fstype = part->sys_ind;
            current->base = get_start_sect(part);
            current->size = get_nr_sects(part) * dsk->sector_size;
            if(is_extended(part->sys_ind)) {
                current->flag = PARTITION_TYPE_EXTENDED;
                scan_ebr(dsk, current);
            } else {
                current->flag = PARTITION_TYPE_PRIMARY;
            }
        }
    }

    return 0;
}
Ejemplo n.º 2
0
static void print_one_part(dos_partition_t *p, int ext_part_sector,
			   int part_num, unsigned int disksig)
{
	int lba_start = ext_part_sector + le32_to_int (p->start4);
	int lba_size  = le32_to_int (p->size4);

	printf("%3d\t%-10d\t%-10d\t%08x-%02x\t%02x%s%s\n",
		part_num, lba_start, lba_size, disksig, part_num, p->sys_ind,
		(is_extended(p->sys_ind) ? " Extd" : ""),
		(is_bootable(p) ? " Boot" : ""));
}
Ejemplo n.º 3
0
/* Reads The Extended Partitions */
int scan_ebr(struct disk_info *dsk, struct partition_info *ext)
{
    static unsigned char sector[SECTOR_SIZE];
    struct MBRpartition *part, *part1;
    struct partition_info *current = NULL, *pt;
    int logical = 4, ret;
    lloff_t  ebrBase, nextPart, ebr2=0;

    ebrBase = ext->base;
    nextPart = ext->base;
    while (1) {
        ret = read_disk(dsk->fd, sector, nextPart, 1, dsk->sector_size);
        if (ret < 0)
            return ret;

        if (ret < dsk->sector_size) {
            LOG_INFO("Error Reading the EBR \n");
            return -1;
        }
        part = pt_offset(sector, 0);
        LOG_INFO("index %d ID %X size %Ld \n", logical, part->sys_ind, get_nr_sects(part));

        if (is_extended(part->sys_ind)) {
            // special case. ebr has extended partition with offset to another ebr.
            ebr2 += get_start_sect(part);
            nextPart = (ebr2 + ebrBase);
            continue;
        }
        part1 = pt_offset(sector, 1);
        ebr2 = get_start_sect(part1);
        nextPart = (ebr2 + ebrBase);

        pt = malloc(sizeof(struct partition_info));
        if (!pt) {
            LOG_INFO("Allocation Error\n");
        }
        memset(pt, 0, sizeof(struct partition_info));
        if (!current) {
            current = pt;
            ext->ext = pt;
        } else {
            current->next = pt;
            current = current->next;
        }
        pt->fstype = part->sys_ind;
        pt->base = get_start_sect(part);
        pt->size = get_nr_sects(part) * dsk->sector_size;
        logical++;
        if (part1->sys_ind == 0)
            break;
    }
    return logical;
}
Ejemplo n.º 4
0
static int
read_extended_partition(int fd, struct partition *ep, int en,
			struct slice *sp, int ns)
{
	struct partition p;
	unsigned long start, here, next;
	unsigned char *bp;
	int loopct = 0;
	int moretodo = 1;
	int i, n=0;

	int sector_size_mul = get_sector_size(fd)/512;

	next = start = sector_size_mul * le32_to_cpu(ep->start_sect);

	while (moretodo) {
		here = next;
		moretodo = 0;
		if (++loopct > 100)
			return n;

		bp = (unsigned char *)getblock(fd, here);
		if (bp == NULL)
			return n;

		if (bp[510] != 0x55 || bp[511] != 0xaa)
			return n;

		for (i=0; i<2; i++) {
			memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p));
			if (is_extended(p.sys_type)) {
				if (p.start_sect && p.nr_sects && !moretodo) {
					next = start + sector_size_mul * le32_to_cpu(p.start_sect);
					moretodo = 1;
				}
				continue;
			}
			if (n < ns) {
				sp[n].start = here + sector_size_mul * le32_to_cpu(p.start_sect);
				sp[n].size = sector_size_mul * le32_to_cpu(p.nr_sects);
				sp[n].container = en + 1;
				n++;
			} else {
				fprintf(stderr,
				    "dos_extd_partition: too many slices\n");
				return n;
			}
			loopct = 0;
		}
	}
	return n;
}
Ejemplo n.º 5
0
/******************************************************************************
Examine the disk partition table and return a list of chunks
A chunk is a block of sectors that is either
(1) a partition
(2) a partition boot track
(3) the block of sectors between two partitions or
(4) the block of sectors after the last partition upto the end of the disk
******************************************************************************/
int layout_disk (pte_ptr pt, /* the partition table */
		layout_ptr lp, /* the disk layout to return */
		disk_control_ptr d)/* the disk containing the partition table */
{
	int		n = 0;
	int		more = 1;
	pte_ptr		min_entry;
	off_t		min = 0,
			alloc = 0,
			at;

	do {
		min_entry = find_min (pt, min, &at);
		if (min_entry) {
			if (alloc < at) {
				lp[n].pt = NULL;
				lp[n].lba_start = alloc;
				lp[n].n_sectors = at /*min_entry -> lba_start*/ - alloc;
				if (n) lp[n].chunk_class = CHUNK_UNALLOCATED;
				else lp[n].chunk_class = CHUNK_BOOT;
				n++;
				if(n >= MAX_PARTITIONS) {
					printf("Error: maximum number of partitions (%d) exceeded.\n", MAX_PARTITIONS);
					exit(1);
				}
			}
			lp[n].pt = min_entry;
			lp[n].lba_start = at; /*min_entry -> lba_start*/
			if (is_extended(min_entry->type)) {
				lp[n].n_sectors = DISK_MAX_SECTORS;
				lp[n].chunk_class = CHUNK_BOOT_EXT;
			} else {
				lp[n].chunk_class = CHUNK_PARTITION;
				lp[n].n_sectors = min_entry -> lba_length;
			}
			min = lp[n].lba_start + lp[n].n_sectors;
			alloc = min;
			n++;
		} else more = 0;
	} while (more);
	if (alloc < n_sectors(d)) {
		lp[n].pt = NULL;
		lp[n].chunk_class = CHUNK_UNALLOCATED;
		lp[n].lba_start = alloc;
		lp[n].n_sectors = n_sectors(d) - alloc;
		n++;
	}
	return n;
}
Ejemplo n.º 6
0
/*
 * data_to_part_desc --
 *      parses raw partition table sector data
 *      to partition description structure
 *
 * PARAMETERS:
 *      data          - raw partition table sector data
 *      new_part_desc - pointer to returned partition description structure
 *
 * RETURNS:
 *      RTEMS_SUCCESSFUL, if success;
 *      RTEMS_NO_MEMOTY, if cannot allocate memory for part_desc_t strucure;
 *      RTEMS_INTERNAL_ERROR, if other error occurs.
 */
static rtems_status_code
data_to_part_desc(uint8_t *data, rtems_part_desc_t **new_part_desc)
{
    rtems_part_desc_t *part_desc;
    uint32_t           temp;

    if (new_part_desc == NULL)
    {
        return RTEMS_INTERNAL_ERROR;
    }

    *new_part_desc = NULL;

    if ((part_desc = calloc(1, sizeof(rtems_part_desc_t))) == NULL)
    {
        return RTEMS_NO_MEMORY;
    }

    part_desc->bootable = *(data + RTEMS_IDE_PARTITION_BOOTABLE_OFFSET);
    part_desc->sys_type = *(data + RTEMS_IDE_PARTITION_SYS_TYPE_OFFSET);

    /* read the offset start position and partition size in sectors */

    /* due to incorrect data alignment one have to align data first */
    memcpy(&temp, data + RTEMS_IDE_PARTITION_START_OFFSET, sizeof(uint32_t));
    part_desc->start = LE_TO_CPU_U32(temp);

    memcpy(&temp, data + RTEMS_IDE_PARTITION_SIZE_OFFSET, sizeof(uint32_t));
    part_desc->size = LE_TO_CPU_U32(temp);

    /*
     * use partitions that are
     * - extended
     * or
     * - FAT type and non-zero
     */
    if (is_extended(part_desc->sys_type) ||
       ((is_fat_partition(part_desc->sys_type)) && (part_desc->size != 0))) {
      *new_part_desc = part_desc;
    }
    else {
      /* empty partition */
      free(part_desc);
    }
    return RTEMS_SUCCESSFUL;
}
Ejemplo n.º 7
0
/*
 * partition free --
 *      frees partition description structure
 *
 * PARAMETERS:
 *      part_desc - returned disc description structure
 *
 * RETURNS:
 *      N/A
 */
static void
partition_free(rtems_part_desc_t *part_desc)
{
    int part_num;

    if (part_desc == NULL)
        return;

    if (is_extended(part_desc->sys_type))
    {
        for (part_num = 0;
             part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
             part_num++)
        {
            partition_free(part_desc->sub_part[part_num]);
        }
    }

    free(part_desc);
}
Ejemplo n.º 8
0
int
read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
	struct partition p;
	unsigned long offset = all.start;
	int i, n=4;
	unsigned char *bp;
	uint64_t  sector_size_mul = get_sector_size(fd)/512;

	bp = (unsigned char *)getblock(fd, offset);
	if (bp == NULL)
		return -1;

	if (bp[510] != 0x55 || bp[511] != 0xaa)
		return -1;

	for (i=0; i<4; i++) {
		memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p));
		if (is_gpt(p.sys_type))
			return 0;
		if (i < ns) {
			sp[i].start =  sector_size_mul * le32_to_cpu(p.start_sect);
			sp[i].size = sector_size_mul * le32_to_cpu(p.nr_sects);
		} else {
			fprintf(stderr,
				"dos_partition: too many slices\n");
			break;
		}
		if (is_extended(p.sys_type)) {
			/* extended partitions only get one or
			   two sectors mapped for LILO to install,
			   whichever is needed to have 1kb of space */
			if (sector_size_mul == 1)
				sp[i].size = 2;
			else sp[i].size = sector_size_mul;
			n += read_extended_partition(fd, &p, i, sp+n, ns-n);
		}
	}
	return n;
}
Ejemplo n.º 9
0
Archivo: mbr.c Proyecto: Fluray/kboot
/** Iterate over an extended partition.
 * @param disk      Disk that the partition is on.
 * @param lba       LBA of the extended partition.
 * @param cb        Callback function. */
static void handle_extended(disk_device_t *disk, uint32_t lba, partition_iterate_cb_t cb) {
    mbr_t *ebr __cleanup_free;
    size_t i = 4;

    ebr = malloc(sizeof(*ebr));

    for (uint32_t curr_ebr = lba, next_ebr = 0; curr_ebr; curr_ebr = next_ebr) {
        mbr_partition_t *partition, *next;

        if (!read_mbr(disk, ebr, curr_ebr)) {
            dprintf("mbr: failed to read EBR at %" PRIu32 "\n", curr_ebr);
            break;
        } else if (ebr->signature != MBR_SIGNATURE) {
            dprintf("mbr: warning: invalid EBR, corrupt partition table\n");
            break;
        }

        /* First entry contains the logical partition, second entry refers to
         * the next EBR, forming a linked list of EBRs. */
        partition = &ebr->partitions[0];
        next = &ebr->partitions[1];

        /* Calculate the location of the next EBR. The start sector is relative
         * to the start of the extended partition. Set to 0 if the second
         * partition doesn't refer to another EBR entry, causes the loop to end. */
        next->start_lba += lba;
        next_ebr = (is_valid(disk, next) && is_extended(next) && next->start_lba > curr_ebr)
            ? next->start_lba
            : 0;

        /* Get the partition. Here the start sector is relative to the current
         * EBR's location. */
        partition->start_lba += curr_ebr;
        if (!is_valid(disk, partition))
            continue;

        cb(disk, i++, partition->start_lba, partition->num_sectors);
    }
}
Ejemplo n.º 10
0
Archivo: mbr.c Proyecto: Fluray/kboot
/** Iterate over the partitions on a device.
 * @param disk          Disk to iterate over.
 * @param cb            Callback function.
 * @return              Whether the device contained an MBR partition table. */
static bool mbr_partition_iterate(disk_device_t *disk, partition_iterate_cb_t cb) {
    mbr_t *mbr __cleanup_free;
    bool seen_extended;

    /* Read in the MBR, which is in the first block on the device. */
    mbr = malloc(sizeof(*mbr));
    if (!read_mbr(disk, mbr, 0) || mbr->signature != MBR_SIGNATURE)
        return false;

    /* Check if this is a GPT partition table (technically we should not get
     * here if this is a GPT disk as the GPT code should be reached first). This
     * is just a safeguard. */
    if (mbr->partitions[0].type == MBR_PARTITION_TYPE_GPT)
        return false;

    /* Loop through all partitions in the table. */
    seen_extended = false;
    for (size_t i = 0; i < array_size(mbr->partitions); i++) {
        mbr_partition_t *partition = &mbr->partitions[i];

        if (!is_valid(disk, partition))
            continue;

        if (is_extended(partition)) {
            if (seen_extended) {
                dprintf("mbr: warning: ignoring multiple extended partitions\n");
                continue;
            }

            handle_extended(disk, partition->start_lba, cb);
            seen_extended = true;
        } else {
            cb(disk, i, partition->start_lba, partition->num_sectors);
        }
    }

    return true;
}
Ejemplo n.º 11
0
int
read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
	struct partition *p;
	unsigned long offset = all.start;
	int i, n=0;
	unsigned char *bp;

	bp = getblock(fd, offset);
	if (bp == NULL)
		return -1;

	if (bp[510] != 0x55 || bp[511] != 0xaa)
		return -1;

	p = (struct partition *) (bp + 0x1be);
	for (i=0; i<4; i++) {
		/* always add, even if zero length */
		if (n < ns) {
			sp[n].start = p->start_sect;
			sp[n].size = p->nr_sects;
			n++;
		} else {
			fprintf(stderr,
				"dos_partition: too many slices\n");
			break;
		}
		p++;
	}
	p = (struct partition *) (bp + 0x1be);
	for (i=0; i<4; i++) {
		if (is_extended(p->sys_type))
			n += read_extended_partition(fd, p, sp+n, ns-n);
		p++;
	}
	return n;
}
Ejemplo n.º 12
0
/*  Print a partition that is relative to its Extended partition table
 */
static int get_partition_info_extended (block_dev_desc_t *dev_desc,
				 lbaint_t ext_part_sector,
				 lbaint_t relative, int part_num,
				 int which_part, disk_partition_t *info,
				 unsigned int disksig)
{
    unsigned char buffer[DOS_PART_DEFAULT_SECTOR];
    dos_partition_t *pt;
    int i;
    int dos_type;

    if (dev_desc->block_read(dev_desc, ext_part_sector, 1, buffer) != 1)
    {
        printf("** Can't read partition table on %d:" LBAFU " **\n", dev_desc->dev, ext_part_sector);
        return -1;
    }
    if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 || buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa)
    {
        printf ("bad MBR sector signature 0x%02x%02x\n", buffer[DOS_PART_MAGIC_OFFSET], buffer[DOS_PART_MAGIC_OFFSET + 1]);
        return -1;
    }

    // disksig is "Disk identifier" shown in "sudo fdisk -l"
    if (!ext_part_sector)
        disksig = le32_to_uint32(&buffer[DOS_PART_DISKSIG_OFFSET]);

    /* Print all primary/logical partitions */
    pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
    for (i = 0; i < 4; i++, pt++)
    {
        /*
         * fdisk does not show the extended partitions that are not in the MBR
         */
        if (((pt->boot_ind & ~0x80) == 0) && (pt->sys_ind != 0) && (part_num == which_part) && (is_extended(pt->sys_ind) == 0))
        {
            info->blksz = DOS_PART_DEFAULT_SECTOR;
            info->start = (lbaint_t)(ext_part_sector + le32_to_uint32(pt->start4));
            info->size  = (lbaint_t)le32_to_uint32(pt->size4);
            switch(dev_desc->if_type)
            {
                case IF_TYPE_IDE:
                case IF_TYPE_SATA:
                case IF_TYPE_ATAPI:
                    sprintf ((char *)info->name, "hd%c%d", 'a' + dev_desc->dev, part_num);
                    break;
                case IF_TYPE_SCSI:
                    sprintf ((char *)info->name, "sd%c%d", 'a' + dev_desc->dev, part_num);
                    break;
                case IF_TYPE_USB:
                    sprintf ((char *)info->name, "usbd%c%d", 'a' + dev_desc->dev, part_num);
                    break;
                case IF_TYPE_DOC:
                    sprintf ((char *)info->name, "docd%c%d", 'a' + dev_desc->dev, part_num);
                    break;
                default:
                    sprintf ((char *)info->name, "xx%c%d", 'a' + dev_desc->dev, part_num);
                    break;
                }
                /* sprintf(info->type, "%d, pt->sys_ind); */
                strcpy((char *)info->type, "U-Boot");
                info->bootable = is_bootable(pt);
                sprintf(info->uuid, "%08x-%02x", disksig, part_num);
                return 0;
        }

        /* Reverse engr the fdisk part# assignment rule! */
        if ((ext_part_sector == 0) || (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) )
        {
            part_num++;
        }
    }

    /* Follows the extended partitions */
    pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
    for (i = 0; i < 4; i++, pt++)
    {
        if (is_extended (pt->sys_ind))
        {
            lbaint_t lba_start = le32_to_uint32(pt->start4) + relative;

            return get_partition_info_extended (dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, part_num, which_part, info, disksig);
        }
    }

    /* Check for DOS PBR if no partition is found */
    dos_type = test_block_type(buffer);

    if (dos_type == DOS_PBR)
    {
        info->start = 0;
        info->size = dev_desc->lba;
        info->blksz = DOS_PART_DEFAULT_SECTOR;
        info->bootable = 0;
        strcpy((char *)info->type, "U-Boot");

        info->uuid[0] = 0;

        return 0;
    }

    return -1;
}
Ejemplo n.º 13
0
static int parse_dos_extended(blkid_probe pr, blkid_parttable tab,
		uint32_t ex_start, uint32_t ex_size, int ssf)
{
	blkid_partlist ls = blkid_probe_get_partlist(pr);
	uint32_t cur_start = ex_start, cur_size = ex_size;
	unsigned char *data;
	int ct_nodata = 0;	/* count ext.partitions without data partitions */
	int i;

	while (1) {
		struct dos_partition *p, *p0;
		uint32_t start, size;

		if (++ct_nodata > 100)
			return 0;
		data = blkid_probe_get_sector(pr, cur_start);
		if (!data)
			goto leave;	/* malformed partition? */

		if (!is_valid_mbr_signature(data))
			goto leave;

		p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);

		/* Usually, the first entry is the real data partition,
		 * the 2nd entry is the next extended partition, or empty,
		 * and the 3rd and 4th entries are unused.
		 * However, DRDOS sometimes has the extended partition as
		 * the first entry (when the data partition is empty),
		 * and OS/2 seems to use all four entries.
		 * -- Linux kernel fs/partitions/dos.c
		 *
		 * See also http://en.wikipedia.org/wiki/Extended_boot_record
		 */

		/* Parse data partition */
		for (p = p0, i = 0; i < 4; i++, p++) {
			uint32_t abs_start;
			blkid_partition par;

			/* the start is relative to the parental ext.partition */
			start = dos_partition_start(p) * ssf;
			size = dos_partition_size(p) * ssf;
			abs_start = cur_start + start;	/* absolute start */

			if (!size || is_extended(p))
				continue;
			if (i >= 2) {
				/* extra checks to detect real data on
				 * 3rd and 4th entries */
				if (start + size > cur_size)
					continue;
				if (abs_start < ex_start)
					continue;
				if (abs_start + size > ex_start + ex_size)
					continue;
			}

			par = blkid_partlist_add_partition(ls, tab, abs_start, size);
			if (!par)
				goto err;

			blkid_partition_set_type(par, p->sys_type);
			blkid_partition_set_flags(par, p->boot_ind);
			ct_nodata = 0;
		}
		/* The first nested ext.partition should be a link to the next
		 * logical partition. Everything other (recursive ext.partitions)
		 * is junk.
		 */
		for (p = p0, i = 0; i < 4; i++, p++) {
			start = dos_partition_start(p) * ssf;
			size = dos_partition_size(p) * ssf;

			if (size && is_extended(p))
				break;
		}
		if (i == 4)
			goto leave;

		cur_start = ex_start + start;
		cur_size = size;
	}
leave:
	return 0;
err:
	return -1;
}
Ejemplo n.º 14
0
/*  Print a partition that is relative to its Extended partition table
 */
static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part_sector,
				 int relative, int part_num,
				 int which_part, disk_partition_t *info)
{
	unsigned char buffer[DEFAULT_SECTOR_SIZE];
	dos_partition_t *pt;
	int i;

	if (dev_desc->block_read (dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
		printf ("** Can't read partition table on %d:%d **\n",
			dev_desc->dev, ext_part_sector);
		return -1;
	}
	if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
		buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
		printf ("bad MBR sector signature 0x%02x%02x\n",
			buffer[DOS_PART_MAGIC_OFFSET],
			buffer[DOS_PART_MAGIC_OFFSET + 1]);
		return -1;
	}

	/* Print all primary/logical partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		/*
		 * fdisk does not show the extended partitions that
		 * are not in the MBR
		 */
		if (((pt->boot_ind & ~0x80) == 0) &&
		    (pt->sys_ind != 0) &&
		    (part_num == which_part) &&
		    (is_extended(pt->sys_ind) == 0)) {
			info->blksz = 512;
			info->start = ext_part_sector + le32_to_int (pt->start4);
			info->size  = le32_to_int (pt->size4);
			switch(dev_desc->if_type) {
				case IF_TYPE_IDE:
				case IF_TYPE_SATA:
				case IF_TYPE_ATAPI:
					sprintf ((char *)info->name, "hd%c%d",
						'a' + dev_desc->dev, part_num);
					break;
				case IF_TYPE_SCSI:
					sprintf ((char *)info->name, "sd%c%d",
						'a' + dev_desc->dev, part_num);
					break;
				case IF_TYPE_USB:
					sprintf ((char *)info->name, "usbd%c%d",
						'a' + dev_desc->dev, part_num);
					break;
				case IF_TYPE_DOC:
					sprintf ((char *)info->name, "docd%c%d",
						'a' + dev_desc->dev, part_num);
					break;
				default:
					sprintf ((char *)info->name, "xx%c%d",
						'a' + dev_desc->dev, part_num);
					break;
			}
			/* sprintf(info->type, "%d, pt->sys_ind); */
			sprintf ((char *)info->type, "U-Boot");
			return 0;
		}

		/* Reverse engr the fdisk part# assignment rule! */
		if ((ext_part_sector == 0) ||
		    (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
			part_num++;
		}
	}

	/* Follows the extended partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		if (is_extended (pt->sys_ind)) {
			int lba_start = le32_to_int (pt->start4) + relative;

			return get_partition_info_extended (dev_desc, lba_start,
				 ext_part_sector == 0 ? lba_start : relative,
				 part_num, which_part, info);
		}
	}
	return -1;
}
Ejemplo n.º 15
0
int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off)
{
	const uint8_t *buf;
	int i;
	uint64_t poff;
	uint64_t plen;
	uint64_t extended = 0;
	uint64_t current;
	uint64_t next;
	int limit;
	int empty = 1;
	struct msdos_partition_entry *part;
	struct volume_id_partition *p;

	dbg("probing at offset 0x%llx", (unsigned long long) off);

	buf = volume_id_get_buffer(id, off, 0x200);
	if (buf == NULL)
		return -1;

	if (buf[MSDOS_SIG_OFF] != 0x55 || buf[MSDOS_SIG_OFF + 1] != 0xaa)
		return -1;

	/* check flags on all entries for a valid partition table */
	part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
	for (i = 0; i < 4; i++) {
		if (part[i].boot_ind != 0
		 && part[i].boot_ind != 0x80
		) {
			return -1;
		}

		if (part[i].nr_sects != 0)
			empty = 0;
	}
	if (empty == 1)
		return -1;

	if (id->partitions != NULL)
		free(id->partitions);
	id->partitions = xzalloc(VOLUME_ID_PARTITIONS_MAX *
				sizeof(struct volume_id_partition));

	for (i = 0; i < 4; i++) {
		poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
		plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;

		if (plen == 0)
			continue;

		p = &id->partitions[i];

//		p->pt_type_raw = part[i].sys_ind;

		if (is_extended(part[i].sys_ind)) {
			dbg("found extended partition at 0x%llx", (unsigned long long) poff);
//			volume_id_set_usage_part(p, VOLUME_ID_PARTITIONTABLE);
//			p->type = "msdos_extended_partition";
			if (extended == 0)
				extended = off + poff;
		} else {
			dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
				part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);

//			if (is_raid(part[i].sys_ind))
//				volume_id_set_usage_part(p, VOLUME_ID_RAID);
//			else
//				volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
		}

//		p->pt_off = off + poff;
//		p->pt_len = plen;
		id->partition_count = i+1;
	}

	next = extended;
	current = extended;
	limit = 50;

	/* follow extended partition chain and add data partitions */
	while (next != 0) {
		if (limit-- == 0) {
			dbg("extended chain limit reached");
			break;
		}

		buf = volume_id_get_buffer(id, current, 0x200);
		if (buf == NULL)
			break;

		part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];

		if (buf[MSDOS_SIG_OFF] != 0x55 || buf[MSDOS_SIG_OFF + 1] != 0xaa)
			break;

		next = 0;

		for (i = 0; i < 4; i++) {
			poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
			plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;

			if (plen == 0)
				continue;

			if (is_extended(part[i].sys_ind)) {
				dbg("found extended partition at 0x%llx", (unsigned long long) poff);
				if (next == 0)
					next = extended + poff;
			} else {
				dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
					part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);

				/* we always start at the 5th entry */
//				while (id->partition_count < 4)
//					volume_id_set_usage_part(&id->partitions[id->partition_count++], VOLUME_ID_UNUSED);
				if (id->partition_count < 4)
					id->partition_count = 4;

//				p = &id->partitions[id->partition_count];

//				if (is_raid(part[i].sys_ind))
//					volume_id_set_usage_part(p, VOLUME_ID_RAID);
//				else
//					volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);

//				p->pt_off = current + poff;
//				p->pt_len = plen;
				id->partition_count++;

//				p->pt_type_raw = part[i].sys_ind;

				if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
					dbg("too many partitions");
					next = 0;
				}
			}
		}

		current = next;
	}

//	volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
//	id->type = "msdos_partition_table";

	return 0;
}
Ejemplo n.º 16
0
static int parse_dos_extended(blkid_probe pr, blkid_parttable tab,
		uint32_t ex_start, uint32_t ex_size, int ssf)
{
	blkid_partlist ls = blkid_probe_get_partlist(pr);
	uint32_t cur_start = ex_start, cur_size = ex_size;
	unsigned char *data;
	int ct_nodata = 0;	/* count ext.partitions without data partitions */
	int i;

	DBG(LOWPROBE, ul_debug("parse EBR [start=%d, size=%d]", ex_start/ssf, ex_size/ssf));
	if (ex_start == 0) {
		DBG(LOWPROBE, ul_debug("Bad offset in primary extended partition -- ignore"));
		return 0;
	}

	while (1) {
		struct dos_partition *p, *p0;
		uint32_t start, size;

		if (++ct_nodata > 100)
			return BLKID_PROBE_OK;
		data = blkid_probe_get_sector(pr, cur_start);
		if (!data) {
			if (errno)
				return -errno;
			goto leave;	/* malformed partition? */
		}

		if (!mbr_is_valid_magic(data))
			goto leave;

		p0 = mbr_get_partition(data, 0);

		/* Usually, the first entry is the real data partition,
		 * the 2nd entry is the next extended partition, or empty,
		 * and the 3rd and 4th entries are unused.
		 * However, DRDOS sometimes has the extended partition as
		 * the first entry (when the data partition is empty),
		 * and OS/2 seems to use all four entries.
		 * -- Linux kernel fs/partitions/dos.c
		 *
		 * See also http://en.wikipedia.org/wiki/Extended_boot_record
		 */

		/* Parse data partition */
		for (p = p0, i = 0; i < 4; i++, p++) {
			uint32_t abs_start;
			blkid_partition par;

			/* the start is relative to the parental ext.partition */
			start = dos_partition_get_start(p) * ssf;
			size = dos_partition_get_size(p) * ssf;
			abs_start = cur_start + start;	/* absolute start */

			if (!size || is_extended(p))
				continue;
			if (i >= 2) {
				/* extra checks to detect real data on
				 * 3rd and 4th entries */
				if (start + size > cur_size)
					continue;
				if (abs_start < ex_start)
					continue;
				if (abs_start + size > ex_start + ex_size)
					continue;
			}

			/* Avoid recursive non-empty links, see ct_nodata counter */
			if (blkid_partlist_get_partition_by_start(ls, abs_start)) {
				DBG(LOWPROBE, ul_debug("#%d: EBR duplicate data partition [abs start=%u] -- ignore",
							i + 1, abs_start));
				continue;
			}

			par = blkid_partlist_add_partition(ls, tab, abs_start, size);
			if (!par)
				return -ENOMEM;

			blkid_partition_set_type(par, p->sys_ind);
			blkid_partition_set_flags(par, p->boot_ind);
			blkid_partition_gen_uuid(par);
			ct_nodata = 0;
		}
		/* The first nested ext.partition should be a link to the next
		 * logical partition. Everything other (recursive ext.partitions)
		 * is junk.
		 */
		for (p = p0, i = 0; i < 4; i++, p++) {
			start = dos_partition_get_start(p) * ssf;
			size = dos_partition_get_size(p) * ssf;

			if (size && is_extended(p)) {
				if (start == 0)
					DBG(LOWPROBE, ul_debug("#%d: EBR link offset is zero -- ignore", i + 1));
				else
					break;
			}
		}
		if (i == 4)
			goto leave;

		cur_start = ex_start + start;
		cur_size = size;
	}
leave:
	return BLKID_PROBE_OK;
}
Ejemplo n.º 17
0
int
create_extended_partition(int fd, int secno, int size) {
	int sec = secno;
	int cursec = secno;
	int pno = partno;	/* number of extd partition */
	int ei = eptsct-1;
	unsigned char type = 0x5;
	int lastseen = secno;
	int ok = 0;

	if (epts[ei].secno != secno) {
		fprintf(stderr, "%s: program bug\n", progname);
		exit(1);
	}

	outmsg("candidate ext pt", secno, secno+1, type);
	addpart(secno, 1, type);		/* size to be filled in later */
	
	while(1) {
		char buf[512];
		struct partition *p1, *p2, *pr, *pe;
		p1 = (struct partition *)(& epts[ei].pt4[0]);
		p2 = (struct partition *)(& epts[ei].pt4[16]);
		/* for the time being we just ignore the rest */

		if (is_extended(p1->sys_type)) {
			pr = p2;
			pe = p1;
		} else if (is_extended(p2->sys_type)) {
			pr = p1;
			pe = p2;
		} else if (p1->sys_type == 0) {
			pr = p2;
			pe = 0;
		} else if (p2->sys_type == 0) {
			pr = p1;
			pe = 0;
		} else
			break;

		/* first handle the real partition, if any */
		if (pr->sys_type != 0) {
			int ss = cursec + pr->start_sect;
			int es = ss + pr->nr_sects;
			outmsg("found in ept", ss, es, pr->sys_type);
			addpart(ss, pr->nr_sects, pr->sys_type);
			if (lastseen < es - 1)
				lastseen = es - 1;
			if (lastseen >= size)
				break;
		}


		/* then the extended link */

		if (!pe) {
			ok = 1;
			break;
		}
		type = pe->sys_type;
		cursec = sec + pe->start_sect;
		if (cursec >= size)
			break;
		read_sectors(fd, buf, cursec, 1);
		addepts(cursec, buf);
		ei = eptsct-1;
	}

	if (!ok || lastseen == secno) {
		printf("# retracted\n");
		partno = pno;
		return 0;
	}

	pts[pno].type = type;
	pts[pno].size = lastseen+1-secno;
	outmsg("extended part ok", secno, lastseen+1, type);
	return lastseen;
}
Ejemplo n.º 18
0
/*  Print a partition that is relative to its Extended partition table
 */
static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part_sector,
				 int relative, int part_num,
				 int which_part, disk_partition_t *info)
{
	unsigned char tmp_buf[DEFAULT_SECTOR_SIZE];
	unsigned char *buffer = KSEG1ADDR(&tmp_buf[0]);
	dos_partition_t *pt;
	int i;

	if (dev_desc->block_read (dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
		printf ("** Can't read partition table on %d:%d **\n",
			dev_desc->dev, ext_part_sector);
		return -1;
	}
	if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
		buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
		printf ("bad MBR sector signature 0x%02x%02x\n",
			buffer[DOS_PART_MAGIC_OFFSET],
			buffer[DOS_PART_MAGIC_OFFSET + 1]);
		return -1;
	}

	/* Print all primary/logical partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);

	/* MTK/Ralink 2012/06/28 -- if no partition table in USB storage first sector */
	if(pt->boot_ind != 0x80 && pt->boot_ind != 0x0){
		boot_sector *bs;
		printf ("It seems no partition tables existed.\n");
		bs = (boot_sector *) (buffer);
		if(ext_part_sector == 0 && bs->reserved && bs->fats){
			info->blksz = 512;
			info->start = ext_part_sector + 0;
	                //FIXME: how to determine info->size? from FAT struct?
			//info->size  = FAT2CPU32(bs->total_sect);
			return 0;
		}else
			return -1;
	}

	for (i = 0; i < 4; i++, pt++) {
		/*
		 * fdisk does not show the extended partitions that
		 * are not in the MBR
		 */
		if ((pt->sys_ind != 0) &&
		    (part_num == which_part) &&
		    (is_extended(pt->sys_ind) == 0)) {
			info->blksz = 512;
			info->start = ext_part_sector + le32_to_int (pt->start4);
			info->size  = le32_to_int (pt->size4);
			switch(dev_desc->if_type) {
				case IF_TYPE_IDE:
				case IF_TYPE_ATAPI:
					sprintf (info->name, "hd%c%d\n", 'a' + dev_desc->dev, part_num);
					break;
				case IF_TYPE_SCSI:
					sprintf (info->name, "sd%c%d\n", 'a' + dev_desc->dev, part_num);
					break;
				case IF_TYPE_USB:
					sprintf (info->name, "usbd%c%d\n", 'a' + dev_desc->dev, part_num);
					break;
				case IF_TYPE_DOC:
					sprintf (info->name, "docd%c%d\n", 'a' + dev_desc->dev, part_num);
					break;
				default:
					sprintf (info->name, "xx%c%d\n", 'a' + dev_desc->dev, part_num);
					break;
			}
			/* sprintf(info->type, "%d, pt->sys_ind); */
			sprintf (info->type, "U-Boot");
			return 0;
		}

		/* Reverse engr the fdisk part# assignment rule! */
		if ((ext_part_sector == 0) ||
		    (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
			part_num++;
		}
	}

	/* Follows the extended partitions */
	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
	for (i = 0; i < 4; i++, pt++) {
		if (is_extended (pt->sys_ind)) {
			int lba_start = le32_to_int (pt->start4) + relative;

			return get_partition_info_extended (dev_desc, lba_start,
				 ext_part_sector == 0 ? lba_start : relative,
				 part_num, which_part, info);
		}
	}
	return -1;
}
Ejemplo n.º 19
0
/*
 * read_mbr --
 *      reads Master Boot Record (sector 0) of physical device and
 *      constructs disk description structure
 *
 * PARAMETERS:
 *      disk_desc - returned disc description structure
 *
 * RETURNS:
 *      RTEMS_SUCCESSFUL if success,
 *      RTEMS_INTERNAL_ERROR otherwise
 */
static rtems_status_code
read_mbr(int fd, rtems_disk_desc_t *disk_desc)
{
    int                  part_num;
    rtems_sector_data_t *sector = NULL;
    rtems_part_desc_t   *part_desc;
    uint8_t             *data;
    rtems_status_code    rc;

    /* get MBR sector */
    rc = get_sector(fd, 0, &sector);
    if (rc != RTEMS_SUCCESSFUL)
    {
        if (sector)
            free(sector);
        return rc;
    }

    /* check if the partition table structure is MS-DOS style */
    if (!msdos_signature_check(sector))
    {
        free(sector);
        return RTEMS_INTERNAL_ERROR;
    }

    /* read and process 4 primary partition descriptors */

    data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;

    for (part_num = 0;
         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
         part_num++)
    {
        rc = data_to_part_desc(data, &part_desc);
        if (rc != RTEMS_SUCCESSFUL)
        {
            free(sector);
            return rc;
        }

        if (part_desc != NULL)
        {
            part_desc->log_id = part_num + 1;
            part_desc->disk_desc = disk_desc;
            part_desc->end = part_desc->start + part_desc->size - 1;
            disk_desc->partitions[part_num] = part_desc;
        }
        else
        {
            disk_desc->partitions[part_num] = NULL;
        }

        data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
    }

    free(sector);

    disk_desc->last_log_id = RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;

    /* There cannot be more than one extended partition,
       but we are to process each primary partition */
    for (part_num = 0;
         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
         part_num++)
    {
        part_desc = disk_desc->partitions[part_num];
        if (part_desc != NULL && is_extended(part_desc->sys_type))
        {
            read_extended_partition(fd, part_desc->start, part_desc);
            free(part_desc);
            disk_desc->partitions[part_num] = NULL;
        }
    }

    return RTEMS_SUCCESSFUL;
}
Ejemplo n.º 20
0
/*
 * read_extended_partition --
 *      recursively reads extended partition sector from the device
 *      and constructs the partition table tree
 *
 * PARAMETERS:
 *      fd       - file descriptor
 *      start    - start sector of primary extended partition, used for
 *                 calculation of absolute partition sector address
 *      ext_part - description of extended partition to process
 *
 * RETURNS:
 *      RTEMS_SUCCESSFUL if success,
 *      RTEMS_NO_MEMOTY if cannot allocate memory for part_desc_t strucure,
 *      RTEMS_INTERNAL_ERROR if other error occurs.
 */
static rtems_status_code
read_extended_partition(int fd, uint32_t start, rtems_part_desc_t *ext_part)
{
    int                  i;
    rtems_sector_data_t *sector = NULL;
    uint32_t             here;
    uint8_t             *data;
    rtems_part_desc_t   *new_part_desc;
    rtems_status_code    rc;

    if ((ext_part == NULL) || (ext_part->disk_desc == NULL))
    {
        return RTEMS_INTERNAL_ERROR;
    }

    /* get start sector of current extended partition */
    here = ext_part->start;

    /* get first extended partition sector */

    rc = get_sector(fd, here, &sector);
    if (rc != RTEMS_SUCCESSFUL)
    {
        if (sector)
            free(sector);
        return rc;
    }

    if (!msdos_signature_check(sector))
    {
        free(sector);
        return RTEMS_INTERNAL_ERROR;
    }

    /* read and process up to 4 logical partition descriptors */

    data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;

    for (i = 0; i < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; i++)
    {
        /* if data_to_part_desc fails skip this partition
         * and parse the next one
         */
        rc = data_to_part_desc(data, &new_part_desc);
        if (rc != RTEMS_SUCCESSFUL)
        {
            free(sector);
            return rc;
        }

        if (new_part_desc == NULL)
        {
            data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
            continue;
        }

        ext_part->sub_part[i] = new_part_desc;
        new_part_desc->ext_part = ext_part;
        new_part_desc->disk_desc = ext_part->disk_desc;

        if (is_extended(new_part_desc->sys_type))
        {
            new_part_desc->log_id = EMPTY_PARTITION;
            new_part_desc->start += start;
            read_extended_partition(fd, start, new_part_desc);
        }
        else
        {
            rtems_disk_desc_t *disk_desc = new_part_desc->disk_desc;
            disk_desc->partitions[disk_desc->last_log_id] = new_part_desc;
            new_part_desc->log_id = ++disk_desc->last_log_id;
            new_part_desc->start += here;
            new_part_desc->end = new_part_desc->start + new_part_desc->size - 1;
        }
        data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
    }

    free(sector);

    return RTEMS_SUCCESSFUL;
}