dm: Drop the block_dev_desc_t typedef
[platform/kernel/u-boot.git] / fs / fat / fat.c
index bccc3e3..2cef3bd 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/byteorder.h>
 #include <part.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <linux/compiler.h>
 #include <linux/ctype.h>
 
@@ -36,7 +37,7 @@ static void downcase(char *str)
        }
 }
 
-static block_dev_desc_t *cur_dev;
+static struct blk_desc *cur_dev;
 static disk_partition_t cur_part_info;
 
 #define DOS_BOOT_MAGIC_OFFSET  0x1fe
@@ -45,14 +46,21 @@ static disk_partition_t cur_part_info;
 
 static int disk_read(__u32 block, __u32 nr_blocks, void *buf)
 {
+       ulong ret;
+
        if (!cur_dev || !cur_dev->block_read)
                return -1;
 
-       return cur_dev->block_read(cur_dev->dev,
-                       cur_part_info.start + block, nr_blocks, buf);
+       ret = cur_dev->block_read(cur_dev, cur_part_info.start + block,
+                                 nr_blocks, buf);
+
+       if (nr_blocks && ret == 0)
+               return -1;
+
+       return ret;
 }
 
-int fat_set_blk_dev(block_dev_desc_t *dev_desc, disk_partition_t *info)
+int fat_set_blk_dev(struct blk_desc *dev_desc, disk_partition_t *info)
 {
        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
 
@@ -81,7 +89,7 @@ int fat_set_blk_dev(block_dev_desc_t *dev_desc, disk_partition_t *info)
        return -1;
 }
 
-int fat_register_device(block_dev_desc_t *dev_desc, int part_no)
+int fat_register_device(struct blk_desc *dev_desc, int part_no)
 {
        disk_partition_t info;
 
@@ -895,6 +903,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
        strcpy(fnamecopy, filename);
        downcase(fnamecopy);
 
+root_reparse:
        if (*fnamecopy == '\0') {
                if (!dols)
                        goto exit;
@@ -1180,6 +1189,34 @@ rootdir_done:
                if (isdir && !(dentptr->attr & ATTR_DIR))
                        goto exit;
 
+               /*
+                * If we are looking for a directory, and found a directory
+                * type entry, and the entry is for the root directory (as
+                * denoted by a cluster number of 0), jump back to the start
+                * of the function, since at least on FAT12/16, the root dir
+                * lives in a hard-coded location and needs special handling
+                * to parse, rather than simply following the cluster linked
+                * list in the FAT, like other directories.
+                */
+               if (isdir && (dentptr->attr & ATTR_DIR) && !START(dentptr)) {
+                       /*
+                        * Modify the filename to remove the prefix that gets
+                        * back to the root directory, so the initial root dir
+                        * parsing code can continue from where we are without
+                        * confusion.
+                        */
+                       strcpy(fnamecopy, nextname ?: "");
+                       /*
+                        * Set up state the same way as the function does when
+                        * first started. This is required for the root dir
+                        * parsing code operates in its expected environment.
+                        */
+                       subname = "";
+                       cursect = mydata->rootdir_sect;
+                       isdir = 0;
+                       goto root_reparse;
+               }
+
                if (idx >= 0)
                        subname = nextname;
        }