Blame view

fs/fs.c 16.8 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0
045fa1e11   Stephen Warren   fs: add filesyste...
2
3
  /*
   * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
045fa1e11   Stephen Warren   fs: add filesyste...
4
5
6
   */
  
  #include <config.h>
59e890ef7   Christian Gmeiner   fs: make it possi...
7
  #include <errno.h>
045fa1e11   Stephen Warren   fs: add filesyste...
8
  #include <common.h>
0eb25b619   Joe Hershberger   common: Make sure...
9
  #include <mapmem.h>
045fa1e11   Stephen Warren   fs: add filesyste...
10
11
12
13
  #include <part.h>
  #include <ext4fs.h>
  #include <fat.h>
  #include <fs.h>
92ccc96bf   Simon Glass   sandbox: Add host...
14
  #include <sandboxfs.h>
251cee0db   Hans de Goede   ubifs: Add generi...
15
  #include <ubifs_uboot.h>
0c936ee31   Marek Behún   fs: btrfs: Add U-...
16
  #include <btrfs.h>
117e05072   Simon Glass   fs: Use map_sysme...
17
  #include <asm/io.h>
9e374e7b7   Tom Rini   fs/ext4/ext4fs.c,...
18
19
  #include <div64.h>
  #include <linux/math64.h>
045fa1e11   Stephen Warren   fs: add filesyste...
20

a1b231cef   Stephen Warren   fs: handle CONFIG...
21
  DECLARE_GLOBAL_DATA_PTR;
4101f6879   Simon Glass   dm: Drop the bloc...
22
  static struct blk_desc *fs_dev_desc;
4bbcc965f   Rob Clark   fs: add fs_readdir()
23
  static int fs_dev_part;
045fa1e11   Stephen Warren   fs: add filesyste...
24
25
  static disk_partition_t fs_partition;
  static int fs_type = FS_TYPE_ANY;
4101f6879   Simon Glass   dm: Drop the bloc...
26
  static inline int fs_probe_unsupported(struct blk_desc *fs_dev_desc,
2ded0d471   Simon Glass   fs: Tell probe fu...
27
  				      disk_partition_t *fs_partition)
