1 #include <linux/ctype.h>
2 #include "parsemtdparts.h"
3 #include <linux/string.h>
6 #include "asm/arch/sci_types.h"
7 #include "asm/arch/nand_controller.h"
8 #include <linux/mtd/mtd.h>
10 #include <linux/mtd/nand.h>
11 #include <jffs2/jffs2.h>
13 #define MTD_WRITEABLE 0x400 /* Device is writeable */
14 #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
15 #define MTD_NO_ERASE 0x1000 /* No erase necessary */
16 #define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
18 #define SIZE_REMAINING 0xffffffff
19 #define OFFSET_CONTINUOUS 0xffffffff
20 #define MTDPARTITION_MAX 40
22 struct cmdline_mtd_partition {
23 struct cmdline_mtd_partition *next;
26 struct mtd_partition *parts;
29 static struct mtd_partition realpart[MTDPARTITION_MAX];
30 static int real_current_part = MTDPARTITION_MAX;
32 /* the command line passed to mtdpart_setupd() */
34 static int cmdline_parsed = 0;
37 #define TOLOWER(x) ((x) | 0x20)
39 extern char * get_mtdparts(void);
41 static unsigned int simple_guess_base(const char *cp)
44 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
53 static unsigned long long memparse(const char *ptr, char **retptr)
55 char *endptr; /* local pointer to end of parsed string */
56 unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
79 static size_t strlcpy(char *dest, char *src, size_t size)
81 size_t ret = strlen(src);
84 size_t len = (ret >= size) ? size - 1 : ret;
85 memcpy(dest, src, len);
91 static struct mtd_partition * newpart(char *s,
95 unsigned char **extra_mem_ptr,
98 struct mtd_partition *parts;
100 unsigned long offset = OFFSET_CONTINUOUS;
103 unsigned char *extra_mem;
105 unsigned int mask_flags;
107 /* fetch the partition size */
109 { /* assign all remaining space to this partition */
110 size = SIZE_REMAINING;
115 size = memparse(s, &s);
116 if (size < PAGE_SIZE)
118 printf("partition size too small (%lx)\n", size);
123 /* fetch partition name and flags */
124 mask_flags = 0; /* this is going to be a regular partition */
126 /* check for offset */
130 offset = memparse(s, &s);
132 /* now look for name */
143 p = strchr(name, delim);
146 printf("no closing %c found in partition name\n", delim);
155 name_len = 13; /* Partition_000 */
158 /* record name length for memory allocation later */
159 extra_mem_size += name_len + 1;
161 /* test for options */
162 if (strncmp(s, "ro", 2) == 0)
164 mask_flags |= MTD_WRITEABLE;
168 /* if lk is found do NOT unlock the MTD partition*/
169 if (strncmp(s, "lk", 2) == 0)
171 mask_flags |= MTD_POWERUP_LOCK;
175 /* test if more partitions are following */
178 if (size == SIZE_REMAINING)
180 printf("no partitions allowed after a fill-up partition\n");
183 /* more partitions follow, parse them */
184 parts = newpart(s + 1, &s, num_parts, this_part + 1,
185 &extra_mem, extra_mem_size);
190 { /* this is the last partition: allocate space for all */
193 *num_parts = this_part + 1;
194 alloc_size = *num_parts * sizeof(struct mtd_partition) +
196 parts = (struct mtd_partition *)malloc(alloc_size);
199 printf("out of memory\n");
202 extra_mem = (unsigned char *)(parts + *num_parts);
204 /* enter this partition (offset will be calculated later if it is zero at this point) */
205 parts[this_part].size = size;
206 parts[this_part].offset = offset;
207 parts[this_part].mask_flags = mask_flags;
210 strlcpy(extra_mem, name, name_len + 1);
214 sprintf(extra_mem, "Partition_%03d", this_part);
216 parts[this_part].name = extra_mem;
217 extra_mem += name_len + 1;
219 /*printf("partition %02d: name <%14s>, offset %08x, size %08x, mask flags %08x\n",
221 parts[this_part].name,
222 parts[this_part].offset,
223 parts[this_part].size,
224 parts[this_part].mask_flags);*/
226 if (real_current_part > 0) {
227 real_current_part --;
228 realpart[real_current_part].name = parts[this_part].name;
229 realpart[real_current_part].offset = parts[this_part].offset;
230 realpart[real_current_part].size = parts[this_part].size;
231 realpart[real_current_part].mask_flags = parts[this_part].mask_flags;
233 printf("mtdparts partition is too much\n");
236 /* return (updated) pointer to extra_mem memory */
238 *extra_mem_ptr = extra_mem;
240 /* return (updated) pointer command line string */
243 /* return partition table */
248 * Parse the command line.
250 static int mtdpart_setup_real(char *s)
256 struct cmdline_mtd_partition *this_mtd;
257 struct mtd_partition *parts;
264 if (!(p = strchr(s, ':')))
266 printf("no mtd-id\n");
269 mtd_id_len = p - mtd_id;
271 //printf("\nparsing <%s>\n", p+1);
274 * parse one mtd. have it reserve memory for the
275 * struct cmdline_mtd_partition and the mtd-id string.
277 parts = newpart(p + 1, /* cmdline */
278 &s, /* out: updated cmdline ptr */
279 &num_parts, /* out: number of parts */
280 0, /* first partition */
281 (unsigned char**)&this_mtd, /* out: extra mem */
282 mtd_id_len + 1 + sizeof(*this_mtd) +
283 sizeof(void*)-1 /*alignment*/);
287 * An error occurred. We're either:
288 * a) out of memory, or
289 * b) in the middle of the partition spec
290 * Either way, this mtd is hosed and we're
291 * unlikely to succeed in parsing any more
296 //printf("mtdid=<%s> num_parts=<%d>\n", this_mtd->mtd_id, this_mtd->num_parts);
297 /* EOS - we're done */
301 /* does another spec follow? */
304 printf("bad character after partition (%c)\n", *s);
312 int parse_cmdline_partitions(unsigned long long mastersize)
315 unsigned long offset;
317 cmdline = get_mtdparts();
319 /* parse command line */
320 if (!cmdline_parsed) {
321 mtdpart_setup_real(cmdline);
323 for (i = real_current_part, offset = 0; i < MTDPARTITION_MAX; i ++) {
324 if (realpart[i].offset == OFFSET_CONTINUOUS)
325 realpart[i].offset = offset;
327 offset = realpart[i].offset;
329 if (realpart[i].size == SIZE_REMAINING)
330 realpart[i].size = mastersize - offset;
332 if (offset + realpart[i].size > mastersize) {
333 printf("partitioning exceeds flash size, truncating\n");
334 realpart[i].size = mastersize - offset;
336 offset += realpart[i].size;
339 printf("id : %02d, name : %20s, offset : 0x%08x, size : 0x%08x\n",
340 (i - real_current_part),
350 int parse_mtd_part_info(char *name,struct mtd_partition *part)
354 if (!cmdline_parsed){
355 printf("get_mtd_part_info: partition not parsed!\n");
359 for(i=MTDPARTITION_MAX;i>0;i--){
360 if(0==strcmp(name, realpart[i].name)){
361 part->offset = realpart[i].offset;
362 part->size = realpart[i].size;
363 part->name = realpart[i].name;
364 part->mask_flags = realpart[i].mask_flags;
365 //debug print,del later
366 printf("get mtd part info:debug i=%d\n",i);
371 printf("get_mtd_part_info: \"%s\" is not a mtd partition.\n",name);