Blame view

fs/fs.c 17.9 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>
c7694dd48   Simon Glass   env: Move env_set...
9
  #include <env.h>
0eb25b619   Joe Hershberger   common: Make sure...
10
  #include <mapmem.h>
045fa1e11   Stephen Warren   fs: add filesyste...
11
12
13
14
  #include <part.h>
  #include <ext4fs.h>
  #include <fat.h>
  #include <fs.h>
92ccc96bf   Simon Glass   sandbox: Add host...
15
  #include <sandboxfs.h>
251cee0db   Hans de Goede   ubifs: Add generi...
16
  #include <ubifs_uboot.h>
0c936ee31   Marek Behún   fs: btrfs: Add U-...
17
  #include <btrfs.h>
117e05072   Simon Glass   fs: Use map_sysme...
18
  #include <asm/io.h>
9e374e7b7   Tom Rini   fs/ext4/ext4fs.c,...
19
20
  #include <div64.h>
  #include <linux/math64.h>
ee88eacbd   Mian Yousaf Kaukab   fs: do_load: pass...
21
  #include <efi_loader.h>
045fa1e11   Stephen Warren   fs: add filesyste...
22

a1b231cef   Stephen Warren   fs: handle CONFIG...
23
  DECLARE_GLOBAL_DATA_PTR;
4101f6879   Simon Glass   dm: Drop the bloc...
24
  static struct blk_desc *fs_dev_desc;
4bbcc965f   Rob Clark   fs: add fs_readdir()
25
  static int fs_dev_part;
045fa1e11   Stephen Warren   fs: add filesyste...
26
27
  static disk_partition_t fs_partition;
  static int fs_type = FS_TYPE_ANY;
4101f6879   Simon Glass   dm: Drop the bloc...
28
  static inline int fs_probe_unsupported(struct blk_desc *fs_dev_desc,
2ded0d471   Simon Glass   fs: Tell probe fu...
29
  				      disk_partition_t *fs_partition)
