]> git.ipfire.org Git - thirdparty/u-boot.git/blob - fs/fs.c
command: Remove the cmd_tbl_t typedef
[thirdparty/u-boot.git] / fs / fs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
4 */
5
6 #include <command.h>
7 #include <config.h>
8 #include <errno.h>
9 #include <common.h>
10 #include <env.h>
11 #include <lmb.h>
12 #include <mapmem.h>
13 #include <part.h>
14 #include <ext4fs.h>
15 #include <fat.h>
16 #include <fs.h>
17 #include <sandboxfs.h>
18 #include <ubifs_uboot.h>
19 #include <btrfs.h>
20 #include <asm/io.h>
21 #include <div64.h>
22 #include <linux/math64.h>
23 #include <efi_loader.h>
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 static struct blk_desc *fs_dev_desc;
28 static int fs_dev_part;
29 static struct disk_partition fs_partition;
30 static int fs_type = FS_TYPE_ANY;
31
32 static inline int fs_probe_unsupported(struct blk_desc *fs_dev_desc,
33 struct disk_partition *fs_partition)
34 {
35 printf("** Unrecognized filesystem type **\n");
36 return -1;
37 }
38
39 static inline int fs_ls_unsupported(const char *dirname)
40 {
41 return -1;
42 }
43
44 /* generic implementation of ls in terms of opendir/readdir/closedir */
45 __maybe_unused
46 static int fs_ls_generic(const char *dirname)
47 {
48 struct fs_dir_stream *dirs;
49 struct fs_dirent *dent;
50 int nfiles = 0, ndirs = 0;
51
52 dirs = fs_opendir(dirname);
53 if (!dirs)
54 return -errno;
55
56 while ((dent = fs_readdir(dirs))) {
57 if (dent->type == FS_DT_DIR) {
58 printf(" %s/\n", dent->name);
59 ndirs++;
60 } else {
61 printf(" %8lld %s\n", dent->size, dent->name);
62 nfiles++;
63 }
64 }
65
66 fs_closedir(dirs);
67
68 printf("\n%d file(s), %d dir(s)\n\n", nfiles, ndirs);
69
70 return 0;
71 }
72
73 static inline int fs_exists_unsupported(const char *filename)
74 {
75 return 0;
76 }
77
78 static inline int fs_size_unsupported(const char *filename, loff_t *size)
79 {
80 return -1;
81 }
82
83 static inline int fs_read_unsupported(const char *filename, void *buf,
84 loff_t offset, loff_t len,
85 loff_t *actread)
86 {
87 return -1;
88 }
89
90 static inline int fs_write_unsupported(const char *filename, void *buf,
91 loff_t offset, loff_t len,
92 loff_t *actwrite)
93 {
94 return -1;
95 }
96
97 static inline int fs_ln_unsupported(const char *filename, const char *target)
98 {
99 return -1;
100 }
101
102 static inline void fs_close_unsupported(void)
103 {
104 }
105
106 static inline int fs_uuid_unsupported(char *uuid_str)
107 {
108 return -1;
109 }
110
111 static inline int fs_opendir_unsupported(const char *filename,
112 struct fs_dir_stream **dirs)
113 {
114 return -EACCES;
115 }
116
117 static inline int fs_unlink_unsupported(const char *filename)
118 {
119 return -1;
120 }
121
122 static inline int fs_mkdir_unsupported(const char *dirname)
123 {
124 return -1;
125 }
126
127 struct fstype_info {
128 int fstype;
129 char *name;
130 /*
131 * Is it legal to pass NULL as .probe()'s fs_dev_desc parameter? This
132 * should be false in most cases. For "virtual" filesystems which
133 * aren't based on a U-Boot block device (e.g. sandbox), this can be
134 * set to true. This should also be true for the dummy entry at the end
135 * of fstypes[], since that is essentially a "virtual" (non-existent)
136 * filesystem.
137 */
138 bool null_dev_desc_ok;
139 int (*probe)(struct blk_desc *fs_dev_desc,
140 struct disk_partition *fs_partition);
141 int (*ls)(const char *dirname);
142 int (*exists)(const char *filename);
143 int (*size)(const char *filename, loff_t *size);
144 int (*read)(const char *filename, void *buf, loff_t offset,
145 loff_t len, loff_t *actread);
146 int (*write)(const char *filename, void *buf, loff_t offset,
147 loff_t len, loff_t *actwrite);
148 void (*close)(void);
149 int (*uuid)(char *uuid_str);
150 /*
151 * Open a directory stream. On success return 0 and directory
152 * stream pointer via 'dirsp'. On error, return -errno. See
153 * fs_opendir().
154 */
155 int (*opendir)(const char *filename, struct fs_dir_stream **dirsp);
156 /*
157 * Read next entry from directory stream. On success return 0
158 * and directory entry pointer via 'dentp'. On error return
159 * -errno. See fs_readdir().
160 */
161 int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
162 /* see fs_closedir() */
163 void (*closedir)(struct fs_dir_stream *dirs);
164 int (*unlink)(const char *filename);
165 int (*mkdir)(const char *dirname);
166 int (*ln)(const char *filename, const char *target);
167 };
168
169 static struct fstype_info fstypes[] = {
170 #ifdef CONFIG_FS_FAT
171 {
172 .fstype = FS_TYPE_FAT,
173 .name = "fat",
174 .null_dev_desc_ok = false,
175 .probe = fat_set_blk_dev,
176 .close = fat_close,
177 .ls = fs_ls_generic,
178 .exists = fat_exists,
179 .size = fat_size,
180 .read = fat_read_file,
181 #if CONFIG_IS_ENABLED(FAT_WRITE)
182 .write = file_fat_write,
183 .unlink = fat_unlink,
184 .mkdir = fat_mkdir,
185 #else
186 .write = fs_write_unsupported,
187 .unlink = fs_unlink_unsupported,
188 .mkdir = fs_mkdir_unsupported,
189 #endif
190 .uuid = fs_uuid_unsupported,
191 .opendir = fat_opendir,
192 .readdir = fat_readdir,
193 .closedir = fat_closedir,
194 .ln = fs_ln_unsupported,
195 },
196 #endif
197
198 #if CONFIG_IS_ENABLED(FS_EXT4)
199 {
200 .fstype = FS_TYPE_EXT,
201 .name = "ext4",
202 .null_dev_desc_ok = false,
203 .probe = ext4fs_probe,
204 .close = ext4fs_close,
205 .ls = ext4fs_ls,
206 .exists = ext4fs_exists,
207 .size = ext4fs_size,
208 .read = ext4_read_file,
209 #ifdef CONFIG_CMD_EXT4_WRITE
210 .write = ext4_write_file,
211 .ln = ext4fs_create_link,
212 #else
213 .write = fs_write_unsupported,
214 .ln = fs_ln_unsupported,
215 #endif
216 .uuid = ext4fs_uuid,
217 .opendir = fs_opendir_unsupported,
218 .unlink = fs_unlink_unsupported,
219 .mkdir = fs_mkdir_unsupported,
220 },
221 #endif
222 #ifdef CONFIG_SANDBOX
223 {
224 .fstype = FS_TYPE_SANDBOX,
225 .name = "sandbox",
226 .null_dev_desc_ok = true,
227 .probe = sandbox_fs_set_blk_dev,
228 .close = sandbox_fs_close,
229 .ls = sandbox_fs_ls,
230 .exists = sandbox_fs_exists,
231 .size = sandbox_fs_size,
232 .read = fs_read_sandbox,
233 .write = fs_write_sandbox,
234 .uuid = fs_uuid_unsupported,
235 .opendir = fs_opendir_unsupported,
236 .unlink = fs_unlink_unsupported,
237 .mkdir = fs_mkdir_unsupported,
238 .ln = fs_ln_unsupported,
239 },
240 #endif
241 #ifdef CONFIG_CMD_UBIFS
242 {
243 .fstype = FS_TYPE_UBIFS,
244 .name = "ubifs",
245 .null_dev_desc_ok = true,
246 .probe = ubifs_set_blk_dev,
247 .close = ubifs_close,
248 .ls = ubifs_ls,
249 .exists = ubifs_exists,
250 .size = ubifs_size,
251 .read = ubifs_read,
252 .write = fs_write_unsupported,
253 .uuid = fs_uuid_unsupported,
254 .opendir = fs_opendir_unsupported,
255 .unlink = fs_unlink_unsupported,
256 .mkdir = fs_mkdir_unsupported,
257 .ln = fs_ln_unsupported,
258 },
259 #endif
260 #ifdef CONFIG_FS_BTRFS
261 {
262 .fstype = FS_TYPE_BTRFS,
263 .name = "btrfs",
264 .null_dev_desc_ok = false,
265 .probe = btrfs_probe,
266 .close = btrfs_close,
267 .ls = btrfs_ls,
268 .exists = btrfs_exists,
269 .size = btrfs_size,
270 .read = btrfs_read,
271 .write = fs_write_unsupported,
272 .uuid = btrfs_uuid,
273 .opendir = fs_opendir_unsupported,
274 .unlink = fs_unlink_unsupported,
275 .mkdir = fs_mkdir_unsupported,
276 .ln = fs_ln_unsupported,
277 },
278 #endif
279 {
280 .fstype = FS_TYPE_ANY,
281 .name = "unsupported",
282 .null_dev_desc_ok = true,
283 .probe = fs_probe_unsupported,
284 .close = fs_close_unsupported,
285 .ls = fs_ls_unsupported,
286 .exists = fs_exists_unsupported,
287 .size = fs_size_unsupported,
288 .read = fs_read_unsupported,
289 .write = fs_write_unsupported,
290 .uuid = fs_uuid_unsupported,
291 .opendir = fs_opendir_unsupported,
292 .unlink = fs_unlink_unsupported,
293 .mkdir = fs_mkdir_unsupported,
294 .ln = fs_ln_unsupported,
295 },
296 };
297
298 static struct fstype_info *fs_get_info(int fstype)
299 {
300 struct fstype_info *info;
301 int i;
302
303 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) {
304 if (fstype == info->fstype)
305 return info;
306 }
307
308 /* Return the 'unsupported' sentinel */
309 return info;
310 }
311
312 /**
313 * fs_get_type() - Get type of current filesystem
314 *
315 * Return: filesystem type
316 *
317 * Returns filesystem type representing the current filesystem, or
318 * FS_TYPE_ANY for any unrecognised filesystem.
319 */
320 int fs_get_type(void)
321 {
322 return fs_type;
323 }
324
325 /**
326 * fs_get_type_name() - Get type of current filesystem
327 *
328 * Return: Pointer to filesystem name
329 *
330 * Returns a string describing the current filesystem, or the sentinel
331 * "unsupported" for any unrecognised filesystem.
332 */
333 const char *fs_get_type_name(void)
334 {
335 return fs_get_info(fs_type)->name;
336 }
337
338 int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
339 {
340 struct fstype_info *info;
341 int part, i;
342 #ifdef CONFIG_NEEDS_MANUAL_RELOC
343 static int relocated;
344
345 if (!relocated) {
346 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
347 i++, info++) {
348 info->name += gd->reloc_off;
349 info->probe += gd->reloc_off;
350 info->close += gd->reloc_off;
351 info->ls += gd->reloc_off;
352 info->read += gd->reloc_off;
353 info->write += gd->reloc_off;
354 }
355 relocated = 1;
356 }
357 #endif
358
359 part = blk_get_device_part_str(ifname, dev_part_str, &fs_dev_desc,
360 &fs_partition, 1);
361 if (part < 0)
362 return -1;
363
364 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
365 if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
366 fstype != info->fstype)
367 continue;
368
369 if (!fs_dev_desc && !info->null_dev_desc_ok)
370 continue;
371
372 if (!info->probe(fs_dev_desc, &fs_partition)) {
373 fs_type = info->fstype;
374 fs_dev_part = part;
375 return 0;
376 }
377 }
378
379 return -1;
380 }
381
382 /* set current blk device w/ blk_desc + partition # */
383 int fs_set_blk_dev_with_part(struct blk_desc *desc, int part)
384 {
385 struct fstype_info *info;
386 int ret, i;
387
388 if (part >= 1)
389 ret = part_get_info(desc, part, &fs_partition);
390 else
391 ret = part_get_info_whole_disk(desc, &fs_partition);
392 if (ret)
393 return ret;
394 fs_dev_desc = desc;
395
396 for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
397 if (!info->probe(fs_dev_desc, &fs_partition)) {
398 fs_type = info->fstype;
399 fs_dev_part = part;
400 return 0;
401 }
402 }
403
404 return -1;
405 }
406
407 void fs_close(void)
408 {
409 struct fstype_info *info = fs_get_info(fs_type);
410
411 info->close();
412
413 fs_type = FS_TYPE_ANY;
414 }
415
416 int fs_uuid(char *uuid_str)
417 {
418 struct fstype_info *info = fs_get_info(fs_type);
419
420 return info->uuid(uuid_str);
421 }
422
423 int fs_ls(const char *dirname)
424 {
425 int ret;
426
427 struct fstype_info *info = fs_get_info(fs_type);
428
429 ret = info->ls(dirname);
430
431 fs_close();
432
433 return ret;
434 }
435
436 int fs_exists(const char *filename)
437 {
438 int ret;
439
440 struct fstype_info *info = fs_get_info(fs_type);
441
442 ret = info->exists(filename);
443
444 fs_close();
445
446 return ret;
447 }
448
449 int fs_size(const char *filename, loff_t *size)
450 {
451 int ret;
452
453 struct fstype_info *info = fs_get_info(fs_type);
454
455 ret = info->size(filename, size);
456
457 fs_close();
458
459 return ret;
460 }
461
462 #ifdef CONFIG_LMB
463 /* Check if a file may be read to the given address */
464 static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
465 loff_t len, struct fstype_info *info)
466 {
467 struct lmb lmb;
468 int ret;
469 loff_t size;
470 loff_t read_len;
471
472 /* get the actual size of the file */
473 ret = info->size(filename, &size);
474 if (ret)
475 return ret;
476 if (offset >= size) {
477 /* offset >= EOF, no bytes will be written */
478 return 0;
479 }
480 read_len = size - offset;
481
482 /* limit to 'len' if it is smaller */
483 if (len && len < read_len)
484 read_len = len;
485
486 lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
487 lmb_dump_all(&lmb);
488
489 if (lmb_alloc_addr(&lmb, addr, read_len) == addr)
490 return 0;
491
492 printf("** Reading file would overwrite reserved memory **\n");
493 return -ENOSPC;
494 }
495 #endif
496
497 static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
498 int do_lmb_check, loff_t *actread)
499 {
500 struct fstype_info *info = fs_get_info(fs_type);
501 void *buf;
502 int ret;
503
504 #ifdef CONFIG_LMB
505 if (do_lmb_check) {
506 ret = fs_read_lmb_check(filename, addr, offset, len, info);
507 if (ret)
508 return ret;
509 }
510 #endif
511
512 /*
513 * We don't actually know how many bytes are being read, since len==0
514 * means read the whole file.
515 */
516 buf = map_sysmem(addr, len);
517 ret = info->read(filename, buf, offset, len, actread);
518 unmap_sysmem(buf);
519
520 /* If we requested a specific number of bytes, check we got it */
521 if (ret == 0 && len && *actread != len)
522 debug("** %s shorter than offset + len **\n", filename);
523 fs_close();
524
525 return ret;
526 }
527
528 int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
529 loff_t *actread)
530 {
531 return _fs_read(filename, addr, offset, len, 0, actread);
532 }
533
534 int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
535 loff_t *actwrite)
536 {
537 struct fstype_info *info = fs_get_info(fs_type);
538 void *buf;
539 int ret;
540
541 buf = map_sysmem(addr, len);
542 ret = info->write(filename, buf, offset, len, actwrite);
543 unmap_sysmem(buf);
544
545 if (ret < 0 && len != *actwrite) {
546 printf("** Unable to write file %s **\n", filename);
547 ret = -1;
548 }
549 fs_close();
550
551 return ret;
552 }
553
554 struct fs_dir_stream *fs_opendir(const char *filename)
555 {
556 struct fstype_info *info = fs_get_info(fs_type);
557 struct fs_dir_stream *dirs = NULL;
558 int ret;
559
560 ret = info->opendir(filename, &dirs);
561 fs_close();
562 if (ret) {
563 errno = -ret;
564 return NULL;
565 }
566
567 dirs->desc = fs_dev_desc;
568 dirs->part = fs_dev_part;
569
570 return dirs;
571 }
572
573 struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs)
574 {
575 struct fstype_info *info;
576 struct fs_dirent *dirent;
577 int ret;
578
579 fs_set_blk_dev_with_part(dirs->desc, dirs->part);
580 info = fs_get_info(fs_type);
581
582 ret = info->readdir(dirs, &dirent);
583 fs_close();
584 if (ret) {
585 errno = -ret;
586 return NULL;
587 }
588
589 return dirent;
590 }
591
592 void fs_closedir(struct fs_dir_stream *dirs)
593 {
594 struct fstype_info *info;
595
596 if (!dirs)
597 return;
598
599 fs_set_blk_dev_with_part(dirs->desc, dirs->part);
600 info = fs_get_info(fs_type);
601
602 info->closedir(dirs);
603 fs_close();
604 }
605
606 int fs_unlink(const char *filename)
607 {
608 int ret;
609
610 struct fstype_info *info = fs_get_info(fs_type);
611
612 ret = info->unlink(filename);
613
614 fs_close();
615
616 return ret;
617 }
618
619 int fs_mkdir(const char *dirname)
620 {
621 int ret;
622
623 struct fstype_info *info = fs_get_info(fs_type);
624
625 ret = info->mkdir(dirname);
626
627 fs_close();
628
629 return ret;
630 }
631
632 int fs_ln(const char *fname, const char *target)
633 {
634 struct fstype_info *info = fs_get_info(fs_type);
635 int ret;
636
637 ret = info->ln(fname, target);
638
639 if (ret < 0) {
640 printf("** Unable to create link %s -> %s **\n", fname, target);
641 ret = -1;
642 }
643 fs_close();
644
645 return ret;
646 }
647
648 int do_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
649 int fstype)
650 {
651 loff_t size;
652
653 if (argc != 4)
654 return CMD_RET_USAGE;
655
656 if (fs_set_blk_dev(argv[1], argv[2], fstype))
657 return 1;
658
659 if (fs_size(argv[3], &size) < 0)
660 return CMD_RET_FAILURE;
661
662 env_set_hex("filesize", size);
663
664 return 0;
665 }
666
667 int do_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
668 int fstype)
669 {
670 unsigned long addr;
671 const char *addr_str;
672 const char *filename;
673 loff_t bytes;
674 loff_t pos;
675 loff_t len_read;
676 int ret;
677 unsigned long time;
678 char *ep;
679
680 if (argc < 2)
681 return CMD_RET_USAGE;
682 if (argc > 7)
683 return CMD_RET_USAGE;
684
685 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
686 return 1;
687
688 if (argc >= 4) {
689 addr = simple_strtoul(argv[3], &ep, 16);
690 if (ep == argv[3] || *ep != '\0')
691 return CMD_RET_USAGE;
692 } else {
693 addr_str = env_get("loadaddr");
694 if (addr_str != NULL)
695 addr = simple_strtoul(addr_str, NULL, 16);
696 else
697 addr = CONFIG_SYS_LOAD_ADDR;
698 }
699 if (argc >= 5) {
700 filename = argv[4];
701 } else {
702 filename = env_get("bootfile");
703 if (!filename) {
704 puts("** No boot file defined **\n");
705 return 1;
706 }
707 }
708 if (argc >= 6)
709 bytes = simple_strtoul(argv[5], NULL, 16);
710 else
711 bytes = 0;
712 if (argc >= 7)
713 pos = simple_strtoul(argv[6], NULL, 16);
714 else
715 pos = 0;
716
717 #ifdef CONFIG_CMD_BOOTEFI
718 efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "",
719 (argc > 4) ? argv[4] : "");
720 #endif
721 time = get_timer(0);
722 ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
723 time = get_timer(time);
724 if (ret < 0)
725 return 1;
726
727 printf("%llu bytes read in %lu ms", len_read, time);
728 if (time > 0) {
729 puts(" (");
730 print_size(div_u64(len_read, time) * 1000, "/s");
731 puts(")");
732 }
733 puts("\n");
734
735 env_set_hex("fileaddr", addr);
736 env_set_hex("filesize", len_read);
737
738 return 0;
739 }
740
741 int do_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
742 int fstype)
743 {
744 if (argc < 2)
745 return CMD_RET_USAGE;
746 if (argc > 4)
747 return CMD_RET_USAGE;
748
749 if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
750 return 1;
751
752 if (fs_ls(argc >= 4 ? argv[3] : "/"))
753 return 1;
754
755 return 0;
756 }
757
758 int file_exists(const char *dev_type, const char *dev_part, const char *file,
759 int fstype)
760 {
761 if (fs_set_blk_dev(dev_type, dev_part, fstype))
762 return 0;
763
764 return fs_exists(file);
765 }
766
767 int do_save(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
768 int fstype)
769 {
770 unsigned long addr;
771 const char *filename;
772 loff_t bytes;
773 loff_t pos;
774 loff_t len;
775 int ret;
776 unsigned long time;
777
778 if (argc < 6 || argc > 7)
779 return CMD_RET_USAGE;
780
781 if (fs_set_blk_dev(argv[1], argv[2], fstype))
782 return 1;
783
784 addr = simple_strtoul(argv[3], NULL, 16);
785 filename = argv[4];
786 bytes = simple_strtoul(argv[5], NULL, 16);
787 if (argc >= 7)
788 pos = simple_strtoul(argv[6], NULL, 16);
789 else
790 pos = 0;
791
792 time = get_timer(0);
793 ret = fs_write(filename, addr, pos, bytes, &len);
794 time = get_timer(time);
795 if (ret < 0)
796 return 1;
797
798 printf("%llu bytes written in %lu ms", len, time);
799 if (time > 0) {
800 puts(" (");
801 print_size(div_u64(len, time) * 1000, "/s");
802 puts(")");
803 }
804 puts("\n");
805
806 return 0;
807 }
808
809 int do_fs_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
810 int fstype)
811 {
812 int ret;
813 char uuid[37];
814 memset(uuid, 0, sizeof(uuid));
815
816 if (argc < 3 || argc > 4)
817 return CMD_RET_USAGE;
818
819 if (fs_set_blk_dev(argv[1], argv[2], fstype))
820 return 1;
821
822 ret = fs_uuid(uuid);
823 if (ret)
824 return CMD_RET_FAILURE;
825
826 if (argc == 4)
827 env_set(argv[3], uuid);
828 else
829 printf("%s\n", uuid);
830
831 return CMD_RET_SUCCESS;
832 }
833
834 int do_fs_type(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
835 {
836 struct fstype_info *info;
837
838 if (argc < 3 || argc > 4)
839 return CMD_RET_USAGE;
840
841 if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
842 return 1;
843
844 info = fs_get_info(fs_type);
845
846 if (argc == 4)
847 env_set(argv[3], info->name);
848 else
849 printf("%s\n", info->name);
850
851 fs_close();
852
853 return CMD_RET_SUCCESS;
854 }
855
856 int do_rm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
857 int fstype)
858 {
859 if (argc != 4)
860 return CMD_RET_USAGE;
861
862 if (fs_set_blk_dev(argv[1], argv[2], fstype))
863 return 1;
864
865 if (fs_unlink(argv[3]))
866 return 1;
867
868 return 0;
869 }
870
871 int do_mkdir(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
872 int fstype)
873 {
874 int ret;
875
876 if (argc != 4)
877 return CMD_RET_USAGE;
878
879 if (fs_set_blk_dev(argv[1], argv[2], fstype))
880 return 1;
881
882 ret = fs_mkdir(argv[3]);
883 if (ret) {
884 printf("** Unable to create a directory \"%s\" **\n", argv[3]);
885 return 1;
886 }
887
888 return 0;
889 }
890
891 int do_ln(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
892 int fstype)
893 {
894 if (argc != 5)
895 return CMD_RET_USAGE;
896
897 if (fs_set_blk_dev(argv[1], argv[2], fstype))
898 return 1;
899
900 if (fs_ln(argv[3], argv[4]))
901 return 1;
902
903 return 0;
904 }