From 6a011a09ab9f21d9e877a2cb33e0908545bfdfb3 Mon Sep 17 00:00:00 2001 From: Luke go Date: Wed, 11 Nov 2020 17:23:28 +0900 Subject: [PATCH] ODROID-COMMON: Support MPT partition from block device. - Before this patch, Only mmc device (eMMC/SD) can use MPT (Multimedia Partition Table). So th other devices like ssd, hdd and usb storage can't be main storage of the android. To solve this problem, Applied new partition support method - mpt partitions. - It works subset of the msdos partition. Change-Id: I2a192bf27e75dc040ccc3ea93a79d35c93db8543 --- arch/arm64/configs/odroidc4_android_defconfig | 1 + block/partition-generic.c | 27 +++- block/partitions/Kconfig | 7 + block/partitions/Makefile | 1 + block/partitions/mpt.c | 120 ++++++++++++++++++ block/partitions/mpt.h | 5 + block/partitions/msdos.c | 4 + drivers/mmc/card/block.c | 58 --------- 8 files changed, 158 insertions(+), 65 deletions(-) create mode 100644 block/partitions/mpt.c create mode 100644 block/partitions/mpt.h 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;