436e2b731   Simon Glass   fs: Fully populat...
30
31
32
33
34
  {
  	printf("** Unrecognized filesystem type **
  ");
  	return -1;
  }
045fa1e11   Stephen Warren   fs: add filesyste...
35
36
  static inline int fs_ls_unsupported(const char *dirname)
  {
045fa1e11   Stephen Warren   fs: add filesyste...
37
38
  	return -1;
  }
89191d626   Rob Clark   fat/fs: move ls t...
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
70
71
  /* 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...
72
73
74
75
  static inline int fs_exists_unsupported(const char *filename)
  {
  	return 0;
  }
d455d8789   Suriyan Ramasami   fs: API changes e...
76
  static inline int fs_size_unsupported(const char *filename, loff_t *size)
cf6598193   Stephen Warren   fs: implement siz...
77
78
79
  {
  	return -1;
  }
117e05072   Simon Glass   fs: Use map_sysme...
80
  static inline int fs_read_unsupported(const char *filename, void *buf,
d455d8789   Suriyan Ramasami   fs: API changes e...
81
82
  				      loff_t offset, loff_t len,
  				      loff_t *actread)
045fa1e11   Stephen Warren   fs: add filesyste...
83
  {
045fa1e11   Stephen Warren   fs: add filesyste...
84
85
  	return -1;
  }
a8f6ab522   Simon Glass   fs: Add support f...
86
  static inline int fs_write_unsupported(const char *filename, void *buf,
d455d8789   Suriyan Ramasami   fs: API changes e...
87
88
  				      loff_t offset, loff_t len,
  				      loff_t *actwrite)
a8f6ab522   Simon Glass   fs: Add support f...
89
90
91
  {
  	return -1;
  }
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
92
93
94
95
  static inline int fs_ln_unsupported(const char *filename, const char *target)
  {
  	return -1;
  }
436e2b731   Simon Glass   fs: Fully populat...
96
97
98
  static inline void fs_close_unsupported(void)
  {
  }
59e890ef7   Christian Gmeiner   fs: make it possi...
99
100
101
102
  static inline int fs_uuid_unsupported(char *uuid_str)
  {
  	return -1;
  }
4bbcc965f   Rob Clark   fs: add fs_readdir()
103
104
105
106
107
  static inline int fs_opendir_unsupported(const char *filename,
  					 struct fs_dir_stream **dirs)
  {
  	return -EACCES;
  }
e2519daf5   AKASHI Takahiro   fs: add unlink in...
108
109
110
111
  static inline int fs_unlink_unsupported(const char *filename)
  {
  	return -1;
  }
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
112
113
114
115
  static inline int fs_mkdir_unsupported(const char *dirname)
  {
  	return -1;
  }
436e2b731   Simon Glass   fs: Fully populat...
116
  struct fstype_info {
045fa1e11   Stephen Warren   fs: add filesyste...
117
  	int fstype;
1a1ad8e09   Sjoerd Simons   fs: Add command t...
118
  	char *name;
377202b56   Stephen Warren   fs: don't pass NU...
119
120
121
122
  	/*
  	 * 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'
123
  	 * set to true. This should also be true for the dummy entry at the end
377202b56   Stephen Warren   fs: don't pass NU...
124
125
126
127
  	 * of fstypes[], since that is essentially a "virtual" (non-existent)
  	 * filesystem.
  	 */
  	bool null_dev_desc_ok;
4101f6879   Simon Glass   dm: Drop the bloc...
128
  	int (*probe)(struct blk_desc *fs_dev_desc,
2ded0d471   Simon Glass   fs: Tell probe fu...
129
  		     disk_partition_t *fs_partition);
436e2b731   Simon Glass   fs: Fully populat...
130
  	int (*ls)(const char *dirname);
6152916a9   Stephen Warren   fs: implement inf...
131
  	int (*exists)(const char *filename);
d455d8789   Suriyan Ramasami   fs: API changes e...
132
133
134
135
136
  	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...
137
  	void (*close)(void);
59e890ef7   Christian Gmeiner   fs: make it possi...
138
  	int (*uuid)(char *uuid_str);
4bbcc965f   Rob Clark   fs: add fs_readdir()
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  	/*
  	 * 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...
153
  	int (*unlink)(const char *filename);
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
154
  	int (*mkdir)(const char *dirname);
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
155
  	int (*ln)(const char *filename, const char *target);
436e2b731   Simon Glass   fs: Fully populat...
156
157
158
159
  };
  
  static struct fstype_info fstypes[] = {
  #ifdef CONFIG_FS_FAT
045fa1e11   Stephen Warren   fs: add filesyste...
160
161
  	{
  		.fstype = FS_TYPE_FAT,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
162
  		.name = "fat",
377202b56   Stephen Warren   fs: don't pass NU...
163
  		.null_dev_desc_ok = false,
e6d524153   Simon Glass   fs: Move ls and r...
164
165
  		.probe = fat_set_blk_dev,
  		.close = fat_close,
89191d626   Rob Clark   fat/fs: move ls t...
166
  		.ls = fs_ls_generic,
b7b5f3195   Stephen Warren   fat: implement ex...
167
  		.exists = fat_exists,
cf6598193   Stephen Warren   fs: implement siz...
168
  		.size = fat_size,
e6d524153   Simon Glass   fs: Move ls and r...
169
  		.read = fat_read_file,
d8c3ea998   Tien Fong Chee   spl: fat/fs: Add ...
170
  #if CONFIG_IS_ENABLED(FAT_WRITE)
d455d8789   Suriyan Ramasami   fs: API changes e...
171
  		.write = file_fat_write,
f8240ce95   AKASHI Takahiro   fs: fat: support ...
172
  		.unlink = fat_unlink,
31a18d570   AKASHI Takahiro   fs: fat: support ...
173
  		.mkdir = fat_mkdir,
d455d8789   Suriyan Ramasami   fs: API changes e...
174
  #else
bd6fb31fa   Stephen Warren   fs: fix generic s...
175
  		.write = fs_write_unsupported,
f8240ce95   AKASHI Takahiro   fs: fat: support ...
176
  		.unlink = fs_unlink_unsupported,
31a18d570   AKASHI Takahiro   fs: fat: support ...
177
  		.mkdir = fs_mkdir_unsupported,
d455d8789   Suriyan Ramasami   fs: API changes e...
178
  #endif
59e890ef7   Christian Gmeiner   fs: make it possi...
179
  		.uuid = fs_uuid_unsupported,
89191d626   Rob Clark   fat/fs: move ls t...
180
181
182
  		.opendir = fat_opendir,
  		.readdir = fat_readdir,
  		.closedir = fat_closedir,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
183
  		.ln = fs_ln_unsupported,
045fa1e11   Stephen Warren   fs: add filesyste...
184
  	},
436e2b731   Simon Glass   fs: Fully populat...
185
  #endif
cafc429fa   Tien Fong Chee   spl: fat/fs: Add ...
186
187
  
  #if CONFIG_IS_ENABLED(FS_EXT4)
045fa1e11   Stephen Warren   fs: add filesyste...
188
189
  	{
  		.fstype = FS_TYPE_EXT,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
190
  		.name = "ext4",
377202b56   Stephen Warren   fs: don't pass NU...
191
  		.null_dev_desc_ok = false,
e6d524153   Simon Glass   fs: Move ls and r...
192
193
  		.probe = ext4fs_probe,
  		.close = ext4fs_close,
436e2b731   Simon Glass   fs: Fully populat...
194
  		.ls = ext4fs_ls,
55af5c931   Stephen Warren   ext4: implement e...
195
  		.exists = ext4fs_exists,
cf6598193   Stephen Warren   fs: implement siz...
196
  		.size = ext4fs_size,
e6d524153   Simon Glass   fs: Move ls and r...
197
  		.read = ext4_read_file,
d455d8789   Suriyan Ramasami   fs: API changes e...
198
199
  #ifdef CONFIG_CMD_EXT4_WRITE
  		.write = ext4_write_file,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
200
  		.ln = ext4fs_create_link,
d455d8789   Suriyan Ramasami   fs: API changes e...
201
  #else
bd6fb31fa   Stephen Warren   fs: fix generic s...
202
  		.write = fs_write_unsupported,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
203
  		.ln = fs_ln_unsupported,
d455d8789   Suriyan Ramasami   fs: API changes e...
204
  #endif
59e890ef7   Christian Gmeiner   fs: make it possi...
205
  		.uuid = ext4fs_uuid,
4bbcc965f   Rob Clark   fs: add fs_readdir()
206
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
207
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
208
  		.mkdir = fs_mkdir_unsupported,
436e2b731   Simon Glass   fs: Fully populat...
209
210
  	},
  #endif
92ccc96bf   Simon Glass   sandbox: Add host...
211
212
213
  #ifdef CONFIG_SANDBOX
  	{
  		.fstype = FS_TYPE_SANDBOX,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
214
  		.name = "sandbox",
377202b56   Stephen Warren   fs: don't pass NU...
215
  		.null_dev_desc_ok = true,
92ccc96bf   Simon Glass   sandbox: Add host...
216
217
218
  		.probe = sandbox_fs_set_blk_dev,
  		.close = sandbox_fs_close,
  		.ls = sandbox_fs_ls,
0a30aa1e7   Stephen Warren   sandbox: implemen...
219
  		.exists = sandbox_fs_exists,
cf6598193   Stephen Warren   fs: implement siz...
220
  		.size = sandbox_fs_size,
92ccc96bf   Simon Glass   sandbox: Add host...
221
  		.read = fs_read_sandbox,
7eb2c8d57   Simon Glass   sandbox: fs: Add ...
222
  		.write = fs_write_sandbox,
59e890ef7   Christian Gmeiner   fs: make it possi...
223
  		.uuid = fs_uuid_unsupported,
4bbcc965f   Rob Clark   fs: add fs_readdir()
224
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
225
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
226
  		.mkdir = fs_mkdir_unsupported,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
227
  		.ln = fs_ln_unsupported,
92ccc96bf   Simon Glass   sandbox: Add host...
228
229
  	},
  #endif
251cee0db   Hans de Goede   ubifs: Add generi...
230
231
232
233
234
235
236
237
238
239
240
241
242
  #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()
243
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
244
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
245
  		.mkdir = fs_mkdir_unsupported,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
246
  		.ln = fs_ln_unsupported,
251cee0db   Hans de Goede   ubifs: Add generi...
247
248
  	},
  #endif
0c936ee31   Marek Behún   fs: btrfs: Add U-...
249
250
251
252
253
254
255
256
257
258
259
260
261
  #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 ...
262
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
263
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
264
  		.mkdir = fs_mkdir_unsupported,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
265
  		.ln = fs_ln_unsupported,
0c936ee31   Marek Behún   fs: btrfs: Add U-...
266
267
  	},
  #endif
436e2b731   Simon Glass   fs: Fully populat...
268
269
  	{
  		.fstype = FS_TYPE_ANY,
1a1ad8e09   Sjoerd Simons   fs: Add command t...
270
  		.name = "unsupported",
377202b56   Stephen Warren   fs: don't pass NU...
271
  		.null_dev_desc_ok = true,
436e2b731   Simon Glass   fs: Fully populat...
272
273
274
  		.probe = fs_probe_unsupported,
  		.close = fs_close_unsupported,
  		.ls = fs_ls_unsupported,
6152916a9   Stephen Warren   fs: implement inf...
275
  		.exists = fs_exists_unsupported,
cf6598193   Stephen Warren   fs: implement siz...
276
  		.size = fs_size_unsupported,
436e2b731   Simon Glass   fs: Fully populat...
277
  		.read = fs_read_unsupported,
a8f6ab522   Simon Glass   fs: Add support f...
278
  		.write = fs_write_unsupported,
59e890ef7   Christian Gmeiner   fs: make it possi...
279
  		.uuid = fs_uuid_unsupported,
4bbcc965f   Rob Clark   fs: add fs_readdir()
280
  		.opendir = fs_opendir_unsupported,
e2519daf5   AKASHI Takahiro   fs: add unlink in...
281
  		.unlink = fs_unlink_unsupported,
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
282
  		.mkdir = fs_mkdir_unsupported,
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
283
  		.ln = fs_ln_unsupported,
045fa1e11   Stephen Warren   fs: add filesyste...
284
285
  	},
  };
c6f548d23   Simon Glass   fs: Use filesyste...
286
287
288
289
290
291
292
293
294
295
296
297
298
  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...
299
  /**
b7cd95627   AKASHI Takahiro   fs: add fs_get_ty...
300
301
302
303
304
305
306
307
308
309
310
311
312
   * fs_get_type() - Get type of current filesystem
   *
   * Return: filesystem type
   *
   * Returns filesystem type representing the current filesystem, or
   * FS_TYPE_ANY for any unrecognised filesystem.
   */
  int fs_get_type(void)
  {
  	return fs_type;
  }
  
  /**
0d488e8f5   Alex Kiernan   fs: Add fs_get_ty...
313
314
315
316
317
318
319
320
321
322
323
   * 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...
324
325
  int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
  {
436e2b731   Simon Glass   fs: Fully populat...
326
  	struct fstype_info *info;
045fa1e11   Stephen Warren   fs: add filesyste...
327
  	int part, i;
a1b231cef   Stephen Warren   fs: handle CONFIG...
328
329
330
331
  #ifdef CONFIG_NEEDS_MANUAL_RELOC
  	static int relocated;
  
  	if (!relocated) {
436e2b731   Simon Glass   fs: Fully populat...
332
333
  		for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
  				i++, info++) {
1a1ad8e09   Sjoerd Simons   fs: Add command t...
334
  			info->name += gd->reloc_off;
436e2b731   Simon Glass   fs: Fully populat...
335
336
337
338
  			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...
339
  			info->write += gd->reloc_off;
436e2b731   Simon Glass   fs: Fully populat...
340
  		}
a1b231cef   Stephen Warren   fs: handle CONFIG...
341
342
343
  		relocated = 1;
  	}
  #endif
045fa1e11   Stephen Warren   fs: add filesyste...
344

e35929e4a   Simon Glass   dm: blk: Rename g...
345
  	part = blk_get_device_part_str(ifname, dev_part_str, &fs_dev_desc,
045fa1e11   Stephen Warren   fs: add filesyste...
346
347
348
  					&fs_partition, 1);
  	if (part < 0)
  		return -1;
436e2b731   Simon Glass   fs: Fully populat...
349
350
351
  	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...
352
  			continue;
377202b56   Stephen Warren   fs: don't pass NU...
353
354
  		if (!fs_dev_desc && !info->null_dev_desc_ok)
  			continue;
2ded0d471   Simon Glass   fs: Tell probe fu...
355
  		if (!info->probe(fs_dev_desc, &fs_partition)) {
436e2b731   Simon Glass   fs: Fully populat...
356
  			fs_type = info->fstype;
4bbcc965f   Rob Clark   fs: add fs_readdir()
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  			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...
382
  			fs_dev_part = part;
045fa1e11   Stephen Warren   fs: add filesyste...
383
384
385
  			return 0;
  		}
  	}
045fa1e11   Stephen Warren   fs: add filesyste...
386
387
  	return -1;
  }
64f49eb7d   AKASHI Takahiro   fs: export fs_clo...
388
  void fs_close(void)
045fa1e11   Stephen Warren   fs: add filesyste...
389
  {
c6f548d23   Simon Glass   fs: Use filesyste...
390
  	struct fstype_info *info = fs_get_info(fs_type);
045fa1e11   Stephen Warren   fs: add filesyste...
391

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

045fa1e11   Stephen Warren   fs: add filesyste...
394
395
  	fs_type = FS_TYPE_ANY;
  }
59e890ef7   Christian Gmeiner   fs: make it possi...
396
397
398
399
400
401
  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...
402
403
404
  int fs_ls(const char *dirname)
  {
  	int ret;
c6f548d23   Simon Glass   fs: Use filesyste...
405
406
407
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->ls(dirname);
045fa1e11   Stephen Warren   fs: add filesyste...
408
409
410
411
412
  
  	fs_close();
  
  	return ret;
  }
6152916a9   Stephen Warren   fs: implement inf...
413
414
415
416
417
418
419
420
421
422
423
424
  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...
425
  int fs_size(const char *filename, loff_t *size)
cf6598193   Stephen Warren   fs: implement siz...
426
427
428
429
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
d455d8789   Suriyan Ramasami   fs: API changes e...
430
  	ret = info->size(filename, size);
cf6598193   Stephen Warren   fs: implement siz...
431
432
433
434
435
  
  	fs_close();
  
  	return ret;
  }
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  #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 ...
459
  	lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
460
461
462
463
464
465
466
467
468
469
470
471
472
  	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...
473
  {
c6f548d23   Simon Glass   fs: Use filesyste...
474
  	struct fstype_info *info = fs_get_info(fs_type);
117e05072   Simon Glass   fs: Use map_sysme...
475
  	void *buf;
045fa1e11   Stephen Warren   fs: add filesyste...
476
  	int ret;
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
477
478
479
480
481
482
483
  #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...
484
485
486
487
488
  	/*
  	 * 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...
489
  	ret = info->read(filename, buf, offset, len, actread);
117e05072   Simon Glass   fs: Use map_sysme...
490
  	unmap_sysmem(buf);
045fa1e11   Stephen Warren   fs: add filesyste...
491

c6f548d23   Simon Glass   fs: Use filesyste...
492
  	/* If we requested a specific number of bytes, check we got it */
7a3e70cfd   Max Krummenacher   fs/fs.c: read up ...
493
  	if (ret == 0 && len && *actread != len)
a327bde78   Heinrich Schuchardt   fs: remove distra...
494
495
  		debug("** %s shorter than offset + len **
  ", filename);
045fa1e11   Stephen Warren   fs: add filesyste...
496
497
498
499
  	fs_close();
  
  	return ret;
  }
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
500
501
502
503
504
  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...
505
506
  int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
  	     loff_t *actwrite)
