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, §); 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; }