/* mtdpart_setup() parses into here */ staticstruct cmdline_mtd_partition *partitions;
/* the command line passed to mtdpart_setup() */ staticchar *mtdparts; staticchar *cmdline; staticint cmdline_parsed;
/* * 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.
*/ staticstruct mtd_partition * newpart(char *s, char **retptr, int *num_parts, int this_part, unsignedchar **extra_mem_ptr, int extra_mem_size)
{ struct mtd_partition *parts; unsignedlonglong size, offset = OFFSET_CONTINUOUS; char *name; int name_len; unsignedchar *extra_mem; char delim; unsignedint mask_flags, add_flags;
/* fetch the partition size */ if (*s == '-') { /* assign all remaining space to this partition */
size = SIZE_REMAINING;
s++;
} else {
size = memparse(s, &s); if (!size) {
pr_err("partition has size 0\n"); return ERR_PTR(-EINVAL);
}
}
/* fetch partition name and flags */
mask_flags = 0; /* this is going to be a regular partition */
add_flags = 0;
delim = 0;
/* check for offset */ if (*s == '@') {
s++;
offset = memparse(s, &s);
}
/* now look for name */ if (*s == '(')
delim = ')';
if (delim) { char *p;
name = ++s;
p = strchr(name, delim); if (!p) {
pr_err("no closing %c found in partition name\n", delim); return ERR_PTR(-EINVAL);
}
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 for options */ if (strncmp(s, "ro", 2) == 0) {
mask_flags |= MTD_WRITEABLE;
s += 2;
}
/* if lk is found do NOT unlock the MTD partition*/ if (strncmp(s, "lk", 2) == 0) {
mask_flags |= MTD_POWERUP_LOCK;
s += 2;
}
/* 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;
}
/* test if more partitions are following */ if (*s == ',') { if (size == SIZE_REMAINING) {
pr_err("no partitions allowed after a fill-up partition\n"); return ERR_PTR(-EINVAL);
} /* more partitions follow, parse them */
parts = newpart(s + 1, &s, num_parts, this_part + 1,
&extra_mem, extra_mem_size); if (IS_ERR(parts)) return parts;
} else { /* this is the last partition: allocate space for all */ int alloc_size;
parts = kzalloc(alloc_size, GFP_KERNEL); if (!parts) return ERR_PTR(-ENOMEM);
extra_mem = (unsignedchar *)(parts + *num_parts);
}
/* * enter this partition (offset will be calculated later if it is * OFFSET_CONTINUOUS at this point)
*/
parts[this_part].size = size;
parts[this_part].offset = offset;
parts[this_part].mask_flags = mask_flags;
parts[this_part].add_flags = add_flags; if (name)
strscpy(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;
/* * Replace the first ';' by a NULL char so strrchr can work * properly.
*/
semicol = strchr(s, ';'); if (semicol)
*semicol = '\0';
/* * 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';
mtd_id = s;
/* * 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, ':');
/* Restore the '(' now. */ if (open_parenth)
*open_parenth = '(';
/* Restore the ';' now. */ if (semicol)
*semicol = ';';
if (!p) {
pr_err("no mtd-id\n"); return -EINVAL;
}
mtd_id_len = p - mtd_id;
pr_debug("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 */
(unsignedchar**)&this_mtd, /* out: extra mem */
mtd_id_len + 1 + sizeof(*this_mtd) + sizeof(void*)-1 /*alignment*/); if (IS_ERR(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 PTR_ERR(parts);
}
/* does another spec follow? */ if (*s != ';') {
pr_err("bad character after partition (%c)\n", *s); return -EINVAL;
}
s++;
}
return 0;
}
/* * 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.
*/ staticint parse_cmdline_partitions(struct mtd_info *master, conststruct mtd_partition **pparts, struct mtd_part_parser_data *data)
{ unsignedlonglong offset; int i, err; struct cmdline_mtd_partition *part; constchar *mtd_id = master->name;
/* parse command line */ if (!cmdline_parsed) {
err = mtdpart_setup_real(cmdline); if (err) return err;
}
/* * Search for the partition definition matching master->name. * If master->name is not set, stop at first partition definition.
*/ for (part = partitions; part; part = part->next) { 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;
/* * This is the handler for our kernel parameter, called from * 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.
*/ staticint __init mtdpart_setup(char *s)
{
cmdline = s; return 1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.