]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_fat.c
* Patches by Denis Peter, 9 Sep 2003:
[karo-tx-uboot.git] / common / cmd_fat.c
1 /*
2  * (C) Copyright 2002
3  * Richard Jones, rjones@nexus-tech.net
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Boot support
26  */
27 #include <common.h>
28 #include <command.h>
29 #include <s_record.h>
30 #include <net.h>
31 #include <ata.h>
32
33 #if (CONFIG_COMMANDS & CFG_CMD_FAT)
34
35 #undef  DEBUG
36
37 #include <fat.h>
38
39
40
41
42 block_dev_desc_t *get_dev (char* ifname, int dev)
43 {
44 #if (CONFIG_COMMANDS & CFG_CMD_IDE)
45         if (strncmp(ifname,"ide",3)==0) {
46                 extern block_dev_desc_t * ide_get_dev(int dev);
47                 return(ide_get_dev(dev));
48         }
49 #endif
50 #if (CONFIG_COMMANDS & CFG_CMD_SCSI)
51         if (strncmp(ifname,"scsi",4)==0) {
52                 extern block_dev_desc_t * scsi_get_dev(int dev);
53                 return(scsi_get_dev(dev));
54         }
55 #endif
56 #if ((CONFIG_COMMANDS & CFG_CMD_USB) && defined(CONFIG_USB_STORAGE))
57         if (strncmp(ifname,"usb",3)==0) {
58                 extern block_dev_desc_t * usb_stor_get_dev(int dev);
59                 return(usb_stor_get_dev(dev));
60         }
61 #endif
62 #if defined(CONFIG_MMC)
63         if (strncmp(ifname,"mmc",3)==0) {
64                 extern block_dev_desc_t *  mmc_get_dev(int dev);
65                 return(mmc_get_dev(dev));
66         }
67 #endif
68         return NULL;
69 }
70
71
72 int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
73 {
74         long size;
75         unsigned long offset;
76         unsigned long count;
77         block_dev_desc_t *dev_desc=NULL;
78         int dev=0;
79         int part=1;
80         char *ep;
81
82         if (argc < 5) {
83                 printf ("usage: fatload <interface> <dev[:part]> <addr> <filename> [bytes]\n");
84                 return (0);
85         }
86         dev = (int)simple_strtoul (argv[2], &ep, 16);
87         dev_desc=get_dev(argv[1],dev);
88         if (dev_desc==NULL) {
89                 puts ("\n** Invalid boot device **\n");
90                 return 1;
91         }
92         if (*ep) {
93                 if (*ep != ':') {
94                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
95                         return 1;
96                 }
97                 part = (int)simple_strtoul(++ep, NULL, 16);
98         }
99         if (fat_register_device(dev_desc,part)!=0) {
100                 printf ("\n** Unable to use %s %d:%d for fatload **\n",argv[1],dev,part);
101                 return 1;
102         }
103         offset = simple_strtoul (argv[3], NULL, 16);
104         if (argc == 6)
105                 count = simple_strtoul (argv[5], NULL, 16);
106         else
107                 count = 0;
108         size = file_fat_read (argv[4], (unsigned char *) offset, count);
109
110         if(size==-1)
111                 printf("\n** Unable to read \"%s\" from %s %d:%d **\n",argv[4],argv[1],dev,part);
112         else
113                 printf ("\n%ld bytes read\n", size);
114
115         return size;
116 }
117
118
119
120
121 U_BOOT_CMD(
122         fatload,        6,      0,      do_fat_fsload,
123         "fatload - load binary file from a dos filesystem\n",
124         "<interface> <dev[:part]>  <addr> <filename> [bytes]\n"
125         "    - load binary file 'filename' from 'dev' on 'interface'\n"
126         "      to address 'addr' from dos filesystem\n"
127 );
128
129 int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
130 {
131         char *filename = "/";
132         int ret;
133         int dev=0;
134         int part=1;
135         char *ep;
136         block_dev_desc_t *dev_desc=NULL;
137
138         if (argc < 3) {
139                 printf ("usage: fatls <interface> <dev[:part]> [directory]\n");
140                 return (0);
141         }
142         dev = (int)simple_strtoul (argv[2], &ep, 16);
143         dev_desc=get_dev(argv[1],dev);
144         if (dev_desc==NULL) {
145                 puts ("\n** Invalid boot device **\n");
146                 return 1;
147         }
148         if (*ep) {
149                 if (*ep != ':') {
150                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
151                         return 1;
152                 }
153                 part = (int)simple_strtoul(++ep, NULL, 16);
154         }
155         if (fat_register_device(dev_desc,part)!=0) {
156                 printf ("\n** Unable to use %s %d:%d for fatls **\n",argv[1],dev,part);
157                 return 1;
158         }
159         if (argc == 4)
160                 ret = file_fat_ls (argv[3]);
161         else
162                 ret = file_fat_ls (filename);
163
164         if(ret!=0)
165                 printf("No Fat FS detected\n");
166         return (ret);
167 }
168
169 U_BOOT_CMD(
170         fatls,  4,      1,      do_fat_ls,
171         "fatls   - list files in a directory (default /)\n",
172         "<interface> <dev[:part]> [directory]\n"
173         "    - list files from 'dev' on 'interface' in a 'directory'\n"
174 );
175
176 int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
177 {
178         int dev=0;
179         int part=1;
180         char *ep;
181         block_dev_desc_t *dev_desc=NULL;
182
183         if (argc < 2) {
184                 printf ("usage: fatinfo <interface> <dev[:part]>\n");
185                 return (0);
186         }
187         dev = (int)simple_strtoul (argv[2], &ep, 16);
188         dev_desc=get_dev(argv[1],dev);
189         if (dev_desc==NULL) {
190                 puts ("\n** Invalid boot device **\n");
191                 return 1;
192         }
193         if (*ep) {
194                 if (*ep != ':') {
195                         puts ("\n** Invalid boot device, use `dev[:part]' **\n");
196                         return 1;
197                 }
198                 part = (int)simple_strtoul(++ep, NULL, 16);
199         }
200         if (fat_register_device(dev_desc,part)!=0) {
201                 printf ("\n** Unable to use %s %d:%d for fatinfo **\n",argv[1],dev,part);
202                 return 1;
203         }
204         return (file_fat_detectfs ());
205 }
206
207 U_BOOT_CMD(
208         fatinfo,        3,      1,      do_fat_fsinfo,
209         "fatinfo - print information about filesystem\n",
210         "<interface> <dev[:part]>\n"
211         "    - print information about filesystem from 'dev' on 'interface'\n"
212 );
213
214 #ifdef NOT_IMPLEMENTED_YET
215 /* find first device whose first partition is a DOS filesystem */
216 int find_fat_partition (void)
217 {
218         int i, j;
219         block_dev_desc_t *dev_desc;
220         unsigned char *part_table;
221         unsigned char buffer[ATA_BLOCKSIZE];
222
223         for (i = 0; i < CFG_IDE_MAXDEVICE; i++) {
224                 dev_desc = ide_get_dev (i);
225                 if (!dev_desc) {
226                         debug ("couldn't get ide device!\n");
227                         return (-1);
228                 }
229                 if (dev_desc->part_type == PART_TYPE_DOS) {
230                         if (dev_desc->
231                                 block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
232                                 debug ("can't perform block_read!\n");
233                                 return (-1);
234                         }
235                         part_table = &buffer[0x1be];    /* start with partition #4 */
236                         for (j = 0; j < 4; j++) {
237                                 if ((part_table[4] == 1 ||      /* 12-bit FAT */
238                                      part_table[4] == 4 ||      /* 16-bit FAT */
239                                      part_table[4] == 6) &&     /* > 32Meg part */
240                                     part_table[0] == 0x80) {    /* bootable? */
241                                         curr_dev = i;
242                                         part_offset = part_table[11];
243                                         part_offset <<= 8;
244                                         part_offset |= part_table[10];
245                                         part_offset <<= 8;
246                                         part_offset |= part_table[9];
247                                         part_offset <<= 8;
248                                         part_offset |= part_table[8];
249                                         debug ("found partition start at %ld\n", part_offset);
250                                         return (0);
251                                 }
252                                 part_table += 16;
253                         }
254                 }
255         }
256
257         debug ("no valid devices found!\n");
258         return (-1);
259 }
260
261 int
262 do_fat_dump (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
263 {
264         __u8 block[1024];
265         int ret;
266         int bknum;
267
268         ret = 0;
269
270         if (argc != 2) {
271                 printf ("needs an argument!\n");
272                 return (0);
273         }
274
275         bknum = simple_strtoul (argv[1], NULL, 10);
276
277         if (disk_read (0, bknum, block) != 0) {
278                 printf ("Error: reading block\n");
279                 return -1;
280         }
281         printf ("FAT dump: %d\n", bknum);
282         hexdump (512, block);
283
284         return (ret);
285 }
286
287 int disk_read (__u32 startblock, __u32 getsize, __u8 *bufptr)
288 {
289         ulong tot;
290         block_dev_desc_t *dev_desc;
291
292         if (curr_dev < 0) {
293                 if (find_fat_partition () != 0)
294                         return (-1);
295         }
296
297         dev_desc = ide_get_dev (curr_dev);
298         if (!dev_desc) {
299                 debug ("couldn't get ide device\n");
300                 return (-1);
301         }
302
303         tot = dev_desc->block_read (0, startblock + part_offset,
304                                     getsize, (ulong *) bufptr);
305
306         /* should we do this here?
307            flush_cache ((ulong)buf, cnt*ide_dev_desc[device].blksz);
308          */
309
310         if (tot == getsize)
311                 return (0);
312
313         debug ("unable to read from device!\n");
314
315         return (-1);
316 }
317
318
319 static int isprint (unsigned char ch)
320 {
321         if (ch >= 32 && ch < 127)
322                 return (1);
323
324         return (0);
325 }
326
327
328 void hexdump (int cnt, unsigned char *data)
329 {
330         int i;
331         int run;
332         int offset;
333
334         offset = 0;
335         while (cnt) {
336                 printf ("%04X : ", offset);
337                 if (cnt >= 16)
338                         run = 16;
339                 else
340                         run = cnt;
341                 cnt -= run;
342                 for (i = 0; i < run; i++)
343                         printf ("%02X ", (unsigned int) data[i]);
344                 printf (": ");
345                 for (i = 0; i < run; i++)
346                         printf ("%c", isprint (data[i]) ? data[i] : '.');
347                 printf ("\n");
348                 data = &data[16];
349                 offset += run;
350         }
351 }
352 #endif  /* NOT_IMPLEMENTED_YET */
353
354 #endif  /* CFG_CMD_FAT */