2019-05-23 11:14:39 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* Read flash partition table from command line
*
2010-08-08 20:58:20 +01:00
* Copyright © 2002 SYSGO Real - Time Solutions GmbH
* Copyright © 2002 - 2010 David Woodhouse < dwmw2 @ infradead . org >
*
2005-04-16 15:20:36 -07:00
* The format for the command line is as follows :
2005-11-07 11:15:26 +00:00
*
2005-04-16 15:20:36 -07:00
* mtdparts = < mtddef > [ ; < mtddef ]
* < mtddef > : = < mtd - id > : < partdef > [ , < partdef > ]
2020-05-03 17:53:40 +02:00
* < partdef > : = < size > [ @ < offset > ] [ < name > ] [ ro ] [ lk ] [ slc ]
2005-04-16 15:20:36 -07:00
* < mtd - id > : = unique name used in mapping driver / device ( mtd - > name )
* < size > : = standard linux memsize OR " - " to denote all remaining space
2012-12-18 16:11:51 -05:00
* size is automatically truncated at end of device
2014-06-29 12:21:37 +02:00
* if specified or truncated size is 0 the part is skipped
2012-12-18 16:11:51 -05:00
* < offset > : = standard linux memsize
* if omitted the part will immediately follow the previous part
* or 0 if the first part
2005-04-16 15:20:36 -07:00
* < name > : = ' ( ' NAME ' ) '
2012-12-18 16:11:52 -05:00
* NAME will appear in / proc / mtd
2005-11-07 11:15:26 +00:00
*
2012-12-18 16:11:51 -05:00
* < size > and < offset > can be specified such that the parts are out of order
* in physical memory and may even overlap .
*
* The parts are assigned MTD numbers in the order they are specified in the
* command line regardless of their order in physical memory .
*
2005-04-16 15:20:36 -07:00
* Examples :
2005-11-07 11:15:26 +00:00
*
2005-04-16 15:20:36 -07:00
* 1 NOR Flash , with 1 single writable partition :
* edb7312 - nor : -
2005-11-07 11:15:26 +00:00
*
2005-04-16 15:20:36 -07:00
* 1 NOR Flash with 2 partitions , 1 NAND with one
* edb7312 - nor : 256 k ( ARMboot ) ro , - ( root ) ; edb7312 - nand : - ( home )
*/
2015-06-19 13:10:07 -07:00
# define pr_fmt(fmt) "mtd: " fmt
2005-04-16 15:20:36 -07:00
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/mtd/mtd.h>
# include <linux/mtd/partitions.h>
2011-07-03 15:17:31 -04:00
# include <linux/module.h>
2012-09-02 13:54:14 +03:00
# include <linux/err.h>
2005-04-16 15:20:36 -07:00
/* debug macro */
#if 0
# define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
# else
# define dbg(x)
# endif
/* special size referring to all the remaining space in a partition */
2012-11-01 13:58:17 +08:00
# define SIZE_REMAINING ULLONG_MAX
# define OFFSET_CONTINUOUS ULLONG_MAX
2005-04-16 15:20:36 -07:00
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 ;
2012-04-25 15:14:17 +02:00
/* the command line passed to mtdpart_setup() */
2013-01-16 02:12:49 +01:00
static char * mtdparts ;
2005-04-16 15:20:36 -07:00
static char * cmdline ;
2012-08-31 16:10:02 +03:00
static int cmdline_parsed ;
2005-04-16 15:20:36 -07:00
/*
* Parse one partition definition for an MTD . Since there can be many
2005-11-07 11:15:26 +00:00
* comma separated partition definitions , this function calls itself
2005-04-16 15:20:36 -07:00
* 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 .
*/
2005-11-07 11:15:26 +00:00
static struct mtd_partition * newpart ( char * s ,
2012-09-03 09:33:32 +03:00
char * * retptr ,
int * num_parts ,
int this_part ,
unsigned char * * extra_mem_ptr ,
int extra_mem_size )
2005-04-16 15:20:36 -07:00
{
struct mtd_partition * parts ;
2012-11-01 13:58:17 +08:00
unsigned long long size , offset = OFFSET_CONTINUOUS ;
2005-04-16 15:20:36 -07:00
char * name ;
int name_len ;
unsigned char * extra_mem ;
char delim ;
2020-05-03 17:53:40 +02:00
unsigned int mask_flags , add_flags ;
2005-04-16 15:20:36 -07:00
/* fetch the partition size */
2012-09-03 09:33:32 +03:00
if ( * s = = ' - ' ) {
/* assign all remaining space to this partition */
2005-04-16 15:20:36 -07:00
size = SIZE_REMAINING ;
s + + ;
2012-09-03 09:33:32 +03:00
} else {
2005-04-16 15:20:36 -07:00
size = memparse ( s , & s ) ;
2015-06-19 13:10:06 -07:00
if ( ! size ) {
2015-06-19 13:10:07 -07:00
pr_err ( " partition has size 0 \n " ) ;
2012-09-02 13:54:14 +03:00
return ERR_PTR ( - EINVAL ) ;
2005-04-16 15:20:36 -07:00
}
}
/* fetch partition name and flags */
mask_flags = 0 ; /* this is going to be a regular partition */
2020-05-03 17:53:40 +02:00
add_flags = 0 ;
2005-04-16 15:20:36 -07:00
delim = 0 ;
2012-09-03 09:33:32 +03:00
/* check for offset */
if ( * s = = ' @ ' ) {
s + + ;
offset = memparse ( s , & s ) ;
}
/* now look for name */
2005-04-16 15:20:36 -07:00
if ( * s = = ' ( ' )
delim = ' ) ' ;
2005-11-07 11:15:26 +00:00
2012-09-03 09:33:32 +03:00
if ( delim ) {
2005-04-16 15:20:36 -07:00
char * p ;
2012-09-03 09:33:32 +03:00
name = + + s ;
2008-04-14 17:20:04 +03:00
p = strchr ( name , delim ) ;
2012-09-03 09:33:32 +03:00
if ( ! p ) {
2015-06-19 13:10:07 -07:00
pr_err ( " no closing %c found in partition name \n " , delim ) ;
2012-09-02 13:54:14 +03:00
return ERR_PTR ( - EINVAL ) ;
2005-04-16 15:20:36 -07:00
}
name_len = p - name ;
s = p + 1 ;
2012-09-03 09:33:32 +03:00
} else {
name = NULL ;
2005-04-16 15:20:36 -07:00
name_len = 13 ; /* Partition_000 */
}
2005-11-07 11:15:26 +00:00
2005-04-16 15:20:36 -07:00
/* record name length for memory allocation later */
extra_mem_size + = name_len + 1 ;
2012-09-03 09:33:32 +03:00
/* test for options */
if ( strncmp ( s , " ro " , 2 ) = = 0 ) {
2005-04-16 15:20:36 -07:00
mask_flags | = MTD_WRITEABLE ;
s + = 2 ;
2012-09-03 09:33:32 +03:00
}
2005-04-16 15:20:36 -07:00
2012-09-03 09:33:32 +03:00
/* if lk is found do NOT unlock the MTD partition*/
if ( strncmp ( s , " lk " , 2 ) = = 0 ) {
2008-01-30 10:25:49 -08:00
mask_flags | = MTD_POWERUP_LOCK ;
s + = 2 ;
2012-09-03 09:33:32 +03:00
}
2008-01-30 10:25:49 -08:00
2020-05-03 17:53:40 +02:00
/* if slc is found use emulated SLC mode on this partition*/
if ( ! strncmp ( s , " slc " , 3 ) ) {
add_flags | = MTD_SLC_ON_MLC_EMULATION ;
s + = 3 ;
}
2005-04-16 15:20:36 -07:00
/* test if more partitions are following */
2012-09-03 09:33:32 +03:00
if ( * s = = ' , ' ) {
if ( size = = SIZE_REMAINING ) {
2015-06-19 13:10:07 -07:00
pr_err ( " no partitions allowed after a fill-up partition \n " ) ;
2012-09-02 13:54:14 +03:00
return ERR_PTR ( - EINVAL ) ;
2005-04-16 15:20:36 -07:00
}
/* more partitions follow, parse them */
2008-04-14 17:20:04 +03:00
parts = newpart ( s + 1 , & s , num_parts , this_part + 1 ,
& extra_mem , extra_mem_size ) ;
2012-09-02 13:54:14 +03:00
if ( IS_ERR ( parts ) )
return parts ;
2012-09-03 09:33:32 +03:00
} else {
/* this is the last partition: allocate space for all */
2005-04-16 15:20:36 -07:00
int alloc_size ;
* num_parts = this_part + 1 ;
alloc_size = * num_parts * sizeof ( struct mtd_partition ) +
extra_mem_size ;
2012-09-03 09:33:32 +03:00
2006-11-15 21:10:29 +02:00
parts = kzalloc ( alloc_size , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( ! parts )
2012-09-02 13:54:14 +03:00
return ERR_PTR ( - ENOMEM ) ;
2005-04-16 15:20:36 -07:00
extra_mem = ( unsigned char * ) ( parts + * num_parts ) ;
}
2012-09-03 09:33:32 +03:00
2018-05-22 17:07:53 +02:00
/*
* enter this partition ( offset will be calculated later if it is
* OFFSET_CONTINUOUS at this point )
*/
2005-04-16 15:20:36 -07:00
parts [ this_part ] . size = size ;
parts [ this_part ] . offset = offset ;
parts [ this_part ] . mask_flags = mask_flags ;
2020-05-03 17:53:40 +02:00
parts [ this_part ] . add_flags = add_flags ;
2005-04-16 15:20:36 -07:00
if ( name )
2022-08-18 23:00:33 +02:00
strscpy ( extra_mem , name , name_len + 1 ) ;
2005-04-16 15:20:36 -07:00
else
sprintf ( extra_mem , " Partition_%03d " , this_part ) ;
parts [ this_part ] . name = extra_mem ;
extra_mem + = name_len + 1 ;
2009-06-24 18:39:09 -03:00
dbg ( ( " partition %d: name <%s>, offset %llx, size %llx, mask flags %x \n " ,
2012-09-03 09:33:32 +03:00
this_part , parts [ this_part ] . name , parts [ this_part ] . offset ,
parts [ this_part ] . size , parts [ this_part ] . mask_flags ) ) ;
2005-04-16 15:20:36 -07:00
/* return (updated) pointer to extra_mem memory */
if ( extra_mem_ptr )
2012-09-03 09:33:32 +03:00
* extra_mem_ptr = extra_mem ;
2005-04-16 15:20:36 -07:00
/* return (updated) pointer command line string */
* retptr = s ;
/* return partition table */
return parts ;
}
2005-11-07 11:15:26 +00:00
/*
* Parse the command line .
2005-04-16 15:20:36 -07:00
*/
static int mtdpart_setup_real ( char * s )
{
cmdline_parsed = 1 ;
for ( ; s ! = NULL ; )
{
struct cmdline_mtd_partition * this_mtd ;
struct mtd_partition * parts ;
2012-09-03 09:33:32 +03:00
int mtd_id_len , num_parts ;
mtd: parser: cmdline: Fix parsing of part-names with colons
Some devices (especially QCA ones) are already using hardcoded partition
names with colons in it. The OpenMesh A62 for example provides following
mtd relevant information via cmdline:
root=31:11 mtdparts=spi0.0:256k(0:SBL1),128k(0:MIBIB),384k(0:QSEE),64k(0:CDT),64k(0:DDRPARAMS),64k(0:APPSBLENV),512k(0:APPSBL),64k(0:ART),64k(custom),64k(0:KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive) rootfsname=rootfs rootwait
The change to split only on the last colon between mtd-id and partitions
will cause newpart to see following string for the first partition:
KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive)
Such a partition list cannot be parsed and thus the device fails to boot.
Avoid this behavior by making sure that the start of the first part-name
("(") will also be the last byte the mtd-id split algorithm is using for
its colon search.
Fixes: eb13fa022741 ("mtd: parser: cmdline: Support MTD names containing one or more colons")
Cc: stable@vger.kernel.org
Cc: Ron Minnich <rminnich@google.com>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20201124062506.185392-1-sven@narfation.org
2020-11-24 07:25:06 +01:00
char * p , * mtd_id , * semicol , * open_parenth ;
2020-04-29 09:53:47 -07:00
/*
* Replace the first ' ; ' by a NULL char so strrchr can work
* properly .
*/
semicol = strchr ( s , ' ; ' ) ;
if ( semicol )
* semicol = ' \0 ' ;
2005-04-16 15:20:36 -07:00
mtd: parser: cmdline: Fix parsing of part-names with colons
Some devices (especially QCA ones) are already using hardcoded partition
names with colons in it. The OpenMesh A62 for example provides following
mtd relevant information via cmdline:
root=31:11 mtdparts=spi0.0:256k(0:SBL1),128k(0:MIBIB),384k(0:QSEE),64k(0:CDT),64k(0:DDRPARAMS),64k(0:APPSBLENV),512k(0:APPSBL),64k(0:ART),64k(custom),64k(0:KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive) rootfsname=rootfs rootwait
The change to split only on the last colon between mtd-id and partitions
will cause newpart to see following string for the first partition:
KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive)
Such a partition list cannot be parsed and thus the device fails to boot.
Avoid this behavior by making sure that the start of the first part-name
("(") will also be the last byte the mtd-id split algorithm is using for
its colon search.
Fixes: eb13fa022741 ("mtd: parser: cmdline: Support MTD names containing one or more colons")
Cc: stable@vger.kernel.org
Cc: Ron Minnich <rminnich@google.com>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20201124062506.185392-1-sven@narfation.org
2020-11-24 07:25:06 +01:00
/*
* make sure that part - names with " : " will not be handled as
* part of the mtd - id with an " : "
*/
open_parenth = strchr ( s , ' ( ' ) ;
if ( open_parenth )
* open_parenth = ' \0 ' ;
2012-09-03 09:33:32 +03:00
mtd_id = s ;
2020-04-29 09:53:47 -07:00
/*
* fetch < mtd - id > . We use strrchr to ignore all ' : ' that could
* be present in the MTD name , only the last one is interpreted
* as an < mtd - id > / < part - definition > separator .
*/
p = strrchr ( s , ' : ' ) ;
mtd: parser: cmdline: Fix parsing of part-names with colons
Some devices (especially QCA ones) are already using hardcoded partition
names with colons in it. The OpenMesh A62 for example provides following
mtd relevant information via cmdline:
root=31:11 mtdparts=spi0.0:256k(0:SBL1),128k(0:MIBIB),384k(0:QSEE),64k(0:CDT),64k(0:DDRPARAMS),64k(0:APPSBLENV),512k(0:APPSBL),64k(0:ART),64k(custom),64k(0:KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive) rootfsname=rootfs rootwait
The change to split only on the last colon between mtd-id and partitions
will cause newpart to see following string for the first partition:
KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive)
Such a partition list cannot be parsed and thus the device fails to boot.
Avoid this behavior by making sure that the start of the first part-name
("(") will also be the last byte the mtd-id split algorithm is using for
its colon search.
Fixes: eb13fa022741 ("mtd: parser: cmdline: Support MTD names containing one or more colons")
Cc: stable@vger.kernel.org
Cc: Ron Minnich <rminnich@google.com>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20201124062506.185392-1-sven@narfation.org
2020-11-24 07:25:06 +01:00
/* Restore the '(' now. */
if ( open_parenth )
* open_parenth = ' ( ' ;
2020-04-29 09:53:47 -07:00
/* Restore the ';' now. */
if ( semicol )
* semicol = ' ; ' ;
2012-09-03 09:33:32 +03:00
if ( ! p ) {
2015-06-19 13:10:07 -07:00
pr_err ( " no mtd-id \n " ) ;
2012-09-02 13:54:14 +03:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
mtd_id_len = p - mtd_id ;
dbg ( ( " parsing <%s> \n " , p + 1 ) ) ;
2005-11-07 11:15:26 +00:00
/*
2005-04-16 15:20:36 -07:00
* 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 */
2005-11-07 11:15:26 +00:00
mtd_id_len + 1 + sizeof ( * this_mtd ) +
2005-06-07 16:04:29 +01:00
sizeof ( void * ) - 1 /*alignment*/ ) ;
2012-09-03 09:33:32 +03:00
if ( IS_ERR ( parts ) ) {
2005-04-16 15:20:36 -07:00
/*
* 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
*/
2012-09-02 13:54:14 +03:00
return PTR_ERR ( parts ) ;
2005-04-16 15:20:36 -07:00
}
2005-06-07 16:04:29 +01:00
/* align this_mtd */
2005-11-07 11:15:26 +00:00
this_mtd = ( struct cmdline_mtd_partition * )
2012-09-03 09:33:32 +03:00
ALIGN ( ( unsigned long ) this_mtd , sizeof ( void * ) ) ;
2005-11-07 11:15:26 +00:00
/* enter results */
2005-04-16 15:20:36 -07:00
this_mtd - > parts = parts ;
this_mtd - > num_parts = num_parts ;
this_mtd - > mtd_id = ( char * ) ( this_mtd + 1 ) ;
2022-08-18 23:00:33 +02:00
strscpy ( this_mtd - > mtd_id , mtd_id , mtd_id_len + 1 ) ;
2005-04-16 15:20:36 -07:00
/* link into chain */
2005-11-07 11:15:26 +00:00
this_mtd - > next = partitions ;
2005-04-16 15:20:36 -07:00
partitions = this_mtd ;
2005-11-07 11:15:26 +00:00
dbg ( ( " mtdid=<%s> num_parts=<%d> \n " ,
2005-04-16 15:20:36 -07:00
this_mtd - > mtd_id , this_mtd - > num_parts ) ) ;
2005-11-07 11:15:26 +00:00
2005-04-16 15:20:36 -07:00
/* EOS - we're done */
if ( * s = = 0 )
break ;
/* does another spec follow? */
2012-09-03 09:33:32 +03:00
if ( * s ! = ' ; ' ) {
2015-06-19 13:10:07 -07:00
pr_err ( " bad character after partition (%c) \n " , * s ) ;
2012-09-02 13:54:14 +03:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
s + + ;
}
2012-09-03 09:33:32 +03:00
2012-09-02 13:54:14 +03:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
/*
* 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 .
*/
2005-11-07 11:15:26 +00:00
static int parse_cmdline_partitions ( struct mtd_info * master ,
2015-12-04 15:25:14 -08:00
const struct mtd_partition * * pparts ,
2011-06-10 18:18:28 +04:00
struct mtd_part_parser_data * data )
2005-04-16 15:20:36 -07:00
{
2012-11-01 13:58:17 +08:00
unsigned long long offset ;
2012-09-02 13:54:14 +03:00
int i , err ;
2005-04-16 15:20:36 -07:00
struct cmdline_mtd_partition * part ;
2008-07-08 17:09:03 +01:00
const char * mtd_id = master - > name ;
2005-04-16 15:20:36 -07:00
/* parse command line */
2012-09-02 13:54:14 +03:00
if ( ! cmdline_parsed ) {
err = mtdpart_setup_real ( cmdline ) ;
if ( err )
return err ;
}
2005-04-16 15:20:36 -07:00
2012-09-23 09:52:29 +02:00
/*
* Search for the partition definition matching master - > name .
* If master - > name is not set , stop at first partition definition .
*/
2012-09-03 09:33:32 +03:00
for ( part = partitions ; part ; part = part - > next ) {
2012-09-23 09:52:29 +02:00
if ( ( ! mtd_id ) | | ( ! strcmp ( part - > mtd_id , mtd_id ) ) )
break ;
}
if ( ! part )
return 0 ;
for ( i = 0 , offset = 0 ; i < part - > num_parts ; i + + ) {
if ( part - > parts [ i ] . offset = = OFFSET_CONTINUOUS )
part - > parts [ i ] . offset = offset ;
else
offset = part - > parts [ i ] . offset ;
if ( part - > parts [ i ] . size = = SIZE_REMAINING )
part - > parts [ i ] . size = master - > size - offset ;
2012-12-16 19:59:30 -05:00
if ( offset + part - > parts [ i ] . size > master - > size ) {
2015-06-19 13:10:07 -07:00
pr_warn ( " %s: partitioning exceeds flash size, truncating \n " ,
part - > mtd_id ) ;
2012-12-16 19:59:30 -05:00
part - > parts [ i ] . size = master - > size - offset ;
}
offset + = part - > parts [ i ] . size ;
2012-09-23 09:52:29 +02:00
if ( part - > parts [ i ] . size = = 0 ) {
2015-06-19 13:10:07 -07:00
pr_warn ( " %s: skipping zero sized partition \n " ,
part - > mtd_id ) ;
2012-09-23 09:52:29 +02:00
part - > num_parts - - ;
memmove ( & part - > parts [ i ] , & part - > parts [ i + 1 ] ,
sizeof ( * part - > parts ) * ( part - > num_parts - i ) ) ;
2012-12-16 19:59:29 -05:00
i - - ;
2005-04-16 15:20:36 -07:00
}
}
2012-09-03 09:33:32 +03:00
2012-09-23 09:52:29 +02:00
* pparts = kmemdup ( part - > parts , sizeof ( * part - > parts ) * part - > num_parts ,
GFP_KERNEL ) ;
if ( ! * pparts )
return - ENOMEM ;
return part - > num_parts ;
2005-04-16 15:20:36 -07:00
}
2005-11-07 11:15:26 +00:00
/*
* This is the handler for our kernel parameter , called from
2005-04-16 15:20:36 -07:00
* main . c : : checksetup ( ) . Note that we can not yet kmalloc ( ) anything ,
* so we only save the commandline for later processing .
*
* This function needs to be visible for bootloaders .
*/
2013-01-16 02:12:49 +01:00
static int __init mtdpart_setup ( char * s )
2005-04-16 15:20:36 -07:00
{
cmdline = s ;
return 1 ;
}
__setup ( " mtdparts= " , mtdpart_setup ) ;
static struct mtd_part_parser cmdline_parser = {
. parse_fn = parse_cmdline_partitions ,
. name = " cmdlinepart " ,
} ;
static int __init cmdline_parser_init ( void )
{
2013-01-16 02:12:49 +01:00
if ( mtdparts )
mtdpart_setup ( mtdparts ) ;
2013-12-01 19:01:06 +08:00
register_mtd_parser ( & cmdline_parser ) ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2013-01-16 02:12:50 +01:00
static void __exit cmdline_parser_exit ( void )
{
deregister_mtd_parser ( & cmdline_parser ) ;
}
2005-04-16 15:20:36 -07:00
module_init ( cmdline_parser_init ) ;
2013-01-16 02:12:50 +01:00
module_exit ( cmdline_parser_exit ) ;
2005-04-16 15:20:36 -07:00
2013-01-16 02:12:49 +01:00
MODULE_PARM_DESC ( mtdparts , " Partitioning specification " ) ;
module_param ( mtdparts , charp , 0 ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Marius Groeger <mag@sysgo.de> " ) ;
MODULE_DESCRIPTION ( " Command line configuration of MTD partitions " ) ;