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>
12 #define MTD_WRITEABLE 0x400 /* Device is writeable */
13 #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
14 #define MTD_NO_ERASE 0x1000 /* No erase necessary */
15 #define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
17 #define SIZE_REMAINING 0xffffffff
18 #define OFFSET_CONTINUOUS 0xffffffff
19 #define MTDPARTITION_MAX 40
21 struct cmdline_mtd_partition {
22 struct cmdline_mtd_partition *next;
25 struct mtd_partition *parts;
28 static struct mtd_partition realpart[MTDPARTITION_MAX];
29 static char realpartname[MTDPARTITION_MAX][255];
30 static int 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 static unsigned int simple_guess_base(const char *cp)
42 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
51 static unsigned long long memparse(const char *ptr, char **retptr)
53 char *endptr; /* local pointer to end of parsed string */
54 unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
77 static size_t strlcpy(char *dest, char *src, size_t size)
79 size_t ret = strlen(src);
82 size_t len = (ret >= size) ? size - 1 : ret;
83 memcpy(dest, src, len);
89 static struct mtd_partition * newpart(char *s,
93 unsigned char **extra_mem_ptr,
96 struct mtd_partition *parts;
98 unsigned long offset = OFFSET_CONTINUOUS;
101 unsigned char *extra_mem;
103 unsigned int mask_flags;
105 /* fetch the partition size */
107 { /* assign all remaining space to this partition */
108 size = SIZE_REMAINING;
113 size = memparse(s, &s);
114 if (size < PAGE_SIZE)
116 printf("partition size too small (%lx)\n", size);
121 /* fetch partition name and flags */
122 mask_flags = 0; /* this is going to be a regular partition */
124 /* check for offset */
128 offset = memparse(s, &s);
130 /* now look for name */
141 p = strchr(name, delim);
144 printf("no closing %c found in partition name\n", delim);
153 name_len = 13; /* Partition_000 */
156 /* record name length for memory allocation later */
157 extra_mem_size += name_len + 1;
159 /* test for options */
160 if (strncmp(s, "ro", 2) == 0)
162 mask_flags |= MTD_WRITEABLE;
166 /* if lk is found do NOT unlock the MTD partition*/
167 if (strncmp(s, "lk", 2) == 0)
169 mask_flags |= MTD_POWERUP_LOCK;
173 /* test if more partitions are following */
176 if (size == SIZE_REMAINING)
178 printf("no partitions allowed after a fill-up partition\n");
181 /* more partitions follow, parse them */
182 parts = newpart(s + 1, &s, num_parts, this_part + 1,
183 &extra_mem, extra_mem_size);
188 { /* this is the last partition: allocate space for all */
191 *num_parts = this_part + 1;
192 alloc_size = *num_parts * sizeof(struct mtd_partition) +
194 parts = (struct mtd_partition *)malloc(alloc_size);
197 printf("out of memory\n");
200 extra_mem = (unsigned char *)(parts + *num_parts);
202 /* enter this partition (offset will be calculated later if it is zero at this point) */
203 parts[this_part].size = size;
204 parts[this_part].offset = offset;
205 parts[this_part].mask_flags = mask_flags;
208 strlcpy(extra_mem, name, name_len + 1);
212 sprintf(extra_mem, "Partition_%03d", this_part);
214 parts[this_part].name = extra_mem;
215 extra_mem += name_len + 1;
217 /*printf("partition %02d: name <%14s>, offset %08x, size %08x, mask flags %08x\n",
219 parts[this_part].name,
220 parts[this_part].offset,
221 parts[this_part].size,
222 parts[this_part].mask_flags);*/
224 if (current_part >= 0) {
226 memset(&(realpartname[current_part]), 0, 255);
227 strcpy(realpartname[current_part], parts[this_part].name);
228 realpart[current_part].name = realpartname[current_part];
229 //printf("realname = %14s partname = %14s\n", realpart[current_part].name, parts[this_part].name);
230 realpart[current_part].offset = parts[this_part].offset;
231 realpart[current_part].size = parts[this_part].size;
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 char * get_mtdparts(void);
313 int yaffs_parse_cmdline_partitions(struct mtd_partition *current, unsigned long long mastersize)
315 unsigned long offset;
317 struct cmdline_mtd_partition *part;
319 cmdline = get_mtdparts();
321 /* parse command line */
322 if (!cmdline_parsed) {
323 mtdpart_setup_real(cmdline);
325 for (i = current_part, offset = 0; i < MTDPARTITION_MAX; i ++) {
326 if (realpart[i].offset == OFFSET_CONTINUOUS)
327 realpart[i].offset = offset;
329 offset = realpart[i].offset;
331 if (realpart[i].size == SIZE_REMAINING)
332 realpart[i].size = mastersize - offset;
334 if (offset + realpart[i].size > mastersize) {
335 printf("partitioning exceeds flash size, truncating\n");
336 realpart[i].size = mastersize - offset;
338 offset += realpart[i].size;
341 /*printf("realpart %02d : offset %08x, size %08x name %14s\n",
350 for (i = current_part; i < MTDPARTITION_MAX; i ++) {
351 if (realpart[i].offset == current->offset) {
352 current->size = realpart[i].size;
353 strcpy(current->name, realpart[i].name);
357 if (strcmp(realpart[i].name, current->name) == 0) {
358 current->size = realpart[i].size;
359 current->offset = realpart[i].offset;