1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73#include <common.h>
74#include <command.h>
75#include <env.h>
76#include <flash.h>
77#include <image.h>
78#include <malloc.h>
79#include <jffs2/jffs2.h>
80#include <linux/bug.h>
81#include <linux/list.h>
82#include <linux/ctype.h>
83#include <cramfs/cramfs_fs.h>
84
85#if defined(CONFIG_CMD_NAND)
86#include <linux/mtd/rawnand.h>
87#include <nand.h>
88#endif
89
90#if defined(CONFIG_CMD_ONENAND)
91#include <linux/mtd/mtd.h>
92#include <linux/mtd/onenand.h>
93#include <onenand_uboot.h>
94#endif
95
96
97#define DEBUG_JFFS
98#undef DEBUG_JFFS
99
100#ifdef DEBUG_JFFS
101# define DEBUGF(fmt, args...) printf(fmt ,##args)
102#else
103# define DEBUGF(fmt, args...)
104#endif
105
106
107#define SIZE_REMAINING 0xFFFFFFFF
108
109
110
111
112
113#define OFFSET_NOT_SPECIFIED 0xFFFFFFFF
114
115
116#define MIN_PART_SIZE 4096
117
118
119
120#define MTD_WRITEABLE_CMD 1
121
122
123#ifdef CONFIG_CMD_MTDPARTS
124
125extern struct mtd_device *current_mtd_dev;
126extern u8 current_mtd_partnum;
127#else
128
129struct mtd_device *current_mtd_dev = NULL;
130u8 current_mtd_partnum = 0;
131#endif
132
133#if defined(CONFIG_CMD_CRAMFS)
134extern int cramfs_check (struct part_info *info);
135extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename);
136extern int cramfs_ls (struct part_info *info, char *filename);
137extern int cramfs_info (struct part_info *info);
138#else
139
140
141#define cramfs_check(x) (0)
142#define cramfs_load(x,y,z) (-1)
143#define cramfs_ls(x,y) (0)
144#define cramfs_info(x) (0)
145#endif
146
147#ifndef CONFIG_CMD_MTDPARTS
148
149
150
151
152
153
154static int mtd_device_validate(u8 type, u8 num, u32 *size)
155{
156 if (type == MTD_DEV_TYPE_NOR) {
157#if defined(CONFIG_CMD_FLASH)
158 if (num < CONFIG_SYS_MAX_FLASH_BANKS) {
159 extern flash_info_t flash_info[];
160 *size = flash_info[num].size;
161
162 return 0;
163 }
164
165 printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
166 MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1);
167#else
168 printf("support for FLASH devices not present\n");
169#endif
170 } else if (type == MTD_DEV_TYPE_NAND) {
171#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
172 struct mtd_info *mtd = get_nand_dev_by_index(num);
173 if (mtd) {
174 *size = mtd->size;
175 return 0;
176 }
177
178 printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
179 MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1);
180#else
181 printf("support for NAND devices not present\n");
182#endif
183 } else if (type == MTD_DEV_TYPE_ONENAND) {
184#if defined(CONFIG_CMD_ONENAND)
185 *size = onenand_mtd.size;
186 return 0;
187#else
188 printf("support for OneNAND devices not present\n");
189#endif
190 } else
191 printf("Unknown defice type %d\n", type);
192
193 return 1;
194}
195
196
197
198
199
200
201
202
203
204
205
206static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
207{
208 const char *p = id;
209
210 *dev_type = 0;
211 if (strncmp(p, "nand", 4) == 0) {
212 *dev_type = MTD_DEV_TYPE_NAND;
213 p += 4;
214 } else if (strncmp(p, "nor", 3) == 0) {
215 *dev_type = MTD_DEV_TYPE_NOR;
216 p += 3;
217 } else if (strncmp(p, "onenand", 7) == 0) {
218 *dev_type = MTD_DEV_TYPE_ONENAND;
219 p += 7;
220 } else {
221 printf("incorrect device type in %s\n", id);
222 return 1;
223 }
224
225 if (!isdigit(*p)) {
226 printf("incorrect device number in %s\n", id);
227 return 1;
228 }
229
230 *dev_num = simple_strtoul(p, (char **)&p, 0);
231 if (ret_id)
232 *ret_id = p;
233 return 0;
234}
235
236
237
238
239
240
241
242
243
244
245
246static inline u32 get_part_sector_size_nand(struct mtdids *id)
247{
248#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
249 struct mtd_info *mtd;
250
251 mtd = get_nand_dev_by_index(id->num);
252
253 return mtd->erasesize;
254#else
255 BUG();
256 return 0;
257#endif
258}
259
260static inline u32 get_part_sector_size_nor(struct mtdids *id, struct part_info *part)
261{
262#if defined(CONFIG_CMD_FLASH)
263 extern flash_info_t flash_info[];
264
265 u32 end_phys, start_phys, sector_size = 0, size = 0;
266 int i;
267 flash_info_t *flash;
268
269 flash = &flash_info[id->num];
270
271 start_phys = flash->start[0] + part->offset;
272 end_phys = start_phys + part->size - 1;
273
274 for (i = 0; i < flash->sector_count; i++) {
275 if (flash->start[i] >= end_phys)
276 break;
277
278 if (flash->start[i] >= start_phys) {
279 if (i == flash->sector_count - 1) {
280 size = flash->start[0] + flash->size - flash->start[i];
281 } else {
282 size = flash->start[i+1] - flash->start[i];
283 }
284
285 if (sector_size < size)
286 sector_size = size;
287 }
288 }
289
290 return sector_size;
291#else
292 BUG();
293 return 0;
294#endif
295}
296
297static inline u32 get_part_sector_size_onenand(void)
298{
299#if defined(CONFIG_CMD_ONENAND)
300 struct mtd_info *mtd;
301
302 mtd = &onenand_mtd;
303
304 return mtd->erasesize;
305#else
306 BUG();
307 return 0;
308#endif
309}
310
311static inline u32 get_part_sector_size(struct mtdids *id, struct part_info *part)
312{
313 if (id->type == MTD_DEV_TYPE_NAND)
314 return get_part_sector_size_nand(id);
315 else if (id->type == MTD_DEV_TYPE_NOR)
316 return get_part_sector_size_nor(id, part);
317 else if (id->type == MTD_DEV_TYPE_ONENAND)
318 return get_part_sector_size_onenand();
319 else
320 DEBUGF("Error: Unknown device type.\n");
321
322 return 0;
323}
324
325
326
327
328
329
330
331
332
333
334int mtdparts_init(void)
335{
336 static int initialized = 0;
337 u32 size;
338 char *dev_name;
339
340 DEBUGF("\n---mtdparts_init---\n");
341 if (!initialized) {
342 struct mtdids *id;
343 struct part_info *part;
344
345 initialized = 1;
346 current_mtd_dev = (struct mtd_device *)
347 malloc(sizeof(struct mtd_device) +
348 sizeof(struct part_info) +
349 sizeof(struct mtdids));
350 if (!current_mtd_dev) {
351 printf("out of memory\n");
352 return 1;
353 }
354 memset(current_mtd_dev, 0, sizeof(struct mtd_device) +
355 sizeof(struct part_info) + sizeof(struct mtdids));
356
357 id = (struct mtdids *)(current_mtd_dev + 1);
358 part = (struct part_info *)(id + 1);
359
360
361 id->mtd_id = "single part";
362
363#if defined(CONFIG_JFFS2_DEV)
364 dev_name = CONFIG_JFFS2_DEV;
365#else
366 dev_name = "nor0";
367#endif
368
369 if ((mtd_id_parse(dev_name, NULL, &id->type, &id->num) != 0) ||
370 (mtd_device_validate(id->type, id->num, &size) != 0)) {
371 printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num);
372 free(current_mtd_dev);
373 return 1;
374 }
375 id->size = size;
376 INIT_LIST_HEAD(&id->link);
377
378 DEBUGF("dev id: type = %d, num = %d, size = 0x%08lx, mtd_id = %s\n",
379 id->type, id->num, id->size, id->mtd_id);
380
381
382 part->name = "static";
383 part->auto_name = 0;
384
385#if defined(CONFIG_JFFS2_PART_SIZE)
386 part->size = CONFIG_JFFS2_PART_SIZE;
387#else
388 part->size = SIZE_REMAINING;
389#endif
390
391#if defined(CONFIG_JFFS2_PART_OFFSET)
392 part->offset = CONFIG_JFFS2_PART_OFFSET;
393#else
394 part->offset = 0x00000000;
395#endif
396
397 part->dev = current_mtd_dev;
398 INIT_LIST_HEAD(&part->link);
399
400
401 if (part->size == SIZE_REMAINING)
402 part->size = id->size - part->offset;
403
404 part->sector_size = get_part_sector_size(id, part);
405
406 DEBUGF("part : name = %s, size = 0x%08lx, offset = 0x%08lx\n",
407 part->name, part->size, part->offset);
408
409
410 current_mtd_dev->id = id;
411 INIT_LIST_HEAD(¤t_mtd_dev->link);
412 current_mtd_dev->num_parts = 1;
413 INIT_LIST_HEAD(¤t_mtd_dev->parts);
414 list_add(&part->link, ¤t_mtd_dev->parts);
415 }
416
417 return 0;
418}
419#endif
420
421
422
423
424
425
426
427
428
429static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num)
430{
431 struct list_head *entry;
432 struct part_info *part;
433 int num;
434
435 if (!dev)
436 return NULL;
437
438 DEBUGF("\n--- jffs2_part_info: partition number %d for device %s%d (%s)\n",
439 part_num, MTD_DEV_TYPE(dev->id->type),
440 dev->id->num, dev->id->mtd_id);
441
442 if (part_num >= dev->num_parts) {
443 printf("invalid partition number %d for device %s%d (%s)\n",
444 part_num, MTD_DEV_TYPE(dev->id->type),
445 dev->id->num, dev->id->mtd_id);
446 return NULL;
447 }
448
449
450 num = 0;
451 list_for_each(entry, &dev->parts) {
452 part = list_entry(entry, struct part_info, link);
453
454 if (part_num == num++) {
455 return part;
456 }
457 }
458
459 return NULL;
460}
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476int do_jffs2_fsload(struct cmd_tbl *cmdtp, int flag, int argc,
477 char *const argv[])
478{
479 char *fsname;
480 char *filename;
481 int size;
482 struct part_info *part;
483 ulong offset = image_load_addr;
484
485
486 filename = env_get("bootfile");
487 if (!filename)
488 filename = "uImage";
489
490 if (argc == 2) {
491 filename = argv[1];
492 }
493 if (argc == 3) {
494 offset = simple_strtoul(argv[1], NULL, 16);
495 image_load_addr = offset;
496 filename = argv[2];
497 }
498
499
500 if (mtdparts_init() !=0)
501 return 1;
502
503 if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
504
505
506 fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
507 printf("### %s loading '%s' to 0x%lx\n", fsname, filename, offset);
508
509 if (cramfs_check(part)) {
510 size = cramfs_load ((char *) offset, part, filename);
511 } else {
512
513 size = jffs2_1pass_load((char *)offset, part, filename);
514 }
515
516 if (size > 0) {
517 printf("### %s load complete: %d bytes loaded to 0x%lx\n",
518 fsname, size, offset);
519 env_set_hex("filesize", size);
520 } else {
521 printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename);
522 }
523
524 return !(size > 0);
525 }
526 return 1;
527}
528
529
530
531
532
533
534
535
536
537
538
539int do_jffs2_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
540{
541 char *filename = "/";
542 int ret;
543 struct part_info *part;
544
545 if (argc == 2)
546 filename = argv[1];
547
548
549 if (mtdparts_init() !=0)
550 return 1;
551
552 if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
553
554
555 if (cramfs_check(part)) {
556 ret = cramfs_ls (part, filename);
557 } else {
558
559 ret = jffs2_1pass_ls(part, filename);
560 }
561
562 return ret ? 0 : 1;
563 }
564 return 1;
565}
566
567
568
569
570
571
572
573
574
575
576
577int do_jffs2_fsinfo(struct cmd_tbl *cmdtp, int flag, int argc,
578 char *const argv[])
579{
580 struct part_info *part;
581 char *fsname;
582 int ret;
583
584
585 if (mtdparts_init() !=0)
586 return 1;
587
588 if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
589
590
591 fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
592 printf("### filesystem type is %s\n", fsname);
593
594 if (cramfs_check(part)) {
595 ret = cramfs_info (part);
596 } else {
597
598 ret = jffs2_1pass_info(part);
599 }
600
601 return ret ? 0 : 1;
602 }
603 return 1;
604}
605
606
607U_BOOT_CMD(
608 fsload, 3, 0, do_jffs2_fsload,
609 "load binary file from a filesystem image",
610 "[ off ] [ filename ]\n"
611 " - load binary file from flash bank\n"
612 " with offset 'off'"
613);
614U_BOOT_CMD(
615 fsls, 2, 1, do_jffs2_ls,
616 "list files in a directory (default /)",
617 "[ directory ]"
618);
619
620U_BOOT_CMD(
621 fsinfo, 1, 1, do_jffs2_fsinfo,
622 "print information about filesystems",
623 ""
624);
625
626