blob: b2d6a532330cb2cc14d77a5490971b6bcebd1d0b [file] [log] [blame]
Stephen Warren045fa1e2012-10-22 06:43:51 +00001/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <config.h>
Christian Gmeiner59e890e2014-11-12 14:35:04 +010018#include <errno.h>
Stephen Warren045fa1e2012-10-22 06:43:51 +000019#include <common.h>
Joe Hershberger0eb25b62015-03-22 17:08:59 -050020#include <mapmem.h>
Stephen Warren045fa1e2012-10-22 06:43:51 +000021#include <part.h>
22#include <ext4fs.h>
23#include <fat.h>
24#include <fs.h>
Simon Glass92ccc962012-12-26 09:53:35 +000025#include <sandboxfs.h>
Hans de Goede251cee02015-09-17 18:46:58 -040026#include <ubifs_uboot.h>
Simon Glass117e0502012-12-26 09:53:32 +000027#include <asm/io.h>
Tom Rini9e374e72014-11-24 11:50:46 -050028#include <div64.h>
29#include <linux/math64.h>
Stephen Warren045fa1e2012-10-22 06:43:51 +000030
Stephen Warrena1b231c2012-10-30 07:50:47 +000031DECLARE_GLOBAL_DATA_PTR;
32
Stephen Warren045fa1e2012-10-22 06:43:51 +000033static block_dev_desc_t *fs_dev_desc;
34static disk_partition_t fs_partition;
35static int fs_type = FS_TYPE_ANY;
36
Simon Glass2ded0d42012-12-26 09:53:31 +000037static inline int fs_probe_unsupported(block_dev_desc_t *fs_dev_desc,
38 disk_partition_t *fs_partition)
Simon Glass436e2b72012-12-26 09:53:29 +000039{
40 printf("** Unrecognized filesystem type **\n");
41 return -1;
42}
43
Stephen Warren045fa1e2012-10-22 06:43:51 +000044static inline int fs_ls_unsupported(const char *dirname)
45{
Stephen Warren045fa1e2012-10-22 06:43:51 +000046 return -1;
47}
48
Stephen Warren61529162014-02-03 13:21:00 -070049static inline int fs_exists_unsupported(const char *filename)
50{
51 return 0;
52}
53
Suriyan Ramasamid455d872014-11-17 14:39:38 -080054static inline int fs_size_unsupported(const char *filename, loff_t *size)
Stephen Warrencf659812014-06-11 12:47:26 -060055{
56 return -1;
57}
58
Simon Glass117e0502012-12-26 09:53:32 +000059static inline int fs_read_unsupported(const char *filename, void *buf,
Suriyan Ramasamid455d872014-11-17 14:39:38 -080060 loff_t offset, loff_t len,
61 loff_t *actread)
Stephen Warren045fa1e2012-10-22 06:43:51 +000062{
Stephen Warren045fa1e2012-10-22 06:43:51 +000063 return -1;
64}
65
Simon Glassa8f6ab52013-04-20 08:42:50 +000066static inline int fs_write_unsupported(const char *filename, void *buf,
Suriyan Ramasamid455d872014-11-17 14:39:38 -080067 loff_t offset, loff_t len,
68 loff_t *actwrite)
Simon Glassa8f6ab52013-04-20 08:42:50 +000069{
70 return -1;
71}
72
Simon Glass436e2b72012-12-26 09:53:29 +000073static inline void fs_close_unsupported(void)
74{
75}
76
Christian Gmeiner59e890e2014-11-12 14:35:04 +010077static inline int fs_uuid_unsupported(char *uuid_str)
78{
79 return -1;
80}
81
Simon Glass436e2b72012-12-26 09:53:29 +000082struct fstype_info {
Stephen Warren045fa1e2012-10-22 06:43:51 +000083 int fstype;
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +010084 char *name;
Stephen Warren377202b2014-02-03 13:21:01 -070085 /*
86 * Is it legal to pass NULL as .probe()'s fs_dev_desc parameter? This
87 * should be false in most cases. For "virtual" filesystems which
88 * aren't based on a U-Boot block device (e.g. sandbox), this can be
89 * set to true. This should also be true for the dumm entry at the end
90 * of fstypes[], since that is essentially a "virtual" (non-existent)
91 * filesystem.
92 */
93 bool null_dev_desc_ok;
Simon Glass2ded0d42012-12-26 09:53:31 +000094 int (*probe)(block_dev_desc_t *fs_dev_desc,
95 disk_partition_t *fs_partition);
Simon Glass436e2b72012-12-26 09:53:29 +000096 int (*ls)(const char *dirname);
Stephen Warren61529162014-02-03 13:21:00 -070097 int (*exists)(const char *filename);
Suriyan Ramasamid455d872014-11-17 14:39:38 -080098 int (*size)(const char *filename, loff_t *size);
99 int (*read)(const char *filename, void *buf, loff_t offset,
100 loff_t len, loff_t *actread);
101 int (*write)(const char *filename, void *buf, loff_t offset,
102 loff_t len, loff_t *actwrite);
Simon Glass436e2b72012-12-26 09:53:29 +0000103 void (*close)(void);
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100104 int (*uuid)(char *uuid_str);
Simon Glass436e2b72012-12-26 09:53:29 +0000105};
106
107static struct fstype_info fstypes[] = {
108#ifdef CONFIG_FS_FAT
Stephen Warren045fa1e2012-10-22 06:43:51 +0000109 {
110 .fstype = FS_TYPE_FAT,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100111 .name = "fat",
Stephen Warren377202b2014-02-03 13:21:01 -0700112 .null_dev_desc_ok = false,
Simon Glasse6d52412012-12-26 09:53:33 +0000113 .probe = fat_set_blk_dev,
114 .close = fat_close,
Simon Glass436e2b72012-12-26 09:53:29 +0000115 .ls = file_fat_ls,
Stephen Warrenb7b5f312014-02-03 13:21:10 -0700116 .exists = fat_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600117 .size = fat_size,
Simon Glasse6d52412012-12-26 09:53:33 +0000118 .read = fat_read_file,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800119#ifdef CONFIG_FAT_WRITE
120 .write = file_fat_write,
121#else
Stephen Warrenbd6fb312014-02-03 13:20:59 -0700122 .write = fs_write_unsupported,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800123#endif
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100124 .uuid = fs_uuid_unsupported,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000125 },
Simon Glass436e2b72012-12-26 09:53:29 +0000126#endif
127#ifdef CONFIG_FS_EXT4
Stephen Warren045fa1e2012-10-22 06:43:51 +0000128 {
129 .fstype = FS_TYPE_EXT,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100130 .name = "ext4",
Stephen Warren377202b2014-02-03 13:21:01 -0700131 .null_dev_desc_ok = false,
Simon Glasse6d52412012-12-26 09:53:33 +0000132 .probe = ext4fs_probe,
133 .close = ext4fs_close,
Simon Glass436e2b72012-12-26 09:53:29 +0000134 .ls = ext4fs_ls,
Stephen Warren55af5c92014-02-03 13:21:09 -0700135 .exists = ext4fs_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600136 .size = ext4fs_size,
Simon Glasse6d52412012-12-26 09:53:33 +0000137 .read = ext4_read_file,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800138#ifdef CONFIG_CMD_EXT4_WRITE
139 .write = ext4_write_file,
140#else
Stephen Warrenbd6fb312014-02-03 13:20:59 -0700141 .write = fs_write_unsupported,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800142#endif
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100143 .uuid = ext4fs_uuid,
Simon Glass436e2b72012-12-26 09:53:29 +0000144 },
145#endif
Simon Glass92ccc962012-12-26 09:53:35 +0000146#ifdef CONFIG_SANDBOX
147 {
148 .fstype = FS_TYPE_SANDBOX,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100149 .name = "sandbox",
Stephen Warren377202b2014-02-03 13:21:01 -0700150 .null_dev_desc_ok = true,
Simon Glass92ccc962012-12-26 09:53:35 +0000151 .probe = sandbox_fs_set_blk_dev,
152 .close = sandbox_fs_close,
153 .ls = sandbox_fs_ls,
Stephen Warren0a30aa12014-02-03 13:21:07 -0700154 .exists = sandbox_fs_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600155 .size = sandbox_fs_size,
Simon Glass92ccc962012-12-26 09:53:35 +0000156 .read = fs_read_sandbox,
Simon Glass7eb2c8d2013-04-20 08:42:51 +0000157 .write = fs_write_sandbox,
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100158 .uuid = fs_uuid_unsupported,
Simon Glass92ccc962012-12-26 09:53:35 +0000159 },
160#endif
Hans de Goede251cee02015-09-17 18:46:58 -0400161#ifdef CONFIG_CMD_UBIFS
162 {
163 .fstype = FS_TYPE_UBIFS,
164 .name = "ubifs",
165 .null_dev_desc_ok = true,
166 .probe = ubifs_set_blk_dev,
167 .close = ubifs_close,
168 .ls = ubifs_ls,
169 .exists = ubifs_exists,
170 .size = ubifs_size,
171 .read = ubifs_read,
172 .write = fs_write_unsupported,
173 .uuid = fs_uuid_unsupported,
174 },
175#endif
Simon Glass436e2b72012-12-26 09:53:29 +0000176 {
177 .fstype = FS_TYPE_ANY,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100178 .name = "unsupported",
Stephen Warren377202b2014-02-03 13:21:01 -0700179 .null_dev_desc_ok = true,
Simon Glass436e2b72012-12-26 09:53:29 +0000180 .probe = fs_probe_unsupported,
181 .close = fs_close_unsupported,
182 .ls = fs_ls_unsupported,
Stephen Warren61529162014-02-03 13:21:00 -0700183 .exists = fs_exists_unsupported,
Stephen Warrencf659812014-06-11 12:47:26 -0600184 .size = fs_size_unsupported,
Simon Glass436e2b72012-12-26 09:53:29 +0000185 .read = fs_read_unsupported,
Simon Glassa8f6ab52013-04-20 08:42:50 +0000186 .write = fs_write_unsupported,
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100187 .uuid = fs_uuid_unsupported,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000188 },
189};
190
Simon Glassc6f548d2012-12-26 09:53:30 +0000191static struct fstype_info *fs_get_info(int fstype)
192{
193 struct fstype_info *info;
194 int i;
195
196 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) {
197 if (fstype == info->fstype)
198 return info;
199 }
200
201 /* Return the 'unsupported' sentinel */
202 return info;
203}
204
Stephen Warren045fa1e2012-10-22 06:43:51 +0000205int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
206{
Simon Glass436e2b72012-12-26 09:53:29 +0000207 struct fstype_info *info;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000208 int part, i;
Stephen Warrena1b231c2012-10-30 07:50:47 +0000209#ifdef CONFIG_NEEDS_MANUAL_RELOC
210 static int relocated;
211
212 if (!relocated) {
Simon Glass436e2b72012-12-26 09:53:29 +0000213 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
214 i++, info++) {
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100215 info->name += gd->reloc_off;
Simon Glass436e2b72012-12-26 09:53:29 +0000216 info->probe += gd->reloc_off;
217 info->close += gd->reloc_off;
218 info->ls += gd->reloc_off;
219 info->read += gd->reloc_off;
Simon Glassa8f6ab52013-04-20 08:42:50 +0000220 info->write += gd->reloc_off;
Simon Glass436e2b72012-12-26 09:53:29 +0000221 }
Stephen Warrena1b231c2012-10-30 07:50:47 +0000222 relocated = 1;
223 }
224#endif
Stephen Warren045fa1e2012-10-22 06:43:51 +0000225
226 part = get_device_and_partition(ifname, dev_part_str, &fs_dev_desc,
227 &fs_partition, 1);
228 if (part < 0)
229 return -1;
230
Simon Glass436e2b72012-12-26 09:53:29 +0000231 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
232 if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
233 fstype != info->fstype)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000234 continue;
235
Stephen Warren377202b2014-02-03 13:21:01 -0700236 if (!fs_dev_desc && !info->null_dev_desc_ok)
237 continue;
238
Simon Glass2ded0d42012-12-26 09:53:31 +0000239 if (!info->probe(fs_dev_desc, &fs_partition)) {
Simon Glass436e2b72012-12-26 09:53:29 +0000240 fs_type = info->fstype;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000241 return 0;
242 }
243 }
244
Stephen Warren045fa1e2012-10-22 06:43:51 +0000245 return -1;
246}
247
248static void fs_close(void)
249{
Simon Glassc6f548d2012-12-26 09:53:30 +0000250 struct fstype_info *info = fs_get_info(fs_type);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000251
Simon Glassc6f548d2012-12-26 09:53:30 +0000252 info->close();
Simon Glasse6d52412012-12-26 09:53:33 +0000253
Stephen Warren045fa1e2012-10-22 06:43:51 +0000254 fs_type = FS_TYPE_ANY;
255}
256
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100257int fs_uuid(char *uuid_str)
258{
259 struct fstype_info *info = fs_get_info(fs_type);
260
261 return info->uuid(uuid_str);
262}
263
Stephen Warren045fa1e2012-10-22 06:43:51 +0000264int fs_ls(const char *dirname)
265{
266 int ret;
267
Simon Glassc6f548d2012-12-26 09:53:30 +0000268 struct fstype_info *info = fs_get_info(fs_type);
269
270 ret = info->ls(dirname);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000271
Simon Glasse6d52412012-12-26 09:53:33 +0000272 fs_type = FS_TYPE_ANY;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000273 fs_close();
274
275 return ret;
276}
277
Stephen Warren61529162014-02-03 13:21:00 -0700278int fs_exists(const char *filename)
279{
280 int ret;
281
282 struct fstype_info *info = fs_get_info(fs_type);
283
284 ret = info->exists(filename);
285
286 fs_close();
287
288 return ret;
289}
290
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800291int fs_size(const char *filename, loff_t *size)
Stephen Warrencf659812014-06-11 12:47:26 -0600292{
293 int ret;
294
295 struct fstype_info *info = fs_get_info(fs_type);
296
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800297 ret = info->size(filename, size);
Stephen Warrencf659812014-06-11 12:47:26 -0600298
299 fs_close();
300
301 return ret;
302}
303
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800304int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
305 loff_t *actread)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000306{
Simon Glassc6f548d2012-12-26 09:53:30 +0000307 struct fstype_info *info = fs_get_info(fs_type);
Simon Glass117e0502012-12-26 09:53:32 +0000308 void *buf;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000309 int ret;
310
Simon Glass117e0502012-12-26 09:53:32 +0000311 /*
312 * We don't actually know how many bytes are being read, since len==0
313 * means read the whole file.
314 */
315 buf = map_sysmem(addr, len);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800316 ret = info->read(filename, buf, offset, len, actread);
Simon Glass117e0502012-12-26 09:53:32 +0000317 unmap_sysmem(buf);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000318
Simon Glassc6f548d2012-12-26 09:53:30 +0000319 /* If we requested a specific number of bytes, check we got it */
Max Krummenacher7a3e70c2015-08-05 17:16:58 +0200320 if (ret == 0 && len && *actread != len)
321 printf("** %s shorter than offset + len **\n", filename);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000322 fs_close();
323
324 return ret;
325}
326
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800327int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
328 loff_t *actwrite)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000329{
330 struct fstype_info *info = fs_get_info(fs_type);
331 void *buf;
332 int ret;
333
Simon Glassa8f6ab52013-04-20 08:42:50 +0000334 buf = map_sysmem(addr, len);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800335 ret = info->write(filename, buf, offset, len, actwrite);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000336 unmap_sysmem(buf);
337
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800338 if (ret < 0 && len != *actwrite) {
Simon Glassa8f6ab52013-04-20 08:42:50 +0000339 printf("** Unable to write file %s **\n", filename);
340 ret = -1;
341 }
342 fs_close();
343
344 return ret;
345}
346
Stephen Warrencf659812014-06-11 12:47:26 -0600347int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
348 int fstype)
349{
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800350 loff_t size;
Stephen Warrencf659812014-06-11 12:47:26 -0600351
352 if (argc != 4)
353 return CMD_RET_USAGE;
354
355 if (fs_set_blk_dev(argv[1], argv[2], fstype))
356 return 1;
357
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800358 if (fs_size(argv[3], &size) < 0)
Stephen Warrencf659812014-06-11 12:47:26 -0600359 return CMD_RET_FAILURE;
360
361 setenv_hex("filesize", size);
362
363 return 0;
364}
365
Stephen Warrenf9b55e22012-10-31 11:05:07 +0000366int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
Wolfgang Denkb770e882013-10-05 21:07:25 +0200367 int fstype)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000368{
369 unsigned long addr;
370 const char *addr_str;
371 const char *filename;
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800372 loff_t bytes;
373 loff_t pos;
374 loff_t len_read;
375 int ret;
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100376 unsigned long time;
Pavel Machek949bbd72014-07-09 22:42:57 +0200377 char *ep;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000378
Stephen Warrene9b0f992012-10-30 12:04:17 +0000379 if (argc < 2)
380 return CMD_RET_USAGE;
381 if (argc > 7)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000382 return CMD_RET_USAGE;
383
Stephen Warrene9b0f992012-10-30 12:04:17 +0000384 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
Stephen Warren045fa1e2012-10-22 06:43:51 +0000385 return 1;
386
387 if (argc >= 4) {
Pavel Machek949bbd72014-07-09 22:42:57 +0200388 addr = simple_strtoul(argv[3], &ep, 16);
389 if (ep == argv[3] || *ep != '\0')
390 return CMD_RET_USAGE;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000391 } else {
392 addr_str = getenv("loadaddr");
393 if (addr_str != NULL)
394 addr = simple_strtoul(addr_str, NULL, 16);
395 else
396 addr = CONFIG_SYS_LOAD_ADDR;
397 }
398 if (argc >= 5) {
399 filename = argv[4];
400 } else {
401 filename = getenv("bootfile");
402 if (!filename) {
403 puts("** No boot file defined **\n");
404 return 1;
405 }
406 }
407 if (argc >= 6)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200408 bytes = simple_strtoul(argv[5], NULL, 16);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000409 else
410 bytes = 0;
411 if (argc >= 7)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200412 pos = simple_strtoul(argv[6], NULL, 16);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000413 else
414 pos = 0;
415
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100416 time = get_timer(0);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800417 ret = fs_read(filename, addr, pos, bytes, &len_read);
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100418 time = get_timer(time);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800419 if (ret < 0)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000420 return 1;
421
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800422 printf("%llu bytes read in %lu ms", len_read, time);
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100423 if (time > 0) {
424 puts(" (");
Tom Rini9e374e72014-11-24 11:50:46 -0500425 print_size(div_u64(len_read, time) * 1000, "/s");
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100426 puts(")");
427 }
428 puts("\n");
Stephen Warren045fa1e2012-10-22 06:43:51 +0000429
Simon Glass49c4f032013-02-24 17:33:23 +0000430 setenv_hex("filesize", len_read);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000431
432 return 0;
433}
434
435int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
436 int fstype)
437{
438 if (argc < 2)
439 return CMD_RET_USAGE;
Stephen Warrene9b0f992012-10-30 12:04:17 +0000440 if (argc > 4)
441 return CMD_RET_USAGE;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000442
443 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
444 return 1;
445
Stephen Warrene9b0f992012-10-30 12:04:17 +0000446 if (fs_ls(argc >= 4 ? argv[3] : "/"))
Stephen Warren045fa1e2012-10-22 06:43:51 +0000447 return 1;
448
449 return 0;
450}
Simon Glassa8f6ab52013-04-20 08:42:50 +0000451
Stephen Warren61529162014-02-03 13:21:00 -0700452int file_exists(const char *dev_type, const char *dev_part, const char *file,
453 int fstype)
454{
455 if (fs_set_blk_dev(dev_type, dev_part, fstype))
456 return 0;
457
458 return fs_exists(file);
459}
460
Simon Glassa8f6ab52013-04-20 08:42:50 +0000461int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
Wolfgang Denkb770e882013-10-05 21:07:25 +0200462 int fstype)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000463{
464 unsigned long addr;
465 const char *filename;
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800466 loff_t bytes;
467 loff_t pos;
468 loff_t len;
469 int ret;
Simon Glassa8f6ab52013-04-20 08:42:50 +0000470 unsigned long time;
471
472 if (argc < 6 || argc > 7)
473 return CMD_RET_USAGE;
474
475 if (fs_set_blk_dev(argv[1], argv[2], fstype))
476 return 1;
477
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800478 addr = simple_strtoul(argv[3], NULL, 16);
479 filename = argv[4];
Wolfgang Denkb770e882013-10-05 21:07:25 +0200480 bytes = simple_strtoul(argv[5], NULL, 16);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000481 if (argc >= 7)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200482 pos = simple_strtoul(argv[6], NULL, 16);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000483 else
484 pos = 0;
485
486 time = get_timer(0);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800487 ret = fs_write(filename, addr, pos, bytes, &len);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000488 time = get_timer(time);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800489 if (ret < 0)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000490 return 1;
491
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800492 printf("%llu bytes written in %lu ms", len, time);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000493 if (time > 0) {
494 puts(" (");
Tom Rini9e374e72014-11-24 11:50:46 -0500495 print_size(div_u64(len, time) * 1000, "/s");
Simon Glassa8f6ab52013-04-20 08:42:50 +0000496 puts(")");
497 }
498 puts("\n");
499
500 return 0;
501}
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100502
503int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
504 int fstype)
505{
506 int ret;
507 char uuid[37];
508 memset(uuid, 0, sizeof(uuid));
509
510 if (argc < 3 || argc > 4)
511 return CMD_RET_USAGE;
512
513 if (fs_set_blk_dev(argv[1], argv[2], fstype))
514 return 1;
515
516 ret = fs_uuid(uuid);
517 if (ret)
518 return CMD_RET_FAILURE;
519
520 if (argc == 4)
521 setenv(argv[3], uuid);
522 else
523 printf("%s\n", uuid);
524
525 return CMD_RET_SUCCESS;
526}
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100527
528int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
529{
530 struct fstype_info *info;
531
532 if (argc < 3 || argc > 4)
533 return CMD_RET_USAGE;
534
535 if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
536 return 1;
537
538 info = fs_get_info(fs_type);
539
540 if (argc == 4)
541 setenv(argv[3], info->name);
542 else
543 printf("%s\n", info->name);
544
545 return CMD_RET_SUCCESS;
546}
547