a8f6ab522   Simon Glass   fs: Add support f...
507
508
509
510
  {
  	struct fstype_info *info = fs_get_info(fs_type);
  	void *buf;
  	int ret;
a8f6ab522   Simon Glass   fs: Add support f...
511
  	buf = map_sysmem(addr, len);
d455d8789   Suriyan Ramasami   fs: API changes e...
512
  	ret = info->write(filename, buf, offset, len, actwrite);
a8f6ab522   Simon Glass   fs: Add support f...
513
  	unmap_sysmem(buf);
d455d8789   Suriyan Ramasami   fs: API changes e...
514
  	if (ret < 0 && len != *actwrite) {
a8f6ab522   Simon Glass   fs: Add support f...
515
516
517
518
519
520
521
522
  		printf("** Unable to write file %s **
  ", filename);
  		ret = -1;
  	}
  	fs_close();
  
  	return ret;
  }
4bbcc965f   Rob Clark   fs: add fs_readdir()
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
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  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...
574
575
576
577
578
579
580
  int fs_unlink(const char *filename)
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->unlink(filename);
e2519daf5   AKASHI Takahiro   fs: add unlink in...
581
582
583
584
  	fs_close();
  
  	return ret;
  }
4bbcc965f   Rob Clark   fs: add fs_readdir()
585

