Merge branch 'master' of http://www.denx.de/git/u-boot
[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
37 #if (CONFIG_COMMANDS & CFG_CMD_EXT2)
38 #include <config.h>
39 #include <command.h>
40 #include <image.h>
41 #include <linux/ctype.h>
42 #include <asm/byteorder.h>
43 #include <ext2fs.h>
44 #if ((CONFIG_COMMANDS & CFG_CMD_USB) && defined(CONFIG_USB_STORAGE))
45 #include <usb.h>
46 #endif
47
48 #ifndef CONFIG_DOS_PARTITION
49 #error DOS partition support must be selected
50 #endif
51
52 /* #define      EXT2_DEBUG */
53
54 #ifdef  EXT2_DEBUG
55 #define PRINTF(fmt,args...)     printf (fmt ,##args)
56 #else
57 #define PRINTF(fmt,args...)
58 #endif
59
60 static block_dev_desc_t *get_dev (char* ifname, int dev)
61 {
62 #if (CONFIG_COMMANDS & CFG_CMD_IDE)
63         if (strncmp(ifname,"ide",3)==0) {
64                 extern block_dev_desc_t * ide_get_dev(int dev);
65                 return((dev >= CFG_IDE_MAXDEVICE) ? NULL : ide_get_dev(dev));
66         }
67 #endif
68 #if (CONFIG_COMMANDS & CFG_CMD_SCSI)
69         if (strncmp(ifname,"scsi",4)==0) {
70                 extern block_dev_desc_t * scsi_get_dev(int dev);
71                 return((dev >= CFG_SCSI_MAXDEVICE) ? NULL : scsi_get_dev(dev));
72         }
73 #endif
74 #if ((CONFIG_COMMANDS & CFG_CMD_USB) && defined(CONFIG_USB_STORAGE))
75         if (strncmp(ifname,"usb",3)==0) {
76                 extern block_dev_desc_t * usb_stor_get_dev(int dev);
77                 return((dev >= USB_MAX_STOR_DEV) ? NULL : usb_stor_get_dev(dev));
78         }
79 #endif
80 #if defined(CONFIG_MMC)
81         if (strncmp(ifname,"mmc",3)==0) {
82                 extern block_dev_desc_t *  mmc_get_dev(int dev);
83                 return((dev >= 1) ? NULL : mmc_get_dev(dev));
84         }
85 #endif
86 #if defined(CONFIG_SYSTEMACE)
87         if (strcmp(ifname,"ace")==0) {
88                 extern block_dev_desc_t *  systemace_get_dev(int dev);
89                 return((dev >= 1) ? NULL : systemace_get_dev(dev));
90         }
91 #endif
92         return(NULL);
93 }
94
95 int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
96 {
97         char *filename = "/";
98         int dev=0;
99         int part=1;
100         char *ep;
101         block_dev_desc_t *dev_desc=NULL;
102         int part_length;
103
104         if (argc < 3) {
105                 printf ("Usage:\n%s\n", cmdtp->usage);
106                 return(1);
107         }
108         dev = (int)simple_strtoul (argv[2], &ep, 16);
109         dev_desc=get_dev(argv[1],dev);
110
111         if (dev_desc == NULL) {
112                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
113                 return(1);
114         }
115
116         if (*ep) {
117                 if (*ep != ':') {
118                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
119                         return(1);
120                 }
121                 part = (int)simple_strtoul(++ep, NULL, 16);
122         }
123
124         if (argc == 4) {
125             filename = argv[3];
126         }
127
128         PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
129
130         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
131                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
132                 ext2fs_close();
133                 return(1);
134         }
135
136         if (!ext2fs_mount(part_length)) {
137                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
138                 ext2fs_close();
139                 return(1);
140         }
141
142         if (ext2fs_ls (filename)) {
143                 printf ("** Error ext2fs_ls() **\n");
144                 ext2fs_close();
145                 return(1);
146         };
147
148         ext2fs_close();
149
150         return(0);
151 }
152
153 U_BOOT_CMD(
154         ext2ls, 4,      1,      do_ext2ls,
155         "ext2ls  - list files in a directory (default /)\n",
156         "<interface> <dev[:part]> [directory]\n"
157         "    - list files from 'dev' on 'interface' in a 'directory'\n"
158 );
159
160 /******************************************************************************
161  * Ext2fs boot command intepreter. Derived from diskboot
162  */
163 int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
164 {
165         char *filename = NULL;
166         char *ep;
167         int dev, part = 1;
168         ulong addr = 0, part_length, filelen;
169         disk_partition_t info;
170         block_dev_desc_t *dev_desc = NULL;
171         char buf [12];
172         unsigned long count;
173         char *addr_str;
174
175         switch (argc) {
176         case 3:
177                 addr_str = getenv("loadaddr");
178                 if (addr_str != NULL) {
179                         addr = simple_strtoul (addr_str, NULL, 16);
180                 } else {
181                         addr = CFG_LOAD_ADDR;
182                 }
183                 filename = getenv ("bootfile");
184                 count = 0;
185                 break;
186         case 4:
187                 addr = simple_strtoul (argv[3], NULL, 16);
188                 filename = getenv ("bootfile");
189                 count = 0;
190                 break;
191         case 5:
192                 addr = simple_strtoul (argv[3], NULL, 16);
193                 filename = argv[4];
194                 count = 0;
195                 break;
196         case 6:
197                 addr = simple_strtoul (argv[3], NULL, 16);
198                 filename = argv[4];
199                 count = simple_strtoul (argv[5], NULL, 16);
200                 break;
201
202         default:
203                 printf ("Usage:\n%s\n", cmdtp->usage);
204                 return(1);
205         }
206
207         if (!filename) {
208                 puts ("\n** No boot file defined **\n");
209                 return(1);
210         }
211
212         dev = (int)simple_strtoul (argv[2], &ep, 16);
213         dev_desc=get_dev(argv[1],dev);
214         if (dev_desc==NULL) {
215                 printf ("\n** Block device %s %d not supported\n", argv[1], dev);
216                 return(1);
217         }
218         if (*ep) {
219                 if (*ep != ':') {
220                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
221                         return(1);
222                 }
223                 part = (int)simple_strtoul(++ep, NULL, 16);
224         }
225
226         PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
227
228         if (part != 0) {
229                 if (get_partition_info (dev_desc, part, &info)) {
230                         printf ("** Bad partition %d **\n", part);
231                         return(1);
232                 }
233
234                 if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
235                         printf ("\n** Invalid partition type \"%.32s\""
236                                 " (expect \"" BOOT_PART_TYPE "\")\n",
237                                 info.type);
238                         return(1);
239                 }
240                 PRINTF ("\nLoading from block device %s device %d, partition %d: "
241                         "Name: %.32s  Type: %.32s  File:%s\n",
242                         argv[1], dev, part, info.name, info.type, filename);
243         } else {
244                 PRINTF ("\nLoading from block device %s device %d, File:%s\n",
245                         argv[1], dev, filename);
246         }
247
248
249         if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
250                 printf ("** Bad partition - %s %d:%d **\n",  argv[1], dev, part);
251                 ext2fs_close();
252                 return(1);
253         }
254
255         if (!ext2fs_mount(part_length)) {
256                 printf ("** Bad ext2 partition or disk - %s %d:%d **\n",  argv[1], dev, part);
257                 ext2fs_close();
258                 return(1);
259         }
260
261         filelen = ext2fs_open(filename);
262         if (filelen < 0) {
263                 printf("** File not found %s\n", filename);
264                 ext2fs_close();
265                 return(1);
266         }
267         if ((count < filelen) && (count != 0)) {
268             filelen = count;
269         }
270
271         if (ext2fs_read((char *)addr, filelen) != filelen) {
272                 printf("\n** Unable to read \"%s\" from %s %d:%d **\n", filename, argv[1], dev, part);
273                 ext2fs_close();
274                 return(1);
275         }
276
277         ext2fs_close();
278
279         /* Loading ok, update default load address */
280         load_addr = addr;
281
282         printf ("\n%ld bytes read\n", filelen);
283         sprintf(buf, "%lX", filelen);
284         setenv("filesize", buf);
285
286         return(filelen);
287 }
288
289 U_BOOT_CMD(
290         ext2load,       6,      0,      do_ext2load,
291         "ext2load- load binary file from a Ext2 filesystem\n",
292         "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
293         "    - load binary file 'filename' from 'dev' on 'interface'\n"
294         "      to address 'addr' from ext2 filesystem\n"
295 );
296
297 #endif  /* CONFIG_COMMANDS & CFG_CMD_EXT2 */