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
This commit is contained in:
Luke go
2020-11-11 17:23:28 +09:00
committed by Chris
parent 5fcc6be139
commit 6a011a09ab
8 changed files with 158 additions and 65 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View File

@@ -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

120
block/partitions/mpt.c Normal file
View File

@@ -0,0 +1,120 @@
#include "check.h"
#include <linux/printk.h>
#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, &sect);
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;
}

5
block/partitions/mpt.h Normal file
View File

@@ -0,0 +1,5 @@
/*
* fs/partitions/mtp.h
*/
int mpt_partition(struct parsed_partitions *state);

View File

@@ -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;
}

View File

@@ -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;