static void parse_minix(struct parsed_partitions *state, sector_t offset, sector_t size, int origin) { #ifdef CONFIG_MINIX_SUBPARTITION Sector sect; unsigned char *data; struct partition *p; int i; data = read_part_sector(state, offset, §); if (!data) return; p = (struct partition *)(data + 0x1be); /* The first sector of a Minix partition can have either * a secondary MBR describing its subpartitions, or * the normal boot sector. */ if (msdos_magic_present (data + 510) && SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */ printk(" %s%d: <minix:", state->name, origin); for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) { if (state->next == state->limit) break; /* add each partition in use */ if (SYS_IND(p) == MINIX_PARTITION) put_partition(state, state->next++, start_sect(p), nr_sects(p)); } printk(" >\n"); } put_dev_sector(sect); #endif /* CONFIG_MINIX_SUBPARTITION */ }
int tegra_msdos_parse(struct parsed_partitions *state, struct block_device *bdev, u64 mbr_offset) { int sector_size = bdev_logical_block_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; int slot; printk(KERN_INFO "tegra_msdos_parse: mbr_offset=%llu\n", mbr_offset); data = read_dev_sector(bdev, mbr_offset, §); if (!data) { printk(KERN_INFO "tegra_msdos_parse: read error. exit\n"); return -1; } if (!msdos_magic_present(data + 510)) { printk(KERN_INFO "tegra_msdos_parse: no msdos magic\n"); put_dev_sector(sect); return 0; } p = (struct partition *) (data + 0x1be); for (slot = 1; slot <= 4; slot++, p++) { if (p->boot_ind != 0 && p->boot_ind != 0x80) { // 0x1be,0x1ce,0x1de,0x1fe printk("tegra_msdos_parse: slot %d, boot_ind=0x%x. exit\n", slot, p->boot_ind); put_dev_sector(sect); return 0; } } p = (struct partition *) (data + 0x1be); for (slot = 1 ; slot <= 4 ; slot++, p++) { u64 start = START_SECT(p)*sector_size; // 0015f800 1439744 u64 size = NR_SECTS(p)*sector_size; // 01c41400 29627392 printk(KERN_INFO "tegra_msdos_parse: slot %d, start=%llu size=%llu\n", slot, start, size); if (!size) continue; if (is_extended_partition(p)) { printk(KERN_INFO "tegra_msdos_parse: slot %d extended partition\n", slot); //put_partition(state, state->next++, start+mbr_offset, size == 1 ? 1 : 2); printk(" <"); tegra_msdos_parse_extended(state, state->bdev, mbr_offset, start, size); printk(" >"); continue; } printk(KERN_INFO "tegra_msdos_parse: put_partition\n"); put_partition(state, state->next++, start+mbr_offset, size); } printk("\n"); printk(KERN_INFO "tegra_msdos_parse: done\n"); put_dev_sector(sect); return 1; }
/* * Minix 2.0.0/2.0.2 subpartition support. * Anand Krishnamurthy <*****@*****.**> * Rajeev V. Pillai <*****@*****.**> */ static void minix_partition(struct gendisk *hd, struct block_device *bdev, int minor, int *current_minor) { #ifdef CONFIG_MINIX_SUBPARTITION long offset = hd->part[minor].start_sect; Sector sect; unsigned char *data; struct partition *p; int mask = (1 << hd->minor_shift) - 1; int i; char buf[40]; data = read_dev_sector(bdev, offset, §); if (!data) return; p = (struct partition *)(data + 0x1be); /* The first sector of a Minix partition can have either * a secondary MBR describing its subpartitions, or * the normal boot sector. */ if (msdos_magic_present (data + 510) && SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */ printk(" %s: <minix:", partition_name(hd, minor, buf)); for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) { if ((*current_minor & mask) == 0) break; /* add each partition in use */ if (SYS_IND(p) == MINIX_PARTITION) { add_gd_partition(hd, *current_minor, START_SECT(p), NR_SECTS(p)); (*current_minor)++; } } printk(" >\n"); } put_dev_sector(sect); #endif /* CONFIG_MINIX_SUBPARTITION */ }
static void parse_extended(struct parsed_partitions *state, sector_t first_sector, sector_t first_size) { struct partition *p; Sector sect; unsigned char *data; sector_t this_sector, this_size; sector_t sector_size = bdev_logical_block_size(state->bdev) / 512; int loopct = 0; /* number of links followed without finding a data partition */ int i; this_sector = first_sector; this_size = first_size; while (1) { if (++loopct > 100) return; if (state->next == state->limit) return; data = read_part_sector(state, this_sector, §); if (!data) return; if (!msdos_magic_present(data + 510)) goto done; p = (struct partition *) (data + 0x1be); /* * 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. */ /* * First process the data partition(s) */ for (i=0; i<4; i++, p++) { sector_t offs, size, next; if (!nr_sects(p) || is_extended_partition(p)) continue; /* Check the 3rd and 4th entries - these sometimes contain random garbage */ offs = start_sect(p)*sector_size; size = nr_sects(p)*sector_size; next = this_sector + offs; if (i >= 2) { if (offs + size > this_size) continue; if (next < first_sector) continue; if (next + size > first_sector + first_size) continue; } put_partition(state, state->next, next, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[state->next].flags = ADDPART_FLAG_RAID; loopct = 0; if (++state->next == state->limit) goto done; } /* * Next, process the (first) extended partition, if present. * (So far, there seems to be no reason to make * parse_extended() recursive and allow a tree * of extended partitions.) * It should be a link to the next logical partition. */ p -= 4; for (i=0; i<4; i++, p++) if (nr_sects(p) && is_extended_partition(p)) break; if (i == 4) goto done; /* nothing left to do */ this_sector = first_sector + start_sect(p) * sector_size; this_size = nr_sects(p) * sector_size; put_dev_sector(sect); } done: put_dev_sector(sect); }
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; }
static int __update_msdos_partition(int px, unsigned long long start, unsigned long long size) { int err = 0; int i, slot; int xbr_idx = 0; char *this_name = NULL; unsigned long long this_addr; unsigned char *buf = NULL; struct partition *p; buf = kzalloc(512, GFP_KERNEL); if (!buf) { err = -ENOMEM; pmt_err("update_msdos_partition: malloc buf fail\n"); goto fail_malloc; } //find px in which mbr/ebr. for (i = 0;i < MBR_COUNT; i++) { for (slot = 0; slot < 4; slot++) { if (MBR_EBR_px[i].part_index[slot] == px) { /* this_name is mbr or ebrx */ xbr_idx = i; this_name = MBR_EBR_px[i].part_name; goto found; } } } if (slot >= 4) { pmt_err("p%d can not be found in mbr\n", px); err = -EINVAL; goto out; } found: pmt_info("update %s\n", this_name); /* check mbr or ebrx partition info */ for (i = 0; i < PART_NUM; i++) { if (!strcmp(this_name, PartInfo[i].name)) { this_addr = PartInfo[i].start_address; pmt_info("update %s addr %llx\n", this_name, this_addr); break; } } if (i == PART_NUM) { pmt_err("can not find %s\n", this_name); err = -EINVAL; goto out; } /* read mbr or ebr into buf */ err = eMMC_rw_x(this_addr, (u32*)buf, 0, 0, 512, 1, EMMC_PART_USER); if (err || !msdos_magic_present(buf + 510)) { pmt_err("read %s error\n", this_name); err = -EIO; goto out; } if (!msdos_magic_present(buf + 510)) { pmt_err("read MBR/EBR fail\n"); err = -1; goto out; } p = (struct partition *) (buf + 0x1be); p[slot].start_sect = (unsigned int)((start - this_addr) / 512); p[slot].nr_sects = (unsigned int)(size / 512); err = eMMC_rw_x(this_addr, (u32*)buf, 0, 1, 512, 1, EMMC_PART_USER); if (err) { pmt_err("write %s error\n", this_name); err = -EIO; goto out; } out: kfree(buf); fail_malloc: return err; }
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { int sector_size = bdev_hardsect_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; int slot; data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } if (aix_magic_present(data, bdev)) { 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) { 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++) { u32 start = START_SECT(p)*sector_size; u32 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 */ put_partition(state, slot, start, size == 1 ? 1 : 2); printk(" <"); parse_extended(state, bdev, start, size); printk(" >"); continue; } put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; 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, bdev, START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, slot); } put_dev_sector(sect); return 1; }
static void tegra_msdos_parse_extended(struct parsed_partitions *state, struct block_device *bdev, u64 mbr_offset, u64 first_sector, u64 first_size) { struct partition *p; Sector sect; unsigned char *data; u64 this_sector, this_size; int sector_size = bdev_logical_block_size(bdev) / 512; int loopct = 0; /* number of links followed without finding a data partition */ int i; this_sector = first_sector; this_size = first_size; while (1) { if (++loopct > 2) { printk(KERN_INFO "tegra_msdos_parse_extended: loopcnt>2. exit\n"); return; } printk(KERN_INFO "tegra_msdos_parse_extended: read part sector, start=%llu+%llu size=%llu\n", mbr_offset, this_sector, this_size); data = read_dev_sector(bdev, mbr_offset+this_sector, §); if (!data) { printk(KERN_INFO "tegra_msdos_parse_extended: read error. exit\n"); return; } if (!msdos_magic_present(data + 510)) { printk(KERN_INFO "tegra_msdos_parse_extended: no msdos magic. exit\n"); goto done; } p = (struct partition *) (data + 0x1be); /* * First process the data partition(s) */ for (i=0; i<4; i++, p++) { u64 offs, size, next; if (!NR_SECTS(p) || is_extended_partition(p)) continue; offs = START_SECT(p)*sector_size; size = NR_SECTS(p)*sector_size; next = this_sector + offs; if (i >= 2) { if (offs + size > this_size) continue; if (next < first_sector) continue; if (next + size > first_sector + first_size) continue; } printk(KERN_INFO "tegra_msdos_parse_extended: put_partition %d start=%llu+%llu size=%llu\n", state->next, mbr_offset, next, size); put_partition(state, state->next++, mbr_offset+next, size); loopct = 0; } printk(KERN_INFO "tegra_msdos_parse_extended: done with this sector\n"); p -= 4; for (i=0; i<4; i++, p++) if (NR_SECTS(p) && is_extended_partition(p)) { printk(KERN_INFO "tegra_msdos_parse_extended: extended part slot %d\n", i+1); break; } if (i == 4) goto done; /* nothing left to do */ this_sector = first_sector + START_SECT(p) * sector_size; this_size = NR_SECTS(p) * sector_size; put_dev_sector(sect); } done: printk(KERN_INFO "tegra_msdos_parse_extended: done\n"); put_dev_sector(sect); }
int msdos_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor) { int i, minor = first_part_minor; Sector sect; struct partition *p; unsigned char *data; int mask = (1 << hd->minor_shift) - 1; int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512; int current_minor = first_part_minor; int err; err = handle_ide_mess(bdev); if (err <= 0) return err; data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } 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. */ current_minor += 4; for (i=1 ; i<=4 ; minor++,i++,p++) { if (!NR_SECTS(p)) continue; add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); #if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { md_autodetect_dev(MKDEV(hd->major,minor)); } #endif if (is_extended_partition(p)) { unsigned long size = hd->part[minor].nr_sects; printk(" <"); /* prevent someone doing mkfs or mkswap on an extended partition, but leave room for LILO */ if (size > 2) hd->part[minor].nr_sects = 2; extended_partition(hd, bdev, minor, size, ¤t_minor); printk(" >"); } } /* * Check for old-style Disk Manager partition table */ if (msdos_magic_present(data + 0xfc)) { p = (struct partition *) (0x1be + data); for (i = 4 ; i < 16 ; i++, current_minor++) { p--; if ((current_minor & mask) == 0) break; if (!(START_SECT(p) && NR_SECTS(p))) continue; add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); } } printk("\n"); /* second pass - output for each on a separate line */ minor -= 4; p = (struct partition *) (0x1be + data); for (i=1 ; i<=4 ; minor++,i++,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) subtypes[n].parse(hd, bdev, minor, ¤t_minor); } put_dev_sector(sect); return 1; }
/* * Look for various forms of IDE disk geometry translation */ static int handle_ide_mess(struct block_device *bdev) { #ifdef CONFIG_BLK_DEV_IDE Sector sect; unsigned char *data; kdev_t dev = to_kdev_t(bdev->bd_dev); unsigned int sig; int heads = 0; struct partition *p; int i; /* * The i386 partition handling programs very often * make partitions end on cylinder boundaries. * There is no need to do so, and Linux fdisk doesnt always * do this, and Windows NT on Alpha doesnt do this either, * but still, this helps to guess #heads. */ data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } sig = le16_to_cpu(*(unsigned short *)(data + 2)); p = (struct partition *) (data + 0x1be); for (i = 0; i < 4; i++) { struct partition *q = &p[i]; if (NR_SECTS(q)) { if ((q->sector & 63) == 1 && (q->end_sector & 63) == 63) heads = q->end_head + 1; break; } } if (SYS_IND(p) == EZD_PARTITION) { /* * Accesses to sector 0 must go to sector 1 instead. */ if (ide_xlate_1024(dev, -1, heads, " [EZD]")) goto reread; } else if (SYS_IND(p) == DM6_PARTITION) { /* * Everything on the disk is offset by 63 sectors, * including a "new" MBR with its own partition table. */ if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) goto reread; } else if (sig <= 0x1ae && data[sig] == 0xAA && data[sig+1] == 0x55 && (data[sig+2] & 1)) { /* DM6 signature in MBR, courtesy of OnTrack */ (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]"); } else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) { /* * DM6 on other than the first (boot) drive */ (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]"); } else { (void) ide_xlate_1024(dev, 2, heads, " [PTBL]"); } put_dev_sector(sect); return 1; reread: put_dev_sector(sect); /* Flush the cache */ invalidate_bdev(bdev, 1); truncate_inode_pages(bdev->bd_inode->i_mapping, 0); #endif /* CONFIG_BLK_DEV_IDE */ return 1; }
static void extended_partition(struct gendisk *hd, struct block_device *bdev, int minor, unsigned long first_size, int *current_minor) { struct partition *p; Sector sect; unsigned char *data; unsigned long first_sector, this_sector, this_size; int mask = (1 << hd->minor_shift) - 1; int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512; int loopct = 0; /* number of links followed without finding a data partition */ int i; this_sector = first_sector = hd->part[minor].start_sect; this_size = first_size; while (1) { if (++loopct > 100) return; if ((*current_minor & mask) == 0) return; data = read_dev_sector(bdev, this_sector, §); if (!data) return; if (!msdos_magic_present(data + 510)) goto done; p = (struct partition *) (data + 0x1be); /* * 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. */ /* * First process the data partition(s) */ for (i=0; i<4; i++, p++) { unsigned long offs, size, next; if (!NR_SECTS(p) || is_extended_partition(p)) continue; /* Check the 3rd and 4th entries - these sometimes contain random garbage */ offs = START_SECT(p)*sector_size; size = NR_SECTS(p)*sector_size; next = this_sector + offs; if (i >= 2) { if (offs + size > this_size) continue; if (next < first_sector) continue; if (next + size > first_sector + first_size) continue; } add_gd_partition(hd, *current_minor, next, size); #if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { md_autodetect_dev(MKDEV(hd->major,*current_minor)); } #endif (*current_minor)++; loopct = 0; if ((*current_minor & mask) == 0) goto done; } /* * Next, process the (first) extended partition, if present. * (So far, there seems to be no reason to make * extended_partition() recursive and allow a tree * of extended partitions.) * It should be a link to the next logical partition. * Create a minor for this just long enough to get the next * partition table. The minor will be reused for the next * data partition. */ p -= 4; for (i=0; i<4; i++, p++) if (NR_SECTS(p) && is_extended_partition(p)) break; if (i == 4) goto done; /* nothing left to do */ this_sector = first_sector + START_SECT(p) * sector_size; this_size = NR_SECTS(p) * sector_size; minor = *current_minor; put_dev_sector(sect); } done: put_dev_sector(sect); }
static int update_MBR_or_EBR(int px, u64 start_addr, u64 length) { int i,ret,j; int found_mbr = 0; loff_t update_addr = 0; int index_in_mbr = 0; int mbr_index = 0; char *change_pt_name = NULL; struct partition *p; u8 *page_buf = NULL; ret =0; page_buf = kmalloc(512, GFP_KERNEL); if (!page_buf) { ret = -ENOMEM; printk("update_MBR_or_EBR: malloc page_buf fail\n"); goto fail_malloc; } //data -1MB /* for(i=0;i<PART_NUM;i++){ if((PartInfo[i].partition_idx == px)&&((!strncmp(PartInfo[i].name,"usrdata",7))||(!strncmp(PartInfo[i].name,"sec_ro",6))||(!strncmp(PartInfo[i].name,"android",7))||(!strncmp(PartInfo[i].name,"cache",5)))){ printk("update %s,need reduce 1MB in MBR\n",PartInfo[i].name); length -= 0x100000; } }*/ //find px in which mbr/ebr. for(i=0;i<MBR_COUNT;i++){ for(j=0;j<SLOT_PER_MBR;j++){ if(MBR_EBR_px[i].part_index[j]==px){ found_mbr = 1; change_pt_name = MBR_EBR_px[i].part_name; index_in_mbr = j; mbr_index = i; } } } if(found_mbr!=1){ printk("p%d can not be found in mbr\n",px); ret = -1; goto end; } printk("update %s\n",change_pt_name); for(i=0; i<PART_NUM;i++){ if(!strcmp(change_pt_name,PartInfo[i].name)){ update_addr = PartInfo[i].start_address - MBR_START_ADDR; printk("update %s addr %llx\n",change_pt_name,update_addr); break; } } if(i==PART_MAX_COUNT){ printk("can not find %s\n",change_pt_name); ret = -1; goto end; } ret = eMMC_rw_x(update_addr,(u32*)page_buf,0,0,512,1,USER); if(ret){ printk("read %s error\n",change_pt_name); goto end; } if (!msdos_magic_present(page_buf + 510)) { printk("read MBR/EBR fail\n"); ret = -1; goto end; } p = (struct partition *) (page_buf + 0x1be); for(i=0;i<4;i++){ if(MBR_EBR_px[mbr_index].part_index[i]!=0){ printk("p%d: %x %x\n",MBR_EBR_px[mbr_index].part_index[i],p[i].start_sect,p[i].nr_sects); if(i==index_in_mbr){ printk("p%d: change to %x %x\n",MBR_EBR_px[mbr_index].part_index[i],(u32)((start_addr-update_addr)/512),(u32)(length/512)); p[i].start_sect = (u32)((start_addr-update_addr)/512); p[i].nr_sects = (u32)(length/512); } } } ret = eMMC_rw_x(update_addr,(u32*)page_buf,0,1,512,1,USER); if(ret){ printk("write %s error\n",change_pt_name); goto end; } end: kfree(page_buf); fail_malloc: return ret; }
int msdos_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor) { int i, minor = first_part_minor; Sector sect; struct partition *p; unsigned char *data; int mask = (1 << hd->minor_shift) - 1; int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512; int current_minor = first_part_minor; int err; #ifdef CONFIG_IDE_IPOD int sector_mult = 1; #endif err = handle_ide_mess(bdev); if (err <= 0) return err; data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } p = (struct partition *) (data + 0x1be); #ifdef CONFIG_IDE_IPOD /* * Addition for iPods: check for actual filesystems to figure out the correct partition layout */ for (i=1 ; i<=4 ; i++,p++) { unsigned char *partdata; if (!NR_SECTS(p)) continue; if (SYS_IND(p) == 0xb) { partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*4, §); if (msdos_magic_present(partdata + 510)) sector_mult = 4; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*2, §); if (msdos_magic_present(partdata + 510)) sector_mult = 2; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size, §); if (msdos_magic_present(partdata + 510)) sector_mult = 1; } else if (SYS_IND(p) == 0x83) { partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*4+2, §); if (ext3_magic_present(partdata + 56)) sector_mult = 4; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*2+2, §); if (ext3_magic_present(partdata + 56)) sector_mult = 2; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size+2, §); if (ext3_magic_present(partdata + 56)) sector_mult = 1; } } printk("Experimental partition and filesystem detection code by Vincent Huisman ([email protected])\n"); printk("Partition sector size: %d\n", sector_mult); sector_size *= sector_mult; p = (struct partition *) (data + 0x1be); // Reinitialize, duh #endif /* * 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. */ current_minor += 4; for (i=1 ; i<=4 ; minor++,i++,p++) { if (!NR_SECTS(p)) continue; add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); #if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { md_autodetect_dev(MKDEV(hd->major,minor)); } #endif if (is_extended_partition(p)) { unsigned long size = hd->part[minor].nr_sects; printk(" <"); /* prevent someone doing mkfs or mkswap on an extended partition, but leave room for LILO */ if (size > 2) hd->part[minor].nr_sects = 2; extended_partition(hd, bdev, minor, size, ¤t_minor); printk(" >"); } } /* * Check for old-style Disk Manager partition table */ if (msdos_magic_present(data + 0xfc)) { p = (struct partition *) (0x1be + data); for (i = 4 ; i < 16 ; i++, current_minor++) { p--; if ((current_minor & mask) == 0) break; if (!(START_SECT(p) && NR_SECTS(p))) continue; add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); } } printk("\n"); /* second pass - output for each on a separate line */ minor -= 4; p = (struct partition *) (0x1be + data); for (i=1 ; i<=4 ; minor++,i++,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) subtypes[n].parse(hd, bdev, minor, ¤t_minor); } put_dev_sector(sect); return 1; }
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { int sector_size = bdev_hardsect_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; int slot; #ifdef HACK_PARTITION_TABLE_BOOT_IND int check_times = 0; #endif data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); 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) { #ifdef HACK_PARTITION_TABLE_BOOT_IND // hack for boot_ind != 0 && boot_ind != 0x80 printk("\n[cfyeh-hack] %s(%d) partition->boot_ind = 0x%.2x (should be 0x0 or 0x80)\n", __func__, __LINE__, p->boot_ind); check_times++; #else put_dev_sector(sect); return 0; #endif } } #ifdef HACK_PARTITION_TABLE_BOOT_IND // hack for boot_ind != 0 && boot_ind != 0x80 if(check_times > 1) { printk("[cfyeh-hack] %s(%d) partition->boot_ind fail %d times !!!\n", __func__, __LINE__, check_times); put_dev_sector(sect); return 0; } #endif #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++) { u32 start = START_SECT(p)*sector_size; u32 size = NR_SECTS(p)*sector_size; if (!size) continue; if (is_extended_partition(p)) { // add to know which partition is a extended partition // by cfyeh 2007/11/13 + state->parts[slot].is_part_extended = 1; // by cfyeh 2007/11/13 - /* prevent someone doing mkfs or mkswap on an extended partition, but leave room for LILO */ put_partition(state, slot, start, size == 1 ? 1 : 2); printk(" <"); parse_extended(state, bdev, start, size); printk(" >"); continue; } put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; 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, bdev, START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, slot); } put_dev_sector(sect); return 1; }