e7074cffb   AKASHI Takahiro   fs: add mkdir int...
586
587
588
589
590
591
592
  int fs_mkdir(const char *dirname)
  {
  	int ret;
  
  	struct fstype_info *info = fs_get_info(fs_type);
  
  	ret = info->mkdir(dirname);
e7074cffb   AKASHI Takahiro   fs: add mkdir int...
593
594
595
596
  	fs_close();
  
  	return ret;
  }
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  int fs_ln(const char *fname, const char *target)
  {
  	struct fstype_info *info = fs_get_info(fs_type);
  	int ret;
  
  	ret = info->ln(fname, target);
  
  	if (ret < 0) {
  		printf("** Unable to create link %s -> %s **
  ", fname, target);
  		ret = -1;
  	}
  	fs_close();
  
  	return ret;
  }
cf6598193   Stephen Warren   fs: implement siz...
613
614
615
  int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  		int fstype)
  {
d455d8789   Suriyan Ramasami   fs: API changes e...
616
  	loff_t size;
cf6598193   Stephen Warren   fs: implement siz...
617
618
619
620
621
622
  
  	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...
623
  	if (fs_size(argv[3], &size) < 0)
cf6598193   Stephen Warren   fs: implement siz...
624
  		return CMD_RET_FAILURE;
018f53032   Simon Glass   env: Rename commo...
625
  	env_set_hex("filesize", size);
cf6598193   Stephen Warren   fs: implement siz...
626
627
628
  
  	return 0;
  }
