Tizen 2.1 base
[kernel/u-boot.git] / common / cmd_ext4.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  * Ext4fs 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 static int total_sector;
56 static unsigned long part_offset = 0;
57 static unsigned long part_size = 0;
58
59 static int cur_part = 1;
60
61 #define DOS_PART_MAGIC_OFFSET 0x1fe
62 #define DOS_FS_TYPE_OFFSET 0x36
63 #define DOS_FS32_TYPE_OFFSET    0x52
64
65
66 /*main entrance of mkfs.ext4 or ext4formating..*/
67 extern int mkfs_ext4(block_dev_desc_t *, int);
68
69 void put_ext4(block_dev_desc_t *dev_desc,uint64_t off, void *buf, uint32_t size)
70 {
71         uint64_t startblock,remainder;
72         unsigned int sector_size = 512; 
73         unsigned char *temp_ptr=NULL;
74         char sec_buf[SECTOR_SIZE];
75         startblock = off / (uint64_t)sector_size;
76         startblock += part_offset;
77         remainder = off % (uint64_t)sector_size;
78         remainder &= SECTOR_SIZE - 1;
79         
80         if (dev_desc == NULL)
81                 return ;
82
83         if ((startblock + (size/SECTOR_SIZE)) > (part_offset +total_sector)) 
84         {
85                 printf("part_offset is %u\n",part_offset);
86                 printf("total_sector is %u\n",total_sector);
87                 printf("error: overflow occurs\n");
88                 return ;
89         }
90
91         if(remainder)
92         {
93                 if (dev_desc->block_read) 
94                 {
95                         dev_desc->block_read(dev_desc->dev, startblock, 1,
96                                 (unsigned char *) sec_buf);
97                         temp_ptr=(unsigned char*)sec_buf;
98                         memcpy((temp_ptr + remainder),(unsigned char*)buf,size);
99                         dev_desc->block_write(dev_desc->dev, startblock, 1,
100                                 (unsigned char *)sec_buf);
101                 }
102         }
103         else
104         {
105                 if(size/SECTOR_SIZE!=0)
106                 {
107                         dev_desc->block_write(dev_desc->dev, startblock,
108                         size/SECTOR_SIZE,(unsigned long *) buf);
109                 }
110                 else
111                 {
112                         dev_desc->block_read(dev_desc->dev, startblock, 1,
113                         (unsigned char *) sec_buf);
114                         temp_ptr=(unsigned char*)sec_buf;
115                         memcpy(temp_ptr,buf,size);
116                         dev_desc->block_write(dev_desc->dev, startblock,
117                         1,(unsigned long *) sec_buf);
118                 }
119         }
120         return;
121 }
122
123
124
125 int ext4_register_device (block_dev_desc_t * dev_desc, int part_no)
126 {
127         unsigned char buffer[SECTOR_SIZE];
128
129         disk_partition_t info;
130
131         if (!dev_desc->block_read)
132                 return -1;
133
134         /* check if we have a MBR (on floppies we have only a PBR) */
135         if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)buffer) != 1) 
136         {
137                 printf("** Can't read from device %d **\n",
138                         dev_desc->dev);
139                 return -1;
140         }
141         if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
142                  buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) 
143         {
144                 /* no signature found */
145                 return -1;
146         }
147
148         /* First we assume there is a MBR */
149         if (!get_partition_info(dev_desc, part_no, &info)) 
150         {
151                 part_offset = info.start;
152                 cur_part = part_no;
153                 part_size = info.size;
154         }
155         else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3) == 0) ||
156                         (strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET], "FAT32", 5) == 0)) 
157         {
158                 /* ok, we assume we are on a PBR only */
159                 cur_part = 1;
160                 part_offset = 0;
161         }
162         else 
163         {
164                 printf("** Partition %d not valid on device %d **\n",
165                         part_no, dev_desc->dev);
166                 return -1;
167         }
168
169         return 0;
170 }
171
172
173
174 int do_ext4_load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
175 {
176         char *filename = NULL;
177         char *ep;
178         int dev, part = 1;
179         ulong addr = 0, part_length;
180         int filelen;
181         disk_partition_t info;
182         block_dev_desc_t *dev_desc = NULL;
183         char buf [12];
184         unsigned long count;
185         char *addr_str;
186
187         switch (argc) {
188         case 3:
189                 addr_str = getenv("loadaddr");
190                 if (addr_str != NULL)
191                         addr = simple_strtoul (addr_str, NULL, 16);
192                 else
193                         addr = CONFIG_SYS_LOAD_ADDR;
194
195                 filename = getenv ("bootfile");
196                 count = 0;
197                 break;
198         case 4:
199                 addr = simple_strtoul (argv[3], NULL, 16);
200                 filename = getenv ("bootfile");
201                 count = 0;
202                 break;
203         case 5:
204                 addr = simple_strtoul (argv[3], NULL, 16);
205                 filename = argv[4];
206                 count = 0;
207                 break;
208         case 6:
209                 addr = simple_strtoul (argv[3], NULL, 16);
210                 filename = argv[4];
211                 count = simple_strtoul (argv[5], NULL, 16);
212                 break;
213
214         default:
215                 return cmd_usage(cmdtp);
216         }
217
218         if (!filename) {
219                 puts ("** No boot file defined **\n");
220                 return 1;
221         }
222
223         dev = (int)simple_strtoul (argv[2], &ep, 16);
224         dev_desc = get_dev(argv[1],dev);
225         if (dev_desc==NULL) {
226                 printf ("** Block device %s %d not supported\n", argv[1], dev);
227                 return 1;
228         }
229         if (*ep) {
230                 if (*ep != ':') {
231                         puts ("** Invalid boot device, use `dev[:part]' **\n");
232                         return 1;
233                 }
234                 part = (int)simple_strtoul(++ep, NULL, 16);
235         }
236
237         //PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
238
239         if (part != 0) {
240                 if (get_partition_info (dev_desc, part, &info)) {
241                         printf ("** Bad partition %d **\n", part);
242                         return 1;
243                 }
244
245                 if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
246                         printf ("** Invalid partition type \"%.32s\""
247                                 " (expect \"" BOOT_PART_TYPE "\")\n",
248                                 info.type);
249                         return 1;
250                 }
251                 printf ("Loading file \"%s\" "
252                         "from %s device %d:%d (%.32s)\n",
253                         filename,
254                         argv[1], dev, part, info.name);
255         } else {
256                 printf ("Loading file \"%s\" from %s device %d\n",
257                         filename, argv[1], dev);
258         }
259
260
261         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
262                 printf ("** Bad partition - %s %d:%d **\n",     argv[1], dev, part);
263                 ext4fs_close();
264                 return 1;
265         }
266
267         if (!ext4fs_mount(part_length)) {
268                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",
269                         argv[1], dev, part);
270                 ext4fs_close();
271                 return 1;
272         }
273
274         filelen = ext4fs_open(filename);
275         if (filelen < 0) {
276                 printf("** File not found %s\n", filename);
277                 ext4fs_close();
278                 return 1;
279         }
280         if ((count < filelen) && (count != 0)) {
281                  filelen = count;
282         }
283
284         if (ext4fs_read((char *)addr, filelen) != filelen) {
285                 printf("** Unable to read \"%s\" from %s %d:%d **\n",
286                         filename, argv[1], dev, part);
287                 ext4fs_close();
288                 return 1;
289         }
290
291         ext4fs_close();
292
293         /* Loading ok, update default load address */
294         load_addr = addr;
295
296         printf ("%d bytes read\n", filelen);
297         sprintf(buf, "%X", filelen);
298         setenv("filesize", buf);
299
300         return 0;
301 }
302
303
304
305
306 int do_ext4_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
307 {
308         char *filename = "/";
309         int dev=0;
310         int part=1;
311         char *ep;
312         block_dev_desc_t *dev_desc=NULL;
313         int part_length;
314
315         if (argc < 3)
316                 return cmd_usage(cmdtp);
317
318         dev = (int)simple_strtoul (argv[2], &ep, 16);
319         dev_desc = get_dev(argv[1],dev);
320
321         if (dev_desc == NULL) {
322                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
323                 return 1;
324         }
325
326         if (*ep) {
327                 if (*ep != ':') {
328                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
329                         return 1;
330                 }
331                 part = (int)simple_strtoul(++ep, NULL, 16);
332         }
333
334         if (argc == 4)
335                 filename = argv[3];
336
337         //PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
338
339         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
340                 printf ("** Bad partition - %s %d:%d **\n",     argv[1], dev, part);
341                 ext4fs_close();
342                 return 1;
343         }
344
345         if (!ext4fs_mount(part_length)) {
346                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
347                 ext4fs_close();
348                 return 1;
349         }
350
351         if (ext4fs_ls (filename)) {
352                 printf ("** Error ext2fs_ls() **\n");
353                 ext4fs_close();
354                 return 1;
355         };
356
357         ext4fs_close();
358
359         return 0;
360 }
361
362 int do_ext4_format (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
363 {
364         char *filename = "/";
365         int dev=0;
366         int part=1;
367         char *ep;
368         block_dev_desc_t *dev_desc=NULL;
369         int part_length;
370         disk_partition_t info;
371
372         if (argc < 3)
373                 return cmd_usage(cmdtp);
374
375         dev = (int)simple_strtoul (argv[2], &ep, 16);
376         dev_desc = get_dev(argv[1],dev);
377
378         if (dev_desc == NULL) {
379                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
380                 return 1;
381         }
382
383         if (*ep) 
384         {
385                 if (*ep != ':') 
386                 {
387                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
388                         return 1;
389                 }
390                 part = (int)simple_strtoul(++ep, NULL, 16);
391         }
392
393         if (argc == 4)
394                 filename = argv[3];
395
396         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) 
397         {
398                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
399                 ext4fs_close();
400                 return 1;
401         }
402
403         if (ext4_register_device(dev_desc,part)!=0) 
404         {
405                 printf("\n** Unable to use %s %d:%d for fattable **\n",
406                         argv[1], dev, part);
407                 return 1;
408         }
409
410         if (!get_partition_info(dev_desc, part, &info)) 
411         {
412                 total_sector = (info.size * info.blksz) / SECTOR_SIZE;
413         } else 
414         {
415                 printf("error : get partition info\n");
416                 return 1;
417         }
418
419         printf("formatting...\n\n");
420         if (mkfs_ext4(dev_desc, part))
421                 return 1;
422
423         return 0;
424 }
425
426
427
428 int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
429 {
430         block_dev_desc_t *dev_desc=NULL;
431         char *filename = "/";
432         int part_length;
433         int part=1;
434         int dev=0;
435         char *ep;
436         unsigned long ram_address;
437         unsigned long file_size;
438         disk_partition_t info;
439
440         if (argc < 6)
441                 return cmd_usage(cmdtp);
442
443         dev = (int)simple_strtoul (argv[2], &ep, 16);
444         dev_desc = get_dev(argv[1],dev);
445
446         if (dev_desc == NULL) {
447                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
448                 return 1;
449         }
450
451         if (*ep) {
452                 if (*ep != ':') {
453                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
454                         return 1;
455                 }
456                 part = (int)simple_strtoul(++ep, NULL, 16);
457         }
458
459         /*get the filename*/
460         filename = argv[3];
461
462         /*get the address in hexadecimal format (string to int)*/
463         ram_address = simple_strtoul (argv[4], NULL, 16);
464
465         /*get the filesize in base 10 format*/
466         file_size=simple_strtoul (argv[5], NULL, 10);
467
468         /*set the device as block device*/
469         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) 
470         {
471                 printf ("** Bad partition - %s %d:%d **\n",     argv[1], dev, part);
472                 ext4fs_close();
473                 return 1;
474         }
475
476         /*register the device and partition*/
477         if (ext4_register_device(dev_desc,part)!=0)
478         {
479                 printf("\n** Unable to use %s %d:%d for fattable **\n",
480                         argv[1], dev, part);
481                 return 1;
482         }       
483
484
485         /*get the partition information*/
486         if (!get_partition_info(dev_desc, part, &info))
487         {               
488                 total_sector = (info.size * info.blksz) / SECTOR_SIZE;
489         } 
490         else 
491         {
492                 printf("error : get partition info\n");
493                 return 1;
494         }
495         
496
497         /*mount the filesystem*/
498         if (!ext4fs_mount(part_length)) 
499         {
500                 printf ("** Bad ext4 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
501                 ext4fs_close();
502                 return 1;
503         }
504
505         /*start write*/
506         if (ext4fs_write(dev_desc,part,filename,(unsigned char*)ram_address,file_size))
507         {
508                 printf ("** Error ext4fs_write() **\n");
509                 ext4fs_close();
510                 return 1;
511         }
512         return 0;
513 }
514
515 int do_ext4_create_dir(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
516 {
517         char *dirname = "/";
518         int dev=0;
519         int part=1;
520         char *ep;
521         block_dev_desc_t *dev_desc=NULL;
522         int part_length;
523         disk_partition_t info;
524
525         if (argc < 4)
526                 return cmd_usage(cmdtp);
527
528         dev = (int)simple_strtoul (argv[2], &ep, 16);
529         dev_desc = get_dev(argv[1],dev);
530
531         if (dev_desc == NULL) {
532                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
533                 return 1;
534         }
535
536         if (*ep) {
537                 if (*ep != ':') {
538                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
539                         return 1;
540                 }
541                 part = (int)simple_strtoul(++ep, NULL, 16);
542         }
543
544         if (argc == 4)
545                 dirname = argv[3];
546
547         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
548                 printf ("** Bad partition - %s %d:%d **\n",     argv[1], dev, part);
549                 ext4fs_close();
550                 return 1;
551         }
552         /*register the device and partition*/
553         if (ext4_register_device(dev_desc,part)!=0)
554         {
555                 printf("\n** Unable to use %s %d:%d for fattable **\n",
556                         argv[1], dev, part);
557                 return 1;
558         }       
559
560         if (!get_partition_info(dev_desc, part, &info)) 
561         {
562                 total_sector = (info.size * info.blksz) / SECTOR_SIZE;
563         } else 
564         {
565                 printf("error : get partition info\n");
566                 return 1;
567         }
568         
569         if (!ext4fs_mount(part_length)) {
570                 printf ("** Bad ext4 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
571                 ext4fs_close();
572                 return 1;
573         }
574
575         if (ext4fs_create_dir (dev_desc,dirname)) {
576                 printf ("** Error ext4fs_create_dir() **\n");
577                 ext4fs_close();
578                 return 1;
579         };
580
581         ext4fs_close();
582
583         return 0;
584 }
585 int do_ext4_create_symlink(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
586 {
587         char *src_path = "/";
588         char *target_path = "/";
589         int dev=0;
590         int part=1;
591         char *ep;
592         block_dev_desc_t *dev_desc=NULL;
593         int part_length;
594         int link_type;
595         disk_partition_t info;
596
597         if (argc < 6)
598                 return cmd_usage(cmdtp);
599
600         dev = (int)simple_strtoul (argv[2], &ep, 16);
601         dev_desc = get_dev(argv[1],dev);
602
603         if (dev_desc == NULL) {
604                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
605                 return 1;
606         }
607
608         if (*ep) {
609                 if (*ep != ':') {
610                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
611                         return 1;
612                 }
613                 part = (int)simple_strtoul(++ep, NULL, 16);
614         }
615         if(!strcmp(argv[3],"H") || !strcmp(argv[3],"h"))
616                 link_type = HARD_LINK;
617         else
618         if(!strcmp(argv[3],"S") || !strcmp(argv[3],"s"))
619                 link_type = SOFT_LINK;
620         else
621                 return cmd_usage(cmdtp);
622         
623         src_path        = argv[4];
624         target_path = argv[5];
625
626         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
627                 printf ("** Bad partition - %s %d:%d **\n",     argv[1], dev, part);
628                 ext4fs_close();
629                 return 1;
630         }
631         /*register the device and partition*/
632         if (ext4_register_device(dev_desc,part)!=0)
633         {
634                 printf("\n** Unable to use %s %d:%d for fattable **\n",
635                         argv[1], dev, part);
636                 return 1;
637         }       
638
639         if (!get_partition_info(dev_desc, part, &info)) 
640         {
641                 total_sector = (info.size * info.blksz) / SECTOR_SIZE;
642         } else 
643         {
644                 printf("error : get partition info\n");
645                 return 1;
646         }
647         
648         if (!ext4fs_mount(part_length)) {
649                 printf ("** Bad ext4 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
650                 ext4fs_close();
651                 return 1;
652         }
653
654         if (ext4fs_create_symlink (dev_desc,link_type,src_path,target_path)) {
655                 printf ("** Error ext4fs_create_dir() **\n");
656                 ext4fs_close();
657                 return 1;
658         };
659
660         ext4fs_close();
661
662         return 0;
663 }
664 U_BOOT_CMD
665 (
666         ext4symlink,    6, 1, do_ext4_create_symlink,
667         "create a file in the root directory",
668         "<interface> <dev[:part]> [H:Hardlink/S:Softlink][Absolute Source Path] [Absolute Target Path]\n"
669         "         - create a Symbolic Link"
670 );
671
672
673 U_BOOT_CMD
674 (
675         ext4mkdir,      4, 1, do_ext4_create_dir,
676         "create a file in the root directory",
677         "<interface> <dev[:part]> [Absolute Directory Path]\n"
678         "         - create a directory"
679 );
680 U_BOOT_CMD
681 (
682         ext4write,      6, 1, do_ext4_write,
683         "create a file in the root directory",
684         "<interface> <dev[:part]> [Absolute filename path] [Address] [sizebytes]\n"
685         "         - create a file in / directory"
686 );
687
688 U_BOOT_CMD
689 (
690         ext4format, 3, 1, do_ext4_format,
691         "format device as EXT4 filesystem",
692         "<interface> <dev[:part]>\n"
693         "         - format device as EXT4 filesystem on 'dev'"
694 );
695
696 U_BOOT_CMD(
697         ext4ls, 4, 1, do_ext4_ls,
698         "list files in a directory (default /)",
699         "<interface> <dev[:part]> [directory]\n"
700         "         - list files from 'dev' on 'interface' in a 'directory'"
701 );
702
703
704 U_BOOT_CMD(
705         ext4load,       6, 0, do_ext4_load,
706         "load binary file from a Ext2 filesystem",
707         "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
708         "         - load binary file 'filename' from 'dev' on 'interface'\n"
709         "                to address 'addr' from ext2 filesystem"
710 );
711
712