436e2b731   Simon Glass   fs: Fully populat...
28
29
30
31
32
  {
  	printf("** Unrecognized filesystem type **
  ");
  	return -1;
  }
045fa1e11   Stephen Warren   fs: add filesyste...
33
34
  static inline int fs_ls_unsupported(const char *dirname)
  {
045fa1e11   Stephen Warren   fs: add filesyste...
35
36
  	return -1;
  }
89191d626   Rob Clark   fat/fs: move ls t...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  /* generic implementation of ls in terms of opendir/readdir/closedir */
  __maybe_unused
  static int fs_ls_generic(const char *dirname)
  {
  	struct fs_dir_stream *dirs;
  	struct fs_dirent *dent;
  	int nfiles = 0, ndirs = 0;
  
  	dirs = fs_opendir(dirname);
  	if (!dirs)
  		return -errno;
  
  	while ((dent = fs_readdir(dirs))) {
  		if (dent->type == FS_DT_DIR) {
  			printf("            %s/
  ", dent->name);
  			ndirs++;
  		} else {
  			printf(" %8lld   %s
  ", dent->size, dent->name);
  			nfiles++;
  		}
  	}
  
  	fs_closedir(dirs);
  
  	printf("
  %d file(s), %d dir(s)
  
  ", nfiles, ndirs);
  
  	return 0;
  }
6152916a9   Stephen Warren   fs: implement inf...
70
71
72
73
  static inline int fs_exists_unsupported(const char *filename)
  {
  	return 0;
  }
d455d8789   Suriyan Ramasami   fs: API changes e...
74
  static inline int fs_size_unsupported(const char *filename, loff_t *size)
cf6598193   Stephen Warren   fs: implement siz...
75
76
77
  {
  	return -1;
  }
117e05072   Simon Glass   fs: Use map_sysme...
78
  static inline int fs_read_unsupported(const char *filename, void *buf,
d455d8789   Suriyan Ramasami   fs: API changes e...
79
80
  				      loff_t offset, loff_t len,
  				      loff_t *actread)
045fa1e11   Stephen Warren   fs: add filesyste...
81
  {
045fa1e11   Stephen Warren   fs: add filesyste...
82
83
  	return -1;
  }
a8f6ab522   Simon Glass   fs: Add support f...
84
  static inline int fs_write_unsupported(const char *filename, void *buf,
d455d8789   Suriyan Ramasami   fs: API changes e...
85
86
  				      loff_t offset, loff_t len,
  				      loff_t *actwrite)
a8f6ab522   Simon Glass   fs: Add support f...
87
88
89
  {
  	return -1;
  }
436e2b731   Simon Glass   fs: Fully populat...
90
91
92
  static inline void fs_close_unsupported(void)
  {
  }
59e890ef7   Christian Gmeiner   fs: make it possi...
93
94
95
96
  static inline int fs_uuid_unsupported(char *uuid_str)
  {
  	return -1;
  }
4bbcc965f   Rob Clark   fs: add fs_readdir()
97
98
99
100
101
  static inline int fs_opendir_unsupported(const char *filename,
  					 struct fs_dir_stream **dirs)
  {
  	return -EACCES;
  }
e2519daf5   AKASHI Takahiro   fs: add unlink in...
102
103
104
105
  static inline int fs_unlink_unsupported(const char *filename)
  {
  	return -1;
  }
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
106
107
108
109
  static inline int fs_mkdir_unsupported(const char *dirname)
  {
  	return -1;
  }
436e2b731   Simon Glass   fs: Fully populat...
110
  struct fstype_info {
045fa1e11   Stephen Warren   fs: add filesyste...
111
  	int fstype;
1a1ad8e09   Sjoerd Simons   fs: Add command t...
112
  	char *name;
377202b56   Stephen Warren   fs: don't pass NU...
113
114
115
116
  	/*
  	 * Is it legal to pass NULL as .probe()'s  fs_dev_desc parameter? This
  	 * should be false in most cases. For "virtual" filesystems which
  	 * aren't based on a U-Boot block device (e.g. sandbox), this can be
ca230b094   Heinrich Schuchardt   fs: fix typo 'dumm'
117
  	 * set to true. This should also be true for the dummy entry at the end
377202b56   Stephen Warren   fs: don't pass NU...
118
119
120
121
  	 * of fstypes[], since that is essentially a "virtual" (non-existent)
  	 * filesystem.
  	 */
  	bool null_dev_desc_ok;
4101f6879   Simon Glass   dm: Drop the bloc...
122
  	int (*probe)(struct blk_desc *fs_dev_desc,
2ded0d471   Simon Glass   fs: Tell probe fu...
123
  		     disk_partition_t *fs_partition);
436e2b731   Simon Glass   fs: Fully populat...
124
  	int (*ls)(const char *dirname);
6152916a9   Stephen Warren   fs: implement inf...
125
  	int (*exists)(const char *filename);
d455d8789   Suriyan Ramasami   fs: API changes e...
126
127
128
129
130
  	int (*size)(const char *filename, loff_t *size);
  	int (*read)(const char *filename, void *buf, loff_t offset,
  		    loff_t len, loff_t *actread);
  	int (*write)(const char *filename, void *buf, loff_t offset,
  		     loff_t len, loff_t *actwrite);
436e2b731   Simon Glass   fs: Fully populat...
131
  	void (*close)(void);
59e890ef7   Christian Gmeiner   fs: make it possi...
132
  	int (*uuid)(char *uuid_str);
4bbcc965f   Rob Clark   fs: add fs_readdir()
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  	/*
  	 * Open a directory stream.  On success return 0 and directory
  	 * stream pointer via 'dirsp'.  On error, return -errno.  See
  	 * fs_opendir().
  	 */
  	int (*opendir)(const char *filename, struct fs_dir_stream **dirsp);
  	/*
  	 * Read next entry from directory stream.  On success return 0
  	 * and directory entry pointer via 'dentp'.  On error return
  	 * -errno.  See fs_readdir().
  	 */
  	int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
  	/* see fs_closedir() */
  	void (*closedir)(struct fs_dir_stream *dirs);
e2519daf5   AKASHI Takahiro   fs: add unlink in...
147
  	int (*unlink)(const char *filename);
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
148
  	int (*mkdir)(const char *dirname);
436e2b731   Simon Glass   fs: Fully populat...
149
150
151
152
  };
  
  static struct fstype_info fstypes[] = {
  #ifdef CONFIG_FS_FAT
045fa1e11   Stephen Warren   fs: add filesyste...
153
154
  	{
  		.fstype = FS_TYPE_FAT,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
155
  		.name = "fat",
377202b56   Stephen Warren   fs: don't pass NU...
156
  		.null_dev_desc_ok = false,
e6d524153   Simon Glass   fs: Move ls and r...
157
158
  		.probe = fat_set_blk_dev,
  		.close = fat_close,
89191d626   Rob Clark   fat/fs: move ls t...
159
  		.ls = fs_ls_generic,
b7b5f3195   Stephen Warren   fat: implement ex...
160
  		.exists = fat_exists,
cf6598193   Stephen Warren   fs: implement siz...
161
  		.size = fat_size,
e6d524153   Simon Glass   fs: Move ls and r...
162
  		.read = fat_read_file,
d8c3ea998   Tien Fong Chee   spl: fat/fs: Add ...
163
  #if CONFIG_IS_ENABLED(FAT_WRITE)
d455d8789   Suriyan Ramasami   fs: API changes e...
164
  		.write = file_fat_write,
f8240ce95   AKASHI Takahiro   fs: fat: support ...
165
  		.unlink = fat_unlink,
31a18d570   AKASHI Takahiro   fs: fat: support ...
166
  		.mkdir = fat_mkdir,
d455d8789   Suriyan Ramasami   fs: API changes e...
167
  #else
bd6fb31fa   Stephen Warren   fs: fix generic s...
168
  		.write = fs_write_unsupported,
f8240ce95   AKASHI Takahiro   fs: fat: support ...
169
  		.unlink = fs_unlink_unsupported,
31a18d570   AKASHI Takahiro   fs: fat: support ...
170
  		.mkdir = fs_mkdir_unsupported,
d455d8789   Suriyan Ramasami   fs: API changes e...
171
  #endif
59e890ef7   Christian Gmeiner   fs: make it possi...
172
  		.uuid = fs_uuid_unsupported,
89191d626   Rob Clark   fat/fs: move ls t...
173
174
175
  		.opendir = fat_opendir,
  		.readdir = fat_readdir,
  		.closedir = fat_closedir,
045fa1e11   Stephen Warren   fs: add filesyste...
176
  	},
436e2b731   Simon Glass   fs: Fully populat...
177
  #endif
cafc429fa   Tien Fong Chee   spl: fat/fs: Add ...
178
179
  
  #if CONFIG_IS_ENABLED(FS_EXT4)
045fa1e11   Stephen Warren   fs: add filesyste...
180
181
  	{
  		.fstype = FS_TYPE_EXT,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
182
  		.name = "ext4",
377202b56   Stephen Warren   fs: don't pass NU...
183
  		.null_dev_desc_ok = false,
e6d524153   Simon Glass   fs: Move ls and r...
184
185
  		.probe = ext4fs_probe,
  		.close = ext4fs_close,
436e2b731   Simon Glass   fs: Fully populat...
186
  		.ls = ext4fs_ls,
55af5c931   Stephen Warren   ext4: implement e...
187
  		.exists = ext4fs_exists,
cf6598193   Stephen Warren   fs: implement siz...
188
  		.size = ext4fs_size,
e6d524153   Simon Glass   fs: Move ls and r...
189
  		.read = ext4_read_file,
d455d8789   Suriyan Ramasami   fs: API changes e...
190
191
192
  #ifdef CONFIG_CMD_EXT4_WRITE
  		.write = ext4_write_file,
  #else
bd6fb31fa   Stephen Warren   fs: fix generic s...
193
  		.write = fs_write_unsupported,
d455d8789   Suriyan Ramasami   fs: API changes e...
194
  #endif
59e890ef7   Christian Gmeiner   fs: make it possi...
195
  		.uuid = ext4fs_uuid,
4bbcc965f   Rob Clark   fs: add fs_readdir()
196
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
197
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
198
  		.mkdir = fs_mkdir_unsupported,
436e2b731   Simon Glass   fs: Fully populat...
199
200
  	},
  #endif
92ccc96bf   Simon Glass   sandbox: Add host...
201
202
203
  #ifdef CONFIG_SANDBOX
  	{
  		.fstype = FS_TYPE_SANDBOX,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
204
  		.name = "sandbox",
377202b56   Stephen Warren   fs: don't pass NU...
205
  		.null_dev_desc_ok = true,
92ccc96bf   Simon Glass   sandbox: Add host...
206
207
208
  		.probe = sandbox_fs_set_blk_dev,
  		.close = sandbox_fs_close,
  		.ls = sandbox_fs_ls,
0a30aa1e7   Stephen Warren   sandbox: implemen...
209
  		.exists = sandbox_fs_exists,
cf6598193   Stephen Warren   fs: implement siz...
210
  		.size = sandbox_fs_size,
92ccc96bf   Simon Glass   sandbox: Add host...
211
  		.read = fs_read_sandbox,
7eb2c8d57   Simon Glass   sandbox: fs: Add ...
212
  		.write = fs_write_sandbox,
59e890ef7   Christian Gmeiner   fs: make it possi...
213
  		.uuid = fs_uuid_unsupported,
4bbcc965f   Rob Clark   fs: add fs_readdir()
214
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
215
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
216
  		.mkdir = fs_mkdir_unsupported,
92ccc96bf   Simon Glass   sandbox: Add host...
217
218
  	},
  #endif
251cee0db   Hans de Goede   ubifs: Add generi...
219
220
221
222
223
224
225
226
227
228
229
230
231
  #ifdef CONFIG_CMD_UBIFS
  	{
  		.fstype = FS_TYPE_UBIFS,
  		.name = "ubifs",
  		.null_dev_desc_ok = true,
  		.probe = ubifs_set_blk_dev,
  		.close = ubifs_close,
  		.ls = ubifs_ls,
  		.exists = ubifs_exists,
  		.size = ubifs_size,
  		.read = ubifs_read,
  		.write = fs_write_unsupported,
  		.uuid = fs_uuid_unsupported,
4bbcc965f   Rob Clark   fs: add fs_readdir()
232
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
233
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
234
  		.mkdir = fs_mkdir_unsupported,
251cee0db   Hans de Goede   ubifs: Add generi...
235
236
  	},
  #endif
0c936ee31   Marek Behún   fs: btrfs: Add U-...
237
238
239
240
241
242
243
244
245
246
247
248
249
  #ifdef CONFIG_FS_BTRFS
  	{
  		.fstype = FS_TYPE_BTRFS,
  		.name = "btrfs",
  		.null_dev_desc_ok = false,
  		.probe = btrfs_probe,
  		.close = btrfs_close,
  		.ls = btrfs_ls,
  		.exists = btrfs_exists,
  		.size = btrfs_size,
  		.read = btrfs_read,
  		.write = fs_write_unsupported,
  		.uuid = btrfs_uuid,
38fc683d3   Marek Behún   fs: Set .opendir ...
250
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
251
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
252
  		.mkdir = fs_mkdir_unsupported,
0c936ee31   Marek Behún   fs: btrfs: Add U-...
253
254
  	},
  #endif
436e2b731   Simon Glass   fs: Fully populat...
255
256
  	{
  		.fstype = FS_TYPE_ANY,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
257
  		.name = "unsupported",
377202b56   Stephen Warren   fs: don't pass NU...
258
  		.null_dev_desc_ok = true,
436e2b731   Simon Glass   fs: Fully populat...
259
260
261
  		.probe = fs_probe_unsupported,
  		.close = fs_close_unsupported,
  		.ls = fs_ls_unsupported,
6152916a9   Stephen Warren   fs: implement inf...
262
  		.exists = fs_exists_unsupported,
cf6598193   Stephen Warren   fs: implement siz...
263
  		.size = fs_size_unsupported,
436e2b731   Simon Glass   fs: Fully populat...
264
  		.read = fs_read_unsupported,
a8f6ab522   Simon Glass   fs: Add support f...
265
  		.write = fs_write_unsupported,
59e890ef7   Christian Gmeiner   fs: make it possi...
266
  		.uuid = fs_uuid_unsupported,
4bbcc965f   Rob Clark   fs: add fs_readdir()
267
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
268
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
269
  		.mkdir = fs_mkdir_unsupported,
045fa1e11   Stephen Warren   fs: add filesyste...
270
271
  	},
  };
c6f548d23   Simon Glass   fs: Use filesyste...
272
273
274
275
276
277
278
279
280
281
282
283
284
  static struct fstype_info *fs_get_info(int fstype)
  {
  	struct fstype_info *info;
  	int i;
  
  	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) {
  		if (fstype == info->fstype)
  			return info;
  	}
  
  	/* Return the 'unsupported' sentinel */
  	return info;
  }
0d488e8f5   Alex Kiernan   fs: Add fs_get_ty...
285
286
287
288
289
290
291
292
293
294
295
296
  /**
   * fs_get_type_name() - Get type of current filesystem
   *
   * Return: Pointer to filesystem name
   *
   * Returns a string describing the current filesystem, or the sentinel
   * "unsupported" for any unrecognised filesystem.
   */
  const char *fs_get_type_name(void)
  {
  	return fs_get_info(fs_type)->name;
  }
045fa1e11   Stephen Warren   fs: add filesyste...
297
298
  int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
  {
436e2b731   Simon Glass   fs: Fully populat...
299
  	struct fstype_info *info;
045fa1e11   Stephen Warren   fs: add filesyste...
300
  	int part, i;
a1b231cef   Stephen Warren   fs: handle CONFIG...
301
302
303
304
  #ifdef CONFIG_NEEDS_MANUAL_RELOC
  	static int relocated;
  
  	if (!relocated) {
436e2b731   Simon Glass   fs: Fully populat...
305
306
  		for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
  				i++, info++) {
1a1ad8e09   Sjoerd Simons   fs: Add command t...
307
  			info->name += gd->reloc_off;
436e2b731   Simon Glass   fs: Fully populat...
308
309
310
311
  			info->probe += gd->reloc_off;
  			info->close += gd->reloc_off;
  			info->ls += gd->reloc_off;
  			info->read += gd->reloc_off;
a8f6ab522   Simon Glass   fs: Add support f...
312
  			info->write += gd->reloc_off;
436e2b731   Simon Glass   fs: Fully populat...
313
  		}
a1b231cef   Stephen Warren   fs: handle CONFIG...
314
315
316
  		relocated = 1;
  	}
  #endif
045fa1e11   Stephen Warren   fs: add filesyste...
317

e35929e4a   Simon Glass   dm: blk: Rename g...
318
  	part = blk_get_device_part_str(ifname, dev_part_str, &fs_dev_desc,
045fa1e11   Stephen Warren   fs: add filesyste...
319
320
321
  					&fs_partition, 1);
  	if (part < 0)
  		return -1;
436e2b731   Simon Glass   fs: Fully populat...
322
323
324
  	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
  		if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
  				fstype != info->fstype)
045fa1e11   Stephen Warren   fs: add filesyste...
325
  			continue;
377202b56   Stephen Warren   fs: don't pass NU...
326
327
  		if (!fs_dev_desc && !info->null_dev_desc_ok)
  			continue;
2ded0d471   Simon Glass   fs: Tell probe fu...
328
  		if (!info->probe(fs_dev_desc, &fs_partition)) {
436e2b731   Simon Glass   fs: Fully populat...
329
  			fs_type = info->fstype;
4bbcc965f   Rob Clark   fs: add fs_readdir()
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  			fs_dev_part = part;
  			return 0;
  		}
  	}
  
  	return -1;
  }
  
  /* set current blk device w/ blk_desc + partition # */
  int fs_set_blk_dev_with_part(struct blk_desc *desc, int part)
  {
  	struct fstype_info *info;
  	int ret, i;
  
  	if (part >= 1)
  		ret = part_get_info(desc, part, &fs_partition);
  	else
  		ret = part_get_info_whole_disk(desc, &fs_partition);
  	if (ret)
  		return ret;
  	fs_dev_desc = desc;
  
  	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
  		if (!info->probe(fs_dev_desc, &fs_partition)) {
  			fs_type = info->fstype;
b0c78d8ff   AKASHI Takahiro   fs: update fs_dev...
355
  			fs_dev_part = part;
045fa1e11   Stephen Warren   fs: add filesyste...
356
357
358
  			return 0;
  		}
  	}
