From: lintao Date: Wed, 30 Jul 2014 03:16:42 +0000 (+0800) Subject: block: partitions: add rockchip partition support X-Git-Tag: firefly_0821_release~4916^2~123 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=7fc89efff78a2ac5f7060b805539cbe1629df1ea;p=firefly-linux-kernel-4.4.55.git block: partitions: add rockchip partition support --- diff --git a/arch/arm/configs/rk3036_defconfig b/arch/arm/configs/rk3036_defconfig index d4554a48dccf..a0ecdf18584f 100644 --- a/arch/arm/configs/rk3036_defconfig +++ b/arch/arm/configs/rk3036_defconfig @@ -32,6 +32,7 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y CONFIG_ARCH_ROCKCHIP=y +CONFIG_RK_PARTITION=y CONFIG_BLOCK_RKNAND=y CONFIG_ARM_ERRATA_720789=y CONFIG_PL310_ERRATA_753970=y diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 554a4d770a8d..5e2fc53cb328 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -34,6 +34,7 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y CONFIG_ARCH_ROCKCHIP=y +CONFIG_RK_PARTITION=y CONFIG_RK_USB_UART=y CONFIG_BLOCK_RKNAND=y CONFIG_ARM_ERRATA_720789=y diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig index 75a54e1adbb5..1a9c61ee4d80 100644 --- a/block/partitions/Kconfig +++ b/block/partitions/Kconfig @@ -249,3 +249,14 @@ config SYSV68_PARTITION partition table format used by Motorola Delta machines (using sysv68). Otherwise, say N. + + +config RK_PARTITION + bool "Rockchip partition table support" if PARTITION_ADVANCED + default y if ARCH_ROCKCHIP + ---help--- + Like most systems, Rockchip use its own hard disk partition table + format,incompatible with all others. Say Y here if you would like + to be able to read the hard diskpartition table format used by Rockchip + Soc inside machines with eMMC as main storage disk. Otherwise, as well + as you don't know what all this about, say N. diff --git a/block/partitions/Makefile b/block/partitions/Makefile index 1e5d63d1f01c..d6842b632b61 100644 --- a/block/partitions/Makefile +++ b/block/partitions/Makefile @@ -18,6 +18,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 - -#added for emmc in Rockchip project. -obj-$(CONFIG_MMC_DW_ROCKCHIP) += mtdpart.o +obj-$(CONFIG_RK_PARTITION) += rk.o diff --git a/block/partitions/check.c b/block/partitions/check.c index 4997581ae64f..a7c678fff0b7 100755 --- a/block/partitions/check.c +++ b/block/partitions/check.c @@ -19,8 +19,6 @@ #include #include "check.h" -#include "mtdpart.h" - #include "acorn.h" #include "amiga.h" #include "atari.h" @@ -35,6 +33,7 @@ #include "efi.h" #include "karma.h" #include "sysv68.h" +#include "rk.h" int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ @@ -105,9 +104,8 @@ static int (*check_part[])(struct parsed_partitions *) = { #ifdef CONFIG_SYSV68_PARTITION sysv68_partition, #endif - -#if CONFIG_MMC_DW_ROCKCHIP - mtdpart_partition, +#ifdef CONFIG_RK_PARTITION + rkpart_partition, #endif NULL @@ -163,10 +161,12 @@ check_partition(struct gendisk *hd, struct block_device *bdev) sprintf(state->name, "p"); i = res = err = 0; - - //if the disk is eMMC,then skip directly the check_part to mtdpart_partition; added by xbw, at 2014-03-24 - if((179 == MAJOR(bdev->bd_dev)&& (1 == hd->emmc_disk))) - i=sizeof(check_part)/sizeof(struct parsed_partitions *)-2; + + /* Rockchip partition table ONLY used by eMMC disk */ + #ifdef CONFIG_RK_PARTITION + if ((179 == MAJOR(bdev->bd_dev) && (1 == hd->emmc_disk))) + i = sizeof(check_part) / sizeof(struct parsed_partitions *) - 2; + #endif while (!res && check_part[i]) { memset(state->parts, 0, state->limit * sizeof(state->parts[0])); diff --git a/block/partitions/mtdpart.c b/block/partitions/mtdpart.c deleted file mode 100755 index 6f3e0044bfdb..000000000000 --- a/block/partitions/mtdpart.c +++ /dev/null @@ -1,365 +0,0 @@ -#include -#include -#include - -#include "check.h" -#include "mtdpart.h" - -/* error message prefix */ -#define ERRP "mtd: " - -/* debug macro */ -#if 0 -#define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0) -#else -#define dbg(x) -#endif - -#define SECTOR_1G 0x200000 // 0x200000 * 512 = 1G -#define FROM_OFFSET 0x2000 // 4MB - -/* special size referring to all the remaining space in a partition */ -#define SIZE_REMAINING UINT_MAX -#define OFFSET_CONTINUOUS UINT_MAX - -struct mtd_partition{ - char *name; - sector_t from; - sector_t size; -}; -struct cmdline_mtd_partition { - struct cmdline_mtd_partition *next; - char *mtd_id; - int num_parts; - struct mtd_partition *parts; -}; - -/* mtdpart_setup() parses into here */ -static struct cmdline_mtd_partition *partitions; - -/* the command line passed to mtdpart_setupd() */ -static char *cmdline; -static int cmdline_parsed = 0; - -/* - * Parse one partition definition for an MTD. Since there can be many - * comma separated partition definitions, this function calls itself - * recursively until no more partition definitions are found. Nice side - * effect: the memory to keep the mtd_partition structs and the names - * is allocated upon the last definition being found. At that point the - * syntax has been verified ok. - */ -static struct mtd_partition * newpart(char *s, - char **retptr, - int *num_parts, - int this_part, - unsigned char **extra_mem_ptr, - int extra_mem_size) -{ - struct mtd_partition *parts; - sector_t size; - sector_t from = OFFSET_CONTINUOUS; - char *name; - int name_len; - unsigned char *extra_mem; - char delim; - - /* fetch the partition size */ - if (*s == '-') - { /* assign all remaining space to this partition */ - size = SIZE_REMAINING; - s++; - } - else - { - size = memparse(s, &s); - if (size < (PAGE_SIZE)>>9) - { - printk(KERN_ERR ERRP "partition size too small (%llx)\n", size); - return NULL; - } - } - - /* fetch partition name */ - delim = 0; - /* check for from */ - if (*s == '@') - { - s++; - from = memparse(s, &s); - } - /* now look for name */ - if (*s == '(') - { - delim = ')'; - } - - if (delim) - { - char *p; - - name = ++s; - p = strchr(name, delim); - if (!p) - { - printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim); - return NULL; - } - name_len = p - name; - s = p + 1; - } - else - { - name = NULL; - name_len = 13; /* Partition_000 */ - } - - /* record name length for memory allocation later */ - extra_mem_size += name_len + 1; - - /* test if more partitions are following */ - if (*s == ',') - { - if (size == SIZE_REMAINING) - { - printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n"); - return NULL; - } - /* more partitions follow, parse them */ - parts = newpart(s + 1, &s, num_parts, this_part + 1, - &extra_mem, extra_mem_size); - if (!parts) - return NULL; - } - else - { /* this is the last partition: allocate space for all */ - int alloc_size; - - *num_parts = this_part + 1; - alloc_size = *num_parts * sizeof(struct mtd_partition) + - extra_mem_size; - parts = kzalloc(alloc_size, GFP_KERNEL); - if (!parts) - { - printk(KERN_ERR ERRP "out of memory\n"); - return NULL; - } - extra_mem = (unsigned char *)(parts + *num_parts); - } - /* enter this partition (from will be calculated later if it is zero at this point) */ - parts[this_part].size = size; - parts[this_part].from = from; - if (name) - { - strlcpy(extra_mem, name, name_len + 1); - } - else - { - sprintf(extra_mem, "Partition_%03d", this_part); - } - parts[this_part].name = extra_mem; - extra_mem += name_len + 1; - - dbg(("partition %d: name <%s>, from %llx, size %llx\n", - this_part, - parts[this_part].name, - parts[this_part].from, - parts[this_part].size)); - - /* return (updated) pointer to extra_mem memory */ - if (extra_mem_ptr) - *extra_mem_ptr = extra_mem; - - /* return (updated) pointer command line string */ - *retptr = s; - - /* return partition table */ - return parts; -} - -/* - * Parse the command line. - */ -static int mtdpart_setup_real(char *s) -{ - cmdline_parsed = 1; - - for( ; s != NULL; ) - { - struct cmdline_mtd_partition *this_mtd; - struct mtd_partition *parts; - int mtd_id_len; - int num_parts; - char *p, *mtd_id; - - mtd_id = s; - /* fetch */ - if (!(p = strchr(s, ':'))) - { - dbg(( "no mtd-id\n")); - return 0; - } - mtd_id_len = p - mtd_id; - - dbg(("parsing <%s>\n", p+1)); - - /* - * parse one mtd. have it reserve memory for the - * struct cmdline_mtd_partition and the mtd-id string. - */ - parts = newpart(p + 1, /* cmdline */ - &s, /* out: updated cmdline ptr */ - &num_parts, /* out: number of parts */ - 0, /* first partition */ - (unsigned char**)&this_mtd, /* out: extra mem */ - mtd_id_len + 1 + sizeof(*this_mtd) + - sizeof(void*)-1 /*alignment*/); - if(!parts) - { - /* - * An error occurred. We're either: - * a) out of memory, or - * b) in the middle of the partition spec - * Either way, this mtd is hosed and we're - * unlikely to succeed in parsing any more - */ - return 0; - } - - /* align this_mtd */ - this_mtd = (struct cmdline_mtd_partition *) - ALIGN((unsigned long)this_mtd, sizeof(void*)); - /* enter results */ - this_mtd->parts = parts; - this_mtd->num_parts = num_parts; - this_mtd->mtd_id = (char*)(this_mtd + 1); - strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); - - /* link into chain */ - this_mtd->next = partitions; - partitions = this_mtd; - - dbg(("mtdid=<%s> num_parts=<%d>\n", - this_mtd->mtd_id, this_mtd->num_parts)); - - /* EOS - we're done */ - if (*s == 0) - break; -#if 0 - /* does another spec follow? */ - if (*s != ';') - { - printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s); - return 0; - } -#endif - s++; - } - return 1; -} - -/* - * Main function to be called from the MTD mapping driver/device to - * obtain the partitioning information. At this point the command line - * arguments will actually be parsed and turned to struct mtd_partition - * information. It returns partitions for the requested mtd device, or - * the first one in the chain if a NULL mtd_id is passed in. - */ -static int parse_cmdline_partitions(sector_t n, - struct mtd_partition **pparts, - unsigned long origin) -{ - unsigned long from; - int i; - struct cmdline_mtd_partition *part; - const char *mtd_id = "rk29xxnand"; - - /* parse command line */ - if (!cmdline_parsed) - mtdpart_setup_real(cmdline); - - for(part = partitions; part; part = part->next) - { - if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) - { - for(i = 0, from = 0; i < part->num_parts; i++) - { - if (part->parts[i].from == OFFSET_CONTINUOUS) - part->parts[i].from = from; - else - from = part->parts[i].from; - if (part->parts[i].size == SIZE_REMAINING) - part->parts[i].size = n - from - FROM_OFFSET; - if (from + part->parts[i].size > n) - { - printk(KERN_WARNING ERRP - "%s: partitioning exceeds flash size, truncating\n", - part->mtd_id); - part->parts[i].size = n - from; - part->num_parts = i; - } - from += part->parts[i].size; - } - *pparts = kmemdup(part->parts, - sizeof(*part->parts) * part->num_parts, - GFP_KERNEL); - if (!*pparts) - return -ENOMEM; - return part->num_parts; - } - } - return 0; -} - -static void rk_emmc_fix(void) -{ - const char mode_emmc[] = " androidboot.mode=emmc"; - const char charger_emmc[] = " androidboot.charger.emmc=1"; - char *new_command_line; - size_t saved_command_line_len = strlen(saved_command_line); - - if (strstr(saved_command_line, "androidboot.mode=charger")) { - new_command_line = kzalloc(saved_command_line_len + strlen(charger_emmc) + 1, GFP_KERNEL); - sprintf(new_command_line, "%s%s", saved_command_line, charger_emmc); - } else { - new_command_line = kzalloc(saved_command_line_len + strlen(mode_emmc) + 1, GFP_KERNEL); - sprintf(new_command_line, "%s%s", saved_command_line, mode_emmc); - } - saved_command_line = new_command_line; -} - -int mtdpart_partition(struct parsed_partitions *state) -{ - int num_parts = 0, i; - sector_t n = get_capacity(state->bdev->bd_disk); - struct mtd_partition *parts = NULL; - - if(n < SECTOR_1G) - return 0; - - //only used to eMMC-disk - if(1 != state->bdev->bd_disk->emmc_disk) - return 0; - - cmdline = strstr(saved_command_line, "mtdparts=") + 9; - - num_parts = parse_cmdline_partitions(n, &parts, 0); - if(num_parts < 0) - return num_parts; - - for(i = 0; i < num_parts; i++){ - put_partition(state, i+1, parts[i].from + FROM_OFFSET, parts[i].size); - strcpy(state->parts[i+1].info.volname, parts[i].name); - printk(KERN_INFO "%10s: 0x%09llx -- 0x%09llx (%llu MB)\n", - parts[i].name, - parts[i].from * 512, - (parts[i].from + parts[i].size) * 512, - parts[i].size / 2048); - } - - rk_emmc_fix(); - - return 1; -} - - diff --git a/block/partitions/mtdpart.h b/block/partitions/mtdpart.h deleted file mode 100755 index e5cde6a8dc15..000000000000 --- a/block/partitions/mtdpart.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * fs/partitions/mtdpart.h - */ - -int mtdpart_partition(struct parsed_partitions *state); diff --git a/block/partitions/rk.c b/block/partitions/rk.c new file mode 100755 index 000000000000..93cb0d6d4b60 --- /dev/null +++ b/block/partitions/rk.c @@ -0,0 +1,333 @@ +#include +#include +#include +#include "check.h" +#include "rk.h" + +/* rkpart_setup() parses into here */ +static struct cmdline_rk_partition *partitions; +/* the command line passed to mtdpart_setupd() */ +static char *cmdline; +static int cmdline_parsed; + +/* + * Parse one partition definition for an rkpart. Since there can be many + * comma separated partition definitions, this function calls itself + * recursively until no more partition definitions are found. Nice side + * effect: the memory to keep the rk_partition structs and the names + * is allocated upon the last definition being found. At that point the + * syntax has been verified ok. + */ +static struct rk_partition *newpart(char *s, + char **retptr, + int *num_parts, + int this_part, + unsigned char **extra_mem_ptr, + int extra_mem_size) +{ + struct rk_partition *parts; + sector_t size; + sector_t from = OFFSET_CONTINUOUS; + char *name; + int name_len; + unsigned char *extra_mem; + char delim; + + /* fetch the partition size */ + if (*s == '-') + { /* assign all remaining space to this partition */ + size = SIZE_REMAINING; + s++; + } + else + { + size = memparse(s, &s); + /* No sense support partition less than 8B */ + if (size < ((PAGE_SIZE) >> 9)) + { + printk(KERN_ERR ERRP "partition size too small (%llx)\n", size); + return NULL; + } + } + + /* fetch partition name */ + delim = 0; + /* check for from */ + if (*s == '@') + { + s++; + from = memparse(s, &s); + } + /* now look for name */ + if (*s == '(') + { + delim = ')'; + } + + if (delim) + { + char *p; + + name = ++s; + p = strchr(name, delim); + if (!p) + { + printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim); + return NULL; + } + name_len = p - name; + s = p + 1; + } + else + { + name = NULL; + name_len = 13; /* Partition_000 */ + } + + /* record name length for memory allocation later */ + extra_mem_size += name_len + 1; + + /* test if more partitions are following */ + if (*s == ',') + { + if (size == SIZE_REMAINING) + { + printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n"); + return NULL; + } + /* more partitions follow, parse them */ + parts = newpart(s + 1, &s, num_parts, this_part + 1, + &extra_mem, extra_mem_size); + if (!parts) + return NULL; + } + else + { /* this is the last partition: allocate space for all */ + int alloc_size; + + *num_parts = this_part + 1; + alloc_size = *num_parts * sizeof(struct rk_partition) + + extra_mem_size; + parts = kzalloc(alloc_size, GFP_KERNEL); + if (!parts) + { + printk(KERN_ERR ERRP "out of memory\n"); + return NULL; + } + extra_mem = (unsigned char *)(parts + *num_parts); + } + /* enter this partition (from will be calculated later if it is zero at this point) */ + parts[this_part].size = size; + parts[this_part].from = from; + if (name) + { + strlcpy(extra_mem, name, name_len + 1); + } + else + { + sprintf(extra_mem, "Partition_%03d", this_part); + } + parts[this_part].name = extra_mem; + extra_mem += name_len + 1; + + dbg(("partition %d: name <%s>, from %llx, size %llx\n", + this_part, + parts[this_part].name, + parts[this_part].from, + parts[this_part].size)); + + /* return (updated) pointer to extra_mem memory */ + if (extra_mem_ptr) + *extra_mem_ptr = extra_mem; + + /* return (updated) pointer command line string */ + *retptr = s; + + /* return partition table */ + return parts; +} + +/* + * Parse the command line. + */ +static int rkpart_setup_real(char *s) +{ + cmdline_parsed = 1; + + for( ; s != NULL; ) + { + struct cmdline_rk_partition *this_rk; + struct rk_partition *parts; + int rk_id_len; + int num_parts; + char *p, *rk_id; + + rk_id = s; + /* fetch */ + if (!(p = strchr(s, ':'))) + { + dbg(( "no rk-id\n")); + return 0; + } + rk_id_len = p - rk_id; + + dbg(("parsing <%s>\n", p + 1)); + + /* + * parse one mtd. have it reserve memory for the + * struct cmdline_mtd_partition and the mtd-id string. + */ + parts = newpart(p + 1, /* cmdline */ + &s, /* out: updated cmdline ptr */ + &num_parts, /* out: number of parts */ + 0, /* first partition */ + (unsigned char**)&this_rk, /* out: extra mem */ + rk_id_len + 1 + sizeof(*this_rk) + + sizeof(void*)-1 /*alignment*/); + if(!parts) + { + /* + * An error occurred. We're either: + * a) out of memory, or + * b) in the middle of the partition spec + * Either way, this mtd is hosed and we're + * unlikely to succeed in parsing any more + */ + return 0; + } + + /* align this_rk */ + this_rk = (struct cmdline_rk_partition *) + ALIGN((unsigned long)this_rk, sizeof(void*)); + /* enter results */ + this_rk->parts = parts; + this_rk->num_parts = num_parts; + this_rk->rk_id = (char*)(this_rk + 1); + strlcpy(this_rk->rk_id, rk_id, rk_id_len + 1); + + /* link into chain */ + this_rk->next = partitions; + partitions = this_rk; + + dbg(("rkid=<%s> num_parts=<%d>\n", + this_rk->mtd_id, this_rk->num_parts)); + + /* EOS - we're done */ + if (*s == 0) + break; + s++; + } + return 1; +} + +/* + * Main function to be called from the MTD mapping driver/device to + * obtain the partitioning information. At this point the command line + * arguments will actually be parsed and turned to struct mtd_partition + * information. It returns partitions for the requested mtd device, or + * the first one in the chain if a NULL mtd_id is passed in. + */ +static int parse_cmdline_partitions(sector_t n, + struct rk_partition **pparts, + unsigned long origin) +{ + unsigned long from; + int i; + struct cmdline_rk_partition *part; + /* Fixme: parameter should be coherence with part table id */ + const char *rk_id = "rk29xxnand"; + + /* parse command line */ + if (!cmdline_parsed) + rkpart_setup_real(cmdline); + + for(part = partitions; part; part = part->next) + { + if ((!rk_id) || (!strcmp(part->rk_id, rk_id))) + { + for(i = 0, from = 0; i < part->num_parts; i++) + { + if (part->parts[i].from == OFFSET_CONTINUOUS) + part->parts[i].from = from; + else + from = part->parts[i].from; + if (part->parts[i].size == SIZE_REMAINING) + part->parts[i].size = n - from - FROM_OFFSET; + if (from + part->parts[i].size > n) + { + printk(KERN_WARNING ERRP + "%s: partitioning exceeds flash size, truncating\n", + part->rk_id); + part->parts[i].size = n - from; + part->num_parts = i; + } + from += part->parts[i].size; + } + *pparts = kmemdup(part->parts, + sizeof(*part->parts) * part->num_parts, + GFP_KERNEL); + if (!*pparts) + return -ENOMEM; + return part->num_parts; + } + } + return 0; +} + +static void rkpart_bootmode_fixup(void) +{ + const char mode[] = " androidboot.mode=emmc"; + const char charger[] = " androidboot.charger.emmc=1"; + char *new_command_line; + size_t saved_command_line_len = strlen(saved_command_line); + + if (strstr(saved_command_line, "androidboot.mode=charger")) { + new_command_line = kzalloc(saved_command_line_len + strlen(charger) + 1, GFP_KERNEL); + sprintf(new_command_line, "%s%s", saved_command_line, charger); + } else { + new_command_line = kzalloc(saved_command_line_len + strlen(mode) + 1, GFP_KERNEL); + sprintf(new_command_line, "%s%s", saved_command_line, mode); + } + saved_command_line = new_command_line; +} + +int rkpart_partition(struct parsed_partitions *state) +{ + int num_parts = 0, i; + sector_t n = get_capacity(state->bdev->bd_disk); + struct rk_partition *parts = NULL; + + if (n < SECTOR_1G) + return 0; + + /* ONLY be used by eMMC-disk */ + if (1 != state->bdev->bd_disk->emmc_disk) + return 0; + + /* Fixme: parameter should be coherence with part table */ + cmdline = strstr(saved_command_line, "mtdparts=") + 9; + cmdline_parsed = 0; + + num_parts = parse_cmdline_partitions(n, &parts, 0); + if (num_parts < 0) + return num_parts; + + for (i = 0; i < num_parts; i++) { + put_partition( state, + i+1, + parts[i].from + FROM_OFFSET, + parts[i].size); + strcpy(state->parts[i+1].info.volname, parts[i].name); + printk(KERN_INFO "%10s: 0x%09llx -- 0x%09llx (%llu MB)\n", + parts[i].name, + parts[i].from * 512, + (parts[i].from + parts[i].size) * 512, + parts[i].size / 2048); + } + + rkpart_bootmode_fixup(); + + return 1; +} + + diff --git a/block/partitions/rk.h b/block/partitions/rk.h new file mode 100755 index 000000000000..25085e716df5 --- /dev/null +++ b/block/partitions/rk.h @@ -0,0 +1,40 @@ +/* + * block/partitions/rk.h + */ + +/* error message prefix */ +#define ERRP "rkpart: " + +/* debug macro */ +#define RKPART_DEBUG 0 +#if RKPART_DEBUG +#define dbg(x) do { \ +printk("DEBUG-CMDLINE-PART: "); \ +printk x; \ +} while (0) +#else +#define dbg(x) +#endif + +/* At least 1GB disk support*/ +#define SECTOR_1G 0x200000 + +/* Default partition table offet got from loader: 4MB*/ +#define FROM_OFFSET 0x2000 + +/* special size referring to all the remaining space in a partition */ +#define SIZE_REMAINING UINT_MAX +#define OFFSET_CONTINUOUS UINT_MAX + +struct rk_partition { + char *name; + sector_t from; + sector_t size; +}; +struct cmdline_rk_partition { + struct cmdline_rk_partition *next; + char *rk_id; + int num_parts; + struct rk_partition *parts; +}; +int rkpart_partition(struct parsed_partitions *state);