f9b55e228   Stephen Warren   fs: rename fsload...
629
  int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
b770e88a6   Wolfgang Denk   Fix number base h...
630
  		int fstype)
045fa1e11   Stephen Warren   fs: add filesyste...
631
632
633
634
  {
  	unsigned long addr;
  	const char *addr_str;
  	const char *filename;
d455d8789   Suriyan Ramasami   fs: API changes e...
635
636
637
638
  	loff_t bytes;
  	loff_t pos;
  	loff_t len_read;
  	int ret;
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
639
  	unsigned long time;
949bbd7c8   Pavel Machek   catch wrong load ...
640
  	char *ep;
045fa1e11   Stephen Warren   fs: add filesyste...
641

e9b0f99e8   Stephen Warren   fs: fix do_fsload...
642
643
644
  	if (argc < 2)
  		return CMD_RET_USAGE;
  	if (argc > 7)
045fa1e11   Stephen Warren   fs: add filesyste...
645
  		return CMD_RET_USAGE;
e9b0f99e8   Stephen Warren   fs: fix do_fsload...
646
  	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
045fa1e11   Stephen Warren   fs: add filesyste...
647
648
649
  		return 1;
  
  	if (argc >= 4) {
949bbd7c8   Pavel Machek   catch wrong load ...
650
651
652
  		addr = simple_strtoul(argv[3], &ep, 16);
  		if (ep == argv[3] || *ep != '\0')
  			return CMD_RET_USAGE;
045fa1e11   Stephen Warren   fs: add filesyste...
653
  	} else {
00caae6d4   Simon Glass   env: Rename geten...
654
  		addr_str = env_get("loadaddr");
045fa1e11   Stephen Warren   fs: add filesyste...
655
656
657
658
659
660
661
662
  		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...
663
  		filename = env_get("bootfile");
045fa1e11   Stephen Warren   fs: add filesyste...
664
665
666
667
668
669
670
  		if (!filename) {
  			puts("** No boot file defined **
  ");
  			return 1;
  		}
  	}
  	if (argc >= 6)
b770e88a6   Wolfgang Denk   Fix number base h...
671
  		bytes = simple_strtoul(argv[5], NULL, 16);
045fa1e11   Stephen Warren   fs: add filesyste...
672
673
674
  	else
  		bytes = 0;
  	if (argc >= 7)
b770e88a6   Wolfgang Denk   Fix number base h...
675
  		pos = simple_strtoul(argv[6], NULL, 16);
045fa1e11   Stephen Warren   fs: add filesyste...
676
677
  	else
  		pos = 0;
ee88eacbd   Mian Yousaf Kaukab   fs: do_load: pass...
678
679
680
681
  #ifdef CONFIG_CMD_BOOTEFI
  	efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "",
  			(argc > 4) ? argv[4] : "");
  #endif
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
682
  	time = get_timer(0);
aa3c609e2   Simon Goldschmidt   fs: prevent overw...
683
  	ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
684
  	time = get_timer(time);
d455d8789   Suriyan Ramasami   fs: API changes e...
685
  	if (ret < 0)
045fa1e11   Stephen Warren   fs: add filesyste...
686
  		return 1;
d455d8789   Suriyan Ramasami   fs: API changes e...
687
  	printf("%llu bytes read in %lu ms", len_read, time);
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
688
689
  	if (time > 0) {
  		puts(" (");
9e374e7b7   Tom Rini   fs/ext4/ext4fs.c,...
690
  		print_size(div_u64(len_read, time) * 1000, "/s");
da1fd96ce   Andreas Bießmann   fs/fs.c: do_fsloa...
691
692
693
694
  		puts(")");
  	}
  	puts("
  ");
045fa1e11   Stephen Warren   fs: add filesyste...
695

018f53032   Simon Glass   env: Rename commo...
696
697
  	env_set_hex("fileaddr", addr);
  	env_set_hex("filesize", len_read);
045fa1e11   Stephen Warren   fs: add filesyste...
698
699
700
701
702
703
704
705
706
  
  	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...
707
708
  	if (argc > 4)
  		return CMD_RET_USAGE;
045fa1e11   Stephen Warren   fs: add filesyste...
709
710
711
  
  	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
  		return 1;
e9b0f99e8   Stephen Warren   fs: fix do_fsload...
712
  	if (fs_ls(argc >= 4 ? argv[3] : "/"))
045fa1e11   Stephen Warren   fs: add filesyste...
713
714
715
716
  		return 1;
  
  	return 0;
  }
a8f6ab522   Simon Glass   fs: Add support f...
717

6152916a9   Stephen Warren   fs: implement inf...
718
719
720
721
722
723
724
725
  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...
726
  int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
b770e88a6   Wolfgang Denk   Fix number base h...
727
  		int fstype)
