blob: 595ff1fe69b5bc446ebd32c3d7badd7726348d63 [file] [log] [blame]
Stephen Warren045fa1e2012-10-22 06:43:51 +00001/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
Tom Rini5b8031c2016-01-14 22:05:13 -05004 * SPDX-License-Identifier: GPL-2.0
Stephen Warren045fa1e2012-10-22 06:43:51 +00005 */
6
7#include <config.h>
Christian Gmeiner59e890e2014-11-12 14:35:04 +01008#include <errno.h>
Stephen Warren045fa1e2012-10-22 06:43:51 +00009#include <common.h>
Joe Hershberger0eb25b62015-03-22 17:08:59 -050010#include <mapmem.h>
Stephen Warren045fa1e2012-10-22 06:43:51 +000011#include <part.h>
12#include <ext4fs.h>
13#include <fat.h>
14#include <fs.h>
Simon Glass92ccc962012-12-26 09:53:35 +000015#include <sandboxfs.h>
Hans de Goede251cee02015-09-17 18:46:58 -040016#include <ubifs_uboot.h>
Simon Glass117e0502012-12-26 09:53:32 +000017#include <asm/io.h>
Tom Rini9e374e72014-11-24 11:50:46 -050018#include <div64.h>
19#include <linux/math64.h>
Stephen Warren045fa1e2012-10-22 06:43:51 +000020
Stephen Warrena1b231c2012-10-30 07:50:47 +000021DECLARE_GLOBAL_DATA_PTR;
22
Simon Glass4101f682016-02-29 15:25:34 -070023static struct blk_desc *fs_dev_desc;
Stephen Warren045fa1e2012-10-22 06:43:51 +000024static disk_partition_t fs_partition;
25static int fs_type = FS_TYPE_ANY;
26
Simon Glass4101f682016-02-29 15:25:34 -070027static inline int fs_probe_unsupported(struct blk_desc *fs_dev_desc,
Simon Glass2ded0d42012-12-26 09:53:31 +000028 disk_partition_t *fs_partition)
Simon Glass436e2b72012-12-26 09:53:29 +000029{
30 printf("** Unrecognized filesystem type **\n");
31 return -1;
32}
33
Stephen Warren045fa1e2012-10-22 06:43:51 +000034static inline int fs_ls_unsupported(const char *dirname)
35{
Stephen Warren045fa1e2012-10-22 06:43:51 +000036 return -1;
37}
38
Stephen Warren61529162014-02-03 13:21:00 -070039static inline int fs_exists_unsupported(const char *filename)
40{
41 return 0;
42}
43
Suriyan Ramasamid455d872014-11-17 14:39:38 -080044static inline int fs_size_unsupported(const char *filename, loff_t *size)
Stephen Warrencf659812014-06-11 12:47:26 -060045{
46 return -1;
47}
48
Simon Glass117e0502012-12-26 09:53:32 +000049static inline int fs_read_unsupported(const char *filename, void *buf,
Suriyan Ramasamid455d872014-11-17 14:39:38 -080050 loff_t offset, loff_t len,
51 loff_t *actread)
Stephen Warren045fa1e2012-10-22 06:43:51 +000052{
Stephen Warren045fa1e2012-10-22 06:43:51 +000053 return -1;
54}
55
Simon Glassa8f6ab52013-04-20 08:42:50 +000056static inline int fs_write_unsupported(const char *filename, void *buf,
Suriyan Ramasamid455d872014-11-17 14:39:38 -080057 loff_t offset, loff_t len,
58 loff_t *actwrite)
Simon Glassa8f6ab52013-04-20 08:42:50 +000059{
60 return -1;
61}
62
Simon Glass436e2b72012-12-26 09:53:29 +000063static inline void fs_close_unsupported(void)
64{
65}
66
Christian Gmeiner59e890e2014-11-12 14:35:04 +010067static inline int fs_uuid_unsupported(char *uuid_str)
68{
69 return -1;
70}
71
Simon Glass436e2b72012-12-26 09:53:29 +000072struct fstype_info {
Stephen Warren045fa1e2012-10-22 06:43:51 +000073 int fstype;
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +010074 char *name;
Stephen Warren377202b2014-02-03 13:21:01 -070075 /*
76 * Is it legal to pass NULL as .probe()'s fs_dev_desc parameter? This
77 * should be false in most cases. For "virtual" filesystems which
78 * aren't based on a U-Boot block device (e.g. sandbox), this can be
79 * set to true. This should also be true for the dumm entry at the end
80 * of fstypes[], since that is essentially a "virtual" (non-existent)
81 * filesystem.
82 */
83 bool null_dev_desc_ok;
Simon Glass4101f682016-02-29 15:25:34 -070084 int (*probe)(struct blk_desc *fs_dev_desc,
Simon Glass2ded0d42012-12-26 09:53:31 +000085 disk_partition_t *fs_partition);
Simon Glass436e2b72012-12-26 09:53:29 +000086 int (*ls)(const char *dirname);
Stephen Warren61529162014-02-03 13:21:00 -070087 int (*exists)(const char *filename);
Suriyan Ramasamid455d872014-11-17 14:39:38 -080088 int (*size)(const char *filename, loff_t *size);
89 int (*read)(const char *filename, void *buf, loff_t offset,
90 loff_t len, loff_t *actread);
91 int (*write)(const char *filename, void *buf, loff_t offset,
92 loff_t len, loff_t *actwrite);
Simon Glass436e2b72012-12-26 09:53:29 +000093 void (*close)(void);
Christian Gmeiner59e890e2014-11-12 14:35:04 +010094 int (*uuid)(char *uuid_str);
Simon Glass436e2b72012-12-26 09:53:29 +000095};
96
97static struct fstype_info fstypes[] = {
98#ifdef CONFIG_FS_FAT
Stephen Warren045fa1e2012-10-22 06:43:51 +000099 {
100 .fstype = FS_TYPE_FAT,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100101 .name = "fat",
Stephen Warren377202b2014-02-03 13:21:01 -0700102 .null_dev_desc_ok = false,
Simon Glasse6d52412012-12-26 09:53:33 +0000103 .probe = fat_set_blk_dev,
104 .close = fat_close,
Simon Glass436e2b72012-12-26 09:53:29 +0000105 .ls = file_fat_ls,
Stephen Warrenb7b5f312014-02-03 13:21:10 -0700106 .exists = fat_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600107 .size = fat_size,
Simon Glasse6d52412012-12-26 09:53:33 +0000108 .read = fat_read_file,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800109#ifdef CONFIG_FAT_WRITE
110 .write = file_fat_write,
111#else
Stephen Warrenbd6fb312014-02-03 13:20:59 -0700112 .write = fs_write_unsupported,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800113#endif
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100114 .uuid = fs_uuid_unsupported,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000115 },
Simon Glass436e2b72012-12-26 09:53:29 +0000116#endif
117#ifdef CONFIG_FS_EXT4
Stephen Warren045fa1e2012-10-22 06:43:51 +0000118 {
119 .fstype = FS_TYPE_EXT,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100120 .name = "ext4",
Stephen Warren377202b2014-02-03 13:21:01 -0700121 .null_dev_desc_ok = false,
Simon Glasse6d52412012-12-26 09:53:33 +0000122 .probe = ext4fs_probe,
123 .close = ext4fs_close,
Simon Glass436e2b72012-12-26 09:53:29 +0000124 .ls = ext4fs_ls,
Stephen Warren55af5c92014-02-03 13:21:09 -0700125 .exists = ext4fs_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600126 .size = ext4fs_size,
Simon Glasse6d52412012-12-26 09:53:33 +0000127 .read = ext4_read_file,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800128#ifdef CONFIG_CMD_EXT4_WRITE
129 .write = ext4_write_file,
130#else
Stephen Warrenbd6fb312014-02-03 13:20:59 -0700131 .write = fs_write_unsupported,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800132#endif
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100133 .uuid = ext4fs_uuid,
Simon Glass436e2b72012-12-26 09:53:29 +0000134 },
135#endif
Simon Glass92ccc962012-12-26 09:53:35 +0000136#ifdef CONFIG_SANDBOX
137 {
138 .fstype = FS_TYPE_SANDBOX,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100139 .name = "sandbox",
Stephen Warren377202b2014-02-03 13:21:01 -0700140 .null_dev_desc_ok = true,
Simon Glass92ccc962012-12-26 09:53:35 +0000141 .probe = sandbox_fs_set_blk_dev,
142 .close = sandbox_fs_close,
143 .ls = sandbox_fs_ls,
Stephen Warren0a30aa12014-02-03 13:21:07 -0700144 .exists = sandbox_fs_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600145 .size = sandbox_fs_size,
Simon Glass92ccc962012-12-26 09:53:35 +0000146 .read = fs_read_sandbox,
Simon Glass7eb2c8d2013-04-20 08:42:51 +0000147 .write = fs_write_sandbox,
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100148 .uuid = fs_uuid_unsupported,
Simon Glass92ccc962012-12-26 09:53:35 +0000149 },
150#endif
Hans de Goede251cee02015-09-17 18:46:58 -0400151#ifdef CONFIG_CMD_UBIFS
152 {
153 .fstype = FS_TYPE_UBIFS,
154 .name = "ubifs",
155 .null_dev_desc_ok = true,
156 .probe = ubifs_set_blk_dev,
157 .close = ubifs_close,
158 .ls = ubifs_ls,
159 .exists = ubifs_exists,
160 .size = ubifs_size,
161 .read = ubifs_read,
162 .write = fs_write_unsupported,
163 .uuid = fs_uuid_unsupported,
164 },
165#endif
Simon Glass436e2b72012-12-26 09:53:29 +0000166 {
167 .fstype = FS_TYPE_ANY,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100168 .name = "unsupported",
Stephen Warren377202b2014-02-03 13:21:01 -0700169 .null_dev_desc_ok = true,
Simon Glass436e2b72012-12-26 09:53:29 +0000170 .probe = fs_probe_unsupported,
171 .close = fs_close_unsupported,
172 .ls = fs_ls_unsupported,
Stephen Warren61529162014-02-03 13:21:00 -0700173 .exists = fs_exists_unsupported,
Stephen Warrencf659812014-06-11 12:47:26 -0600174 .size = fs_size_unsupported,
Simon Glass436e2b72012-12-26 09:53:29 +0000175 .read = fs_read_unsupported,
Simon Glassa8f6ab52013-04-20 08:42:50 +0000176 .write = fs_write_unsupported,
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100177 .uuid = fs_uuid_unsupported,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000178 },
179};
180
Simon Glassc6f548d2012-12-26 09:53:30 +0000181static struct fstype_info *fs_get_info(int fstype)
182{
183 struct fstype_info *info;
184 int i;
185
186 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) {
187 if (fstype == info->fstype)
188 return info;
189 }
190
191 /* Return the 'unsupported' sentinel */
192 return info;
193}
194
Stephen Warren045fa1e2012-10-22 06:43:51 +0000195int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
196{
Simon Glass436e2b72012-12-26 09:53:29 +0000197 struct fstype_info *info;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000198 int part, i;
Stephen Warrena1b231c2012-10-30 07:50:47 +0000199#ifdef CONFIG_NEEDS_MANUAL_RELOC
200 static int relocated;
201
202 if (!relocated) {
Simon Glass436e2b72012-12-26 09:53:29 +0000203 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
204 i++, info++) {
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100205 info->name += gd->reloc_off;
Simon Glass436e2b72012-12-26 09:53:29 +0000206 info->probe += gd->reloc_off;
207 info->close += gd->reloc_off;
208 info->ls += gd->reloc_off;
209 info->read += gd->reloc_off;
Simon Glassa8f6ab52013-04-20 08:42:50 +0000210 info->write += gd->reloc_off;
Simon Glass436e2b72012-12-26 09:53:29 +0000211 }
Stephen Warrena1b231c2012-10-30 07:50:47 +0000212 relocated = 1;
213 }
214#endif
Stephen Warren045fa1e2012-10-22 06:43:51 +0000215
Simon Glasse35929e2016-02-29 15:25:44 -0700216 part = blk_get_device_part_str(ifname, dev_part_str, &fs_dev_desc,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000217 &fs_partition, 1);
218 if (part < 0)
219 return -1;
220
Simon Glass436e2b72012-12-26 09:53:29 +0000221 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
222 if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
223 fstype != info->fstype)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000224 continue;
225
Stephen Warren377202b2014-02-03 13:21:01 -0700226 if (!fs_dev_desc && !info->null_dev_desc_ok)
227 continue;
228
Simon Glass2ded0d42012-12-26 09:53:31 +0000229 if (!info->probe(fs_dev_desc, &fs_partition)) {
Simon Glass436e2b72012-12-26 09:53:29 +0000230 fs_type = info->fstype;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000231 return 0;
232 }
233 }
234
Stephen Warren045fa1e2012-10-22 06:43:51 +0000235 return -1;
236}
237
238static void fs_close(void)
239{
Simon Glassc6f548d2012-12-26 09:53:30 +0000240 struct fstype_info *info = fs_get_info(fs_type);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000241
Simon Glassc6f548d2012-12-26 09:53:30 +0000242 info->close();
Simon Glasse6d52412012-12-26 09:53:33 +0000243
Stephen Warren045fa1e2012-10-22 06:43:51 +0000244 fs_type = FS_TYPE_ANY;
245}
246
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100247int fs_uuid(char *uuid_str)
248{
249 struct fstype_info *info = fs_get_info(fs_type);
250
251 return info->uuid(uuid_str);
252}
253
Stephen Warren045fa1e2012-10-22 06:43:51 +0000254int fs_ls(const char *dirname)
255{
256 int ret;
257
Simon Glassc6f548d2012-12-26 09:53:30 +0000258 struct fstype_info *info = fs_get_info(fs_type);
259
260 ret = info->ls(dirname);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000261
Simon Glasse6d52412012-12-26 09:53:33 +0000262 fs_type = FS_TYPE_ANY;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000263 fs_close();
264
265 return ret;
266}
267
Stephen Warren61529162014-02-03 13:21:00 -0700268int fs_exists(const char *filename)
269{
270 int ret;
271
272 struct fstype_info *info = fs_get_info(fs_type);
273
274 ret = info->exists(filename);
275
276 fs_close();
277
278 return ret;
279}
280
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800281int fs_size(const char *filename, loff_t *size)
Stephen Warrencf659812014-06-11 12:47:26 -0600282{
283 int ret;
284
285 struct fstype_info *info = fs_get_info(fs_type);
286
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800287 ret = info->size(filename, size);
Stephen Warrencf659812014-06-11 12:47:26 -0600288
289 fs_close();
290
291 return ret;
292}
293
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800294int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
295 loff_t *actread)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000296{
Simon Glassc6f548d2012-12-26 09:53:30 +0000297 struct fstype_info *info = fs_get_info(fs_type);
Simon Glass117e0502012-12-26 09:53:32 +0000298 void *buf;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000299 int ret;
300
Simon Glass117e0502012-12-26 09:53:32 +0000301 /*
302 * We don't actually know how many bytes are being read, since len==0
303 * means read the whole file.
304 */
305 buf = map_sysmem(addr, len);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800306 ret = info->read(filename, buf, offset, len, actread);
Simon Glass117e0502012-12-26 09:53:32 +0000307 unmap_sysmem(buf);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000308
Simon Glassc6f548d2012-12-26 09:53:30 +0000309 /* If we requested a specific number of bytes, check we got it */
Max Krummenacher7a3e70c2015-08-05 17:16:58 +0200310 if (ret == 0 && len && *actread != len)
311 printf("** %s shorter than offset + len **\n", filename);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000312 fs_close();
313
314 return ret;
315}
316
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800317int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
318 loff_t *actwrite)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000319{
320 struct fstype_info *info = fs_get_info(fs_type);
321 void *buf;
322 int ret;
323
Simon Glassa8f6ab52013-04-20 08:42:50 +0000324 buf = map_sysmem(addr, len);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800325 ret = info->write(filename, buf, offset, len, actwrite);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000326 unmap_sysmem(buf);
327
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800328 if (ret < 0 && len != *actwrite) {
Simon Glassa8f6ab52013-04-20 08:42:50 +0000329 printf("** Unable to write file %s **\n", filename);
330 ret = -1;
331 }
332 fs_close();
333
334 return ret;
335}
336
Stephen Warrencf659812014-06-11 12:47:26 -0600337int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
338 int fstype)
339{
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800340 loff_t size;
Stephen Warrencf659812014-06-11 12:47:26 -0600341
342 if (argc != 4)
343 return CMD_RET_USAGE;
344
345 if (fs_set_blk_dev(argv[1], argv[2], fstype))
346 return 1;
347
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800348 if (fs_size(argv[3], &size) < 0)
Stephen Warrencf659812014-06-11 12:47:26 -0600349 return CMD_RET_FAILURE;
350
351 setenv_hex("filesize", size);
352
353 return 0;
354}
355
Stephen Warrenf9b55e22012-10-31 11:05:07 +0000356int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
Wolfgang Denkb770e882013-10-05 21:07:25 +0200357 int fstype)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000358{
359 unsigned long addr;
360 const char *addr_str;
361 const char *filename;
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800362 loff_t bytes;
363 loff_t pos;
364 loff_t len_read;
365 int ret;
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100366 unsigned long time;
Pavel Machek949bbd72014-07-09 22:42:57 +0200367 char *ep;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000368
Stephen Warrene9b0f992012-10-30 12:04:17 +0000369 if (argc < 2)
370 return CMD_RET_USAGE;
371 if (argc > 7)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000372 return CMD_RET_USAGE;
373
Stephen Warrene9b0f992012-10-30 12:04:17 +0000374 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
Stephen Warren045fa1e2012-10-22 06:43:51 +0000375 return 1;
376
377 if (argc >= 4) {
Pavel Machek949bbd72014-07-09 22:42:57 +0200378 addr = simple_strtoul(argv[3], &ep, 16);
379 if (ep == argv[3] || *ep != '\0')
380 return CMD_RET_USAGE;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000381 } else {
382 addr_str = getenv("loadaddr");
383 if (addr_str != NULL)
384 addr = simple_strtoul(addr_str, NULL, 16);
385 else
386 addr = CONFIG_SYS_LOAD_ADDR;
387 }
388 if (argc >= 5) {
389 filename = argv[4];
390 } else {
391 filename = getenv("bootfile");
392 if (!filename) {
393 puts("** No boot file defined **\n");
394 return 1;
395 }
396 }
397 if (argc >= 6)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200398 bytes = simple_strtoul(argv[5], NULL, 16);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000399 else
400 bytes = 0;
401 if (argc >= 7)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200402 pos = simple_strtoul(argv[6], NULL, 16);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000403 else
404 pos = 0;
405
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100406 time = get_timer(0);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800407 ret = fs_read(filename, addr, pos, bytes, &len_read);
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100408 time = get_timer(time);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800409 if (ret < 0)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000410 return 1;
411
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800412 printf("%llu bytes read in %lu ms", len_read, time);
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100413 if (time > 0) {
414 puts(" (");
Tom Rini9e374e72014-11-24 11:50:46 -0500415 print_size(div_u64(len_read, time) * 1000, "/s");
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100416 puts(")");
417 }
418 puts("\n");
Stephen Warren045fa1e2012-10-22 06:43:51 +0000419
David Müller (ELSOFT AG)e9cdf3b2016-01-08 09:39:20 +0100420 setenv_hex("fileaddr", addr);
Simon Glass49c4f032013-02-24 17:33:23 +0000421 setenv_hex("filesize", len_read);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000422
423 return 0;
424}
425
426int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
427 int fstype)
428{
429 if (argc < 2)
430 return CMD_RET_USAGE;
Stephen Warrene9b0f992012-10-30 12:04:17 +0000431 if (argc > 4)
432 return CMD_RET_USAGE;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000433
434 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
435 return 1;
436
Stephen Warrene9b0f992012-10-30 12:04:17 +0000437 if (fs_ls(argc >= 4 ? argv[3] : "/"))
Stephen Warren045fa1e2012-10-22 06:43:51 +0000438 return 1;
439
440 return 0;
441}
Simon Glassa8f6ab52013-04-20 08:42:50 +0000442
Stephen Warren61529162014-02-03 13:21:00 -0700443int file_exists(const char *dev_type, const char *dev_part, const char *file,
444 int fstype)
445{
446 if (fs_set_blk_dev(dev_type, dev_part, fstype))
447 return 0;
448
449 return fs_exists(file);
450}
451
Simon Glassa8f6ab52013-04-20 08:42:50 +0000452int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
Wolfgang Denkb770e882013-10-05 21:07:25 +0200453 int fstype)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000454{
455 unsigned long addr;
456 const char *filename;
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800457 loff_t bytes;
458 loff_t pos;
459 loff_t len;
460 int ret;
Simon Glassa8f6ab52013-04-20 08:42:50 +0000461 unsigned long time;
462
463 if (argc < 6 || argc > 7)
464 return CMD_RET_USAGE;
465
466 if (fs_set_blk_dev(argv[1], argv[2], fstype))
467 return 1;
468
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800469 addr = simple_strtoul(argv[3], NULL, 16);
470 filename = argv[4];
Wolfgang Denkb770e882013-10-05 21:07:25 +0200471 bytes = simple_strtoul(argv[5], NULL, 16);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000472 if (argc >= 7)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200473 pos = simple_strtoul(argv[6], NULL, 16);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000474 else
475 pos = 0;
476
477 time = get_timer(0);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800478 ret = fs_write(filename, addr, pos, bytes, &len);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000479 time = get_timer(time);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800480 if (ret < 0)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000481 return 1;
482
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800483 printf("%llu bytes written in %lu ms", len, time);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000484 if (time > 0) {
485 puts(" (");
Tom Rini9e374e72014-11-24 11:50:46 -0500486 print_size(div_u64(len, time) * 1000, "/s");
Simon Glassa8f6ab52013-04-20 08:42:50 +0000487 puts(")");
488 }
489 puts("\n");
490
491 return 0;
492}
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100493
494int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
495 int fstype)
496{
497 int ret;
498 char uuid[37];
499 memset(uuid, 0, sizeof(uuid));
500
501 if (argc < 3 || argc > 4)
502 return CMD_RET_USAGE;
503
504 if (fs_set_blk_dev(argv[1], argv[2], fstype))
505 return 1;
506
507 ret = fs_uuid(uuid);
508 if (ret)
509 return CMD_RET_FAILURE;
510
511 if (argc == 4)
512 setenv(argv[3], uuid);
513 else
514 printf("%s\n", uuid);
515
516 return CMD_RET_SUCCESS;
517}
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100518
519int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
520{
521 struct fstype_info *info;
522
523 if (argc < 3 || argc > 4)
524 return CMD_RET_USAGE;
525
526 if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
527 return 1;
528
529 info = fs_get_info(fs_type);
530
531 if (argc == 4)
532 setenv(argv[3], info->name);
533 else
534 printf("%s\n", info->name);
535
536 return CMD_RET_SUCCESS;
537}
538