045fa1e11   Stephen Warren   fs: add filesyste...
359
360
361
362
363
  	return -1;
  }
  
  static void fs_close(void)
  {
c6f548d23   Simon Glass   fs: Use filesyste...
364
  	struct fstype_info *info = fs_get_info(fs_type);
045fa1e11   Stephen Warren   fs: add filesyste...
365

c6f548d23   Simon Glass   fs: Use filesyste...
366
  	info->close();
e6d524153   Simon Glass   fs: Move ls and r...
367

045fa1e11   Stephen Warren   fs: add filesyste...
368
369
  	fs_type = FS_TYPE_ANY;
  }
59e890ef7   Christian Gmeiner   fs: make it possi...
370
371
372
373
374
375
  int fs_uuid(char *uuid_str)
  {
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	return info->uuid(uuid_str);
  }
045fa1e11   Stephen Warren   fs: add filesyste...
376
377
378
  int fs_ls(const char *dirname)
  {
  	int ret;
c6f548d23   Simon Glass   fs: Use filesyste...
379
380
381
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->ls(dirname);
045fa1e11   Stephen Warren   fs: add filesyste...
382

e6d524153   Simon Glass   fs: Move ls and r...
383
  	fs_type = FS_TYPE_ANY;
045fa1e11   Stephen Warren   fs: add filesyste...
384
385
386
387
  	fs_close();
  
  	return ret;
  }
