xref: /openbmc/u-boot/fs/fs.c (revision dbe70c7d4e3d5c705a98d82952e05a591efd0683)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
2045fa1e1SStephen Warren /*
3045fa1e1SStephen Warren  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
4045fa1e1SStephen Warren  */
5045fa1e1SStephen Warren 
6045fa1e1SStephen Warren #include <config.h>
759e890efSChristian Gmeiner #include <errno.h>
8045fa1e1SStephen Warren #include <common.h>
90eb25b61SJoe Hershberger #include <mapmem.h>
10045fa1e1SStephen Warren #include <part.h>
11045fa1e1SStephen Warren #include <ext4fs.h>
12045fa1e1SStephen Warren #include <fat.h>
13045fa1e1SStephen Warren #include <fs.h>
1492ccc96bSSimon Glass #include <sandboxfs.h>
15251cee0dSHans de Goede #include <ubifs_uboot.h>
160c936ee3SMarek Behún #include <btrfs.h>
17117e0507SSimon Glass #include <asm/io.h>
189e374e7bSTom Rini #include <div64.h>
199e374e7bSTom Rini #include <linux/math64.h>
20045fa1e1SStephen Warren 
21a1b231ceSStephen Warren DECLARE_GLOBAL_DATA_PTR;
22a1b231ceSStephen Warren 
234101f687SSimon Glass static struct blk_desc *fs_dev_desc;
244bbcc965SRob Clark static int fs_dev_part;
25045fa1e1SStephen Warren static disk_partition_t fs_partition;
26045fa1e1SStephen Warren static int fs_type = FS_TYPE_ANY;
27045fa1e1SStephen Warren 
fs_probe_unsupported(struct blk_desc * fs_dev_desc,disk_partition_t * fs_partition)284101f687SSimon Glass static inline int fs_probe_unsupported(struct blk_desc *fs_dev_desc,
292ded0d47SSimon Glass 				      disk_partition_t *fs_partition)
30436e2b73SSimon Glass {
31436e2b73SSimon Glass 	printf("** Unrecognized filesystem type **\n");
32436e2b73SSimon Glass 	return -1;
33436e2b73SSimon Glass }
34436e2b73SSimon Glass 
fs_ls_unsupported(const char * dirname)35045fa1e1SStephen Warren static inline int fs_ls_unsupported(const char *dirname)
36045fa1e1SStephen Warren {
37045fa1e1SStephen Warren 	return -1;
38045fa1e1SStephen Warren }
39045fa1e1SStephen Warren 
4089191d62SRob Clark /* generic implementation of ls in terms of opendir/readdir/closedir */
4189191d62SRob Clark __maybe_unused
fs_ls_generic(const char * dirname)4289191d62SRob Clark static int fs_ls_generic(const char *dirname)
4389191d62SRob Clark {
4489191d62SRob Clark 	struct fs_dir_stream *dirs;
4589191d62SRob Clark 	struct fs_dirent *dent;
4689191d62SRob Clark 	int nfiles = 0, ndirs = 0;
4789191d62SRob Clark 
4889191d62SRob Clark 	dirs = fs_opendir(dirname);
4989191d62SRob Clark 	if (!dirs)
5089191d62SRob Clark 		return -errno;
5189191d62SRob Clark 
5289191d62SRob Clark 	while ((dent = fs_readdir(dirs))) {
5389191d62SRob Clark 		if (dent->type == FS_DT_DIR) {
5489191d62SRob Clark 			printf("            %s/\n", dent->name);
5589191d62SRob Clark 			ndirs++;
5689191d62SRob Clark 		} else {
5789191d62SRob Clark 			printf(" %8lld   %s\n", dent->size, dent->name);
5889191d62SRob Clark 			nfiles++;
5989191d62SRob Clark 		}
6089191d62SRob Clark 	}
6189191d62SRob Clark 
6289191d62SRob Clark 	fs_closedir(dirs);
6389191d62SRob Clark 
6489191d62SRob Clark 	printf("\n%d file(s), %d dir(s)\n\n", nfiles, ndirs);
6589191d62SRob Clark 
6689191d62SRob Clark 	return 0;
6789191d62SRob Clark }
6889191d62SRob Clark 
fs_exists_unsupported(const char * filename)696152916aSStephen Warren static inline int fs_exists_unsupported(const char *filename)
706152916aSStephen Warren {
716152916aSStephen Warren 	return 0;
726152916aSStephen Warren }
736152916aSStephen Warren 
fs_size_unsupported(const char * filename,loff_t * size)74d455d878SSuriyan Ramasami static inline int fs_size_unsupported(const char *filename, loff_t *size)
75cf659819SStephen Warren {
76cf659819SStephen Warren 	return -1;
77cf659819SStephen Warren }
78cf659819SStephen Warren 
fs_read_unsupported(const char * filename,void * buf,loff_t offset,loff_t len,loff_t * actread)79117e0507SSimon Glass static inline int fs_read_unsupported(const char *filename, void *buf,
80d455d878SSuriyan Ramasami 				      loff_t offset, loff_t len,
81d455d878SSuriyan Ramasami 				      loff_t *actread)
82045fa1e1SStephen Warren {
83045fa1e1SStephen Warren 	return -1;
84045fa1e1SStephen Warren }
85045fa1e1SStephen Warren 
fs_write_unsupported(const char * filename,void * buf,loff_t offset,loff_t len,loff_t * actwrite)86a8f6ab52SSimon Glass static inline int fs_write_unsupported(const char *filename, void *buf,
87d455d878SSuriyan Ramasami 				      loff_t offset, loff_t len,
88d455d878SSuriyan Ramasami 				      loff_t *actwrite)
89a8f6ab52SSimon Glass {
90a8f6ab52SSimon Glass 	return -1;
91a8f6ab52SSimon Glass }
92a8f6ab52SSimon Glass 
fs_close_unsupported(void)93436e2b73SSimon Glass static inline void fs_close_unsupported(void)
94436e2b73SSimon Glass {
95436e2b73SSimon Glass }
96436e2b73SSimon Glass 
fs_uuid_unsupported(char * uuid_str)9759e890efSChristian Gmeiner static inline int fs_uuid_unsupported(char *uuid_str)
9859e890efSChristian Gmeiner {
9959e890efSChristian Gmeiner 	return -1;
10059e890efSChristian Gmeiner }
10159e890efSChristian Gmeiner 
fs_opendir_unsupported(const char * filename,struct fs_dir_stream ** dirs)1024bbcc965SRob Clark static inline int fs_opendir_unsupported(const char *filename,
1034bbcc965SRob Clark 					 struct fs_dir_stream **dirs)
1044bbcc965SRob Clark {
1054bbcc965SRob Clark 	return -EACCES;
1064bbcc965SRob Clark }
1074bbcc965SRob Clark 
fs_unlink_unsupported(const char * filename)108e2519dafSAKASHI Takahiro static inline int fs_unlink_unsupported(const char *filename)
109e2519dafSAKASHI Takahiro {
110e2519dafSAKASHI Takahiro 	return -1;
111e2519dafSAKASHI Takahiro }
112e2519dafSAKASHI Takahiro 
fs_mkdir_unsupported(const char * dirname)113e7074cffSAKASHI Takahiro static inline int fs_mkdir_unsupported(const char *dirname)
114e7074cffSAKASHI Takahiro {
115e7074cffSAKASHI Takahiro 	return -1;
116e7074cffSAKASHI Takahiro }
117e7074cffSAKASHI Takahiro 
118436e2b73SSimon Glass struct fstype_info {
119045fa1e1SStephen Warren 	int fstype;
1201a1ad8e0SSjoerd Simons 	char *name;
121377202b5SStephen Warren 	/*
122377202b5SStephen Warren 	 * Is it legal to pass NULL as .probe()'s  fs_dev_desc parameter? This
123377202b5SStephen Warren 	 * should be false in most cases. For "virtual" filesystems which
124377202b5SStephen Warren 	 * aren't based on a U-Boot block device (e.g. sandbox), this can be
125ca230b09SHeinrich Schuchardt 	 * set to true. This should also be true for the dummy entry at the end
126377202b5SStephen Warren 	 * of fstypes[], since that is essentially a "virtual" (non-existent)
127377202b5SStephen Warren 	 * filesystem.
128377202b5SStephen Warren 	 */
129377202b5SStephen Warren 	bool null_dev_desc_ok;
1304101f687SSimon Glass 	int (*probe)(struct blk_desc *fs_dev_desc,
1312ded0d47SSimon Glass 		     disk_partition_t *fs_partition);
132436e2b73SSimon Glass 	int (*ls)(const char *dirname);
1336152916aSStephen Warren 	int (*exists)(const char *filename);
134d455d878SSuriyan Ramasami 	int (*size)(const char *filename, loff_t *size);
135d455d878SSuriyan Ramasami 	int (*read)(const char *filename, void *buf, loff_t offset,
136d455d878SSuriyan Ramasami 		    loff_t len, loff_t *actread);
137d455d878SSuriyan Ramasami 	int (*write)(const char *filename, void *buf, loff_t offset,
138d455d878SSuriyan Ramasami 		     loff_t len, loff_t *actwrite);
139436e2b73SSimon Glass 	void (*close)(void);
14059e890efSChristian Gmeiner 	int (*uuid)(char *uuid_str);
1414bbcc965SRob Clark 	/*
1424bbcc965SRob Clark 	 * Open a directory stream.  On success return 0 and directory
1434bbcc965SRob Clark 	 * stream pointer via 'dirsp'.  On error, return -errno.  See
1444bbcc965SRob Clark 	 * fs_opendir().
1454bbcc965SRob Clark 	 */
1464bbcc965SRob Clark 	int (*opendir)(const char *filename, struct fs_dir_stream **dirsp);
1474bbcc965SRob Clark 	/*
1484bbcc965SRob Clark 	 * Read next entry from directory stream.  On success return 0
1494bbcc965SRob Clark 	 * and directory entry pointer via 'dentp'.  On error return
1504bbcc965SRob Clark 	 * -errno.  See fs_readdir().
1514bbcc965SRob Clark 	 */
1524bbcc965SRob Clark 	int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
1534bbcc965SRob Clark 	/* see fs_closedir() */
1544bbcc965SRob Clark 	void (*closedir)(struct fs_dir_stream *dirs);
155e2519dafSAKASHI Takahiro 	int (*unlink)(const char *filename);
156e7074cffSAKASHI Takahiro 	int (*mkdir)(const char *dirname);
157436e2b73SSimon Glass };
158436e2b73SSimon Glass 
159436e2b73SSimon Glass static struct fstype_info fstypes[] = {
160436e2b73SSimon Glass #ifdef CONFIG_FS_FAT
161045fa1e1SStephen Warren 	{
162045fa1e1SStephen Warren 		.fstype = FS_TYPE_FAT,
1631a1ad8e0SSjoerd Simons 		.name = "fat",
164377202b5SStephen Warren 		.null_dev_desc_ok = false,
165e6d52415SSimon Glass 		.probe = fat_set_blk_dev,
166e6d52415SSimon Glass 		.close = fat_close,
16789191d62SRob Clark 		.ls = fs_ls_generic,
168b7b5f319SStephen Warren 		.exists = fat_exists,
169cf659819SStephen Warren 		.size = fat_size,
170e6d52415SSimon Glass 		.read = fat_read_file,
171d8c3ea99STien Fong Chee #if CONFIG_IS_ENABLED(FAT_WRITE)
172d455d878SSuriyan Ramasami 		.write = file_fat_write,
173f8240ce9SAKASHI Takahiro 		.unlink = fat_unlink,
17431a18d57SAKASHI Takahiro 		.mkdir = fat_mkdir,
175d455d878SSuriyan Ramasami #else
176bd6fb31fSStephen Warren 		.write = fs_write_unsupported,
177f8240ce9SAKASHI Takahiro 		.unlink = fs_unlink_unsupported,
17831a18d57SAKASHI Takahiro 		.mkdir = fs_mkdir_unsupported,
179d455d878SSuriyan Ramasami #endif
18059e890efSChristian Gmeiner 		.uuid = fs_uuid_unsupported,
18189191d62SRob Clark 		.opendir = fat_opendir,
18289191d62SRob Clark 		.readdir = fat_readdir,
18389191d62SRob Clark 		.closedir = fat_closedir,
184045fa1e1SStephen Warren 	},
185436e2b73SSimon Glass #endif
186cafc429fSTien Fong Chee 
187cafc429fSTien Fong Chee #if CONFIG_IS_ENABLED(FS_EXT4)
188045fa1e1SStephen Warren 	{
189045fa1e1SStephen Warren 		.fstype = FS_TYPE_EXT,
1901a1ad8e0SSjoerd Simons 		.name = "ext4",
191377202b5SStephen Warren 		.null_dev_desc_ok = false,
192e6d52415SSimon Glass 		.probe = ext4fs_probe,
193e6d52415SSimon Glass 		.close = ext4fs_close,
194436e2b73SSimon Glass 		.ls = ext4fs_ls,
19555af5c93SStephen Warren 		.exists = ext4fs_exists,
196cf659819SStephen Warren 		.size = ext4fs_size,
197e6d52415SSimon Glass 		.read = ext4_read_file,
198d455d878SSuriyan Ramasami #ifdef CONFIG_CMD_EXT4_WRITE
199d455d878SSuriyan Ramasami 		.write = ext4_write_file,
200d455d878SSuriyan Ramasami #else
201bd6fb31fSStephen Warren 		.write = fs_write_unsupported,
202d455d878SSuriyan Ramasami #endif
20359e890efSChristian Gmeiner 		.uuid = ext4fs_uuid,
2044bbcc965SRob Clark 		.opendir = fs_opendir_unsupported,
205e2519dafSAKASHI Takahiro 		.unlink = fs_unlink_unsupported,
206e7074cffSAKASHI Takahiro 		.mkdir = fs_mkdir_unsupported,
207436e2b73SSimon Glass 	},
208436e2b73SSimon Glass #endif
20992ccc96bSSimon Glass #ifdef CONFIG_SANDBOX
21092ccc96bSSimon Glass 	{
21192ccc96bSSimon Glass 		.fstype = FS_TYPE_SANDBOX,
2121a1ad8e0SSjoerd Simons 		.name = "sandbox",
213377202b5SStephen Warren 		.null_dev_desc_ok = true,
21492ccc96bSSimon Glass 		.probe = sandbox_fs_set_blk_dev,
21592ccc96bSSimon Glass 		.close = sandbox_fs_close,
21692ccc96bSSimon Glass 		.ls = sandbox_fs_ls,
2170a30aa1eSStephen Warren 		.exists = sandbox_fs_exists,
218cf659819SStephen Warren 		.size = sandbox_fs_size,
21992ccc96bSSimon Glass 		.read = fs_read_sandbox,
2207eb2c8d5SSimon Glass 		.write = fs_write_sandbox,
22159e890efSChristian Gmeiner 		.uuid = fs_uuid_unsupported,
2224bbcc965SRob Clark 		.opendir = fs_opendir_unsupported,
223e2519dafSAKASHI Takahiro 		.unlink = fs_unlink_unsupported,
224e7074cffSAKASHI Takahiro 		.mkdir = fs_mkdir_unsupported,
22592ccc96bSSimon Glass 	},
22692ccc96bSSimon Glass #endif
227251cee0dSHans de Goede #ifdef CONFIG_CMD_UBIFS
228251cee0dSHans de Goede 	{
229251cee0dSHans de Goede 		.fstype = FS_TYPE_UBIFS,
230251cee0dSHans de Goede 		.name = "ubifs",
231251cee0dSHans de Goede 		.null_dev_desc_ok = true,
232251cee0dSHans de Goede 		.probe = ubifs_set_blk_dev,
233251cee0dSHans de Goede 		.close = ubifs_close,
234251cee0dSHans de Goede 		.ls = ubifs_ls,
235251cee0dSHans de Goede 		.exists = ubifs_exists,
236251cee0dSHans de Goede 		.size = ubifs_size,
237251cee0dSHans de Goede 		.read = ubifs_read,
238251cee0dSHans de Goede 		.write = fs_write_unsupported,
239251cee0dSHans de Goede 		.uuid = fs_uuid_unsupported,
2404bbcc965SRob Clark 		.opendir = fs_opendir_unsupported,
241e2519dafSAKASHI Takahiro 		.unlink = fs_unlink_unsupported,
242e7074cffSAKASHI Takahiro 		.mkdir = fs_mkdir_unsupported,
243251cee0dSHans de Goede 	},
244251cee0dSHans de Goede #endif
2450c936ee3SMarek Behún #ifdef CONFIG_FS_BTRFS
2460c936ee3SMarek Behún 	{
2470c936ee3SMarek Behún 		.fstype = FS_TYPE_BTRFS,
2480c936ee3SMarek Behún 		.name = "btrfs",
2490c936ee3SMarek Behún 		.null_dev_desc_ok = false,
2500c936ee3SMarek Behún 		.probe = btrfs_probe,
2510c936ee3SMarek Behún 		.close = btrfs_close,
2520c936ee3SMarek Behún 		.ls = btrfs_ls,
2530c936ee3SMarek Behún 		.exists = btrfs_exists,
2540c936ee3SMarek Behún 		.size = btrfs_size,
2550c936ee3SMarek Behún 		.read = btrfs_read,
2560c936ee3SMarek Behún 		.write = fs_write_unsupported,
2570c936ee3SMarek Behún 		.uuid = btrfs_uuid,
25838fc683dSMarek Behún 		.opendir = fs_opendir_unsupported,
259e2519dafSAKASHI Takahiro 		.unlink = fs_unlink_unsupported,
260e7074cffSAKASHI Takahiro 		.mkdir = fs_mkdir_unsupported,
2610c936ee3SMarek Behún 	},
2620c936ee3SMarek Behún #endif
263436e2b73SSimon Glass 	{
264436e2b73SSimon Glass 		.fstype = FS_TYPE_ANY,
2651a1ad8e0SSjoerd Simons 		.name = "unsupported",
266377202b5SStephen Warren 		.null_dev_desc_ok = true,
267436e2b73SSimon Glass 		.probe = fs_probe_unsupported,
268436e2b73SSimon Glass 		.close = fs_close_unsupported,
269436e2b73SSimon Glass 		.ls = fs_ls_unsupported,
2706152916aSStephen Warren 		.exists = fs_exists_unsupported,
271cf659819SStephen Warren 		.size = fs_size_unsupported,
272436e2b73SSimon Glass 		.read = fs_read_unsupported,
273a8f6ab52SSimon Glass 		.write = fs_write_unsupported,
27459e890efSChristian Gmeiner 		.uuid = fs_uuid_unsupported,
2754bbcc965SRob Clark 		.opendir = fs_opendir_unsupported,
276e2519dafSAKASHI Takahiro 		.unlink = fs_unlink_unsupported,
277e7074cffSAKASHI Takahiro 		.mkdir = fs_mkdir_unsupported,
278045fa1e1SStephen Warren 	},
279045fa1e1SStephen Warren };
280045fa1e1SStephen Warren 
fs_get_info(int fstype)281c6f548d2SSimon Glass static struct fstype_info *fs_get_info(int fstype)
282c6f548d2SSimon Glass {
283c6f548d2SSimon Glass 	struct fstype_info *info;
284c6f548d2SSimon Glass 	int i;
285c6f548d2SSimon Glass 
286c6f548d2SSimon Glass 	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) {
287c6f548d2SSimon Glass 		if (fstype == info->fstype)
288c6f548d2SSimon Glass 			return info;
289c6f548d2SSimon Glass 	}
290c6f548d2SSimon Glass 
291c6f548d2SSimon Glass 	/* Return the 'unsupported' sentinel */
292c6f548d2SSimon Glass 	return info;
293c6f548d2SSimon Glass }
294c6f548d2SSimon Glass 
2950d488e8fSAlex Kiernan /**
2960d488e8fSAlex Kiernan  * fs_get_type_name() - Get type of current filesystem
2970d488e8fSAlex Kiernan  *
2980d488e8fSAlex Kiernan  * Return: Pointer to filesystem name
2990d488e8fSAlex Kiernan  *
3000d488e8fSAlex Kiernan  * Returns a string describing the current filesystem, or the sentinel
3010d488e8fSAlex Kiernan  * "unsupported" for any unrecognised filesystem.
3020d488e8fSAlex Kiernan  */
fs_get_type_name(void)3030d488e8fSAlex Kiernan const char *fs_get_type_name(void)
3040d488e8fSAlex Kiernan {
3050d488e8fSAlex Kiernan 	return fs_get_info(fs_type)->name;
3060d488e8fSAlex Kiernan }
3070d488e8fSAlex Kiernan 
fs_set_blk_dev(const char * ifname,const char * dev_part_str,int fstype)308045fa1e1SStephen Warren int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
309045fa1e1SStephen Warren {
310436e2b73SSimon Glass 	struct fstype_info *info;
311045fa1e1SStephen Warren 	int part, i;
312a1b231ceSStephen Warren #ifdef CONFIG_NEEDS_MANUAL_RELOC
313a1b231ceSStephen Warren 	static int relocated;
314a1b231ceSStephen Warren 
315a1b231ceSStephen Warren 	if (!relocated) {
316436e2b73SSimon Glass 		for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
317436e2b73SSimon Glass 				i++, info++) {
3181a1ad8e0SSjoerd Simons 			info->name += gd->reloc_off;
319436e2b73SSimon Glass 			info->probe += gd->reloc_off;
320436e2b73SSimon Glass 			info->close += gd->reloc_off;
321436e2b73SSimon Glass 			info->ls += gd->reloc_off;
322436e2b73SSimon Glass 			info->read += gd->reloc_off;
323a8f6ab52SSimon Glass 			info->write += gd->reloc_off;
324436e2b73SSimon Glass 		}
325a1b231ceSStephen Warren 		relocated = 1;
326a1b231ceSStephen Warren 	}
327a1b231ceSStephen Warren #endif
328045fa1e1SStephen Warren 
329e35929e4SSimon Glass 	part = blk_get_device_part_str(ifname, dev_part_str, &fs_dev_desc,
330045fa1e1SStephen Warren 					&fs_partition, 1);
331045fa1e1SStephen Warren 	if (part < 0)
332045fa1e1SStephen Warren 		return -1;
333045fa1e1SStephen Warren 
334436e2b73SSimon Glass 	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
335436e2b73SSimon Glass 		if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
336436e2b73SSimon Glass 				fstype != info->fstype)
337045fa1e1SStephen Warren 			continue;
338045fa1e1SStephen Warren 
339377202b5SStephen Warren 		if (!fs_dev_desc && !info->null_dev_desc_ok)
340377202b5SStephen Warren 			continue;
341377202b5SStephen Warren 
3422ded0d47SSimon Glass 		if (!info->probe(fs_dev_desc, &fs_partition)) {
343436e2b73SSimon Glass 			fs_type = info->fstype;
3444bbcc965SRob Clark 			fs_dev_part = part;
3454bbcc965SRob Clark 			return 0;
3464bbcc965SRob Clark 		}
3474bbcc965SRob Clark 	}
3484bbcc965SRob Clark 
3494bbcc965SRob Clark 	return -1;
3504bbcc965SRob Clark }
3514bbcc965SRob Clark 
3524bbcc965SRob Clark /* set current blk device w/ blk_desc + partition # */
fs_set_blk_dev_with_part(struct blk_desc * desc,int part)3534bbcc965SRob Clark int fs_set_blk_dev_with_part(struct blk_desc *desc, int part)
3544bbcc965SRob Clark {
3554bbcc965SRob Clark 	struct fstype_info *info;
3564bbcc965SRob Clark 	int ret, i;
3574bbcc965SRob Clark 
3584bbcc965SRob Clark 	if (part >= 1)
3594bbcc965SRob Clark 		ret = part_get_info(desc, part, &fs_partition);
3604bbcc965SRob Clark 	else
3614bbcc965SRob Clark 		ret = part_get_info_whole_disk(desc, &fs_partition);
3624bbcc965SRob Clark 	if (ret)
3634bbcc965SRob Clark 		return ret;
3644bbcc965SRob Clark 	fs_dev_desc = desc;
3654bbcc965SRob Clark 
3664bbcc965SRob Clark 	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
3674bbcc965SRob Clark 		if (!info->probe(fs_dev_desc, &fs_partition)) {
3684bbcc965SRob Clark 			fs_type = info->fstype;
369b0c78d8fSAKASHI Takahiro 			fs_dev_part = part;
370045fa1e1SStephen Warren 			return 0;
371045fa1e1SStephen Warren 		}
372045fa1e1SStephen Warren 	}
373045fa1e1SStephen Warren 
374045fa1e1SStephen Warren 	return -1;
375045fa1e1SStephen Warren }
376045fa1e1SStephen Warren 
fs_close(void)377045fa1e1SStephen Warren static void fs_close(void)
378045fa1e1SStephen Warren {
379c6f548d2SSimon Glass 	struct fstype_info *info = fs_get_info(fs_type);
380045fa1e1SStephen Warren 
381c6f548d2SSimon Glass 	info->close();
382e6d52415SSimon Glass 
383045fa1e1SStephen Warren 	fs_type = FS_TYPE_ANY;
384045fa1e1SStephen Warren }
385045fa1e1SStephen Warren 
fs_uuid(char * uuid_str)38659e890efSChristian Gmeiner int fs_uuid(char *uuid_str)
38759e890efSChristian Gmeiner {
38859e890efSChristian Gmeiner 	struct fstype_info *info = fs_get_info(fs_type);
38959e890efSChristian Gmeiner 
39059e890efSChristian Gmeiner 	return info->uuid(uuid_str);
39159e890efSChristian Gmeiner }
39259e890efSChristian Gmeiner 
fs_ls(const char * dirname)393045fa1e1SStephen Warren int fs_ls(const char *dirname)
394045fa1e1SStephen Warren {
395045fa1e1SStephen Warren 	int ret;
396045fa1e1SStephen Warren 
397c6f548d2SSimon Glass 	struct fstype_info *info = fs_get_info(fs_type);
398c6f548d2SSimon Glass 
399c6f548d2SSimon Glass 	ret = info->ls(dirname);
400045fa1e1SStephen Warren 
401e6d52415SSimon Glass 	fs_type = FS_TYPE_ANY;
402045fa1e1SStephen Warren 	fs_close();
403045fa1e1SStephen Warren 
404045fa1e1SStephen Warren 	return ret;
405045fa1e1SStephen Warren }
406045fa1e1SStephen Warren 
fs_exists(const char * filename)4076152916aSStephen Warren int fs_exists(const char *filename)
4086152916aSStephen Warren {
4096152916aSStephen Warren 	int ret;
4106152916aSStephen Warren 
4116152916aSStephen Warren 	struct fstype_info *info = fs_get_info(fs_type);
4126152916aSStephen Warren 
4136152916aSStephen Warren 	ret = info->exists(filename);
4146152916aSStephen Warren 
4156152916aSStephen Warren 	fs_close();
4166152916aSStephen Warren 
4176152916aSStephen Warren 	return ret;
4186152916aSStephen Warren }
4196152916aSStephen Warren 
fs_size(const char * filename,loff_t * size)420d455d878SSuriyan Ramasami int fs_size(const char *filename, loff_t *size)
421cf659819SStephen Warren {
422cf659819SStephen Warren 	int ret;
423cf659819SStephen Warren 
424cf659819SStephen Warren 	struct fstype_info *info = fs_get_info(fs_type);
425cf659819SStephen Warren 
426d455d878SSuriyan Ramasami 	ret = info->size(filename, size);
427cf659819SStephen Warren 
428cf659819SStephen Warren 	fs_close();
429cf659819SStephen Warren 
430cf659819SStephen Warren 	return ret;
431cf659819SStephen Warren }
432cf659819SStephen Warren 
433aa3c609eSSimon Goldschmidt #ifdef CONFIG_LMB
434aa3c609eSSimon Goldschmidt /* Check if a file may be read to the given address */
fs_read_lmb_check(const char * filename,ulong addr,loff_t offset,loff_t len,struct fstype_info * info)435aa3c609eSSimon Goldschmidt static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
436aa3c609eSSimon Goldschmidt 			     loff_t len, struct fstype_info *info)
437aa3c609eSSimon Goldschmidt {
438aa3c609eSSimon Goldschmidt 	struct lmb lmb;
439aa3c609eSSimon Goldschmidt 	int ret;
440aa3c609eSSimon Goldschmidt 	loff_t size;
441aa3c609eSSimon Goldschmidt 	loff_t read_len;
442aa3c609eSSimon Goldschmidt 
443aa3c609eSSimon Goldschmidt 	/* get the actual size of the file */
444aa3c609eSSimon Goldschmidt 	ret = info->size(filename, &size);
445aa3c609eSSimon Goldschmidt 	if (ret)
446aa3c609eSSimon Goldschmidt 		return ret;
447aa3c609eSSimon Goldschmidt 	if (offset >= size) {
448aa3c609eSSimon Goldschmidt 		/* offset >= EOF, no bytes will be written */
449aa3c609eSSimon Goldschmidt 		return 0;
450aa3c609eSSimon Goldschmidt 	}
451aa3c609eSSimon Goldschmidt 	read_len = size - offset;
452aa3c609eSSimon Goldschmidt 
453aa3c609eSSimon Goldschmidt 	/* limit to 'len' if it is smaller */
454aa3c609eSSimon Goldschmidt 	if (len && len < read_len)
455aa3c609eSSimon Goldschmidt 		read_len = len;
456aa3c609eSSimon Goldschmidt 
4579cc2323fSSimon Goldschmidt 	lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
458aa3c609eSSimon Goldschmidt 	lmb_dump_all(&lmb);
459aa3c609eSSimon Goldschmidt 
460aa3c609eSSimon Goldschmidt 	if (lmb_alloc_addr(&lmb, addr, read_len) == addr)
461aa3c609eSSimon Goldschmidt 		return 0;
462aa3c609eSSimon Goldschmidt 
463aa3c609eSSimon Goldschmidt 	printf("** Reading file would overwrite reserved memory **\n");
464aa3c609eSSimon Goldschmidt 	return -ENOSPC;
465aa3c609eSSimon Goldschmidt }
466aa3c609eSSimon Goldschmidt #endif
467aa3c609eSSimon Goldschmidt 
_fs_read(const char * filename,ulong addr,loff_t offset,loff_t len,int do_lmb_check,loff_t * actread)468aa3c609eSSimon Goldschmidt static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
469aa3c609eSSimon Goldschmidt 		    int do_lmb_check, loff_t *actread)
470045fa1e1SStephen Warren {
471c6f548d2SSimon Glass 	struct fstype_info *info = fs_get_info(fs_type);
472117e0507SSimon Glass 	void *buf;
473045fa1e1SStephen Warren 	int ret;
474045fa1e1SStephen Warren 
475aa3c609eSSimon Goldschmidt #ifdef CONFIG_LMB
476aa3c609eSSimon Goldschmidt 	if (do_lmb_check) {
477aa3c609eSSimon Goldschmidt 		ret = fs_read_lmb_check(filename, addr, offset, len, info);
478aa3c609eSSimon Goldschmidt 		if (ret)
479aa3c609eSSimon Goldschmidt 			return ret;
480aa3c609eSSimon Goldschmidt 	}
481aa3c609eSSimon Goldschmidt #endif
482aa3c609eSSimon Goldschmidt 
483117e0507SSimon Glass 	/*
484117e0507SSimon Glass 	 * We don't actually know how many bytes are being read, since len==0
485117e0507SSimon Glass 	 * means read the whole file.
486117e0507SSimon Glass 	 */
487117e0507SSimon Glass 	buf = map_sysmem(addr, len);
488d455d878SSuriyan Ramasami 	ret = info->read(filename, buf, offset, len, actread);
489117e0507SSimon Glass 	unmap_sysmem(buf);
490045fa1e1SStephen Warren 
491c6f548d2SSimon Glass 	/* If we requested a specific number of bytes, check we got it */
4927a3e70cfSMax Krummenacher 	if (ret == 0 && len && *actread != len)
493a327bde7SHeinrich Schuchardt 		debug("** %s shorter than offset + len **\n", filename);
494045fa1e1SStephen Warren 	fs_close();
495045fa1e1SStephen Warren 
496045fa1e1SStephen Warren 	return ret;
497045fa1e1SStephen Warren }
498045fa1e1SStephen Warren 
fs_read(const char * filename,ulong addr,loff_t offset,loff_t len,loff_t * actread)499aa3c609eSSimon Goldschmidt int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
500aa3c609eSSimon Goldschmidt 	    loff_t *actread)
501aa3c609eSSimon Goldschmidt {
502aa3c609eSSimon Goldschmidt 	return _fs_read(filename, addr, offset, len, 0, actread);
503aa3c609eSSimon Goldschmidt }
504aa3c609eSSimon Goldschmidt 
fs_write(const char * filename,ulong addr,loff_t offset,loff_t len,loff_t * actwrite)505d455d878SSuriyan Ramasami int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
506d455d878SSuriyan Ramasami 	     loff_t *actwrite)
507a8f6ab52SSimon Glass {
508a8f6ab52SSimon Glass 	struct fstype_info *info = fs_get_info(fs_type);
509a8f6ab52SSimon Glass 	void *buf;
510a8f6ab52SSimon Glass 	int ret;
511a8f6ab52SSimon Glass 
512a8f6ab52SSimon Glass 	buf = map_sysmem(addr, len);
513d455d878SSuriyan Ramasami 	ret = info->write(filename, buf, offset, len, actwrite);
514a8f6ab52SSimon Glass 	unmap_sysmem(buf);
515a8f6ab52SSimon Glass 
516d455d878SSuriyan Ramasami 	if (ret < 0 && len != *actwrite) {
517a8f6ab52SSimon Glass 		printf("** Unable to write file %s **\n", filename);
518a8f6ab52SSimon Glass 		ret = -1;
519a8f6ab52SSimon Glass 	}
520a8f6ab52SSimon Glass 	fs_close();
521a8f6ab52SSimon Glass 
522a8f6ab52SSimon Glass 	return ret;
523a8f6ab52SSimon Glass }
524a8f6ab52SSimon Glass 
fs_opendir(const char * filename)5254bbcc965SRob Clark struct fs_dir_stream *fs_opendir(const char *filename)
5264bbcc965SRob Clark {
5274bbcc965SRob Clark 	struct fstype_info *info = fs_get_info(fs_type);
5284bbcc965SRob Clark 	struct fs_dir_stream *dirs = NULL;
5294bbcc965SRob Clark 	int ret;
5304bbcc965SRob Clark 
5314bbcc965SRob Clark 	ret = info->opendir(filename, &dirs);
5324bbcc965SRob Clark 	fs_close();
5334bbcc965SRob Clark 	if (ret) {
5344bbcc965SRob Clark 		errno = -ret;
5354bbcc965SRob Clark 		return NULL;
5364bbcc965SRob Clark 	}
5374bbcc965SRob Clark 
5384bbcc965SRob Clark 	dirs->desc = fs_dev_desc;
5394bbcc965SRob Clark 	dirs->part = fs_dev_part;
5404bbcc965SRob Clark 
5414bbcc965SRob Clark 	return dirs;
5424bbcc965SRob Clark }
5434bbcc965SRob Clark 
fs_readdir(struct fs_dir_stream * dirs)5444bbcc965SRob Clark struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs)
5454bbcc965SRob Clark {
5464bbcc965SRob Clark 	struct fstype_info *info;
5474bbcc965SRob Clark 	struct fs_dirent *dirent;
5484bbcc965SRob Clark 	int ret;
5494bbcc965SRob Clark 
5504bbcc965SRob Clark 	fs_set_blk_dev_with_part(dirs->desc, dirs->part);
5514bbcc965SRob Clark 	info = fs_get_info(fs_type);
5524bbcc965SRob Clark 
5534bbcc965SRob Clark 	ret = info->readdir(dirs, &dirent);
5544bbcc965SRob Clark 	fs_close();
5554bbcc965SRob Clark 	if (ret) {
5564bbcc965SRob Clark 		errno = -ret;
5574bbcc965SRob Clark 		return NULL;
5584bbcc965SRob Clark 	}
5594bbcc965SRob Clark 
5604bbcc965SRob Clark 	return dirent;
5614bbcc965SRob Clark }
5624bbcc965SRob Clark 
fs_closedir(struct fs_dir_stream * dirs)5634bbcc965SRob Clark void fs_closedir(struct fs_dir_stream *dirs)
5644bbcc965SRob Clark {
5654bbcc965SRob Clark 	struct fstype_info *info;
5664bbcc965SRob Clark 
5674bbcc965SRob Clark 	if (!dirs)
5684bbcc965SRob Clark 		return;
5694bbcc965SRob Clark 
5704bbcc965SRob Clark 	fs_set_blk_dev_with_part(dirs->desc, dirs->part);
5714bbcc965SRob Clark 	info = fs_get_info(fs_type);
5724bbcc965SRob Clark 
5734bbcc965SRob Clark 	info->closedir(dirs);
5744bbcc965SRob Clark 	fs_close();
5754bbcc965SRob Clark }
5764bbcc965SRob Clark 
fs_unlink(const char * filename)577e2519dafSAKASHI Takahiro int fs_unlink(const char *filename)
578e2519dafSAKASHI Takahiro {
579e2519dafSAKASHI Takahiro 	int ret;
580e2519dafSAKASHI Takahiro 
581e2519dafSAKASHI Takahiro 	struct fstype_info *info = fs_get_info(fs_type);
582e2519dafSAKASHI Takahiro 
583e2519dafSAKASHI Takahiro 	ret = info->unlink(filename);
584e2519dafSAKASHI Takahiro 
585e2519dafSAKASHI Takahiro 	fs_type = FS_TYPE_ANY;
586e2519dafSAKASHI Takahiro 	fs_close();
587e2519dafSAKASHI Takahiro 
588e2519dafSAKASHI Takahiro 	return ret;
589e2519dafSAKASHI Takahiro }
5904bbcc965SRob Clark 
fs_mkdir(const char * dirname)591e7074cffSAKASHI Takahiro int fs_mkdir(const char *dirname)
592e7074cffSAKASHI Takahiro {
593e7074cffSAKASHI Takahiro 	int ret;
594e7074cffSAKASHI Takahiro 
595e7074cffSAKASHI Takahiro 	struct fstype_info *info = fs_get_info(fs_type);
596e7074cffSAKASHI Takahiro 
597e7074cffSAKASHI Takahiro 	ret = info->mkdir(dirname);
598e7074cffSAKASHI Takahiro 
599e7074cffSAKASHI Takahiro 	fs_type = FS_TYPE_ANY;
600e7074cffSAKASHI Takahiro 	fs_close();
601e7074cffSAKASHI Takahiro 
602e7074cffSAKASHI Takahiro 	return ret;
603e7074cffSAKASHI Takahiro }
604e7074cffSAKASHI Takahiro 
do_size(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)605cf659819SStephen Warren int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
606cf659819SStephen Warren 		int fstype)
607cf659819SStephen Warren {
608d455d878SSuriyan Ramasami 	loff_t size;
609cf659819SStephen Warren 
610cf659819SStephen Warren 	if (argc != 4)
611cf659819SStephen Warren 		return CMD_RET_USAGE;
612cf659819SStephen Warren 
613cf659819SStephen Warren 	if (fs_set_blk_dev(argv[1], argv[2], fstype))
614cf659819SStephen Warren 		return 1;
615cf659819SStephen Warren 
616d455d878SSuriyan Ramasami 	if (fs_size(argv[3], &size) < 0)
617cf659819SStephen Warren 		return CMD_RET_FAILURE;
618cf659819SStephen Warren 
619018f5303SSimon Glass 	env_set_hex("filesize", size);
620cf659819SStephen Warren 
621cf659819SStephen Warren 	return 0;
622cf659819SStephen Warren }
623cf659819SStephen Warren 
do_load(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)624f9b55e22SStephen Warren int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
625b770e88aSWolfgang Denk 		int fstype)
626045fa1e1SStephen Warren {
627045fa1e1SStephen Warren 	unsigned long addr;
628045fa1e1SStephen Warren 	const char *addr_str;
629045fa1e1SStephen Warren 	const char *filename;
630d455d878SSuriyan Ramasami 	loff_t bytes;
631d455d878SSuriyan Ramasami 	loff_t pos;
632d455d878SSuriyan Ramasami 	loff_t len_read;
633d455d878SSuriyan Ramasami 	int ret;
634da1fd96cSAndreas Bießmann 	unsigned long time;
635949bbd7cSPavel Machek 	char *ep;
636045fa1e1SStephen Warren 
637e9b0f99eSStephen Warren 	if (argc < 2)
638e9b0f99eSStephen Warren 		return CMD_RET_USAGE;
639e9b0f99eSStephen Warren 	if (argc > 7)
640045fa1e1SStephen Warren 		return CMD_RET_USAGE;
641045fa1e1SStephen Warren 
642e9b0f99eSStephen Warren 	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
643045fa1e1SStephen Warren 		return 1;
644045fa1e1SStephen Warren 
645045fa1e1SStephen Warren 	if (argc >= 4) {
646949bbd7cSPavel Machek 		addr = simple_strtoul(argv[3], &ep, 16);
647949bbd7cSPavel Machek 		if (ep == argv[3] || *ep != '\0')
648949bbd7cSPavel Machek 			return CMD_RET_USAGE;
649045fa1e1SStephen Warren 	} else {
65000caae6dSSimon Glass 		addr_str = env_get("loadaddr");
651045fa1e1SStephen Warren 		if (addr_str != NULL)
652045fa1e1SStephen Warren 			addr = simple_strtoul(addr_str, NULL, 16);
653045fa1e1SStephen Warren 		else
654045fa1e1SStephen Warren 			addr = CONFIG_SYS_LOAD_ADDR;
655045fa1e1SStephen Warren 	}
656045fa1e1SStephen Warren 	if (argc >= 5) {
657045fa1e1SStephen Warren 		filename = argv[4];
658045fa1e1SStephen Warren 	} else {
65900caae6dSSimon Glass 		filename = env_get("bootfile");
660045fa1e1SStephen Warren 		if (!filename) {
661045fa1e1SStephen Warren 			puts("** No boot file defined **\n");
662045fa1e1SStephen Warren 			return 1;
663045fa1e1SStephen Warren 		}
664045fa1e1SStephen Warren 	}
665045fa1e1SStephen Warren 	if (argc >= 6)
666b770e88aSWolfgang Denk 		bytes = simple_strtoul(argv[5], NULL, 16);
667045fa1e1SStephen Warren 	else
668045fa1e1SStephen Warren 		bytes = 0;
669045fa1e1SStephen Warren 	if (argc >= 7)
670b770e88aSWolfgang Denk 		pos = simple_strtoul(argv[6], NULL, 16);
671045fa1e1SStephen Warren 	else
672045fa1e1SStephen Warren 		pos = 0;
673045fa1e1SStephen Warren 
674da1fd96cSAndreas Bießmann 	time = get_timer(0);
675aa3c609eSSimon Goldschmidt 	ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
676da1fd96cSAndreas Bießmann 	time = get_timer(time);
677d455d878SSuriyan Ramasami 	if (ret < 0)
678045fa1e1SStephen Warren 		return 1;
679045fa1e1SStephen Warren 
680d455d878SSuriyan Ramasami 	printf("%llu bytes read in %lu ms", len_read, time);
681da1fd96cSAndreas Bießmann 	if (time > 0) {
682da1fd96cSAndreas Bießmann 		puts(" (");
6839e374e7bSTom Rini 		print_size(div_u64(len_read, time) * 1000, "/s");
684da1fd96cSAndreas Bießmann 		puts(")");
685da1fd96cSAndreas Bießmann 	}
686da1fd96cSAndreas Bießmann 	puts("\n");
687045fa1e1SStephen Warren 
688018f5303SSimon Glass 	env_set_hex("fileaddr", addr);
689018f5303SSimon Glass 	env_set_hex("filesize", len_read);
690045fa1e1SStephen Warren 
691045fa1e1SStephen Warren 	return 0;
692045fa1e1SStephen Warren }
693045fa1e1SStephen Warren 
do_ls(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)694045fa1e1SStephen Warren int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
695045fa1e1SStephen Warren 	int fstype)
696045fa1e1SStephen Warren {
697045fa1e1SStephen Warren 	if (argc < 2)
698045fa1e1SStephen Warren 		return CMD_RET_USAGE;
699e9b0f99eSStephen Warren 	if (argc > 4)
700e9b0f99eSStephen Warren 		return CMD_RET_USAGE;
701045fa1e1SStephen Warren 
702045fa1e1SStephen Warren 	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
703045fa1e1SStephen Warren 		return 1;
704045fa1e1SStephen Warren 
705e9b0f99eSStephen Warren 	if (fs_ls(argc >= 4 ? argv[3] : "/"))
706045fa1e1SStephen Warren 		return 1;
707045fa1e1SStephen Warren 
708045fa1e1SStephen Warren 	return 0;
709045fa1e1SStephen Warren }
710a8f6ab52SSimon Glass 
file_exists(const char * dev_type,const char * dev_part,const char * file,int fstype)7116152916aSStephen Warren int file_exists(const char *dev_type, const char *dev_part, const char *file,
7126152916aSStephen Warren 		int fstype)
7136152916aSStephen Warren {
7146152916aSStephen Warren 	if (fs_set_blk_dev(dev_type, dev_part, fstype))
7156152916aSStephen Warren 		return 0;
7166152916aSStephen Warren 
7176152916aSStephen Warren 	return fs_exists(file);
7186152916aSStephen Warren }
7196152916aSStephen Warren 
do_save(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)720a8f6ab52SSimon Glass int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
721b770e88aSWolfgang Denk 		int fstype)
722a8f6ab52SSimon Glass {
723a8f6ab52SSimon Glass 	unsigned long addr;
724a8f6ab52SSimon Glass 	const char *filename;
725d455d878SSuriyan Ramasami 	loff_t bytes;
726d455d878SSuriyan Ramasami 	loff_t pos;
727d455d878SSuriyan Ramasami 	loff_t len;
728d455d878SSuriyan Ramasami 	int ret;
729a8f6ab52SSimon Glass 	unsigned long time;
730a8f6ab52SSimon Glass 
731a8f6ab52SSimon Glass 	if (argc < 6 || argc > 7)
732a8f6ab52SSimon Glass 		return CMD_RET_USAGE;
733a8f6ab52SSimon Glass 
734a8f6ab52SSimon Glass 	if (fs_set_blk_dev(argv[1], argv[2], fstype))
735a8f6ab52SSimon Glass 		return 1;
736a8f6ab52SSimon Glass 
737d455d878SSuriyan Ramasami 	addr = simple_strtoul(argv[3], NULL, 16);
738d455d878SSuriyan Ramasami 	filename = argv[4];
739b770e88aSWolfgang Denk 	bytes = simple_strtoul(argv[5], NULL, 16);
740a8f6ab52SSimon Glass 	if (argc >= 7)
741b770e88aSWolfgang Denk 		pos = simple_strtoul(argv[6], NULL, 16);
742a8f6ab52SSimon Glass 	else
743a8f6ab52SSimon Glass 		pos = 0;
744a8f6ab52SSimon Glass 
745a8f6ab52SSimon Glass 	time = get_timer(0);
746d455d878SSuriyan Ramasami 	ret = fs_write(filename, addr, pos, bytes, &len);
747a8f6ab52SSimon Glass 	time = get_timer(time);
748d455d878SSuriyan Ramasami 	if (ret < 0)
749a8f6ab52SSimon Glass 		return 1;
750a8f6ab52SSimon Glass 
751d455d878SSuriyan Ramasami 	printf("%llu bytes written in %lu ms", len, time);
752a8f6ab52SSimon Glass 	if (time > 0) {
753a8f6ab52SSimon Glass 		puts(" (");
7549e374e7bSTom Rini 		print_size(div_u64(len, time) * 1000, "/s");
755a8f6ab52SSimon Glass 		puts(")");
756a8f6ab52SSimon Glass 	}
757a8f6ab52SSimon Glass 	puts("\n");
758a8f6ab52SSimon Glass 
759a8f6ab52SSimon Glass 	return 0;
760a8f6ab52SSimon Glass }
76159e890efSChristian Gmeiner 
do_fs_uuid(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)76259e890efSChristian Gmeiner int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
76359e890efSChristian Gmeiner 		int fstype)
76459e890efSChristian Gmeiner {
76559e890efSChristian Gmeiner 	int ret;
76659e890efSChristian Gmeiner 	char uuid[37];
76759e890efSChristian Gmeiner 	memset(uuid, 0, sizeof(uuid));
76859e890efSChristian Gmeiner 
76959e890efSChristian Gmeiner 	if (argc < 3 || argc > 4)
77059e890efSChristian Gmeiner 		return CMD_RET_USAGE;
77159e890efSChristian Gmeiner 
77259e890efSChristian Gmeiner 	if (fs_set_blk_dev(argv[1], argv[2], fstype))
77359e890efSChristian Gmeiner 		return 1;
77459e890efSChristian Gmeiner 
77559e890efSChristian Gmeiner 	ret = fs_uuid(uuid);
77659e890efSChristian Gmeiner 	if (ret)
77759e890efSChristian Gmeiner 		return CMD_RET_FAILURE;
77859e890efSChristian Gmeiner 
77959e890efSChristian Gmeiner 	if (argc == 4)
780382bee57SSimon Glass 		env_set(argv[3], uuid);
78159e890efSChristian Gmeiner 	else
78259e890efSChristian Gmeiner 		printf("%s\n", uuid);
78359e890efSChristian Gmeiner 
78459e890efSChristian Gmeiner 	return CMD_RET_SUCCESS;
78559e890efSChristian Gmeiner }
7861a1ad8e0SSjoerd Simons 
do_fs_type(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])7871a1ad8e0SSjoerd Simons int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7881a1ad8e0SSjoerd Simons {
7891a1ad8e0SSjoerd Simons 	struct fstype_info *info;
7901a1ad8e0SSjoerd Simons 
7911a1ad8e0SSjoerd Simons 	if (argc < 3 || argc > 4)
7921a1ad8e0SSjoerd Simons 		return CMD_RET_USAGE;
7931a1ad8e0SSjoerd Simons 
7941a1ad8e0SSjoerd Simons 	if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
7951a1ad8e0SSjoerd Simons 		return 1;
7961a1ad8e0SSjoerd Simons 
7971a1ad8e0SSjoerd Simons 	info = fs_get_info(fs_type);
7981a1ad8e0SSjoerd Simons 
7991a1ad8e0SSjoerd Simons 	if (argc == 4)
800382bee57SSimon Glass 		env_set(argv[3], info->name);
8011a1ad8e0SSjoerd Simons 	else
8021a1ad8e0SSjoerd Simons 		printf("%s\n", info->name);
8031a1ad8e0SSjoerd Simons 
804*e531c673SMarek Vasut 	fs_close();
805*e531c673SMarek Vasut 
8061a1ad8e0SSjoerd Simons 	return CMD_RET_SUCCESS;
8071a1ad8e0SSjoerd Simons }
8081a1ad8e0SSjoerd Simons 
do_rm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)809e2519dafSAKASHI Takahiro int do_rm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
810e2519dafSAKASHI Takahiro 	  int fstype)
811e2519dafSAKASHI Takahiro {
812e2519dafSAKASHI Takahiro 	if (argc != 4)
813e2519dafSAKASHI Takahiro 		return CMD_RET_USAGE;
814e2519dafSAKASHI Takahiro 
815e2519dafSAKASHI Takahiro 	if (fs_set_blk_dev(argv[1], argv[2], fstype))
816e2519dafSAKASHI Takahiro 		return 1;
817e2519dafSAKASHI Takahiro 
818e2519dafSAKASHI Takahiro 	if (fs_unlink(argv[3]))
819e2519dafSAKASHI Takahiro 		return 1;
820e2519dafSAKASHI Takahiro 
821e2519dafSAKASHI Takahiro 	return 0;
822e2519dafSAKASHI Takahiro }
823e2519dafSAKASHI Takahiro 
do_mkdir(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int fstype)824e7074cffSAKASHI Takahiro int do_mkdir(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
825e7074cffSAKASHI Takahiro 	     int fstype)
826e7074cffSAKASHI Takahiro {
827e7074cffSAKASHI Takahiro 	int ret;
828e7074cffSAKASHI Takahiro 
829e7074cffSAKASHI Takahiro 	if (argc != 4)
830e7074cffSAKASHI Takahiro 		return CMD_RET_USAGE;
831e7074cffSAKASHI Takahiro 
832e7074cffSAKASHI Takahiro 	if (fs_set_blk_dev(argv[1], argv[2], fstype))
833e7074cffSAKASHI Takahiro 		return 1;
834e7074cffSAKASHI Takahiro 
835e7074cffSAKASHI Takahiro 	ret = fs_mkdir(argv[3]);
836e7074cffSAKASHI Takahiro 	if (ret) {
837e7074cffSAKASHI Takahiro 		printf("** Unable to create a directory \"%s\" **\n", argv[3]);
838e7074cffSAKASHI Takahiro 		return 1;
839e7074cffSAKASHI Takahiro 	}
840e7074cffSAKASHI Takahiro 
841e7074cffSAKASHI Takahiro 	return 0;
842e7074cffSAKASHI Takahiro }
843