Yes, this is super-hacky.  The FAT code is quite ugly, and this doesn't
improve things.  But it doesn't make it significantly worse either.  The
better option would be a massive FAT re-write to get rid of the hacky
way that fat_file_ls() works.  Volunteers welcome.

Signed-off-by: Rob Clark <robdcl...@gmail.com>
---
Yeah, not my proudest patch, but there is little that can be done in
fat.c to be proud of short of re-writing it.. which I am not signing
up for.  I don't think it makes things that much worse than it already
is, but if you disagree I still suggest we merge the previous patch,
to enable merging the efi_loader patches that directly or indirectly
depend on it.  At least then we minimize what is not upstream in order
to have a useful UEFI implementation in u-boot.

 fs/fat/fat.c  | 59 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 fs/fs.c       |  2 +-
 include/fat.h |  4 +++-
 3 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 9ad18f96ff..04d8616598 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -14,6 +14,7 @@
 #include <config.h>
 #include <exports.h>
 #include <fat.h>
+#include <fs.h>
 #include <asm/byteorder.h>
 #include <part.h>
 #include <malloc.h>
@@ -575,17 +576,25 @@ static __u8 mkcksum(const char name[8], const char ext[3])
 /*
  * Get the directory entry associated with 'filename' from the directory
  * starting at 'startsect'
+ *
+ * Last two args are only used for dols==LS_READDIR
  */
 __u8 get_dentfromdir_block[MAX_CLUSTSIZE]
        __aligned(ARCH_DMA_MINALIGN);
 
-static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
-                                 char *filename, dir_entry *retdent,
-                                 int dols)
+static dir_entry *get_dentfromdir(fsdata *mydata, char *filename,
+                                 dir_entry *retdent, int dols,
+                                 loff_t pos, struct fs_dirent *d)
 {
        __u16 prevcksum = 0xffff;
        __u32 curclust = START(retdent);
        int files = 0, dirs = 0;
+       int readdir = 0;
+
+       if (dols == LS_READDIR) {
+               readdir = 1;
+               dols = 0;
+       }
 
        debug("get_dentfromdir: %s\n", filename);
 
@@ -618,7 +627,7 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int 
startsect,
                                        get_vfatname(mydata, curclust,
                                                     get_dentfromdir_block,
                                                     dentptr, l_name);
-                                       if (dols) {
+                                       if (dols || readdir) {
                                                int isdir;
                                                char dirc;
                                                int doit = 0;
@@ -637,7 +646,14 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int 
startsect,
                                                        }
                                                }
                                                if (doit) {
-                                                       if (dirc == ' ') {
+                                                       if (readdir) {
+                                                               if ((dirs + 
files - 1) == pos) {
+                                                                       
strcpy(d->name, l_name);
+                                                                       if 
(!isdir)
+                                                                               
d->size = FAT2CPU32(dentptr->size);
+                                                                       return 
NULL;
+                                                               }
+                                                       } else if (dirc == ' ') 
{
                                                                printf(" %8u   
%s%c\n",
                                                                       
FAT2CPU32(dentptr->size),
                                                                        l_name,
@@ -676,7 +692,7 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int 
startsect,
                        }
 
                        get_name(dentptr, s_name);
-                       if (dols) {
+                       if (dols || readdir) {
                                int isdir = (dentptr->attr & ATTR_DIR);
                                char dirc;
                                int doit = 0;
@@ -694,7 +710,14 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int 
startsect,
                                }
 
                                if (doit) {
-                                       if (dirc == ' ') {
+                                       if (readdir) {
+                                               if ((dirs + files - 1) == pos) {
+                                                       strcpy(d->name, s_name);
+                                                       if (!isdir)
+                                                               d->size = 
FAT2CPU32(dentptr->size);
+                                                       return NULL;
+                                               }
+                                       } else if (dirc == ' ') {
                                                printf(" %8u   %s%c\n",
                                                       FAT2CPU32(dentptr->size),
                                                        s_name, dirc);
@@ -825,7 +848,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void 
*buffer,
        __u32 cursect;
        int idx, isdir = 0;
        int files = 0, dirs = 0;
-       int ret = -1;
+       int ret = (dols == LS_READDIR) ? -ENOTDIR : -1;
        int firsttime;
        __u32 root_cluster = 0;
        __u32 read_blk;
@@ -906,7 +929,8 @@ root_reparse:
                if (!dols)
                        goto exit;
 
-               dols = LS_ROOT;
+               if (dols == LS_YES)
+                       dols = LS_ROOT;
        } else if ((idx = dirdelim(fnamecopy)) >= 0) {
                isdir = 1;
                fnamecopy[idx] = '\0';
@@ -1151,8 +1175,6 @@ rootdir_done:
        firsttime = 1;
 
        while (isdir) {
-               int startsect = mydata->data_begin
-                       + START(dentptr) * mydata->clust_size;
                dir_entry dent;
                char *nextname = NULL;
 
@@ -1177,10 +1199,14 @@ rootdir_done:
                        }
                }
 
-               if (get_dentfromdir(mydata, startsect, subname, dentptr,
-                                    isdir ? 0 : dols) == NULL) {
+               if (get_dentfromdir(mydata, subname, dentptr,
+                                   isdir ? 0 : dols, pos, buffer) == NULL) {
                        if (dols && !isdir)
                                *size = 0;
+                       if (dols == LS_READDIR) {
+                               struct fs_dirent *dent = buffer;
+                               ret = dent->name[0] ? 0 : -ENOENT;
+                       }
                        goto exit;
                }
 
@@ -1353,6 +1379,13 @@ int fat_read_file(const char *filename, void *buf, 
loff_t offset, loff_t len,
        return ret;
 }
 
+int fat_readdir(const char *filename, loff_t offset, struct fs_dirent *dent)
+{
+       loff_t actread;
+       return do_fat_read_at(filename, offset, dent, sizeof(*dent),
+                             LS_READDIR, 0, &actread);
+}
+
 void fat_close(void)
 {
 }
diff --git a/fs/fs.c b/fs/fs.c
index 5ac4226ece..42a028a6ce 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -119,7 +119,7 @@ static struct fstype_info fstypes[] = {
                .write = fs_write_unsupported,
 #endif
                .uuid = fs_uuid_unsupported,
-               .readdir = fs_readdir_unsupported,
+               .readdir = fat_readdir,
        },
 #endif
 #ifdef CONFIG_FS_EXT4
diff --git a/include/fat.h b/include/fat.h
index 71879f01ca..0ef3f5be16 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -61,8 +61,8 @@
 /* Flags telling whether we should read a file or list a directory */
 #define LS_NO          0
 #define LS_YES         1
-#define LS_DIR         1
 #define LS_ROOT                2
+#define LS_READDIR     3       /* read directory entry at specified offset */
 
 #define ISDIRDELIM(c)  ((c) == '/' || (c) == '\\')
 
@@ -210,5 +210,7 @@ int file_fat_write(const char *filename, void *buf, loff_t 
offset, loff_t len,
                   loff_t *actwrite);
 int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
                  loff_t *actread);
+struct fs_dirent;
+int fat_readdir(const char *filename, loff_t offset, struct fs_dirent *dir);
 void fat_close(void);
 #endif /* _FAT_H_ */
-- 
2.13.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to