6152916a9   Stephen Warren   fs: implement inf...
388
389
390
391
392
393
394
395
396
397
398
399
  int fs_exists(const char *filename)
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->exists(filename);
  
  	fs_close();
  
  	return ret;
  }
d455d8789   Suriyan Ramasami   fs: API changes e...
400
  int fs_size(const char *filename, loff_t *size)
cf6598193   Stephen Warren   fs: implement siz...
401
402
403
404
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
d455d8789   Suriyan Ramasami   fs: API changes e...
405
  	ret = info->size(filename, size);
cf6598193   Stephen Warren   fs: implement siz...
406
407
408
409
410
  
  	fs_close();
  
  	return ret;
  }
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  #ifdef CONFIG_LMB
  /* Check if a file may be read to the given address */
  static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
  			     loff_t len, struct fstype_info *info)
  {
  	struct lmb lmb;
  	int ret;
  	loff_t size;
  	loff_t read_len;
  
  	/* get the actual size of the file */
  	ret = info->size(filename, &size);
  	if (ret)
  		return ret;
  	if (offset >= size) {
  		/* offset >= EOF, no bytes will be written */
  		return 0;
  	}
  	read_len = size - offset;
  
  	/* limit to 'len' if it is smaller */
  	if (len && len < read_len)
  		read_len = len;
9cc2323fe   Simon Goldschmidt   lmb: handle more ...
434
  	lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
435
436
437
438
439
440
441
442
443
444
445
446
447
  	lmb_dump_all(&lmb);
  
  	if (lmb_alloc_addr(&lmb, addr, read_len) == addr)
  		return 0;
  
  	printf("** Reading file would overwrite reserved memory **
  ");
  	return -ENOSPC;
  }
  #endif
  
  static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
  		    int do_lmb_check, loff_t *actread)
