Tizen 2.0 Release
[platform/kernel/u-boot.git] / common / cmd_ext2.c
1 /*
2  * (C) Copyright 2004
3  * esd gmbh <www.esd-electronics.com>
4  * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
5  *
6  * made from cmd_reiserfs by
7  *
8  * (C) Copyright 2003 - 2004
9  * Sysgo Real-Time Solutions, AG <www.elinos.com>
10  * Pavel Bartusek <pba@sysgo.com>
11  *
12  * See file CREDITS for list of people who contributed to this
13  * project.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2 of
18  * the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28  * MA 02111-1307 USA
29  *
30  */
31
32 /*
33  * Ext2fs support
34  */
35 #include <common.h>
36 #include <part.h>
37 #include <config.h>
38 #include <command.h>
39 #include <image.h>
40 #include <linux/ctype.h>
41 #include <asm/byteorder.h>
42 #include <ext2fs.h>
43 #include <linux/stat.h>
44 #include "../disk/part_dos.h"
45 #include <malloc.h>
46
47 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
48 #include <usb.h>
49 #endif
50
51 #if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION)
52 #error DOS or EFI partition support must be selected
53 #endif
54
55 /* #define      EXT2_DEBUG */
56
57 #ifdef  EXT2_DEBUG
58 #define PRINTF(fmt,args...)     printf (fmt ,##args)
59 #else
60 #define PRINTF(fmt,args...)
61 #endif
62
63 static int total_sector;
64 static block_dev_desc_t *cur_dev = NULL;
65 static unsigned long part_offset = 0;
66 static unsigned long part_size = 0;
67
68 static int cur_part = 1;
69
70 #define DOS_PART_MAGIC_OFFSET   0x1fe
71 #define DOS_FS_TYPE_OFFSET      0x36
72 #define DOS_FS32_TYPE_OFFSET    0x52
73
74 /*
75  * Constants relative to the data blocks
76  */
77 #define EXT2_NDIR_BLOCKS        12
78 #define EXT2_IND_BLOCK          EXT2_NDIR_BLOCKS
79 #define EXT2_DIND_BLOCK         (EXT2_IND_BLOCK + 1)
80 #define EXT2_TIND_BLOCK         (EXT2_DIND_BLOCK + 1)
81 #define EXT2_N_BLOCKS           (EXT2_TIND_BLOCK + 1)
82
83 /*
84  * Macro-instructions used to manage several block sizes
85  */
86 #define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
87 #define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
88 #define EXT2_MIN_BLOCK_SIZE     (1 << EXT2_MIN_BLOCK_LOG_SIZE)
89 #define EXT2_MAX_BLOCK_SIZE     (1 << EXT2_MAX_BLOCK_LOG_SIZE)
90
91 #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT   0
92 #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX      1
93 /* First non-reserved inode for old ext2 filesystems */
94 #define EXT2_GOOD_OLD_FIRST_INO 11
95
96 #define SWAP_LE16(x) (x)
97 #define SWAP_LE32(x) (x)
98
99 #define EXT2_DYNAMIC_REV        1       /* V2 format w/ dynamic inode sizes */
100 #define EXT2_FEATURE_COMPAT_RESIZE_INODE        0x0010
101 #define EXT2_FEATURE_COMPAT_DIR_INDEX           0x0020
102 /*
103  * The second extended file system magic number
104  */
105 #define EXT2_SUPER_MAGIC        0xEF53
106 #define EXT2_OS_LINUX           0
107 #define EXT2_HASH_HALF_MD4      1
108
109 #define EXT2_HASH_HALF_MD4              1
110 #define EXT2_FLAGS_SIGNED_HASH          0x0001
111 #define EXT2_FLAGS_UNSIGNED_HASH        0x0002
112 #define EXT2_ROOT_INO                   2 /* Root inode */
113
114 #define EXT2_FEATURE_INCOMPAT_FILETYPE          0x0002
115 #define EXT2_FEATURE_COMPAT_SUPP                0
116 #define EXT2_DFL_MAX_MNT_COUNT                  20 /* Allow 20 mounts */
117 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER     0x0001
118
119 /*
120  * Behaviour when detecting errors
121  */
122 #define EXT2_ERRORS_DEFAULT     1
123
124 /*
125  * Ext2 directory file types.  Only the low 3 bits are used.  The
126  * other bits are reserved for now.
127  */
128 enum {
129         EXT2_FT_UNKNOWN,
130         EXT2_FT_REG_FILE,
131         EXT2_FT_DIR,
132         EXT2_FT_CHRDEV,
133         EXT2_FT_BLKDEV,
134         EXT2_FT_FIFO,
135         EXT2_FT_SOCK,
136         EXT2_FT_SYMLINK,
137         EXT2_FT_MAX
138 };
139
140 /* The ext2 superblock.  */
141 struct ext2_sblock {
142         uint32_t total_inodes;
143         uint32_t total_blocks;
144         uint32_t reserved_blocks;
145         uint32_t free_blocks;
146         uint32_t free_inodes;
147         uint32_t first_data_block;
148         uint32_t log2_block_size;
149         uint32_t log2_fragment_size;
150         uint32_t s_blocks_per_group;
151         uint32_t fragments_per_group;
152         uint32_t inodes_per_group;
153         uint32_t mtime;
154         uint32_t utime;
155         uint16_t mnt_count;
156         uint16_t max_mnt_count;
157         uint16_t magic;
158         uint16_t fs_state;
159         uint16_t error_handling;
160         uint16_t minor_revision_level;
161         uint32_t lastcheck;
162         uint32_t checkinterval;
163         uint32_t creator_os;
164         uint32_t revision_level;
165         uint16_t uid_reserved;
166         uint16_t gid_reserved;
167         uint32_t first_inode;
168         uint16_t inode_size;
169         uint16_t block_group_number;
170         uint32_t feature_compatibility;
171         uint32_t feature_incompat;
172         uint32_t feature_ro_compat;
173         uint32_t unique_id[4];
174         char volume_name[16];
175         char last_mounted_on[64];
176         uint32_t compression_info;
177 };
178
179 /*
180  * Structure of an inode on the disk
181  */
182 struct ext2_inode {
183         uint16_t i_mode;                /* File mode */
184         uint16_t i_uid;         /* Low 16 bits of Owner Uid */
185         uint32_t i_size;                /* Size in bytes */
186         uint32_t i_atime; /* Access time */
187         uint32_t i_ctime; /* Creation time */
188         uint32_t i_mtime; /* Modification time */
189         uint32_t i_dtime; /* Deletion Time */
190         uint16_t i_gid;         /* Low 16 bits of Group Id */
191         uint16_t i_links_count; /* Links count */
192         uint32_t i_blocks;      /* Blocks count */
193         uint32_t i_flags; /* File flags */
194         union {
195                 struct {
196                         uint32_t  l_i_reserved1;
197                 } linux1;
198                 struct {
199                         uint32_t  h_i_translator;
200                 } hurd1;
201                 struct {
202                         uint32_t  m_i_reserved1;
203                 } masix1;
204         } osd1;                         /* OS dependent 1 */
205         uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
206         uint32_t i_generation;  /* File version (for NFS) */
207         uint32_t i_file_acl; /* File ACL */
208         uint32_t i_dir_acl;     /* Directory ACL */
209         uint32_t i_faddr; /* Fragment address */
210         union {
211                 struct {
212                         uint8_t         l_i_frag;       /* Fragment number */
213                         uint8_t         l_i_fsize;      /* Fragment size */
214                         uint16_t i_pad1;
215                         uint16_t l_i_uid_high;  /* these 2 fields       */
216                         uint16_t l_i_gid_high;  /* were reserved2[0] */
217                         uint32_t l_i_reserved2;
218                 } linux2;
219                 struct {
220                         uint8_t         h_i_frag;       /* Fragment number */
221                         uint8_t         h_i_fsize;      /* Fragment size */
222                         uint16_t h_i_mode_high;
223                         uint16_t h_i_uid_high;
224                         uint16_t h_i_gid_high;
225                         uint32_t h_i_author;
226                 } hurd2;
227                 struct {
228                         uint8_t         m_i_frag;       /* Fragment number */
229                         uint8_t         m_i_fsize;      /* Fragment size */
230                         uint16_t m_pad1;
231                         uint32_t m_i_reserved2[2];
232                 } masix2;
233         } osd2;                         /* OS dependent 2 */
234 };
235
236 /*
237  * Structure of a blocks group descriptor
238  */
239 struct ext2_group_desc {
240         uint32_t bg_block_bitmap;       /* Blocks bitmap block */
241         uint32_t bg_inode_bitmap;       /* Inodes bitmap block */
242         uint32_t bg_inode_table;                /* Inodes table block */
243         uint16_t bg_free_blocks_count;  /* Free blocks count */
244         uint16_t bg_free_inodes_count;  /* Free inodes count */
245         uint16_t bg_used_dirs_count;    /* Directories count */
246         uint16_t bg_pad;
247         uint32_t bg_reserved[3];
248 };
249
250 // All fields are little-endian
251 struct ext2_dir {
252         uint32_t inode1;
253         uint16_t rec_len1;
254         uint8_t name_len1;
255         uint8_t file_type1;
256         char            name1[4];
257         uint32_t inode2;
258         uint16_t rec_len2;
259         uint8_t name_len2;
260         uint8_t file_type2;
261         char            name2[4];
262         uint32_t inode3;
263         uint16_t rec_len3;
264         uint8_t name_len3;
265         uint8_t file_type3;
266         char            name3[12];
267 };
268
269 #define FETCH_LE32(field) \
270         (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size())
271
272 // storage helpers
273 char BUG_wrong_field_size(void);
274 #define STORE_LE(field, value) \
275 do { \
276         if (sizeof(field) == 4) \
277                 field = SWAP_LE32(value); \
278         else if (sizeof(field) == 2) \
279                 field = SWAP_LE16(value); \
280         else if (sizeof(field) == 1) \
281                 field = (value); \
282         else \
283                 BUG_wrong_field_size(); \
284 } while (0)
285
286 int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
287 {
288         char *filename = "/";
289         int dev=0;
290         int part=1;
291         char *ep;
292         block_dev_desc_t *dev_desc=NULL;
293         int part_length;
294
295         if (argc < 3)
296                 return cmd_usage(cmdtp);
297
298         dev = (int)simple_strtoul (argv[2], &ep, 16);
299         dev_desc = get_dev(argv[1],dev);
300
301         if (dev_desc == NULL) {
302                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
303                 return 1;
304         }
305
306         if (*ep) {
307                 if (*ep != ':') {
308                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
309                         return 1;
310                 }
311                 part = (int)simple_strtoul(++ep, NULL, 16);
312         }
313
314         if (argc == 4)
315                 filename = argv[3];
316
317         PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
318
319         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
320                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
321                 ext2fs_close();
322                 return 1;
323         }
324
325         if (!ext2fs_mount(part_length)) {
326                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
327                 ext2fs_close();
328                 return 1;
329         }
330
331         if (ext2fs_ls (filename)) {
332                 printf ("** Error ext2fs_ls() **\n");
333                 ext2fs_close();
334                 return 1;
335         };
336
337         ext2fs_close();
338
339         return 0;
340 }
341
342 U_BOOT_CMD(
343         ext2ls, 4,      1,      do_ext2ls,
344         "list files in a directory (default /)",
345         "<interface> <dev[:part]> [directory]\n"
346         "    - list files from 'dev' on 'interface' in a 'directory'"
347 );
348
349 int do_ext2write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
350 {
351         block_dev_desc_t *dev_desc=NULL;
352         char *filename = "/";
353         int part_length;
354         int part=1;
355         int dev=0;
356         char *ep;
357         unsigned long ram_address;
358         unsigned long file_size;
359         disk_partition_t info;
360
361         if (argc < 6)
362                 return cmd_usage(cmdtp);
363
364         dev = (int)simple_strtoul (argv[2], &ep, 16);
365         dev_desc = get_dev(argv[1],dev);
366
367         if (dev_desc == NULL) {
368                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
369                 return 1;
370         }
371
372         if (*ep) {
373                 if (*ep != ':') {
374                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
375                         return 1;
376                 }
377                 part = (int)simple_strtoul(++ep, NULL, 16);
378         }
379
380         /*get the filename*/
381         filename = argv[3];
382
383         /*get the address in hexadecimal format (string to int)*/
384         ram_address = simple_strtoul (argv[4], NULL, 16);
385
386         /*get the filesize in base 10 format*/
387         file_size=simple_strtoul (argv[5], NULL, 10);
388
389
390         PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
391
392         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
393                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
394                 ext2fs_close();
395                 return 1;
396         }
397
398         if (ext2_register_device(dev_desc,part)!=0)
399         {
400                 printf("\n** Unable to use %s %d:%d for fattable **\n",
401                         argv[1], dev, part);
402                 return 1;
403         }
404
405         if (!get_partition_info(dev_desc, part, &info))
406         {
407                 total_sector = (info.size * info.blksz) / SECTOR_SIZE;
408         }
409         else
410         {
411                 printf("error : get partition info\n");
412                 return 1;
413         }
414         if (!ext2fs_mount(part_length)) {
415                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
416                 ext2fs_close();
417                 return 1;
418         }
419
420         if (ext2fs_write(dev_desc,part,filename,(unsigned char*)ram_address,file_size))
421         {
422                         printf ("** Error ext2fs_write() **\n");
423                         ext2fs_close();
424                         return 1;
425         }
426
427         return 0;
428 }
429
430 U_BOOT_CMD(
431         ext2write,      6,      1,      do_ext2write,
432         "create a file in the root directory",
433         "<interface> <dev[:part]> [filename] [Address] [sizebytes]\n"
434         "    - create a file in / directory"
435 );
436
437 /******************************************************************************
438  * Ext2fs boot command intepreter. Derived from diskboot
439  */
440 int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
441 {
442         char *filename = NULL;
443         char *ep;
444         int dev, part = 1;
445         ulong addr = 0, part_length;
446         int filelen;
447         disk_partition_t info;
448         block_dev_desc_t *dev_desc = NULL;
449         char buf [12];
450         unsigned long count;
451         char *addr_str;
452
453         switch (argc) {
454         case 3:
455                 addr_str = getenv("loadaddr");
456                 if (addr_str != NULL)
457                         addr = simple_strtoul (addr_str, NULL, 16);
458                 else
459                         addr = CONFIG_SYS_LOAD_ADDR;
460
461                 filename = getenv ("bootfile");
462                 count = 0;
463                 break;
464         case 4:
465                 addr = simple_strtoul (argv[3], NULL, 16);
466                 filename = getenv ("bootfile");
467                 count = 0;
468                 break;
469         case 5:
470                 addr = simple_strtoul (argv[3], NULL, 16);
471                 filename = argv[4];
472                 count = 0;
473                 break;
474         case 6:
475                 addr = simple_strtoul (argv[3], NULL, 16);
476                 filename = argv[4];
477                 count = simple_strtoul (argv[5], NULL, 16);
478                 break;
479
480         default:
481                 return cmd_usage(cmdtp);
482         }
483
484         if (!filename) {
485                 puts ("** No boot file defined **\n");
486                 return 1;
487         }
488
489         dev = (int)simple_strtoul (argv[2], &ep, 16);
490         dev_desc = get_dev(argv[1],dev);
491         if (dev_desc==NULL) {
492                 printf ("** Block device %s %d not supported\n", argv[1], dev);
493                 return 1;
494         }
495         if (*ep) {
496                 if (*ep != ':') {
497                         puts ("** Invalid boot device, use `dev[:part]' **\n");
498                         return 1;
499                 }
500                 part = (int)simple_strtoul(++ep, NULL, 16);
501         }
502
503         PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
504
505         if (part != 0) {
506                 if (get_partition_info (dev_desc, part, &info)) {
507                         printf ("** Bad partition %d **\n", part);
508                         return 1;
509                 }
510
511                 if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
512                         printf ("** Invalid partition type \"%.32s\""
513                                 " (expect \"" BOOT_PART_TYPE "\")\n",
514                                 info.type);
515                         return 1;
516                 }
517                 printf ("Loading file \"%s\" "
518                         "from %s device %d:%d (%.32s)\n",
519                         filename,
520                         argv[1], dev, part, info.name);
521         } else {
522                 printf ("Loading file \"%s\" from %s device %d\n",
523                         filename, argv[1], dev);
524         }
525
526
527         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
528                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
529                 ext2fs_close();
530                 return 1;
531         }
532
533         if (!ext2fs_mount(part_length)) {
534                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",
535                         argv[1], dev, part);
536                 ext2fs_close();
537                 return 1;
538         }
539
540         filelen = ext2fs_open(filename);
541         if (filelen < 0) {
542                 printf("** File not found %s\n", filename);
543                 ext2fs_close();
544                 return 1;
545         }
546         if ((count < filelen) && (count != 0)) {
547             filelen = count;
548         }
549
550         if (ext2fs_read((char *)addr, filelen) != filelen) {
551                 printf("** Unable to read \"%s\" from %s %d:%d **\n",
552                         filename, argv[1], dev, part);
553                 ext2fs_close();
554                 return 1;
555         }
556
557         ext2fs_close();
558
559         /* Loading ok, update default load address */
560         load_addr = addr;
561
562         printf ("%d bytes read\n", filelen);
563         sprintf(buf, "%X", filelen);
564         setenv("filesize", buf);
565
566         return 0;
567 }
568
569 U_BOOT_CMD(
570         ext2load,       6,      0,      do_ext2load,
571         "load binary file from a Ext2 filesystem",
572         "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
573         "    - load binary file 'filename' from 'dev' on 'interface'\n"
574         "      to address 'addr' from ext2 filesystem"
575 );
576 static unsigned int_log2(unsigned arg)
577 {
578         unsigned r = 0;
579         while ((arg >>= 1) != 0)
580                 r++;
581         return r;
582 }
583 // taken from mkfs_minix.c. libbb candidate?
584 // "uint32_t size", since we never use it for anything >32 bits
585 uint32_t div_roundup(uint32_t size, uint32_t n)
586 {
587         // Overflow-resistant
588         uint32_t res = size / n;
589         if (res * n != size)
590                 res++;
591         return res;
592 }
593
594 static uint32_t has_super(uint32_t x)
595 {
596         // 0, 1 and powers of 3, 5, 7 up to 2^32 limit
597         static const uint32_t supers[] = {
598                 0, 1, 3, 5, 7, 9, 25, 27, 49, 81, 125, 243, 343, 625, 729,
599                 2187, 2401, 3125, 6561, 15625, 16807, 19683, 59049, 78125,
600                 117649, 177147, 390625, 531441, 823543, 1594323, 1953125,
601                 4782969, 5764801, 9765625, 14348907, 40353607, 43046721,
602                 48828125, 129140163, 244140625, 282475249, 387420489,
603                 1162261467, 1220703125, 1977326743, 3486784401/* >2^31 */,
604         };
605         const uint32_t *sp = supers + ARRAY_SIZE(supers);
606         while (1) {
607                 sp--;
608                 if (x == *sp)
609                         return 1;
610                 if (x > *sp)
611                         return 0;
612         }
613 }
614
615 // Die if we can't allocate size bytes of memory.
616 void* xmalloc(size_t size)
617 {
618         void *ptr = malloc(size);
619         if (ptr == NULL && size != 0)
620                 printf("bb_msg_memory_exhausted\n");
621         return ptr;
622 }
623
624 // Die if we can't allocate and zero size bytes of memory.
625 void* xzalloc(size_t size)
626 {
627         void *ptr = xmalloc(size);
628         memset(ptr, 0, size);
629         return ptr;
630 }
631 static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32_t end)
632 {
633         uint32_t i;
634         memset(bitmap, 0, blocksize);
635         i = start / 8;
636         memset(bitmap, 0xFF, i);
637         bitmap[i] = (1 << (start & 7)) - 1;
638         i = end / 8;
639         bitmap[blocksize - i - 1] |= 0x7F00 >> (end & 7);
640         memset(bitmap + blocksize - i, 0xFF, i);
641 }
642
643 /* Like strncpy but make sure the resulting string is always 0 terminated. */
644 char* safe_strncpy(char *dst, const char *src, size_t size)
645 {
646         if (!size) return dst;
647         dst[--size] = '\0';
648         return strncpy(dst, src, size);
649 }
650
651 void PUT(block_dev_desc_t *dev_desc,uint64_t off, void *buf, uint32_t size)
652 {
653         uint64_t startblock,remainder;
654         unsigned int sector_size = 512;
655         unsigned block_len;
656         unsigned char *temp_ptr=NULL;
657         char sec_buf[SECTOR_SIZE];
658         startblock = off / (uint64_t)sector_size;
659         startblock += part_offset;
660         remainder = off % (uint64_t)sector_size;
661         remainder &= SECTOR_SIZE - 1;
662         if (dev_desc == NULL)
663                 return ;
664
665         if ((startblock + (size/SECTOR_SIZE)) > (part_offset +total_sector)) {
666                 printf("part_offset is %d\n",part_offset);
667                 printf("total_sector is %d\n",total_sector);
668                 printf("error: overflow occurs\n");
669                 return ;
670         }
671
672         if(remainder){
673                 if (dev_desc->block_read) {
674                         dev_desc->block_read(dev_desc->dev, startblock, 1,
675                                 (unsigned char *) sec_buf);
676                         temp_ptr=(unsigned char*)sec_buf;
677                         memcpy((temp_ptr + remainder),(unsigned char*)buf,size);
678                         dev_desc->block_write(dev_desc->dev, startblock, 1,
679                                 (unsigned char *)sec_buf);
680                 }
681         }
682         else
683         {
684                 if(size/SECTOR_SIZE!=0)
685                 {
686                         dev_desc->block_write(dev_desc->dev, startblock,
687                         size/SECTOR_SIZE,(unsigned long *) buf);
688                 }
689                 else
690                 {
691                         dev_desc->block_read(dev_desc->dev, startblock, 1,
692                         (unsigned char *) sec_buf);
693                         temp_ptr=(unsigned char*)sec_buf;
694                         memcpy(temp_ptr,buf,size);
695                         dev_desc->block_write(dev_desc->dev, startblock,
696                         1,(unsigned long *) sec_buf);
697                 }
698         }
699
700         return;
701 }
702
703 int mkfs_ext2(block_dev_desc_t *dev_desc, int part_no)
704 {
705         disk_partition_t info;
706         unsigned i, pos, n;
707         unsigned bs, bpi;
708         unsigned blocksize, blocksize_log2;
709         unsigned inodesize, user_inodesize;
710         unsigned reserved_percent = 5;
711         unsigned long long kilobytes;
712         uint32_t nblocks, nblocks_full;
713         uint32_t nreserved;
714         uint32_t ngroups;
715         uint32_t bytes_per_inode;
716         uint32_t first_block;
717         uint32_t inodes_per_group;
718         uint32_t group_desc_blocks;
719         uint32_t inode_table_blocks;
720         uint32_t lost_and_found_blocks;
721         time_t timestamp;
722         const char *label = "";
723         struct ext2_sblock *sb; // superblock
724         struct ext2_group_desc *gd; // group descriptors
725         struct ext2_inode *inode;
726         struct ext2_dir *dir;
727         uint8_t *buf;
728         __u32 volume_id;
729         __u32 bytes_per_sect;
730         __u32 volume_size_sect;
731         __u64 volume_size_bytes;
732         unsigned char *buffer;
733         unsigned char *temp_buffer;
734         dos_partition_t *pt,*temp_pt;
735         pt=xzalloc(sizeof(dos_partition_t));
736
737         /* volume_id is fixed */
738         volume_id = 0x386d43bf;
739
740         /* Get image size and sector size */
741         bytes_per_sect = SECTOR_SIZE;
742
743         if (!get_partition_info(dev_desc, part_no, &info)) {
744                 kilobytes = (info.size * info.blksz)/1024;
745                 volume_size_bytes = info.size * info.blksz;
746                 volume_size_sect = volume_size_bytes / bytes_per_sect;
747
748                 total_sector = volume_size_sect;
749         } else {
750                 printf("error : get partition info\n");
751                 return 1;
752         }
753
754         bytes_per_inode = 16384;
755         if (kilobytes < 512*1024)
756                 bytes_per_inode = 4096;
757         if (kilobytes < 3*1024)
758                 bytes_per_inode = 8192;
759
760         // Determine block size and inode size
761         // block size is a multiple of 1024
762         // inode size is a multiple of 128
763
764         blocksize = 1024;
765         inodesize = sizeof(struct ext2_inode); // 128
766         if (kilobytes >= 512*1024) { // mke2fs 1.41.9 compat
767                 blocksize = 4096;
768                 inodesize = 256;
769         }
770
771         if (EXT2_MAX_BLOCK_SIZE > 4096) {
772                 while ((kilobytes >> 22) >= blocksize)
773                         blocksize *= 2;
774         }
775
776         if ((int32_t)bytes_per_inode < blocksize)
777                 printf("-%c is bad", 'i');
778         // number of bits in one block, i.e. 8*blocksize
779 #define blocks_per_group (8 * blocksize)
780         first_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
781         blocksize_log2 = int_log2(blocksize);
782
783         // Determine number of blocks
784         kilobytes >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
785         nblocks = kilobytes;
786         if (nblocks != kilobytes)
787                 printf("block count doesn't fit in 32 bits");
788 #define kilobytes kilobytes_unused_after_this
789         // Experimentally, standard mke2fs won't work on images smaller than 60k
790         if (nblocks < 60)
791                 printf("need >= 60 blocks");
792
793         // How many reserved blocks?
794         if (reserved_percent > 50)
795                 printf("-%c is bad", 'm');
796         nreserved = (uint64_t)nblocks * reserved_percent / 100;
797
798         // N.B. killing e2fsprogs feature! Unused blocks don't account in calculations
799         nblocks_full = nblocks;
800
801         // If last block group is too small, nblocks may be decreased in order
802         // to discard it, and control returns here to recalculate some
803         // parameters.
804         // Note: blocksize and bytes_per_inode are never recalculated.
805  retry:
806         // N.B. a block group can have no more than blocks_per_group blocks
807         ngroups = div_roundup(nblocks - first_block, blocks_per_group);
808
809         group_desc_blocks = div_roundup(ngroups, blocksize / sizeof(*gd));
810
811         {
812                 // N.B. e2fsprogs does as follows!
813                 uint32_t overhead, remainder;
814                 // ninodes is the max number of inodes in this filesystem
815                 uint32_t ninodes =
816                         ((uint64_t) nblocks_full * blocksize) / bytes_per_inode;
817                 if (ninodes < EXT2_GOOD_OLD_FIRST_INO+1)
818                         ninodes = EXT2_GOOD_OLD_FIRST_INO+1;
819                 inodes_per_group = div_roundup(ninodes, ngroups);
820                 // minimum number because the first EXT2_GOOD_OLD_FIRST_INO-1 are reserved
821                 if (inodes_per_group < 16)
822                         inodes_per_group = 16;
823                 // a block group can't have more inodes than blocks
824                 if (inodes_per_group > blocks_per_group)
825                         inodes_per_group = blocks_per_group;
826                 // adjust inodes per group so they completely fill the inode table blocks in the descriptor
827                 inodes_per_group =
828                         (div_roundup(inodes_per_group * inodesize,
829                                 blocksize) * blocksize) / inodesize;
830                 // make sure the number of inodes per group is a multiple of 8
831                 inodes_per_group &= ~7;
832                 inode_table_blocks = div_roundup(inodes_per_group * inodesize,
833                         blocksize);
834
835                 // to be useful, lost+found should occupy at least 2 blocks (but not exceeding 16*1024 bytes),
836                 // and at most EXT2_NDIR_BLOCKS. So reserve these blocks right now
837                 /* Or e2fsprogs comment verbatim (what does it mean?):
838                  * Ensure that lost+found is at least 2 blocks, so we always
839                  * test large empty blocks for big-block filesystems. */
840                 lost_and_found_blocks = MIN(EXT2_NDIR_BLOCKS,
841                         16 >> (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE));
842
843                 // the last group needs more attention: isn't it too small for possible overhead?
844                 overhead = (has_super(ngroups - 1) ?
845                         (1/*sb*/ + group_desc_blocks) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + inode_table_blocks;
846                 remainder = (nblocks - first_block) % blocks_per_group;
847                 if (remainder && (remainder < overhead + 50)) {
848                         nblocks -= remainder;
849                         goto retry;
850                 }
851         }
852
853         if (nblocks_full - nblocks)
854                 printf("warning: %u blocks unused\n\n", nblocks_full - nblocks);
855         printf(
856                 "Filesystem label=%s\n"
857                 "OS type: Linux\n"
858                 "Block size=%u (log=%u)\n"
859                 "Fragment size=%u (log=%u)\n"
860                 "%u inodes, %u blocks\n"
861                 "%u blocks (%u%%) reserved for the super user\n"
862                 "First data block=%u\n"
863                 "Maximum filesystem blocks=%u\n"
864                 "%u block groups\n"
865                 "%u blocks per group, %u fragments per group\n"
866                 "%u inodes per group"
867                 , label
868                 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
869                 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
870                 , inodes_per_group * ngroups, nblocks
871                 , nreserved, reserved_percent
872                 , first_block
873                 , group_desc_blocks * (blocksize / (unsigned)sizeof(*gd)) * blocks_per_group
874                 , ngroups
875                 , blocks_per_group, blocks_per_group
876                 , inodes_per_group
877         );
878         {
879                 const char *fmt = "\nSuperblock backups stored on blocks:\n"
880                         "\t%u";
881                 pos = first_block;
882                 for (i = 1; i < ngroups; i++) {
883                         pos += blocks_per_group;
884                         if (has_super(i)) {
885                                 printf(fmt, (unsigned)pos);
886                                 fmt = ", %u";
887                         }
888                 }
889         }
890         printf("\n");
891
892         // fill the superblock
893         sb = xzalloc(1024);
894         STORE_LE(sb->revision_level, EXT2_DYNAMIC_REV); // revision 1 filesystem
895         STORE_LE(sb->magic, EXT2_SUPER_MAGIC);
896         STORE_LE(sb->inode_size, inodesize);
897         // set "Required extra isize" and "Desired extra isize" fields to 28
898         //if (inodesize != sizeof(*inode))
899                 //STORE_LE(sb->s_reserved[21], 0x001C001C);
900         STORE_LE(sb->first_inode, EXT2_GOOD_OLD_FIRST_INO);
901         STORE_LE(sb->log2_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
902         STORE_LE(sb->log2_fragment_size,
903                 blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
904         // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then
905         // the first block is 1, otherwise 0
906         STORE_LE(sb->first_data_block, first_block);
907         // block and inode bitmaps occupy no more than one block, so maximum number of blocks is
908         STORE_LE(sb->s_blocks_per_group, blocks_per_group);
909         STORE_LE(sb->fragments_per_group, blocks_per_group);
910         // blocks
911         STORE_LE(sb->total_blocks, nblocks);
912         // reserve blocks for superuser
913         STORE_LE(sb->reserved_blocks, nreserved);
914         // ninodes
915         STORE_LE(sb->inodes_per_group, inodes_per_group);
916         STORE_LE(sb->total_inodes, inodes_per_group * ngroups);
917         STORE_LE(sb->free_inodes,
918                 inodes_per_group * ngroups - EXT2_GOOD_OLD_FIRST_INO);
919         /* TODO: Implement timestamps, currently commented*/
920         #if 0
921         // timestamps
922         timestamp = time(NULL);
923         STORE_LE(sb->s_mkfs_time, timestamp);
924         STORE_LE(sb->s_wtime, timestamp);
925         STORE_LE(sb->s_lastcheck, timestamp);
926         #endif
927         // misc. Values are chosen to match mke2fs 1.41.9
928         STORE_LE(sb->fs_state, 1); //  TODO: what's 1?
929         STORE_LE(sb->creator_os, EXT2_OS_LINUX);
930         STORE_LE(sb->checkinterval, 24*60*60 * 180); // 180 days
931         STORE_LE(sb->error_handling, EXT2_ERRORS_DEFAULT);
932         // mke2fs 1.41.9 also sets EXT3_FEATURE_COMPAT_RESIZE_INODE
933         // and if >= 0.5GB, EXT3_FEATURE_RO_COMPAT_LARGE_FILE.
934         // we use values which match "mke2fs -O ^resize_inode":
935         // in this case 1.41.9 never sets EXT3_FEATURE_RO_COMPAT_LARGE_FILE.
936         STORE_LE(sb->feature_compatibility, EXT2_FEATURE_COMPAT_SUPP
937                 //| (EXT2_FEATURE_COMPAT_RESIZE_INO * ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT)
938                 | (ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT)
939                 | (EXT2_FEATURE_COMPAT_DIR_INDEX * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX));
940         STORE_LE(sb->feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE);
941         STORE_LE(sb->feature_ro_compat, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
942         //STORE_LE(sb->s_flags, EXT2_FLAGS_UNSIGNED_HASH * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX);
943         //generate_uuid(sb->s_uuid);
944         //if (ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX) {
945                 //STORE_LE(sb->s_def_hash_version, EXT2_HASH_HALF_MD4);
946         //      generate_uuid((uint8_t *)sb->s_hash_seed);
947         //}
948         /*
949          * From e2fsprogs: add "jitter" to the superblock's check interval so that we
950          * don't check all the filesystems at the same time.    We use a
951          * kludgy hack of using the UUID to derive a random jitter value.
952          */
953         STORE_LE(sb->max_mnt_count,EXT2_DFL_MAX_MNT_COUNT);
954                 //+ (sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT));
955
956         // write the label
957         safe_strncpy((char *)sb->volume_name, label, sizeof(sb->volume_name));
958
959         // calculate filesystem skeleton structures
960         gd = xzalloc(group_desc_blocks * blocksize);
961         buf = xmalloc(blocksize);
962         sb->free_blocks = 0;
963         for (i = 0, pos = first_block, n = nblocks - first_block;
964                 i < ngroups;
965                 i++, pos += blocks_per_group, n -= blocks_per_group
966         ) {
967                 memset(buf,'\0',blocksize);
968
969                 uint32_t overhead = pos + (has_super(i) ?
970                         (1/*sb*/ + group_desc_blocks) : 0);
971                 uint32_t free_blocks;
972                 // fill group descriptors
973                 STORE_LE(gd[i].bg_block_bitmap, overhead + 0);
974                 STORE_LE(gd[i].bg_inode_bitmap, overhead + 1);
975                 STORE_LE(gd[i].bg_inode_table, overhead + 2);
976                 overhead =
977                         overhead - pos + 1/*bbmp*/ + 1/*ibmp*/ + inode_table_blocks;
978                 gd[i].bg_free_inodes_count = inodes_per_group;
979                 //STORE_LE(gd[i].bg_used_dirs_count, 0);
980                 // N.B. both "/" and "/lost+found" are within the first block group
981                 // "/" occupies 1 block, "/lost+found" occupies lost_and_found_blocks...
982                 if (0 == i) {
983                         // ... thus increased overhead for the first block group ...
984                         overhead += 1 + lost_and_found_blocks;
985                         // ... and 2 used directories
986                         STORE_LE(gd[i].bg_used_dirs_count, 2);
987                         // well known reserved inodes belong to the first block too
988                         gd[i].bg_free_inodes_count -= EXT2_GOOD_OLD_FIRST_INO;
989                 }
990
991                 // cache free block count of the group
992                 free_blocks = (n < blocks_per_group ? n : blocks_per_group)
993                         - overhead;
994
995                 // mark preallocated blocks as allocated
996                 allocate(buf, blocksize,
997                         // reserve "overhead" blocks
998                         overhead,
999                         // mark unused trailing blocks
1000                         blocks_per_group - (free_blocks + overhead)
1001                 );
1002                 // dump block bitmap
1003                 PUT(dev_desc,(uint64_t)(FETCH_LE32(gd[i].bg_block_bitmap)) * blocksize,
1004                         buf, blocksize);
1005                 STORE_LE(gd[i].bg_free_blocks_count, free_blocks);
1006                 memset(buf,'\0',blocksize);
1007
1008                 // mark preallocated inodes as allocated
1009                 allocate(buf, blocksize,
1010                         // mark reserved inodes
1011                         inodes_per_group - gd[i].bg_free_inodes_count,
1012                         // mark unused trailing inodes
1013                         blocks_per_group - inodes_per_group
1014                 );
1015                 // dump inode bitmap, but it's right after block bitmap, so we can just:
1016                 //Modified to write in immediate block after block bitmap
1017                 PUT(dev_desc,((uint64_t)(FETCH_LE32(gd[i].bg_block_bitmap))+1) * blocksize,
1018                         buf, blocksize);
1019                 STORE_LE(gd[i].bg_free_inodes_count, gd[i].bg_free_inodes_count);
1020
1021                 // count overall free blocks
1022                 sb->free_blocks += free_blocks;
1023         }
1024         STORE_LE(sb->free_blocks, sb->free_blocks);
1025
1026         // dump filesystem skeleton structures
1027         for (i = 0, pos = first_block; i < ngroups; i++, pos += blocks_per_group) {
1028                 // dump superblock and group descriptors and their backups
1029                 if (has_super(i)) {
1030                         // N.B. 1024 byte blocks are special
1031                         PUT(dev_desc,((uint64_t)pos * blocksize) +
1032                                 ((0 == i && 1024 != blocksize) ? 1024 : 0),
1033                                 sb, 1024);
1034                         PUT(dev_desc,((uint64_t)pos * blocksize) + blocksize,
1035                                 gd, group_desc_blocks * blocksize);
1036                 }
1037         }
1038
1039         // zero boot sectors
1040         /* Magic number is written in first block*/
1041         buffer= (char *)xmalloc(1024);
1042         temp_buffer= (char *)xmalloc(1024);
1043         memset(buffer, 0, 1024);
1044         buffer[DOS_PART_MAGIC_OFFSET] = 0x55;
1045         buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa;
1046
1047         /* Read the first block and restore the partition info into first block*/
1048         dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) temp_buffer);
1049         temp_pt = (dos_partition_t *) (temp_buffer + DOS_PART_TBL_OFFSET);
1050         pt->boot_ind = 0x0;
1051         pt->sys_ind = 0x83;
1052         memcpy(buffer+DOS_PART_TBL_OFFSET,pt,sizeof(dos_partition_t));
1053         PUT(dev_desc,0, buffer, 1024);
1054         memset(buf, 0, blocksize);
1055
1056 #if 0
1057         // zero inode tables
1058         for (i = 0; i < ngroups; ++i)
1059                 for (n = 0; n < inode_table_blocks; ++n){
1060                         PUT(dev_desc,
1061                                 (uint64_t)(FETCH_LE32(gd[i].bg_inode_table) + n)
1062                                         * blocksize, buf, blocksize);
1063                         }
1064 #endif
1065
1066         // prepare directory inode
1067         inode = (struct ext2_inode *)buf;
1068         STORE_LE(inode->i_mode, S_IFDIR | S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH);
1069         STORE_LE(inode->i_mtime, timestamp);
1070         STORE_LE(inode->i_atime, timestamp);
1071         STORE_LE(inode->i_ctime, timestamp);
1072         STORE_LE(inode->i_size, blocksize);
1073
1074         // inode->i_blocks stores the number of 512 byte data blocks
1075         // (512, because it goes directly to struct stat without scaling)
1076         STORE_LE(inode->i_blocks, blocksize / 512);
1077
1078         // dump root dir inode
1079         STORE_LE(inode->i_links_count, 3); // "/.", "/..", "/lost+found/.." point to this inode
1080         STORE_LE(inode->i_block[0],
1081                 FETCH_LE32(gd[0].bg_inode_table) + inode_table_blocks);
1082         PUT(dev_desc,((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) +
1083                 (EXT2_ROOT_INO-1) * inodesize,buf, inodesize);
1084
1085         // dump lost+found dir inode
1086         STORE_LE(inode->i_links_count, 2); // both "/lost+found" and "/lost+found/." point to this inode
1087         STORE_LE(inode->i_size, lost_and_found_blocks * blocksize);
1088         STORE_LE(inode->i_blocks, (lost_and_found_blocks * blocksize) / 512);
1089         n = FETCH_LE32(inode->i_block[0]) + 1;
1090
1091         for (i = 0; i < lost_and_found_blocks; ++i)
1092                 STORE_LE(inode->i_block[i], i + n); // use next block
1093         PUT(dev_desc,((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) +
1094                 (EXT2_GOOD_OLD_FIRST_INO-1) * inodesize, buf, inodesize);
1095
1096         // dump directories
1097         memset(buf, 0, blocksize);
1098         dir = (struct ext2_dir *)buf;
1099
1100         // dump 2nd+ blocks of "/lost+found"
1101         STORE_LE(dir->rec_len1, blocksize); // e2fsck 1.41.4 compat (1.41.9 does not need this)
1102         for (i = 1; i < lost_and_found_blocks; ++i) {
1103                 PUT(dev_desc,(uint64_t)(FETCH_LE32(gd[0].bg_inode_table) +
1104                         inode_table_blocks + 1+i) * blocksize, buf, blocksize);
1105         }
1106         // dump 1st block of "/lost+found"
1107         STORE_LE(dir->inode1, EXT2_GOOD_OLD_FIRST_INO);
1108         STORE_LE(dir->rec_len1, 12);
1109         STORE_LE(dir->name_len1, 1);
1110         STORE_LE(dir->file_type1, EXT2_FT_DIR);
1111         dir->name1[0] = '.';
1112         STORE_LE(dir->inode2, EXT2_ROOT_INO);
1113         STORE_LE(dir->rec_len2, blocksize - 12);
1114         STORE_LE(dir->name_len2, 2);
1115         STORE_LE(dir->file_type2, EXT2_FT_DIR);
1116         dir->name2[0] = '.'; dir->name2[1] = '.';
1117         PUT(dev_desc,(uint64_t)(FETCH_LE32(gd[0].bg_inode_table) +
1118                 inode_table_blocks + 1) * blocksize, buf, blocksize);
1119
1120         // dump root dir block
1121         STORE_LE(dir->inode1, EXT2_ROOT_INO);
1122         STORE_LE(dir->rec_len2, 12);
1123         STORE_LE(dir->inode3, EXT2_GOOD_OLD_FIRST_INO);
1124         STORE_LE(dir->rec_len3, blocksize - 12 - 12);
1125         STORE_LE(dir->name_len3, 10);
1126         STORE_LE(dir->file_type3, EXT2_FT_DIR);
1127         strcpy(dir->name3, "lost+found");
1128         PUT(dev_desc,(uint64_t)(FETCH_LE32(gd[0].bg_inode_table) +
1129                 inode_table_blocks + 0) * blocksize, buf, blocksize);
1130         free(pt);
1131         free(buffer);
1132         free(temp_buffer);
1133
1134         return 0;
1135 }
1136
1137 int ext2_register_device (block_dev_desc_t * dev_desc, int part_no)
1138 {
1139         unsigned char buffer[SECTOR_SIZE];
1140
1141         disk_partition_t info;
1142
1143         if (!dev_desc->block_read)
1144                 return -1;
1145
1146         /* check if we have a MBR (on floppies we have only a PBR) */
1147         if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)buffer) != 1) {
1148                 printf("** Can't read from device %d **\n",
1149                         dev_desc->dev);
1150                 return -1;
1151         }
1152         if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
1153                  buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
1154                 /* no signature found */
1155                 return -1;
1156         }
1157
1158         /* First we assume there is a MBR */
1159         if (!get_partition_info(dev_desc, part_no, &info)) {
1160                 part_offset = info.start;
1161                 cur_part = part_no;
1162                 part_size = info.size;
1163         } else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3) == 0) ||
1164                         (strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET], "FAT32", 5) == 0)) {
1165                 /* ok, we assume we are on a PBR only */
1166                 cur_part = 1;
1167                 part_offset = 0;
1168         } else {
1169                 printf("** Partition %d not valid on device %d **\n",
1170                         part_no, dev_desc->dev);
1171                 return -1;
1172         }
1173
1174         return 0;
1175 }
1176
1177 int do_ext2_format (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1178 {
1179         char *filename = "/";
1180         int dev=0;
1181         int part=1;
1182         char *ep;
1183         block_dev_desc_t *dev_desc=NULL;
1184         int part_length;
1185         disk_partition_t info;
1186
1187         if (argc < 3)
1188                 return cmd_usage(cmdtp);
1189
1190         dev = (int)simple_strtoul (argv[2], &ep, 16);
1191         dev_desc = get_dev(argv[1],dev);
1192
1193         if (dev_desc == NULL) {
1194                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
1195                 return 1;
1196         }
1197
1198         if (*ep) {
1199                 if (*ep != ':') {
1200                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
1201                         return 1;
1202                 }
1203                 part = (int)simple_strtoul(++ep, NULL, 16);
1204         }
1205
1206         if (argc == 4)
1207                 filename = argv[3];
1208
1209         PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
1210
1211         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
1212                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
1213                 ext2fs_close();
1214                 return 1;
1215         }
1216
1217         if (ext2_register_device(dev_desc,part)!=0) {
1218                 printf("\n** Unable to use %s %d:%d for fattable **\n",
1219                         argv[1], dev, part);
1220                 return 1;
1221         }
1222
1223         if (!get_partition_info(dev_desc, part, &info)) {
1224                 total_sector = (info.size * info.blksz) / SECTOR_SIZE;
1225         } else {
1226                 printf("error : get partition info\n");
1227                 return 1;
1228         }
1229
1230         printf("formatting\n");
1231         if (mkfs_ext2(dev_desc, part))
1232                 return 1;
1233
1234         return 0;
1235 }
1236
1237 U_BOOT_CMD(
1238         ext2format,     3, 1, do_ext2_format,
1239         "format device as EXT2 filesystem",
1240         "<interface> <dev[:part]>\n"
1241         "         - format device as EXT2 filesystem on 'dev'"
1242 );