a8f6ab522   Simon Glass   fs: Add support f...
728
729
730
  {
  	unsigned long addr;
  	const char *filename;
d455d8789   Suriyan Ramasami   fs: API changes e...
731
732
733
734
  	loff_t bytes;
  	loff_t pos;
  	loff_t len;
  	int ret;
a8f6ab522   Simon Glass   fs: Add support f...
735
736
737
738
739
740
741
  	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...
742
743
  	addr = simple_strtoul(argv[3], NULL, 16);
  	filename = argv[4];
b770e88a6   Wolfgang Denk   Fix number base h...
744
  	bytes = simple_strtoul(argv[5], NULL, 16);
a8f6ab522   Simon Glass   fs: Add support f...
745
  	if (argc >= 7)
b770e88a6   Wolfgang Denk   Fix number base h...
746
  		pos = simple_strtoul(argv[6], NULL, 16);
a8f6ab522   Simon Glass   fs: Add support f...
747
748
749
750
  	else
  		pos = 0;
  
  	time = get_timer(0);
d455d8789   Suriyan Ramasami   fs: API changes e...
751
  	ret = fs_write(filename, addr, pos, bytes, &len);
a8f6ab522   Simon Glass   fs: Add support f...
752
  	time = get_timer(time);
d455d8789   Suriyan Ramasami   fs: API changes e...
753
  	if (ret < 0)
a8f6ab522   Simon Glass   fs: Add support f...
754
  		return 1;
d455d8789   Suriyan Ramasami   fs: API changes e...
755
  	printf("%llu bytes written in %lu ms", len, time);
a8f6ab522   Simon Glass   fs: Add support f...
756
757
  	if (time > 0) {
  		puts(" (");
9e374e7b7   Tom Rini   fs/ext4/ext4fs.c,...
758
  		print_size(div_u64(len, time) * 1000, "/s");
a8f6ab522   Simon Glass   fs: Add support f...
759
760
761
762
763
764
765
  		puts(")");
  	}
  	puts("
  ");
  
  	return 0;
  }
59e890ef7   Christian Gmeiner   fs: make it possi...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  
  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...
785
  		env_set(argv[3], uuid);
59e890ef7   Christian Gmeiner   fs: make it possi...
786
787
788
789
790
791
  	else
  		printf("%s
  ", uuid);
  
  	return CMD_RET_SUCCESS;
  }
1a1ad8e09   Sjoerd Simons   fs: Add command t...
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  
  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...
806
  		env_set(argv[3], info->name);
1a1ad8e09   Sjoerd Simons   fs: Add command t...
807
808
809
  	else
  		printf("%s
  ", info->name);
e531c6731   Marek Vasut   fs: ext4: Unmount...
810
  	fs_close();
1a1ad8e09   Sjoerd Simons   fs: Add command t...
811
812
  	return CMD_RET_SUCCESS;
  }
e2519daf5   AKASHI Takahiro   fs: add unlink in...
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  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...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
  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;
  }
aaa12157c   Jean-Jacques Hiblot   fs: Add a new com...
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
  
  int do_ln(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
  	  int fstype)
  {
  	if (argc != 5)
  		return CMD_RET_USAGE;
  
  	if (fs_set_blk_dev(argv[1], argv[2], fstype))
  		return 1;
  
  	if (fs_ln(argv[3], argv[4]))
  		return 1;
  
  	return 0;
  }