cmdline.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: cmdline.c,v 1.3 2002/06/20 18:07:49 jamey Exp $
  3.  *
  4.  * Read flash partition table from command line
  5.  *
  6.  * Copyright 2002 SYSGO Real-Time Solutions GmbH
  7.  *
  8.  * The format for the command line is as follows:
  9.  * 
  10.  * mtdparts=<mtddef>[;<mtddef]
  11.  * <mtddef>  := <mtd-id>:<partdef>[,<partdef>]
  12.  * <partdef> := <size>[@offset][<name>][ro]
  13.  * <mtd-id>  := unique id used in mapping driver/device
  14.  * <size>    := standard linux memsize OR "-" to denote all remaining space
  15.  * <name>    := '(' NAME ')'
  16.  * 
  17.  * Examples:
  18.  * 
  19.  * 1 NOR Flash, with 1 single writable partition:
  20.  * edb7312-nor:-
  21.  * 
  22.  * 1 NOR Flash with 2 partitions, 1 NAND with one
  23.  * edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
  24.  */
  25. #include <linux/kernel.h>
  26. #include <linux/slab.h>
  27. #include <linux/mtd/mtd.h>
  28. #include <linux/mtd/partitions.h>
  29. #include <asm/setup.h>
  30. #include <linux/bootmem.h>
  31. /* error message prefix */
  32. #define ERRP "mtd: "
  33. /* debug macro */
  34. #if 0
  35. #define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
  36. #else
  37. #define dbg(x)
  38. #endif
  39. /* special size referring to all the remaining space in a partition */
  40. #define SIZE_REMAINING 0xffffffff
  41. struct cmdline_mtd_partition {
  42. struct cmdline_mtd_partition *next;
  43. char *mtd_id;
  44. int num_parts;
  45. struct mtd_partition *parts;
  46. };
  47. /* mtdpart_setup() parses into here */
  48. static struct cmdline_mtd_partition *partitions;
  49. /* the command line passed to mtdpart_setupd() */
  50. static char *cmdline;
  51. static int cmdline_parsed = 0;
  52. /*
  53.  * Parse one partition definition for an MTD. Since there can be many
  54.  * comma separated partition definitions, this function calls itself 
  55.  * recursively until no more partition definitions are found. Nice side
  56.  * effect: the memory to keep the mtd_partition structs and the names
  57.  * is allocated upon the last definition being found. At that point the
  58.  * syntax has been verified ok.
  59.  */
  60. static struct mtd_partition * newpart(char *s, 
  61.                                       char **retptr,
  62.                                       int *num_parts,
  63.                                       int this_part, 
  64.                                       unsigned char **extra_mem_ptr, 
  65.                                       int extra_mem_size)
  66. {
  67. struct mtd_partition *parts;
  68. unsigned long size;
  69. unsigned long offset = 0;
  70. char *name;
  71. int name_len;
  72. unsigned char *extra_mem;
  73. char delim;
  74. unsigned int mask_flags;
  75. /* fetch the partition size */
  76. if (*s == '-')
  77. { /* assign all remaining space to this partition */
  78. size = SIZE_REMAINING;
  79. s++;
  80. }
  81. else
  82. {
  83. size = memparse(s, &s);
  84. if (size < PAGE_SIZE)
  85. {
  86. printk(KERN_ERR ERRP "partition size too small (%lx)n", size);
  87. return 0;
  88. }
  89. }
  90. /* fetch partition name and flags */
  91. mask_flags = 0; /* this is going to be a regular partition */
  92. delim = 0;
  93.         /* check for offset */
  94.         if (*s == '@') 
  95. {
  96.            s++;
  97.            offset = memparse(s, &s);
  98.         }
  99.         /* now look for name */
  100. if (*s == '(')
  101. {
  102. delim = ')';
  103. }
  104. if (delim)
  105. {
  106. char *p;
  107.      name = ++s;
  108. if ((p = strchr(name, delim)) == 0)
  109. {
  110. printk(KERN_ERR ERRP "no closing %c found in partition namen", delim);
  111. return 0;
  112. }
  113. name_len = p - name;
  114. s = p + 1;
  115. }
  116. else
  117. {
  118.      name = NULL;
  119. name_len = 13; /* Partition_000 */
  120. }
  121.    
  122. /* record name length for memory allocation later */
  123. extra_mem_size += name_len + 1;
  124.         /* test for options */
  125.         if (strncmp(s, "ro", 2) == 0) 
  126. {
  127. mask_flags |= MTD_WRITEABLE;
  128. s += 2;
  129.         }
  130. /* test if more partitions are following */
  131. if (*s == ',')
  132. {
  133. if (size == SIZE_REMAINING)
  134. {
  135. printk(KERN_ERR ERRP "no partitions allowed after a fill-up partitionn");
  136. return 0;
  137. }
  138. /* more partitions follow, parse them */
  139. if ((parts = newpart(s + 1, &s, num_parts, 
  140.                      this_part + 1, &extra_mem, extra_mem_size)) == 0)
  141.   return 0;
  142. }
  143. else
  144. { /* this is the last partition: allocate space for all */
  145. int alloc_size;
  146. *num_parts = this_part + 1;
  147. alloc_size = *num_parts * sizeof(struct mtd_partition) +
  148.      extra_mem_size;
  149. parts = kmalloc(alloc_size, GFP_KERNEL);
  150. if (!parts)
  151. {
  152. printk(KERN_ERR ERRP "out of memoryn");
  153. return 0;
  154. }
  155. memset(parts, 0, alloc_size);
  156. extra_mem = (unsigned char *)(parts + *num_parts);
  157. }
  158. /* enter this partition (offset will be calculated later if it is zero at this point) */
  159. parts[this_part].size = size;
  160. parts[this_part].offset = offset;
  161. parts[this_part].mask_flags = mask_flags;
  162. if (name)
  163. {
  164. strncpy(extra_mem, name, name_len);
  165. extra_mem[name_len] = 0;
  166. }
  167. else
  168. {
  169. sprintf(extra_mem, "Partition_%03d", this_part);
  170. }
  171. parts[this_part].name = extra_mem;
  172. extra_mem += name_len + 1;
  173. dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %xn",
  174.      this_part, 
  175.      parts[this_part].name,
  176.      parts[this_part].offset,
  177.      parts[this_part].size,
  178.      parts[this_part].mask_flags));
  179. /* return (updated) pointer to extra_mem memory */
  180. if (extra_mem_ptr)
  181.   *extra_mem_ptr = extra_mem;
  182. /* return (updated) pointer command line string */
  183. *retptr = s;
  184. /* return partition table */
  185. return parts;
  186. }
  187. /* 
  188.  * Parse the command line. 
  189.  */
  190. static int mtdpart_setup_real(char *s)
  191. {
  192. cmdline_parsed = 1;
  193. for( ; s != NULL; )
  194. {
  195. struct cmdline_mtd_partition *this_mtd;
  196. struct mtd_partition *parts;
  197.      int mtd_id_len;
  198. int num_parts;
  199. char *p, *mtd_id;
  200.      mtd_id = s;
  201. /* fetch <mtd-id> */
  202. if (!(p = strchr(s, ':')))
  203. {
  204. printk(KERN_ERR ERRP "no mtd-idn");
  205. return 0;
  206. }
  207. mtd_id_len = p - mtd_id;
  208. dbg(("parsing <%s>n", p+1));
  209. /* 
  210.  * parse one mtd. have it reserve memory for the
  211.  * struct cmdline_mtd_partition and the mtd-id string.
  212.  */
  213. parts = newpart(p + 1, /* cmdline */
  214. &s, /* out: updated cmdline ptr */
  215. &num_parts, /* out: number of parts */
  216. 0, /* first partition */
  217. (unsigned char**)&this_mtd, /* out: extra mem */
  218. mtd_id_len + 1 + sizeof(*this_mtd));
  219. /* enter results */     
  220. this_mtd->parts = parts;
  221. this_mtd->num_parts = num_parts;
  222. this_mtd->mtd_id = (char*)(this_mtd + 1);
  223. strncpy(this_mtd->mtd_id, mtd_id, mtd_id_len);
  224. this_mtd->mtd_id[mtd_id_len] = 0;
  225. /* link into chain */
  226. this_mtd->next = partitions;     
  227. partitions = this_mtd;
  228. dbg(("mtdid=<%s> num_parts=<%d>n", 
  229.      this_mtd->mtd_id, this_mtd->num_parts));
  230. /* EOS - we're done */
  231. if (*s == 0)
  232. break;
  233. /* does another spec follow? */
  234. if (*s != ';')
  235. {
  236. printk(KERN_ERR ERRP "bad character after partition (%c)n", *s);
  237. return 0;
  238. }
  239. s++;
  240. }
  241. return 1;
  242. }
  243. /*
  244.  * Main function to be called from the MTD mapping driver/device to
  245.  * obtain the partitioning information. At this point the command line
  246.  * arguments will actually be parsed and turned to struct mtd_partition
  247.  * information.
  248.  */
  249. int parse_cmdline_partitions(struct mtd_info *master, 
  250.                              struct mtd_partition **pparts,
  251.                              const char *mtd_id)
  252. {
  253. unsigned long offset;
  254. int i;
  255. struct cmdline_mtd_partition *part;
  256. /* parse command line */
  257. if (!cmdline_parsed)
  258. mtdpart_setup_real(cmdline);
  259. for(part = partitions; part; part = part->next)
  260. {
  261. if (!strcmp(part->mtd_id, mtd_id))
  262. {
  263. for(i = 0, offset = 0; i < part->num_parts; i++)
  264. {
  265. if (!part->parts[i].offset)
  266.   part->parts[i].offset = offset;
  267. else
  268.   offset = part->parts[i].offset;
  269. if (part->parts[i].size == SIZE_REMAINING)
  270.   part->parts[i].size = master->size - offset;
  271. if (offset + part->parts[i].size > master->size)
  272. {
  273. printk(KERN_WARNING ERRP 
  274.        "%s: partitioning exceeds flash size, truncatingn",
  275.        mtd_id);
  276. part->parts[i].size = master->size - offset;
  277. part->num_parts = i;
  278. }
  279. offset += part->parts[i].size;
  280. }
  281. *pparts = part->parts;
  282. return part->num_parts;
  283. }
  284. }
  285. return -EINVAL;
  286. }
  287. /* 
  288.  * This is the handler for our kernel parameter, called from 
  289.  * main.c::checksetup(). Note that we can not yet kmalloc() anything,
  290.  * so we only save the commandline for later processing.
  291.  */
  292. static int __init mtdpart_setup(char *s)
  293. {
  294. cmdline = s;
  295. return 1;
  296. }
  297. __setup("mtdparts=", mtdpart_setup);
  298. EXPORT_SYMBOL(parse_cmdline_partitions);
  299. MODULE_LICENSE("GPL");
  300. MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
  301. MODULE_DESCRIPTION("Command line configuration of MTD partitions");