On 08/10/2017 08:29 PM, Rob Clark wrote: > Needed to support efi file protocol. The fallback.efi loader wants > to be able to read the contents of the /EFI directory to find an OS > to boot. > > Also included is an ls2 command which implements ls on top of > fs_readdir(), to more easily test the readdir functionality. > > Signed-off-by: Rob Clark <robdcl...@gmail.com> > --- > cmd/fs.c | 14 +++++++++++ > fs/fs.c | 80 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > include/fs.h | 23 +++++++++++++++++ > 3 files changed, 117 insertions(+) > > diff --git a/cmd/fs.c b/cmd/fs.c > index abfe5be172..58ddcec1a9 100644 > --- a/cmd/fs.c > +++ b/cmd/fs.c > @@ -75,6 +75,20 @@ U_BOOT_CMD( > " device type 'interface' instance 'dev'." > ) > > +static int do_ls2_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, > + char * const argv[]) > +{ > + return do_ls2(cmdtp, flag, argc, argv, FS_TYPE_ANY); > +} > + > +U_BOOT_CMD( > + ls2, 4, 1, do_ls2_wrapper, > + "list files in a directory using fs_readdir (default /)", > + "<interface> [<dev[:part]> [directory]]\n" > + " - List files in directory 'directory' of partition 'part' on\n" > + " device type 'interface' instance 'dev'." > +) > + > static int do_fstype_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, > char * const argv[]) > { > diff --git a/fs/fs.c b/fs/fs.c > index 595ff1fe69..5720ceec49 100644 > --- a/fs/fs.c > +++ b/fs/fs.c > @@ -69,6 +69,12 @@ static inline int fs_uuid_unsupported(char *uuid_str) > return -1; > } > > +static inline int fs_readdir_unsupported(const char *filename, loff_t offset, > + struct fs_dirent *dent) > +{ > + return -ENXIO; > +} > + > struct fstype_info { > int fstype; > char *name; > @@ -92,6 +98,7 @@ struct fstype_info { > loff_t len, loff_t *actwrite); > void (*close)(void); > int (*uuid)(char *uuid_str); > + int (*readdir)(const char *filename, loff_t offset, struct fs_dirent > *dent); > }; > > static struct fstype_info fstypes[] = { > @@ -112,6 +119,7 @@ static struct fstype_info fstypes[] = { > .write = fs_write_unsupported, > #endif > .uuid = fs_uuid_unsupported, > + .readdir = fs_readdir_unsupported, > }, > #endif > #ifdef CONFIG_FS_EXT4 > @@ -131,6 +139,7 @@ static struct fstype_info fstypes[] = { > .write = fs_write_unsupported, > #endif > .uuid = ext4fs_uuid, > + .readdir = fs_readdir_unsupported, > }, > #endif > #ifdef CONFIG_SANDBOX > @@ -146,6 +155,7 @@ static struct fstype_info fstypes[] = { > .read = fs_read_sandbox, > .write = fs_write_sandbox, > .uuid = fs_uuid_unsupported, > + .readdir = fs_readdir_unsupported, > }, > #endif > #ifdef CONFIG_CMD_UBIFS > @@ -161,6 +171,7 @@ static struct fstype_info fstypes[] = { > .read = ubifs_read, > .write = fs_write_unsupported, > .uuid = fs_uuid_unsupported, > + .readdir = fs_readdir_unsupported, > }, > #endif > { > @@ -175,6 +186,7 @@ static struct fstype_info fstypes[] = { > .read = fs_read_unsupported, > .write = fs_write_unsupported, > .uuid = fs_uuid_unsupported, > + .readdir = fs_readdir_unsupported, > }, > }; > > @@ -334,6 +346,19 @@ int fs_write(const char *filename, ulong addr, loff_t > offset, loff_t len, > return ret; > } > > +int fs_readdir(const char *filename, loff_t offset, struct fs_dirent *dent) > +{ > + struct fstype_info *info = fs_get_info(fs_type); > + int ret; > + > + memset(dent, 0, sizeof(*dent)); > + > + ret = info->readdir(filename, offset, dent); > + fs_close(); > + > + return ret; > +} > + > int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], > int fstype) > { > @@ -440,6 +465,61 @@ int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * > const argv[], > return 0; > } > > +int do_ls2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], > + int fstype) > +{ > + const char *filename = argc >= 4 ? argv[3] : "/";
Do we really want to update filename and dev_part_str if argc is illegal? I would suggest to put the assignments below the argc check. Could you, please, add comment lines above the function describing the usage of argv[0..3]. Best regards Heinrich > + const char *ifname = argv[1]; > + const char *dev_part_str = (argc >= 3) ? argv[2] : NULL; > + loff_t offset = 0; > + int ret, files = 0, dirs = 0; > + > + if (argc < 2) > + return CMD_RET_USAGE; > + if (argc > 4) > + return CMD_RET_USAGE; > + > + while (1) { > + struct fs_dirent dent, dent2; > + char buf[256]; > + > + if (fs_set_blk_dev(ifname, dev_part_str, fstype)) > + return 1; > + > + ret = fs_readdir(filename, offset, &dent); > + if (ret == -ENOENT) { > + /* no more directory entries */ > + break; > + } else if (ret) { > + printf("command failed at offset %lld (%d)\n", > + offset, ret); > + return 1; > + } > + > + /* figure out if the entry is a directory: */ > + ret = snprintf(buf, sizeof(buf), "%s/%s", filename, dent.name); > + if (ret >= sizeof(buf)) > + return 1; > + > + fs_set_blk_dev(ifname, dev_part_str, fstype); > + ret = fs_readdir(buf, 0, &dent2); > + > + if (ret == -ENOTDIR) { > + printf(" %8lld %s\n", dent.size, dent.name); > + files++; > + } else { > + printf(" %s/\n", dent.name); > + dirs++; > + } > + > + offset++; > + } > + > + printf("\n%d file(s), %d dir(s)\n\n", files, dirs); > + > + return 0; > +} > + > int file_exists(const char *dev_type, const char *dev_part, const char *file, > int fstype) > { > diff --git a/include/fs.h b/include/fs.h > index 2f2aca8378..d8be5cc9a6 100644 > --- a/include/fs.h > +++ b/include/fs.h > @@ -79,6 +79,27 @@ int fs_write(const char *filename, ulong addr, loff_t > offset, loff_t len, > loff_t *actwrite); > > /* > + * A directory entry. > + */ > +struct fs_dirent { > + loff_t size; > + char name[256]; > +}; > + > +/* > + * fs_readdir - Read a directory. > + * > + * @filename: Name of file to read from > + * @offset: The offset into the directory to read, ie. offset of N returns > + * the N'th directory entry > + * @dent: on success, filled in with directory entry > + * @return 0 on success, -ENOTDIR if specified file is not a directory, > + * or -ENOENT if offset is beyond last directory entry, or -ENXIO if > + * operation is not supported. > + */ > +int fs_readdir(const char *filename, loff_t offset, struct fs_dirent *dent); > + > +/* > * Common implementation for various filesystem commands, optionally limited > * to a specific filesystem type via the fstype parameter. > */ > @@ -88,6 +109,8 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * > const argv[], > int fstype); > int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], > int fstype); > +int do_ls2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], > + int fstype); > int file_exists(const char *dev_type, const char *dev_part, const char *file, > int fstype); > int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot