2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
4 * SPDX-License-Identifier: GPL-2.0
15 #include <sandboxfs.h>
16 #include <ubifs_uboot.h>
19 #include <linux/math64.h>
21 DECLARE_GLOBAL_DATA_PTR
;
23 static struct blk_desc
*fs_dev_desc
;
24 static disk_partition_t fs_partition
;
25 static int fs_type
= FS_TYPE_ANY
;
27 static inline int fs_probe_unsupported(struct blk_desc
*fs_dev_desc
,
28 disk_partition_t
*fs_partition
)
30 printf("** Unrecognized filesystem type **\n");
34 static inline int fs_ls_unsupported(const char *dirname
)
39 static inline int fs_exists_unsupported(const char *filename
)
44 static inline int fs_size_unsupported(const char *filename
, loff_t
*size
)
49 static inline int fs_read_unsupported(const char *filename
, void *buf
,
50 loff_t offset
, loff_t len
,
56 static inline int fs_write_unsupported(const char *filename
, void *buf
,
57 loff_t offset
, loff_t len
,
63 static inline void fs_close_unsupported(void)
67 static inline int fs_uuid_unsupported(char *uuid_str
)
76 * Is it legal to pass NULL as .probe()'s fs_dev_desc parameter? This
77 * should be false in most cases. For "virtual" filesystems which
78 * aren't based on a U-Boot block device (e.g. sandbox), this can be
79 * set to true. This should also be true for the dumm entry at the end
80 * of fstypes[], since that is essentially a "virtual" (non-existent)
83 bool null_dev_desc_ok
;
84 int (*probe
)(struct blk_desc
*fs_dev_desc
,
85 disk_partition_t
*fs_partition
);
86 int (*ls
)(const char *dirname
);
87 int (*exists
)(const char *filename
);
88 int (*size
)(const char *filename
, loff_t
*size
);
89 int (*read
)(const char *filename
, void *buf
, loff_t offset
,
90 loff_t len
, loff_t
*actread
);
91 int (*write
)(const char *filename
, void *buf
, loff_t offset
,
92 loff_t len
, loff_t
*actwrite
);
94 int (*uuid
)(char *uuid_str
);
97 static struct fstype_info fstypes
[] = {
100 .fstype
= FS_TYPE_FAT
,
102 .null_dev_desc_ok
= false,
103 .probe
= fat_set_blk_dev
,
106 .exists
= fat_exists
,
108 .read
= fat_read_file
,
109 #ifdef CONFIG_FAT_WRITE
110 .write
= file_fat_write
,
112 .write
= fs_write_unsupported
,
114 .uuid
= fs_uuid_unsupported
,
117 #ifdef CONFIG_FS_EXT4
119 .fstype
= FS_TYPE_EXT
,
121 .null_dev_desc_ok
= false,
122 .probe
= ext4fs_probe
,
123 .close
= ext4fs_close
,
125 .exists
= ext4fs_exists
,
127 .read
= ext4_read_file
,
128 #ifdef CONFIG_CMD_EXT4_WRITE
129 .write
= ext4_write_file
,
131 .write
= fs_write_unsupported
,
136 #ifdef CONFIG_SANDBOX
138 .fstype
= FS_TYPE_SANDBOX
,
140 .null_dev_desc_ok
= true,
141 .probe
= sandbox_fs_set_blk_dev
,
142 .close
= sandbox_fs_close
,
144 .exists
= sandbox_fs_exists
,
145 .size
= sandbox_fs_size
,
146 .read
= fs_read_sandbox
,
147 .write
= fs_write_sandbox
,
148 .uuid
= fs_uuid_unsupported
,
151 #ifdef CONFIG_CMD_UBIFS
153 .fstype
= FS_TYPE_UBIFS
,
155 .null_dev_desc_ok
= true,
156 .probe
= ubifs_set_blk_dev
,
157 .close
= ubifs_close
,
159 .exists
= ubifs_exists
,
162 .write
= fs_write_unsupported
,
163 .uuid
= fs_uuid_unsupported
,
167 .fstype
= FS_TYPE_ANY
,
168 .name
= "unsupported",
169 .null_dev_desc_ok
= true,
170 .probe
= fs_probe_unsupported
,
171 .close
= fs_close_unsupported
,
172 .ls
= fs_ls_unsupported
,
173 .exists
= fs_exists_unsupported
,
174 .size
= fs_size_unsupported
,
175 .read
= fs_read_unsupported
,
176 .write
= fs_write_unsupported
,
177 .uuid
= fs_uuid_unsupported
,
181 static struct fstype_info
*fs_get_info(int fstype
)
183 struct fstype_info
*info
;
186 for (i
= 0, info
= fstypes
; i
< ARRAY_SIZE(fstypes
) - 1; i
++, info
++) {
187 if (fstype
== info
->fstype
)
191 /* Return the 'unsupported' sentinel */
195 int fs_set_blk_dev(const char *ifname
, const char *dev_part_str
, int fstype
)
197 struct fstype_info
*info
;
199 #ifdef CONFIG_NEEDS_MANUAL_RELOC
200 static int relocated
;
203 for (i
= 0, info
= fstypes
; i
< ARRAY_SIZE(fstypes
);
205 info
->name
+= gd
->reloc_off
;
206 info
->probe
+= gd
->reloc_off
;
207 info
->close
+= gd
->reloc_off
;
208 info
->ls
+= gd
->reloc_off
;
209 info
->read
+= gd
->reloc_off
;
210 info
->write
+= gd
->reloc_off
;
216 part
= blk_get_device_part_str(ifname
, dev_part_str
, &fs_dev_desc
,
221 for (i
= 0, info
= fstypes
; i
< ARRAY_SIZE(fstypes
); i
++, info
++) {
222 if (fstype
!= FS_TYPE_ANY
&& info
->fstype
!= FS_TYPE_ANY
&&
223 fstype
!= info
->fstype
)
226 if (!fs_dev_desc
&& !info
->null_dev_desc_ok
)
229 if (!info
->probe(fs_dev_desc
, &fs_partition
)) {
230 fs_type
= info
->fstype
;
238 static void fs_close(void)
240 struct fstype_info
*info
= fs_get_info(fs_type
);
244 fs_type
= FS_TYPE_ANY
;
247 int fs_uuid(char *uuid_str
)
249 struct fstype_info
*info
= fs_get_info(fs_type
);
251 return info
->uuid(uuid_str
);
254 int fs_ls(const char *dirname
)
258 struct fstype_info
*info
= fs_get_info(fs_type
);
260 ret
= info
->ls(dirname
);
262 fs_type
= FS_TYPE_ANY
;
268 int fs_exists(const char *filename
)
272 struct fstype_info
*info
= fs_get_info(fs_type
);
274 ret
= info
->exists(filename
);
281 int fs_size(const char *filename
, loff_t
*size
)
285 struct fstype_info
*info
= fs_get_info(fs_type
);
287 ret
= info
->size(filename
, size
);
294 int fs_read(const char *filename
, ulong addr
, loff_t offset
, loff_t len
,
297 struct fstype_info
*info
= fs_get_info(fs_type
);
302 * We don't actually know how many bytes are being read, since len==0
303 * means read the whole file.
305 buf
= map_sysmem(addr
, len
);
306 ret
= info
->read(filename
, buf
, offset
, len
, actread
);
309 /* If we requested a specific number of bytes, check we got it */
310 if (ret
== 0 && len
&& *actread
!= len
)
311 printf("** %s shorter than offset + len **\n", filename
);
317 int fs_write(const char *filename
, ulong addr
, loff_t offset
, loff_t len
,
320 struct fstype_info
*info
= fs_get_info(fs_type
);
324 buf
= map_sysmem(addr
, len
);
325 ret
= info
->write(filename
, buf
, offset
, len
, actwrite
);
328 if (ret
< 0 && len
!= *actwrite
) {
329 printf("** Unable to write file %s **\n", filename
);
337 int do_size(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[],
343 return CMD_RET_USAGE
;
345 if (fs_set_blk_dev(argv
[1], argv
[2], fstype
))
348 if (fs_size(argv
[3], &size
) < 0)
349 return CMD_RET_FAILURE
;
351 setenv_hex("filesize", size
);
356 int do_load(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[],
360 const char *addr_str
;
361 const char *filename
;
370 return CMD_RET_USAGE
;
372 return CMD_RET_USAGE
;
374 if (fs_set_blk_dev(argv
[1], (argc
>= 3) ? argv
[2] : NULL
, fstype
))
378 addr
= simple_strtoul(argv
[3], &ep
, 16);
379 if (ep
== argv
[3] || *ep
!= '\0')
380 return CMD_RET_USAGE
;
382 addr_str
= getenv("loadaddr");
383 if (addr_str
!= NULL
)
384 addr
= simple_strtoul(addr_str
, NULL
, 16);
386 addr
= CONFIG_SYS_LOAD_ADDR
;
391 filename
= getenv("bootfile");
393 puts("** No boot file defined **\n");
398 bytes
= simple_strtoul(argv
[5], NULL
, 16);
402 pos
= simple_strtoul(argv
[6], NULL
, 16);
407 ret
= fs_read(filename
, addr
, pos
, bytes
, &len_read
);
408 time
= get_timer(time
);
412 printf("%llu bytes read in %lu ms", len_read
, time
);
415 print_size(div_u64(len_read
, time
) * 1000, "/s");
420 setenv_hex("fileaddr", addr
);
421 setenv_hex("filesize", len_read
);
426 int do_ls(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[],
430 return CMD_RET_USAGE
;
432 return CMD_RET_USAGE
;
434 if (fs_set_blk_dev(argv
[1], (argc
>= 3) ? argv
[2] : NULL
, fstype
))
437 if (fs_ls(argc
>= 4 ? argv
[3] : "/"))
443 int file_exists(const char *dev_type
, const char *dev_part
, const char *file
,
446 if (fs_set_blk_dev(dev_type
, dev_part
, fstype
))
449 return fs_exists(file
);
452 int do_save(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[],
456 const char *filename
;
463 if (argc
< 6 || argc
> 7)
464 return CMD_RET_USAGE
;
466 if (fs_set_blk_dev(argv
[1], argv
[2], fstype
))
469 addr
= simple_strtoul(argv
[3], NULL
, 16);
471 bytes
= simple_strtoul(argv
[5], NULL
, 16);
473 pos
= simple_strtoul(argv
[6], NULL
, 16);
478 ret
= fs_write(filename
, addr
, pos
, bytes
, &len
);
479 time
= get_timer(time
);
483 printf("%llu bytes written in %lu ms", len
, time
);
486 print_size(div_u64(len
, time
) * 1000, "/s");
494 int do_fs_uuid(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[],
499 memset(uuid
, 0, sizeof(uuid
));
501 if (argc
< 3 || argc
> 4)
502 return CMD_RET_USAGE
;
504 if (fs_set_blk_dev(argv
[1], argv
[2], fstype
))
509 return CMD_RET_FAILURE
;
512 setenv(argv
[3], uuid
);
514 printf("%s\n", uuid
);
516 return CMD_RET_SUCCESS
;
519 int do_fs_type(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
521 struct fstype_info
*info
;
523 if (argc
< 3 || argc
> 4)
524 return CMD_RET_USAGE
;
526 if (fs_set_blk_dev(argv
[1], argv
[2], FS_TYPE_ANY
))
529 info
= fs_get_info(fs_type
);
532 setenv(argv
[3], info
->name
);
534 printf("%s\n", info
->name
);
536 return CMD_RET_SUCCESS
;