045fa1e11   Stephen Warren   fs: add filesyste...
448
  {
c6f548d23   Simon Glass   fs: Use filesyste...
449
  	struct fstype_info *info = fs_get_info(fs_type);
117e05072   Simon Glass   fs: Use map_sysme...
450
  	void *buf;
045fa1e11   Stephen Warren   fs: add filesyste...
451
  	int ret;
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
452
453
454
455
456
457
458
  #ifdef CONFIG_LMB
  	if (do_lmb_check) {
  		ret = fs_read_lmb_check(filename, addr, offset, len, info);
  		if (ret)
  			return ret;
  	}
  #endif
117e05072   Simon Glass   fs: Use map_sysme...
459
460
461
462
463
  	/*
  	 * We don't actually know how many bytes are being read, since len==0
  	 * means read the whole file.
  	 */
  	buf = map_sysmem(addr, len);
d455d8789   Suriyan Ramasami   fs: API changes e...
464
  	ret = info->read(filename, buf, offset, len, actread);
117e05072   Simon Glass   fs: Use map_sysme...
465
  	unmap_sysmem(buf);
045fa1e11   Stephen Warren   fs: add filesyste...
466

c6f548d23   Simon Glass   fs: Use filesyste...
467
  	/* If we requested a specific number of bytes, check we got it */
7a3e70cfd   Max Krummenacher   fs/fs.c: read up ...
468
  	if (ret == 0 && len && *actread != len)
a327bde78   Heinrich Schuchardt   fs: remove distra...
469
470
  		debug("** %s shorter than offset + len **
  ", filename);
045fa1e11   Stephen Warren   fs: add filesyste...
471
472
473
474
  	fs_close();
  
  	return ret;
  }
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
475
476
477
478
479
  int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
  	    loff_t *actread)
  {
  	return _fs_read(filename, addr, offset, len, 0, actread);
  }
