Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[platform/kernel/u-boot.git] / fs / fat / fat.c
index b08949d..6ade4ea 100644 (file)
@@ -145,7 +145,8 @@ static void get_name(dir_entry *dirent, char *s_name)
 }
 
 static int flush_dirty_fat_buffer(fsdata *mydata);
-#if !defined(CONFIG_FAT_WRITE)
+
+#if !CONFIG_IS_ENABLED(FAT_WRITE)
 /* Stub for read only operation */
 int flush_dirty_fat_buffer(fsdata *mydata)
 {
@@ -305,9 +306,6 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
  * into 'buffer'.
  * Update the number of bytes read in *gotsize or return -1 on fatal errors.
  */
-__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
-       __aligned(ARCH_DMA_MINALIGN);
-
 static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
                        __u8 *buffer, loff_t maxsize, loff_t *gotsize)
 {
@@ -350,15 +348,24 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
 
        /* align to beginning of next cluster if any */
        if (pos) {
+               __u8 *tmp_buffer;
+
                actsize = min(filesize, (loff_t)bytesperclust);
-               if (get_cluster(mydata, curclust, get_contents_vfatname_block,
-                               (int)actsize) != 0) {
+               tmp_buffer = malloc_cache_aligned(actsize);
+               if (!tmp_buffer) {
+                       debug("Error: allocating buffer\n");
+                       return -ENOMEM;
+               }
+
+               if (get_cluster(mydata, curclust, tmp_buffer, actsize) != 0) {
                        printf("Error reading cluster\n");
+                       free(tmp_buffer);
                        return -1;
                }
                filesize -= actsize;
                actsize -= pos;
-               memcpy(buffer, get_contents_vfatname_block + pos, actsize);
+               memcpy(buffer, tmp_buffer + pos, actsize);
+               free(tmp_buffer);
                *gotsize += actsize;
                if (!filesize)
                        return 0;
@@ -571,6 +578,17 @@ static int get_fs_info(fsdata *mydata)
                                mydata->sect_size, cur_part_info.blksz);
                return -1;
        }
+       if (mydata->clust_size == 0) {
+               printf("Error: FAT cluster size not set\n");
+               return -1;
+       }
+       if ((unsigned int)mydata->clust_size * mydata->sect_size >
+           MAX_CLUSTSIZE) {
+               printf("Error: FAT cluster size too big (cs=%u, max=%u)\n",
+                      (unsigned int)mydata->clust_size * mydata->sect_size,
+                      MAX_CLUSTSIZE);
+               return -1;
+       }
 
        if (mydata->fatsize == 32) {
                mydata->data_begin = mydata->rootdir_sect -
@@ -807,6 +825,9 @@ static dir_entry *extract_vfat_name(fat_itr *itr)
 
                slot2str((dir_slot *)dent, buf, &idx);
 
+               if (n + idx >= sizeof(itr->l_name))
+                       return NULL;
+
                /* shift accumulated long-name up and copy new part in: */
                memmove(itr->l_name + idx, itr->l_name, n);
                memcpy(itr->l_name, buf, idx);
@@ -1127,7 +1148,15 @@ int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
                goto out_free_both;
 
        debug("reading %s at pos %llu\n", filename, pos);
-       ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
+
+       /* For saving default max clustersize memory allocated to malloc pool */
+       dir_entry *dentptr = itr->dent;
+
+       free(itr);
+
+       itr = NULL;
+
+       ret = get_contents(&fsdata, dentptr, pos, buffer, maxsize, actread);
 
 out_free_both:
        free(fsdata.fatbuf);