mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
120
block/partitions/mpt.c
Normal 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, §);
|
||||
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
5
block/partitions/mpt.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
* fs/partitions/mtp.h
|
||||
*/
|
||||
|
||||
int mpt_partition(struct parsed_partitions *state);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user