d455d8789   Suriyan Ramasami   fs: API changes e...
480
481
  int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
  	     loff_t *actwrite)
a8f6ab522   Simon Glass   fs: Add support f...
482
483
484
485
  {
  	struct fstype_info *info = fs_get_info(fs_type);
  	void *buf;
  	int ret;
a8f6ab522   Simon Glass   fs: Add support f...
486
  	buf = map_sysmem(addr, len);
d455d8789   Suriyan Ramasami   fs: API changes e...
487
  	ret = info->write(filename, buf, offset, len, actwrite);
a8f6ab522   Simon Glass   fs: Add support f...
488
  	unmap_sysmem(buf);
d455d8789   Suriyan Ramasami   fs: API changes e...
489
  	if (ret < 0 && len != *actwrite) {
a8f6ab522   Simon Glass   fs: Add support f...
490
491
492
493
494
495
496
497
  		printf("** Unable to write file %s **
  ", filename);
  		ret = -1;
  	}
  	fs_close();
  
  	return ret;
  }
4bbcc965f   Rob Clark   fs: add fs_readdir()
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  struct fs_dir_stream *fs_opendir(const char *filename)
  {
  	struct fstype_info *info = fs_get_info(fs_type);
  	struct fs_dir_stream *dirs = NULL;
  	int ret;
  
  	ret = info->opendir(filename, &dirs);
  	fs_close();
  	if (ret) {
  		errno = -ret;
  		return NULL;
  	}
  
  	dirs->desc = fs_dev_desc;
  	dirs->part = fs_dev_part;
  
  	return dirs;
  }
  
  struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs)
  {
  	struct fstype_info *info;
  	struct fs_dirent *dirent;
  	int ret;
  
  	fs_set_blk_dev_with_part(dirs->desc, dirs->part);
  	info = fs_get_info(fs_type);
  
  	ret = info->readdir(dirs, &dirent);
  	fs_close();
  	if (ret) {
  		errno = -ret;
  		return NULL;
  	}
  
  	return dirent;
  }
  
  void fs_closedir(struct fs_dir_stream *dirs)
  {
  	struct fstype_info *info;
  
  	if (!dirs)
  		return;
  
  	fs_set_blk_dev_with_part(dirs->desc, dirs->part);
  	info = fs_get_info(fs_type);
  
  	info->closedir(dirs);
  	fs_close();
  }
e2519daf5   AKASHI Takahiro   fs: add unlink in...
549
550
551
552
553
554
555
556
557
558
559
560
561
  int fs_unlink(const char *filename)
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->unlink(filename);
  
  	fs_type = FS_TYPE_ANY;
  	fs_close();
  
  	return ret;
  }
4bbcc965f   Rob Clark   fs: add fs_readdir()
562

e7074cffb   AKASHI Takahiro   fs: add mkdir int...
563
564
565
566
567
568
569
570
571
572
573
574
575
  int fs_mkdir(const char *dirname)
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->mkdir(dirname);
  
  	fs_type = FS_TYPE_ANY;
  	fs_close();
  
  	return ret;
  }
cf6598193   Stephen Warren   fs: implement siz...
576
577
578
  int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  		int fstype)
  {
d455d8789   Suriyan Ramasami   fs: API changes e...
579
  	loff_t size;
cf6598193   Stephen Warren   fs: implement siz...
580
581
582
583
584
585
  
  	if (argc != 4)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], fstype))
  		return 1;
