]> git.ipfire.org Git - people/jschlag/ipfire-2.x.git/commitdiff
u-boot: fix fat16 reader
authorArne Fitzenreiter <arne_f@ipfire.org>
Wed, 16 Mar 2016 21:58:21 +0000 (22:58 +0100)
committerArne Fitzenreiter <arne_f@ipfire.org>
Wed, 16 Mar 2016 21:58:21 +0000 (22:58 +0100)
lfs/u-boot
src/patches/U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch [new file with mode: 0644]

index 28f65083cf9659a9c93eb2f0a34c52d4e20f3902..3b3fbf22117fe5027aa89eda1ae31a01f42f6eb1 100644 (file)
@@ -75,6 +75,8 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        @$(PREBUILD)
        @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
 
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch
+
        # Pandaboard
        -mkdir -pv /usr/share/u-boot/pandaboard
        cd $(DIR_APP) && make CROSS_COMPILE="" omap4_panda_config
diff --git a/src/patches/U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch b/src/patches/U-Boot-v2-fs-fat-read-fix-fat16-ls-read-issue.patch
new file mode 100644 (file)
index 0000000..39acf14
--- /dev/null
@@ -0,0 +1,128 @@
+diff --git a/fs/fat/fat.c b/fs/fat/fat.c
+index 04a51db..bccc3e3 100644
+--- a/fs/fat/fat.c
++++ b/fs/fat/fat.c
+@@ -823,8 +823,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
+       int ret = -1;
+       int firsttime;
+       __u32 root_cluster = 0;
++      __u32 read_blk;
+       int rootdir_size = 0;
+-      int j;
++      int buffer_blk_cnt;
++      int do_read;
++      __u8 *dir_ptr;
+       if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
+               debug("Error: reading boot sector\n");
+@@ -909,24 +912,54 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
+               isdir = 1;
+       }
+-      j = 0;
++      buffer_blk_cnt = 0;
++      firsttime = 1;
+       while (1) {
+               int i;
+-              if (j == 0) {
+-                      debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
+-                              cursect, mydata->clust_size, DIRENTSPERBLOCK);
++              if (mydata->fatsize == 32 || firsttime) {
++                      dir_ptr = do_fat_read_at_block;
++                      firsttime = 0;
++              } else {
++                      /**
++                       * FAT16 sector buffer modification:
++                       * Each loop, the second buffered block is moved to
++                       * the buffer begin, and two next sectors are read
++                       * next to the previously moved one. So the sector
++                       * buffer keeps always 3 sectors for fat16.
++                       * And the current sector is the buffer second sector
++                       * beside the "firsttime" read, when it is the first one.
++                       *
++                       * PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1]
++                       * n = computed root dir sector
++                       * loop |  cursect-1  | cursect    | cursect+1  |
++                       *   0  |  sector n+0 | sector n+1 | none       |
++                       *   1  |  none       | sector n+0 | sector n+1 |
++                       *   0  |  sector n+1 | sector n+2 | sector n+3 |
++                       *   1  |  sector n+3 | ...
++                      */
++                      dir_ptr = (do_fat_read_at_block + mydata->sect_size);
++                      memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
++              }
++
++              do_read = 1;
++
++              if (mydata->fatsize == 32 && buffer_blk_cnt)
++                      do_read = 0;
++
++              if (do_read) {
++                      read_blk = (mydata->fatsize == 32) ?
++                                  mydata->clust_size : PREFETCH_BLOCKS;
++
++                      debug("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n",
++                              cursect, read_blk, mydata->clust_size, DIRENTSPERBLOCK);
+-                      if (disk_read(cursect,
+-                                      (mydata->fatsize == 32) ?
+-                                      (mydata->clust_size) :
+-                                      PREFETCH_BLOCKS,
+-                                      do_fat_read_at_block) < 0) {
++                      if (disk_read(cursect, read_blk, dir_ptr) < 0) {
+                               debug("Error: reading rootdir block\n");
+                               goto exit;
+                       }
+-                      dentptr = (dir_entry *) do_fat_read_at_block;
++                      dentptr = (dir_entry *)dir_ptr;
+               }
+               for (i = 0; i < DIRENTSPERBLOCK; i++) {
+@@ -951,7 +984,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
+                                       get_vfatname(mydata,
+                                                    root_cluster,
+-                                                   do_fat_read_at_block,
++                                                   dir_ptr,
+                                                    dentptr, l_name);
+                                       if (dols == LS_ROOT) {
+@@ -1062,7 +1095,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
+                       goto rootdir_done;      /* We got a match */
+               }
+-              debug("END LOOP: j=%d   clust_size=%d\n", j,
++              debug("END LOOP: buffer_blk_cnt=%d   clust_size=%d\n", buffer_blk_cnt,
+                      mydata->clust_size);
+               /*
+@@ -1070,10 +1103,10 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
+                * root directory clusters when a cluster has been
+                * completely processed.
+                */
+-              ++j;
++              ++buffer_blk_cnt;
+               int rootdir_end = 0;
+               if (mydata->fatsize == 32) {
+-                      if (j == mydata->clust_size) {
++                      if (buffer_blk_cnt == mydata->clust_size) {
+                               int nxtsect = 0;
+                               int nxt_clust = 0;
+@@ -1086,11 +1119,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
+                               root_cluster = nxt_clust;
+                               cursect = nxtsect;
+-                              j = 0;
++                              buffer_blk_cnt = 0;
+                       }
+               } else {
+-                      if (j == PREFETCH_BLOCKS)
+-                              j = 0;
++                      if (buffer_blk_cnt == PREFETCH_BLOCKS)
++                              buffer_blk_cnt = 0;
+                       rootdir_end = (++cursect - mydata->rootdir_sect >=
+                                      rootdir_size);