diff --git a/arch/arm64/configs/odroidc4_android_defconfig b/arch/arm64/configs/odroidc4_android_defconfig index 60312cac573f..224f4b8b63cc 100644 --- a/arch/arm64/configs/odroidc4_android_defconfig +++ b/arch/arm64/configs/odroidc4_android_defconfig @@ -300,6 +300,7 @@ CONFIG_BLK_DEV_BSG=y # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y CONFIG_EFI_PARTITION=y +CONFIG_MPT_PARTITION=y CONFIG_BLOCK_COMPAT=y CONFIG_BLK_MQ_PCI=y diff --git a/block/partition-generic.c b/block/partition-generic.c index 736f5b979a21..ee3d10cdef7c 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -222,8 +222,14 @@ static int part_uevent(struct device *dev, struct kobj_uevent_env *env) struct hd_struct *part = dev_to_part(dev); add_uevent_var(env, "PARTN=%u", part->partno); - if (part->info && part->info->volname[0]) - add_uevent_var(env, "PARTNAME=%s", part->info->volname); + if (part->info && part->info->volname[0]) { +#ifdef CONFIG_MPT_PARTITION + if (part->info->volname[0] == 0x09) + add_uevent_var(env, "PARTNAME=%s", &(part->info->volname[1])); + else +#endif + add_uevent_var(env, "PARTNAME=%s", part->info->volname); + } return 0; } @@ -331,11 +337,18 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, } dname = dev_name(ddev); - - if (isdigit(dname[strlen(dname) - 1])) - dev_set_name(pdev, "%sp%d", dname, partno); - else - dev_set_name(pdev, "%s%d", dname, partno); +#ifdef CONFIG_MPT_PARTITION + if (p->info->volname[0] == 0x09) + dev_set_name(pdev, "%s", &(p->info->volname[1])); + else{ +#endif + if (isdigit(dname[strlen(dname) - 1])) + dev_set_name(pdev, "%sp%d", dname, partno); + else + dev_set_name(pdev, "%s%d", dname, partno); +#ifdef CONFIG_MPT_PARTITION + } +#endif device_initialize(pdev); pdev->class = &block_class; diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig index 9b29a996c311..215e86d632ce 100644 --- a/block/partitions/Kconfig +++ b/block/partitions/Kconfig @@ -267,3 +267,10 @@ config CMDLINE_PARTITION help Say Y here if you want to read the partition table from bootargs. The format for the command line is just like mtdparts. + +config MPT_PARTITION + bool "MPT partition support" if PARTITION_ADVANCED + default y + help + Say Y here if you would like to use hard disks under Linux which + were partitioned using MPT. diff --git a/block/partitions/Makefile b/block/partitions/Makefile index 37a95270503c..bd6685bf775d 100644 --- a/block/partitions/Makefile +++ b/block/partitions/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o obj-$(CONFIG_EFI_PARTITION) += efi.o obj-$(CONFIG_KARMA_PARTITION) += karma.o obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o +obj-$(CONFIG_MPT_PARTITION) += mpt.o diff --git a/block/partitions/mpt.c b/block/partitions/mpt.c new file mode 100644 index 000000000000..5bb1139214d5 --- /dev/null +++ b/block/partitions/mpt.c @@ -0,0 +1,120 @@ +#include "check.h" +#include + +#define MAX_MPT_PART_NAME_LEN 16 +#define MAX_MPT_PART_NUM 32 + +#define MPT_PARTITION_SECTOR_OFFSET 2048 + +struct partition_mpt { + char name[MAX_MPT_PART_NAME_LEN]; + uint64_t size; + uint64_t offset; + unsigned int mask_flags; +}; + +struct ptable_t { + char magic[4]; + unsigned char version[12]; + int nr_parts; + int checksum; + struct partition_mpt partitions[MAX_MPT_PART_NUM]; +}; +/* + * MPT Magic Label "MPT" + */ +#define MPT_LABEL_MAGIC1 0x4D +#define MPT_LABEL_MAGIC2 0x50 +#define MPT_LABEL_MAGIC3 0x54 + +static inline int +mpt_magic_present(const char *p) +{ + return (p[0] == MPT_LABEL_MAGIC1 && + p[1] == MPT_LABEL_MAGIC2 && + p[2] == MPT_LABEL_MAGIC3); +} + +#define MPT_VERSION "01.00.00" + +static inline int +mpt_version_present(const unsigned char *p) +{ + return strncmp(p, MPT_VERSION, strlen(MPT_VERSION)); +} + +static uint32_t mpt_partition_checksum(const struct partition_mpt *part, int count) +{ + uint32_t sum = 0; + + while (count--) { + uint32_t *p = (uint32_t *) part; + int j = sizeof(struct partition_mpt) / sizeof(sum); + + for (; j > 0; j--) + sum += *p++; + } + + return sum; +} + +static inline int is_mpt_valid(const struct ptable_t *mpt, int strict) +{ + if (!mpt_magic_present(mpt->magic) || mpt_version_present(mpt->version)) + return 0; + + if (strict) { + if (mpt->checksum != mpt_partition_checksum(mpt->partitions, + mpt->nr_parts)) + return 0; + } + + return 1; +} + +static void applyInfo(struct parsed_partitions *state, int slot, struct ptable_t *mpt) +{ + struct partition_meta_info *info = &state->parts[state->next].info; + + info->uuid[0] = 0; + snprintf(info->volname, sizeof(info->volname), "\x09%s", + mpt->partitions[slot].name); + + state->parts[state->next].has_info = true; +} + +int mpt_partition(struct parsed_partitions *state) +{ + Sector sect; + unsigned char *data; + struct ptable_t *mpt; + + data = read_part_sector(state, MPT_PARTITION_SECTOR_OFFSET, §); + if (!data) + return -1; + + mpt = (struct ptable_t *) data; + + if (!is_mpt_valid(mpt, 1)) { + put_dev_sector(sect); + return 0; + } + + printk(KERN_CONT "magic - %s\n", mpt->magic); + printk(KERN_CONT "version - %s\n", mpt->version); + printk(KERN_CONT "checksum - %x, result - %x\n", mpt->checksum, mpt_partition_checksum(mpt->partitions, + mpt->nr_parts)); + + { + int slot; + for (slot = 0; slot < mpt->nr_parts; slot++) { + put_partition(state, state->next, + le32_to_cpu(mpt->partitions[slot].offset), + le32_to_cpu(mpt->partitions[slot].size)); + applyInfo(state, slot, mpt); + state->parts[state->next++].flags = mpt->partitions[slot].mask_flags; + } + } + put_dev_sector(sect); + return 1; +} diff --git a/block/partitions/mpt.h b/block/partitions/mpt.h new file mode 100644 index 000000000000..ebb356db7852 --- /dev/null +++ b/block/partitions/mpt.h @@ -0,0 +1,5 @@ +/* + * fs/partitions/mtp.h + */ + +int mpt_partition(struct parsed_partitions *state); diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c index 7d8d50c11ce7..71af73858443 100644 --- a/block/partitions/msdos.c +++ b/block/partitions/msdos.c @@ -24,6 +24,7 @@ #include "msdos.h" #include "efi.h" #include "aix.h" +#include "mpt.h" /* * Many architectures don't like unaligned accesses, while @@ -581,6 +582,9 @@ int msdos_partition(struct parsed_partitions *state) subtypes[n].parse(state, start_sect(p) * sector_size, nr_sects(p) * sector_size, slot); } +#ifdef CONFIG_MPT_PARTITION + mpt_partition(state); +#endif put_dev_sector(sect); return 1; } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 12b948db85a2..efe1d80fc855 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -3018,56 +3018,6 @@ static const struct mmc_fixup blk_fixups[] = END_FIXUP }; -#ifdef CONFIG_AMLOGIC_MMC -static int mmc_validate_mpt_partition(struct mmc_card *card) -{ - char *buf; - int ret; - -#if !defined(CONFIG_ARCH_MESON64_ODROID_COMMON) - /* check only if 'card' is eMMC device */ - if (strcmp(mmc_hostname(card->host), "emmc")) - return -EINVAL; -#endif - - buf = (char*)kmalloc(1 << card->csd.read_blkbits, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - mmc_claim_host(card->host); - - /* FIXME: fix up the magic number for start block to check MPT partition */ - ret = mmc_read_internal(card, 2048, 1, buf); - if (ret == 0) { - if (strncmp(buf, MMC_PARTITIONS_MAGIC, - sizeof(((struct mmc_partitions_fmt*)0)->magic)) != 0) { - ret = -EINVAL; - } - } - - mmc_release_host(card->host); - - kfree(buf); - return ret; -} - -#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) -static bool mmc_is_ignore_mpt(struct mmc_host *host) -{ - bool ignore = false; - struct device_node *of_node = host->parent->of_node; - struct device_node *child; - - for_each_child_of_node(of_node, child) { - if (of_property_read_bool(child, "ignore_mpt")) - ignore = true; - } - - return ignore; -} -#endif // defined(CONFIG_ARCH_MESON64_ODROID_COMMON) -#endif - static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; @@ -3099,14 +3049,6 @@ static int mmc_blk_probe(struct mmc_card *card) if (mmc_add_disk(md)) goto out; -#ifdef CONFIG_AMLOGIC_MMC - if (mmc_validate_mpt_partition(card) == 0 && - !mmc_is_ignore_mpt(card->host)) { - /* amlogic add emmc partitions ops */ - aml_emmc_partition_ops(card, md->disk); - } -#endif - list_for_each_entry(part_md, &md->part, part) { if (mmc_add_disk(part_md)) goto out;