blob: fc0c953fcbd13a6089a6dbdaade234c104710261 [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;
Rob Clark4bbcc962017-09-09 13:15:55 -040024static int fs_dev_part;
Stephen Warren045fa1e2012-10-22 06:43:51 +000025static disk_partition_t fs_partition;
26static int fs_type = FS_TYPE_ANY;
27
Simon Glass4101f682016-02-29 15:25:34 -070028static inline int fs_probe_unsupported(struct blk_desc *fs_dev_desc,
Simon Glass2ded0d42012-12-26 09:53:31 +000029 disk_partition_t *fs_partition)
Simon Glass436e2b72012-12-26 09:53:29 +000030{
31 printf("** Unrecognized filesystem type **\n");
32 return -1;
33}
34
Stephen Warren045fa1e2012-10-22 06:43:51 +000035static inline int fs_ls_unsupported(const char *dirname)
36{
Stephen Warren045fa1e2012-10-22 06:43:51 +000037 return -1;
38}
39
Stephen Warren61529162014-02-03 13:21:00 -070040static inline int fs_exists_unsupported(const char *filename)
41{
42 return 0;
43}
44
Suriyan Ramasamid455d872014-11-17 14:39:38 -080045static inline int fs_size_unsupported(const char *filename, loff_t *size)
Stephen Warrencf659812014-06-11 12:47:26 -060046{
47 return -1;
48}
49
Simon Glass117e0502012-12-26 09:53:32 +000050static inline int fs_read_unsupported(const char *filename, void *buf,
Suriyan Ramasamid455d872014-11-17 14:39:38 -080051 loff_t offset, loff_t len,
52 loff_t *actread)
Stephen Warren045fa1e2012-10-22 06:43:51 +000053{
Stephen Warren045fa1e2012-10-22 06:43:51 +000054 return -1;
55}
56
Simon Glassa8f6ab52013-04-20 08:42:50 +000057static inline int fs_write_unsupported(const char *filename, void *buf,
Suriyan Ramasamid455d872014-11-17 14:39:38 -080058 loff_t offset, loff_t len,
59 loff_t *actwrite)
Simon Glassa8f6ab52013-04-20 08:42:50 +000060{
61 return -1;
62}
63
Simon Glass436e2b72012-12-26 09:53:29 +000064static inline void fs_close_unsupported(void)
65{
66}
67
Christian Gmeiner59e890e2014-11-12 14:35:04 +010068static inline int fs_uuid_unsupported(char *uuid_str)
69{
70 return -1;
71}
72
Rob Clark4bbcc962017-09-09 13:15:55 -040073static inline int fs_opendir_unsupported(const char *filename,
74 struct fs_dir_stream **dirs)
75{
76 return -EACCES;
77}
78
Simon Glass436e2b72012-12-26 09:53:29 +000079struct fstype_info {
Stephen Warren045fa1e2012-10-22 06:43:51 +000080 int fstype;
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +010081 char *name;
Stephen Warren377202b2014-02-03 13:21:01 -070082 /*
83 * Is it legal to pass NULL as .probe()'s fs_dev_desc parameter? This
84 * should be false in most cases. For "virtual" filesystems which
85 * aren't based on a U-Boot block device (e.g. sandbox), this can be
86 * set to true. This should also be true for the dumm entry at the end
87 * of fstypes[], since that is essentially a "virtual" (non-existent)
88 * filesystem.
89 */
90 bool null_dev_desc_ok;
Simon Glass4101f682016-02-29 15:25:34 -070091 int (*probe)(struct blk_desc *fs_dev_desc,
Simon Glass2ded0d42012-12-26 09:53:31 +000092 disk_partition_t *fs_partition);
Simon Glass436e2b72012-12-26 09:53:29 +000093 int (*ls)(const char *dirname);
Stephen Warren61529162014-02-03 13:21:00 -070094 int (*exists)(const char *filename);
Suriyan Ramasamid455d872014-11-17 14:39:38 -080095 int (*size)(const char *filename, loff_t *size);
96 int (*read)(const char *filename, void *buf, loff_t offset,
97 loff_t len, loff_t *actread);
98 int (*write)(const char *filename, void *buf, loff_t offset,
99 loff_t len, loff_t *actwrite);
Simon Glass436e2b72012-12-26 09:53:29 +0000100 void (*close)(void);
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100101 int (*uuid)(char *uuid_str);
Rob Clark4bbcc962017-09-09 13:15:55 -0400102 /*
103 * Open a directory stream. On success return 0 and directory
104 * stream pointer via 'dirsp'. On error, return -errno. See
105 * fs_opendir().
106 */
107 int (*opendir)(const char *filename, struct fs_dir_stream **dirsp);
108 /*
109 * Read next entry from directory stream. On success return 0
110 * and directory entry pointer via 'dentp'. On error return
111 * -errno. See fs_readdir().
112 */
113 int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
114 /* see fs_closedir() */
115 void (*closedir)(struct fs_dir_stream *dirs);
Simon Glass436e2b72012-12-26 09:53:29 +0000116};
117
118static struct fstype_info fstypes[] = {
119#ifdef CONFIG_FS_FAT
Stephen Warren045fa1e2012-10-22 06:43:51 +0000120 {
121 .fstype = FS_TYPE_FAT,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100122 .name = "fat",
Stephen Warren377202b2014-02-03 13:21:01 -0700123 .null_dev_desc_ok = false,
Simon Glasse6d52412012-12-26 09:53:33 +0000124 .probe = fat_set_blk_dev,
125 .close = fat_close,
Simon Glass436e2b72012-12-26 09:53:29 +0000126 .ls = file_fat_ls,
Stephen Warrenb7b5f312014-02-03 13:21:10 -0700127 .exists = fat_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600128 .size = fat_size,
Simon Glasse6d52412012-12-26 09:53:33 +0000129 .read = fat_read_file,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800130#ifdef CONFIG_FAT_WRITE
131 .write = file_fat_write,
132#else
Stephen Warrenbd6fb312014-02-03 13:20:59 -0700133 .write = fs_write_unsupported,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800134#endif
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100135 .uuid = fs_uuid_unsupported,
Rob Clark4bbcc962017-09-09 13:15:55 -0400136 .opendir = fs_opendir_unsupported,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000137 },
Simon Glass436e2b72012-12-26 09:53:29 +0000138#endif
139#ifdef CONFIG_FS_EXT4
Stephen Warren045fa1e2012-10-22 06:43:51 +0000140 {
141 .fstype = FS_TYPE_EXT,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100142 .name = "ext4",
Stephen Warren377202b2014-02-03 13:21:01 -0700143 .null_dev_desc_ok = false,
Simon Glasse6d52412012-12-26 09:53:33 +0000144 .probe = ext4fs_probe,
145 .close = ext4fs_close,
Simon Glass436e2b72012-12-26 09:53:29 +0000146 .ls = ext4fs_ls,
Stephen Warren55af5c92014-02-03 13:21:09 -0700147 .exists = ext4fs_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600148 .size = ext4fs_size,
Simon Glasse6d52412012-12-26 09:53:33 +0000149 .read = ext4_read_file,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800150#ifdef CONFIG_CMD_EXT4_WRITE
151 .write = ext4_write_file,
152#else
Stephen Warrenbd6fb312014-02-03 13:20:59 -0700153 .write = fs_write_unsupported,
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800154#endif
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100155 .uuid = ext4fs_uuid,
Rob Clark4bbcc962017-09-09 13:15:55 -0400156 .opendir = fs_opendir_unsupported,
Simon Glass436e2b72012-12-26 09:53:29 +0000157 },
158#endif
Simon Glass92ccc962012-12-26 09:53:35 +0000159#ifdef CONFIG_SANDBOX
160 {
161 .fstype = FS_TYPE_SANDBOX,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100162 .name = "sandbox",
Stephen Warren377202b2014-02-03 13:21:01 -0700163 .null_dev_desc_ok = true,
Simon Glass92ccc962012-12-26 09:53:35 +0000164 .probe = sandbox_fs_set_blk_dev,
165 .close = sandbox_fs_close,
166 .ls = sandbox_fs_ls,
Stephen Warren0a30aa12014-02-03 13:21:07 -0700167 .exists = sandbox_fs_exists,
Stephen Warrencf659812014-06-11 12:47:26 -0600168 .size = sandbox_fs_size,
Simon Glass92ccc962012-12-26 09:53:35 +0000169 .read = fs_read_sandbox,
Simon Glass7eb2c8d2013-04-20 08:42:51 +0000170 .write = fs_write_sandbox,
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100171 .uuid = fs_uuid_unsupported,
Rob Clark4bbcc962017-09-09 13:15:55 -0400172 .opendir = fs_opendir_unsupported,
Simon Glass92ccc962012-12-26 09:53:35 +0000173 },
174#endif
Hans de Goede251cee02015-09-17 18:46:58 -0400175#ifdef CONFIG_CMD_UBIFS
176 {
177 .fstype = FS_TYPE_UBIFS,
178 .name = "ubifs",
179 .null_dev_desc_ok = true,
180 .probe = ubifs_set_blk_dev,
181 .close = ubifs_close,
182 .ls = ubifs_ls,
183 .exists = ubifs_exists,
184 .size = ubifs_size,
185 .read = ubifs_read,
186 .write = fs_write_unsupported,
187 .uuid = fs_uuid_unsupported,
Rob Clark4bbcc962017-09-09 13:15:55 -0400188 .opendir = fs_opendir_unsupported,
Hans de Goede251cee02015-09-17 18:46:58 -0400189 },
190#endif
Simon Glass436e2b72012-12-26 09:53:29 +0000191 {
192 .fstype = FS_TYPE_ANY,
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100193 .name = "unsupported",
Stephen Warren377202b2014-02-03 13:21:01 -0700194 .null_dev_desc_ok = true,
Simon Glass436e2b72012-12-26 09:53:29 +0000195 .probe = fs_probe_unsupported,
196 .close = fs_close_unsupported,
197 .ls = fs_ls_unsupported,
Stephen Warren61529162014-02-03 13:21:00 -0700198 .exists = fs_exists_unsupported,
Stephen Warrencf659812014-06-11 12:47:26 -0600199 .size = fs_size_unsupported,
Simon Glass436e2b72012-12-26 09:53:29 +0000200 .read = fs_read_unsupported,
Simon Glassa8f6ab52013-04-20 08:42:50 +0000201 .write = fs_write_unsupported,
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100202 .uuid = fs_uuid_unsupported,
Rob Clark4bbcc962017-09-09 13:15:55 -0400203 .opendir = fs_opendir_unsupported,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000204 },
205};
206
Simon Glassc6f548d2012-12-26 09:53:30 +0000207static struct fstype_info *fs_get_info(int fstype)
208{
209 struct fstype_info *info;
210 int i;
211
212 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) {
213 if (fstype == info->fstype)
214 return info;
215 }
216
217 /* Return the 'unsupported' sentinel */
218 return info;
219}
220
Stephen Warren045fa1e2012-10-22 06:43:51 +0000221int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
222{
Simon Glass436e2b72012-12-26 09:53:29 +0000223 struct fstype_info *info;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000224 int part, i;
Stephen Warrena1b231c2012-10-30 07:50:47 +0000225#ifdef CONFIG_NEEDS_MANUAL_RELOC
226 static int relocated;
227
228 if (!relocated) {
Simon Glass436e2b72012-12-26 09:53:29 +0000229 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
230 i++, info++) {
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100231 info->name += gd->reloc_off;
Simon Glass436e2b72012-12-26 09:53:29 +0000232 info->probe += gd->reloc_off;
233 info->close += gd->reloc_off;
234 info->ls += gd->reloc_off;
235 info->read += gd->reloc_off;
Simon Glassa8f6ab52013-04-20 08:42:50 +0000236 info->write += gd->reloc_off;
Simon Glass436e2b72012-12-26 09:53:29 +0000237 }
Stephen Warrena1b231c2012-10-30 07:50:47 +0000238 relocated = 1;
239 }
240#endif
Stephen Warren045fa1e2012-10-22 06:43:51 +0000241
Simon Glasse35929e2016-02-29 15:25:44 -0700242 part = blk_get_device_part_str(ifname, dev_part_str, &fs_dev_desc,
Stephen Warren045fa1e2012-10-22 06:43:51 +0000243 &fs_partition, 1);
244 if (part < 0)
245 return -1;
246
Simon Glass436e2b72012-12-26 09:53:29 +0000247 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
248 if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
249 fstype != info->fstype)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000250 continue;
251
Stephen Warren377202b2014-02-03 13:21:01 -0700252 if (!fs_dev_desc && !info->null_dev_desc_ok)
253 continue;
254
Simon Glass2ded0d42012-12-26 09:53:31 +0000255 if (!info->probe(fs_dev_desc, &fs_partition)) {
Simon Glass436e2b72012-12-26 09:53:29 +0000256 fs_type = info->fstype;
Rob Clark4bbcc962017-09-09 13:15:55 -0400257 fs_dev_part = part;
258 return 0;
259 }
260 }
261
262 return -1;
263}
264
265/* set current blk device w/ blk_desc + partition # */
266int fs_set_blk_dev_with_part(struct blk_desc *desc, int part)
267{
268 struct fstype_info *info;
269 int ret, i;
270
271 if (part >= 1)
272 ret = part_get_info(desc, part, &fs_partition);
273 else
274 ret = part_get_info_whole_disk(desc, &fs_partition);
275 if (ret)
276 return ret;
277 fs_dev_desc = desc;
278
279 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
280 if (!info->probe(fs_dev_desc, &fs_partition)) {
281 fs_type = info->fstype;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000282 return 0;
283 }
284 }
285
Stephen Warren045fa1e2012-10-22 06:43:51 +0000286 return -1;
287}
288
289static void fs_close(void)
290{
Simon Glassc6f548d2012-12-26 09:53:30 +0000291 struct fstype_info *info = fs_get_info(fs_type);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000292
Simon Glassc6f548d2012-12-26 09:53:30 +0000293 info->close();
Simon Glasse6d52412012-12-26 09:53:33 +0000294
Stephen Warren045fa1e2012-10-22 06:43:51 +0000295 fs_type = FS_TYPE_ANY;
296}
297
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100298int fs_uuid(char *uuid_str)
299{
300 struct fstype_info *info = fs_get_info(fs_type);
301
302 return info->uuid(uuid_str);
303}
304
Stephen Warren045fa1e2012-10-22 06:43:51 +0000305int fs_ls(const char *dirname)
306{
307 int ret;
308
Simon Glassc6f548d2012-12-26 09:53:30 +0000309 struct fstype_info *info = fs_get_info(fs_type);
310
311 ret = info->ls(dirname);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000312
Simon Glasse6d52412012-12-26 09:53:33 +0000313 fs_type = FS_TYPE_ANY;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000314 fs_close();
315
316 return ret;
317}
318
Stephen Warren61529162014-02-03 13:21:00 -0700319int fs_exists(const char *filename)
320{
321 int ret;
322
323 struct fstype_info *info = fs_get_info(fs_type);
324
325 ret = info->exists(filename);
326
327 fs_close();
328
329 return ret;
330}
331
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800332int fs_size(const char *filename, loff_t *size)
Stephen Warrencf659812014-06-11 12:47:26 -0600333{
334 int ret;
335
336 struct fstype_info *info = fs_get_info(fs_type);
337
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800338 ret = info->size(filename, size);
Stephen Warrencf659812014-06-11 12:47:26 -0600339
340 fs_close();
341
342 return ret;
343}
344
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800345int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
346 loff_t *actread)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000347{
Simon Glassc6f548d2012-12-26 09:53:30 +0000348 struct fstype_info *info = fs_get_info(fs_type);
Simon Glass117e0502012-12-26 09:53:32 +0000349 void *buf;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000350 int ret;
351
Simon Glass117e0502012-12-26 09:53:32 +0000352 /*
353 * We don't actually know how many bytes are being read, since len==0
354 * means read the whole file.
355 */
356 buf = map_sysmem(addr, len);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800357 ret = info->read(filename, buf, offset, len, actread);
Simon Glass117e0502012-12-26 09:53:32 +0000358 unmap_sysmem(buf);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000359
Simon Glassc6f548d2012-12-26 09:53:30 +0000360 /* If we requested a specific number of bytes, check we got it */
Max Krummenacher7a3e70c2015-08-05 17:16:58 +0200361 if (ret == 0 && len && *actread != len)
362 printf("** %s shorter than offset + len **\n", filename);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000363 fs_close();
364
365 return ret;
366}
367
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800368int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
369 loff_t *actwrite)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000370{
371 struct fstype_info *info = fs_get_info(fs_type);
372 void *buf;
373 int ret;
374
Simon Glassa8f6ab52013-04-20 08:42:50 +0000375 buf = map_sysmem(addr, len);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800376 ret = info->write(filename, buf, offset, len, actwrite);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000377 unmap_sysmem(buf);
378
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800379 if (ret < 0 && len != *actwrite) {
Simon Glassa8f6ab52013-04-20 08:42:50 +0000380 printf("** Unable to write file %s **\n", filename);
381 ret = -1;
382 }
383 fs_close();
384
385 return ret;
386}
387
Rob Clark4bbcc962017-09-09 13:15:55 -0400388struct fs_dir_stream *fs_opendir(const char *filename)
389{
390 struct fstype_info *info = fs_get_info(fs_type);
391 struct fs_dir_stream *dirs = NULL;
392 int ret;
393
394 ret = info->opendir(filename, &dirs);
395 fs_close();
396 if (ret) {
397 errno = -ret;
398 return NULL;
399 }
400
401 dirs->desc = fs_dev_desc;
402 dirs->part = fs_dev_part;
403
404 return dirs;
405}
406
407struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs)
408{
409 struct fstype_info *info;
410 struct fs_dirent *dirent;
411 int ret;
412
413 fs_set_blk_dev_with_part(dirs->desc, dirs->part);
414 info = fs_get_info(fs_type);
415
416 ret = info->readdir(dirs, &dirent);
417 fs_close();
418 if (ret) {
419 errno = -ret;
420 return NULL;
421 }
422
423 return dirent;
424}
425
426void fs_closedir(struct fs_dir_stream *dirs)
427{
428 struct fstype_info *info;
429
430 if (!dirs)
431 return;
432
433 fs_set_blk_dev_with_part(dirs->desc, dirs->part);
434 info = fs_get_info(fs_type);
435
436 info->closedir(dirs);
437 fs_close();
438}
439
440
Stephen Warrencf659812014-06-11 12:47:26 -0600441int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
442 int fstype)
443{
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800444 loff_t size;
Stephen Warrencf659812014-06-11 12:47:26 -0600445
446 if (argc != 4)
447 return CMD_RET_USAGE;
448
449 if (fs_set_blk_dev(argv[1], argv[2], fstype))
450 return 1;
451
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800452 if (fs_size(argv[3], &size) < 0)
Stephen Warrencf659812014-06-11 12:47:26 -0600453 return CMD_RET_FAILURE;
454
Simon Glass018f5302017-08-03 12:22:10 -0600455 env_set_hex("filesize", size);
Stephen Warrencf659812014-06-11 12:47:26 -0600456
457 return 0;
458}
459
Stephen Warrenf9b55e22012-10-31 11:05:07 +0000460int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
Wolfgang Denkb770e882013-10-05 21:07:25 +0200461 int fstype)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000462{
463 unsigned long addr;
464 const char *addr_str;
465 const char *filename;
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800466 loff_t bytes;
467 loff_t pos;
468 loff_t len_read;
469 int ret;
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100470 unsigned long time;
Pavel Machek949bbd72014-07-09 22:42:57 +0200471 char *ep;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000472
Stephen Warrene9b0f992012-10-30 12:04:17 +0000473 if (argc < 2)
474 return CMD_RET_USAGE;
475 if (argc > 7)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000476 return CMD_RET_USAGE;
477
Stephen Warrene9b0f992012-10-30 12:04:17 +0000478 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
Stephen Warren045fa1e2012-10-22 06:43:51 +0000479 return 1;
480
481 if (argc >= 4) {
Pavel Machek949bbd72014-07-09 22:42:57 +0200482 addr = simple_strtoul(argv[3], &ep, 16);
483 if (ep == argv[3] || *ep != '\0')
484 return CMD_RET_USAGE;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000485 } else {
Simon Glass00caae62017-08-03 12:22:12 -0600486 addr_str = env_get("loadaddr");
Stephen Warren045fa1e2012-10-22 06:43:51 +0000487 if (addr_str != NULL)
488 addr = simple_strtoul(addr_str, NULL, 16);
489 else
490 addr = CONFIG_SYS_LOAD_ADDR;
491 }
492 if (argc >= 5) {
493 filename = argv[4];
494 } else {
Simon Glass00caae62017-08-03 12:22:12 -0600495 filename = env_get("bootfile");
Stephen Warren045fa1e2012-10-22 06:43:51 +0000496 if (!filename) {
497 puts("** No boot file defined **\n");
498 return 1;
499 }
500 }
501 if (argc >= 6)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200502 bytes = simple_strtoul(argv[5], NULL, 16);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000503 else
504 bytes = 0;
505 if (argc >= 7)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200506 pos = simple_strtoul(argv[6], NULL, 16);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000507 else
508 pos = 0;
509
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100510 time = get_timer(0);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800511 ret = fs_read(filename, addr, pos, bytes, &len_read);
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100512 time = get_timer(time);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800513 if (ret < 0)
Stephen Warren045fa1e2012-10-22 06:43:51 +0000514 return 1;
515
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800516 printf("%llu bytes read in %lu ms", len_read, time);
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100517 if (time > 0) {
518 puts(" (");
Tom Rini9e374e72014-11-24 11:50:46 -0500519 print_size(div_u64(len_read, time) * 1000, "/s");
Andreas Bießmannda1fd962012-11-14 13:32:37 +0100520 puts(")");
521 }
522 puts("\n");
Stephen Warren045fa1e2012-10-22 06:43:51 +0000523
Simon Glass018f5302017-08-03 12:22:10 -0600524 env_set_hex("fileaddr", addr);
525 env_set_hex("filesize", len_read);
Stephen Warren045fa1e2012-10-22 06:43:51 +0000526
527 return 0;
528}
529
530int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
531 int fstype)
532{
533 if (argc < 2)
534 return CMD_RET_USAGE;
Stephen Warrene9b0f992012-10-30 12:04:17 +0000535 if (argc > 4)
536 return CMD_RET_USAGE;
Stephen Warren045fa1e2012-10-22 06:43:51 +0000537
538 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
539 return 1;
540
Stephen Warrene9b0f992012-10-30 12:04:17 +0000541 if (fs_ls(argc >= 4 ? argv[3] : "/"))
Stephen Warren045fa1e2012-10-22 06:43:51 +0000542 return 1;
543
544 return 0;
545}
Simon Glassa8f6ab52013-04-20 08:42:50 +0000546
Stephen Warren61529162014-02-03 13:21:00 -0700547int file_exists(const char *dev_type, const char *dev_part, const char *file,
548 int fstype)
549{
550 if (fs_set_blk_dev(dev_type, dev_part, fstype))
551 return 0;
552
553 return fs_exists(file);
554}
555
Simon Glassa8f6ab52013-04-20 08:42:50 +0000556int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
Wolfgang Denkb770e882013-10-05 21:07:25 +0200557 int fstype)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000558{
559 unsigned long addr;
560 const char *filename;
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800561 loff_t bytes;
562 loff_t pos;
563 loff_t len;
564 int ret;
Simon Glassa8f6ab52013-04-20 08:42:50 +0000565 unsigned long time;
566
567 if (argc < 6 || argc > 7)
568 return CMD_RET_USAGE;
569
570 if (fs_set_blk_dev(argv[1], argv[2], fstype))
571 return 1;
572
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800573 addr = simple_strtoul(argv[3], NULL, 16);
574 filename = argv[4];
Wolfgang Denkb770e882013-10-05 21:07:25 +0200575 bytes = simple_strtoul(argv[5], NULL, 16);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000576 if (argc >= 7)
Wolfgang Denkb770e882013-10-05 21:07:25 +0200577 pos = simple_strtoul(argv[6], NULL, 16);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000578 else
579 pos = 0;
580
581 time = get_timer(0);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800582 ret = fs_write(filename, addr, pos, bytes, &len);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000583 time = get_timer(time);
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800584 if (ret < 0)
Simon Glassa8f6ab52013-04-20 08:42:50 +0000585 return 1;
586
Suriyan Ramasamid455d872014-11-17 14:39:38 -0800587 printf("%llu bytes written in %lu ms", len, time);
Simon Glassa8f6ab52013-04-20 08:42:50 +0000588 if (time > 0) {
589 puts(" (");
Tom Rini9e374e72014-11-24 11:50:46 -0500590 print_size(div_u64(len, time) * 1000, "/s");
Simon Glassa8f6ab52013-04-20 08:42:50 +0000591 puts(")");
592 }
593 puts("\n");
594
595 return 0;
596}
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100597
598int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
599 int fstype)
600{
601 int ret;
602 char uuid[37];
603 memset(uuid, 0, sizeof(uuid));
604
605 if (argc < 3 || argc > 4)
606 return CMD_RET_USAGE;
607
608 if (fs_set_blk_dev(argv[1], argv[2], fstype))
609 return 1;
610
611 ret = fs_uuid(uuid);
612 if (ret)
613 return CMD_RET_FAILURE;
614
615 if (argc == 4)
Simon Glass382bee52017-08-03 12:22:09 -0600616 env_set(argv[3], uuid);
Christian Gmeiner59e890e2014-11-12 14:35:04 +0100617 else
618 printf("%s\n", uuid);
619
620 return CMD_RET_SUCCESS;
621}
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100622
623int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
624{
625 struct fstype_info *info;
626
627 if (argc < 3 || argc > 4)
628 return CMD_RET_USAGE;
629
630 if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
631 return 1;
632
633 info = fs_get_info(fs_type);
634
635 if (argc == 4)
Simon Glass382bee52017-08-03 12:22:09 -0600636 env_set(argv[3], info->name);
Sjoerd Simons1a1ad8e2015-01-05 18:13:36 +0100637 else
638 printf("%s\n", info->name);
639
640 return CMD_RET_SUCCESS;
641}
642