d455d8789   Suriyan Ramasami   fs: API changes e...
586
  	if (fs_size(argv[3], &size) < 0)
cf6598193   Stephen Warren   fs: implement siz...
587
  		return CMD_RET_FAILURE;
018f53032   Simon Glass   env: Rename commo...
588
  	env_set_hex("filesize", size);
cf6598193   Stephen Warren   fs: implement siz...
589
590
591
  
  	return 0;
  }
f9b55e228   Stephen Warren   fs: rename fsload...
592
  int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
b770e88a6   Wolfgang Denk   Fix number base h...
593
  		int fstype)
045fa1e11   Stephen Warren   fs: add filesyste...
594
595
596
597
  {
  	unsigned long addr;
  	const char *addr_str;
  	const char *filename;
d455d8789   Suriyan Ramasami   fs: API changes e...
598
599
600
601
  	loff_t bytes;
  	loff_t pos;
  	loff_t len_read;
  	int ret;
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
602
  	unsigned long time;
949bbd7c8   Pavel Machek   catch wrong load ...
603
  	char *ep;
045fa1e11   Stephen Warren   fs: add filesyste...
604

e9b0f99e8   Stephen Warren   fs: fix do_fsload...
605
606
607
  	if (argc < 2)
  		return CMD_RET_USAGE;
  	if (argc > 7)
045fa1e11   Stephen Warren   fs: add filesyste...
608
  		return CMD_RET_USAGE;
e9b0f99e8   Stephen Warren   fs: fix do_fsload...
609
  	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
045fa1e11   Stephen Warren   fs: add filesyste...
610
611
612
  		return 1;
  
  	if (argc >= 4) {
949bbd7c8   Pavel Machek   catch wrong load ...
613
614
615
  		addr = simple_strtoul(argv[3], &ep, 16);
  		if (ep == argv[3] || *ep != '\0')
  			return CMD_RET_USAGE;
045fa1e11   Stephen Warren   fs: add filesyste...
616
  	} else {
00caae6d4   Simon Glass   env: Rename geten...
617
  		addr_str = env_get("loadaddr");
045fa1e11   Stephen Warren   fs: add filesyste...
618
619
620
621
622
623
624
625
  		if (addr_str != NULL)
  			addr = simple_strtoul(addr_str, NULL, 16);
  		else
  			addr = CONFIG_SYS_LOAD_ADDR;
  	}
  	if (argc >= 5) {
  		filename = argv[4];
  	} else {
00caae6d4   Simon Glass   env: Rename geten...
626
  		filename = env_get("bootfile");
045fa1e11   Stephen Warren   fs: add filesyste...
627
628
629
630
631
632
633
  		if (!filename) {
  			puts("** No boot file defined **
  ");
  			return 1;
  		}
  	}
  	if (argc >= 6)
b770e88a6   Wolfgang Denk   Fix number base h...
634
  		bytes = simple_strtoul(argv[5], NULL, 16);
045fa1e11   Stephen Warren   fs: add filesyste...
635
636
637
  	else
  		bytes = 0;
  	if (argc >= 7)
b770e88a6   Wolfgang Denk   Fix number base h...
638
  		pos = simple_strtoul(argv[6], NULL, 16);
045fa1e11   Stephen Warren   fs: add filesyste...
639
640
  	else
  		pos = 0;
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
641
  	time = get_timer(0);
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
642
  	ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
643
  	time = get_timer(time);
d455d8789   Suriyan Ramasami   fs: API changes e...
644
  	if (ret < 0)
045fa1e11   Stephen Warren   fs: add filesyste...
645
  		return 1;
d455d8789   Suriyan Ramasami   fs: API changes e...
646
  	printf("%llu bytes read in %lu ms", len_read, time);
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
647
648
  	if (time > 0) {
  		puts(" (");
9e374e7b7   Tom Rini   fs/ext4/ext4fs.c,...
649
  		print_size(div_u64(len_read, time) * 1000, "/s");
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
650
651
652
653
  		puts(")");
  	}
  	puts("
  ");
045fa1e11   Stephen Warren   fs: add filesyste...
654

018f53032   Simon Glass   env: Rename commo...
655
656
  	env_set_hex("fileaddr", addr);
  	env_set_hex("filesize", len_read);
045fa1e11   Stephen Warren   fs: add filesyste...
657
658
659
660
661
662
663
664
665
  
  	return 0;
  }
  
  int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  	int fstype)
  {
  	if (argc < 2)
  		return CMD_RET_USAGE;
e9b0f99e8   Stephen Warren   fs: fix do_fsload...
666
667
  	if (argc > 4)
  		return CMD_RET_USAGE;
045fa1e11   Stephen Warren   fs: add filesyste...
668
669
670
  
  	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
  		return 1;
e9b0f99e8   Stephen Warren   fs: fix do_fsload...
671
  	if (fs_ls(argc >= 4 ? argv[3] : "/"))
045fa1e11   Stephen Warren   fs: add filesyste...
672
673
674
675
  		return 1;
  
  	return 0;
  }
a8f6ab522   Simon Glass   fs: Add support f...
676

6152916a9   Stephen Warren   fs: implement inf...
677
678
679
680
681
682
683
684
  int file_exists(const char *dev_type, const char *dev_part, const char *file,
  		int fstype)
  {
  	if (fs_set_blk_dev(dev_type, dev_part, fstype))
  		return 0;
  
  	return fs_exists(file);
  }
a8f6ab522   Simon Glass   fs: Add support f...
685
  int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
b770e88a6   Wolfgang Denk   Fix number base h...
686
  		int fstype)
