block: support embedded device command line partition

Read block device partition table from command line.  The partition used
for fixed block device (eMMC) embedded device.  It is no MBR, save
storage space.  Bootloader can be easily accessed by absolute address of
data on the block device.  Users can easily change the partition.

This code reference MTD partition, source "drivers/mtd/cmdlinepart.c"
About the partition verbose reference
"Documentation/block/cmdline-partition.txt"

[[email protected]: fix printk text]
[[email protected]: fix error return code in parse_parts()]
Signed-off-by: Cai Zhiyong <[email protected]>
Cc: Karel Zak <[email protected]>
Cc: "Wanglin (Albert)" <[email protected]>
Cc: Marius Groeger <[email protected]>
Cc: David Woodhouse <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Brian Norris <[email protected]>
Cc: Artem Bityutskiy <[email protected]>
Signed-off-by: Wei Yongjun <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
Cai Zhiyong 2013-09-11 14:20:09 -07:00 • committed by Linus Torvalds
commit bab55417b1
10 changed files with 452 additions and 0 deletions

View file

@ -260,3 +260,10 @@ config SYSV68_PARTITION
partition table format used by Motorola Delta machines (using
sysv68).
Otherwise, say N.
config CMDLINE_PARTITION
bool "Command line partition support" if PARTITION_ADVANCED
select CMDLINE_PARSER
help
Say Y here if you would read the partitions table from bootargs.
The format for the command line is just like mtdparts.

View file

@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o
obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
obj-$(CONFIG_ATARI_PARTITION) += atari.o
obj-$(CONFIG_AIX_PARTITION) += aix.o
obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o
obj-$(CONFIG_MAC_PARTITION) += mac.o
obj-$(CONFIG_LDM_PARTITION) += ldm.o
obj-$(CONFIG_MSDOS_PARTITION) += msdos.o

View file

@ -34,6 +34,7 @@
#include "efi.h"
#include "karma.h"
#include "sysv68.h"
#include "cmdline.h"
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
@ -65,6 +66,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
adfspart_check_ADFS,
#endif
#ifdef CONFIG_CMDLINE_PARTITION
cmdline_partition,
#endif
#ifdef CONFIG_EFI_PARTITION
efi_partition, /* this must come before msdos */
#endif

View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2013 HUAWEI
* Author: Cai Zhiyong <caizhiyong@huawei.com>
*
* Read block device partition table from command line.
* The partition used for fixed block device (eMMC) embedded device.
* It is no MBR, save storage space. Bootloader can be easily accessed
* by absolute address of data on the block device.
* Users can easily change the partition.
*
* The format for the command line is just like mtdparts.
*
* Verbose config please reference "Documentation/block/cmdline-partition.txt"
*
*/
#include <linux/cmdline-parser.h>
#include "check.h"
#include "cmdline.h"
static char *cmdline;
static struct cmdline_parts *bdev_parts;
static int add_part(int slot, struct cmdline_subpart *subpart, void *param)
{
int label_min;
struct partition_meta_info *info;
char tmp[sizeof(info->volname) + 4];
struct parsed_partitions *state = (struct parsed_partitions *)param;
if (slot >= state->limit)
return 1;
put_partition(state, slot, subpart->from >> 9,
subpart->size >> 9);
info = &state->parts[slot].info;
label_min = min_t(int, sizeof(info->volname) - 1,
sizeof(subpart->name));
strncpy(info->volname, subpart->name, label_min);
info->volname[label_min] = '\0';
snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
strlcat(state->pp_buf, tmp, PAGE_SIZE);
state->parts[slot].has_info = true;
return 0;
}
static int __init cmdline_parts_setup(char *s)
{
cmdline = s;
return 1;
}
__setup("blkdevparts=", cmdline_parts_setup);
/*
* Purpose: allocate cmdline partitions.
* Returns:
* -1 if unable to read the partition table
* 0 if this isn't our partition table
* 1 if successful
*/
int cmdline_partition(struct parsed_partitions *state)
{
sector_t disk_size;
char bdev[BDEVNAME_SIZE];
struct cmdline_parts *parts;
if (cmdline) {
if (bdev_parts)
cmdline_parts_free(&bdev_parts);
if (cmdline_parts_parse(&bdev_parts, cmdline)) {
cmdline = NULL;
return -1;
}
cmdline = NULL;
}
if (!bdev_parts)
return 0;
bdevname(state->bdev, bdev);
parts = cmdline_parts_find(bdev_parts, bdev);
if (!parts)
return 0;
disk_size = get_capacity(state->bdev->bd_disk) << 9;
cmdline_parts_set(parts, disk_size, 1, add_part, (void *)state);
strlcat(state->pp_buf, "\n", PAGE_SIZE);
return 1;
}

View file

@ -0,0 +1,2 @@
int cmdline_partition(struct parsed_partitions *state);