fs.c 22 KB

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