a8f6ab522   Simon Glass   fs: Add support f...
687
688
689
  {
  	unsigned long addr;
  	const char *filename;
d455d8789   Suriyan Ramasami   fs: API changes e...
690
691
692
693
  	loff_t bytes;
  	loff_t pos;
  	loff_t len;
  	int ret;
a8f6ab522   Simon Glass   fs: Add support f...
694
695
696
697
698
699
700
  	unsigned long time;
  
  	if (argc < 6 || argc > 7)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], fstype))
  		return 1;
d455d8789   Suriyan Ramasami   fs: API changes e...
701
702
  	addr = simple_strtoul(argv[3], NULL, 16);
  	filename = argv[4];
b770e88a6   Wolfgang Denk   Fix number base h...
703
  	bytes = simple_strtoul(argv[5], NULL, 16);
a8f6ab522   Simon Glass   fs: Add support f...
704
  	if (argc >= 7)
b770e88a6   Wolfgang Denk   Fix number base h...
705
  		pos = simple_strtoul(argv[6], NULL, 16);
a8f6ab522   Simon Glass   fs: Add support f...
706
707
708
709
  	else
  		pos = 0;
  
  	time = get_timer(0);
d455d8789   Suriyan Ramasami   fs: API changes e...
710
  	ret = fs_write(filename, addr, pos, bytes, &len);
a8f6ab522   Simon Glass   fs: Add support f...
711
  	time = get_timer(time);
d455d8789   Suriyan Ramasami   fs: API changes e...
712
  	if (ret < 0)
a8f6ab522   Simon Glass   fs: Add support f...
713
  		return 1;
d455d8789   Suriyan Ramasami   fs: API changes e...
714
  	printf("%llu bytes written in %lu ms", len, time);
a8f6ab522   Simon Glass   fs: Add support f...
715
716
  	if (time > 0) {
  		puts(" (");
9e374e7b7   Tom Rini   fs/ext4/ext4fs.c,...
717
  		print_size(div_u64(len, time) * 1000, "/s");
a8f6ab522   Simon Glass   fs: Add support f...
718
719
720
721
722
723
724
  		puts(")");
  	}
  	puts("
  ");
  
  	return 0;
  }
59e890ef7   Christian Gmeiner   fs: make it possi...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  
  int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  		int fstype)
  {
  	int ret;
  	char uuid[37];
  	memset(uuid, 0, sizeof(uuid));
  
  	if (argc < 3 || argc > 4)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], fstype))
  		return 1;
  
  	ret = fs_uuid(uuid);
  	if (ret)
  		return CMD_RET_FAILURE;
  
  	if (argc == 4)
382bee57f   Simon Glass   env: Rename seten...
744
  		env_set(argv[3], uuid);
59e890ef7   Christian Gmeiner   fs: make it possi...
745
746
747
748
749
750
  	else
  		printf("%s
  ", uuid);
  
  	return CMD_RET_SUCCESS;
  }
1a1ad8e09   Sjoerd Simons   fs: Add command t...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
  
  int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct fstype_info *info;
  
  	if (argc < 3 || argc > 4)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
  		return 1;
  
  	info = fs_get_info(fs_type);
  
  	if (argc == 4)
382bee57f   Simon Glass   env: Rename seten...
765
  		env_set(argv[3], info->name);
1a1ad8e09   Sjoerd Simons   fs: Add command t...
766
767
768
  	else
  		printf("%s
  ", info->name);
e531c6731   Marek Vasut   fs: ext4: Unmount...
769
  	fs_close();
1a1ad8e09   Sjoerd Simons   fs: Add command t...
770
771
  	return CMD_RET_SUCCESS;
  }
e2519daf5   AKASHI Takahiro   fs: add unlink in...
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  int do_rm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  	  int fstype)
  {
  	if (argc != 4)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], fstype))
  		return 1;
  
  	if (fs_unlink(argv[3]))
  		return 1;
  
  	return 0;
  }
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  int do_mkdir(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  	     int fstype)
  {
  	int ret;
  
  	if (argc != 4)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], fstype))
  		return 1;
  
  	ret = fs_mkdir(argv[3]);
  	if (ret) {
  		printf("** Unable to create a directory \"%s\" **
  ", argv[3]);
  		return 1;
  	}
  
  	return 0;
  }