path: root/fs/fat/fat.c
Commit message (Collapse)AuthorAgeFilesLines
* dm: scsi: Rename CONFIG_CMD_SCSI to CONFIG_SCSISimon Glass2016-05-171-1/+1
| | | | | | | | This option currently enables both the command and the SCSI functionality. Rename the existing option to CONFIG_SCSI since most of the code relates to the feature. Signed-off-by: Simon Glass <>
* dm: block: Adjust device calls to go through helpers functionSimon Glass2016-03-141-3/+3
| | | | | | | | | | | | To ease conversion to driver model, add helper functions which deal with calling each block device method. With driver model we can reimplement these functions with the same arguments. Use inline functions to avoid increasing code size on some boards. Signed-off-by: Simon Glass <> Reviewed-by: Bin Meng <> Tested-by: Stephen Warren <>
* dm: block: Rename device number member dev to devnumSimon Glass2016-03-141-2/+2
| | | | | | | | | This is a device number, and we want to use 'dev' to mean a driver model device. Rename the member. Signed-off-by: Simon Glass <> Reviewed-by: Bin Meng <> Tested-by: Stephen Warren <>
* dm: part: Rename some partition functionsSimon Glass2016-03-141-1/+1
| | | | | | | | Rename three partition functions so that they start with part_. This makes it clear what they relate to. Signed-off-by: Simon Glass <> Tested-by: Stephen Warren <>
* dm: Drop the block_dev_desc_t typedefSimon Glass2016-03-141-3/+3
| | | | | | | | | Use 'struct' instead of a typdef. Also since 'struct block_dev_desc' is long and causes 80-column violations, rename it to struct blk_desc. Signed-off-by: Simon Glass <> Reviewed-by: Bin Meng <> Tested-by: Stephen Warren <>
* block: pass block dev not num to read/write/erase()Stephen Warren2016-01-131-2/+2
| | | | | | | | | | | This will allow the implementation to make use of data in the block_dev structure beyond the base device number. This will be useful so that eMMC block devices can encompass the HW partition ID rather than treating this out-of-band. Equally, the existence of the priv field is crying out for this patch to exist. Signed-off-by: Stephen Warren <> Reviewed-by: Tom Rini <>
* FIX: fat: Provide correct return code from disk_{read|write} to upper layersŁukasz Majewski2015-09-111-2/+9
| | | | | | | | | | | | | | | | | | | | | | It is very common that FAT code is using following pattern: if (disk_{read|write}() < 0) return -1; Up till now the above code was dead, since disk_{read|write) could only return value >= 0. As a result some errors from medium layer (i.e. eMMC/SD) were not caught. The above behavior was caused by block_{read|write|erase} declared at struct block_dev_desc (@part.h). It returns unsigned long, where 0 indicates error and > 0 indicates that medium operation was correct. This patch as error regards 0 returned from block_{read|write|erase} when nr_blocks is grater than zero. Read/Write operation with nr_blocks=0 should return 0 and hence is not considered as an error. Signed-off-by: Lukasz Majewski <> Test HW: Odroid XU3 - Exynos 5433
* Move ALLOC_CACHE_ALIGN_BUFFER() to the new memalign.h headerSimon Glass2015-09-111-0/+1
| | | | | | | Now that we have a new header file for cache-aligned allocation, we should move the stack-based allocation macro there also. Signed-off-by: Simon Glass <>
* fat: handle paths that include ../Stephen Warren2015-09-111-0/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The FAT code contains a special case to parse the root directory. This is needed since the root directory location/layout on disk is special cased for FAT12/16. In particular, the location and size of the FAT12/16 root directory is hard-coded and contiguous, whereas all FAT12/16 non-root directories, and all FAT32 directories, are stored in a non-contiguous fashion, with the layout represented by a linked-list of clusters in the FAT. If a file path contains ../ (for example /extlinux/../bcm2835-rpi-cm.dtb), it is possible to need to parse the root directory for the first element in the path (requiring application of the special case), then a sub- directory (in the general way), then re-parse the root directory (again requiring the special case). However, the current code in U-Boot only applies the special case for the very first path element, and never for any later path element. When reparsing the root directory without applying the special case, any file in a sector (or cluster?) other than the first sector/cluster of the root directory will not be found. This change modifies the non-root-dir-parsing loop of do_fat_read_at() to detect if it's walked back to the root directory, and if so, jumps back to the special case code that handles parsing of the root directory. This change was tested using sandbox by executing: ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/.." ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/../" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/../backup" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/../backup/" ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/../backup/.." ./u-boot -c "host bind 0 ../sd-p1.bin; ls host 0:0 /extlinux/../backup/../" ./u-boot -c "host bind 0 ../sd-p1.bin; load host 0:0 0 /bcm2835-rpi-cm.dtb" ./u-boot -c "host bind 0 ../sd-p1.bin; load host 0:0 0 /extlinux/../bcm2835-rpi-cm.dtb" ./u-boot -c "host bind 0 ../sd-p1.bin; load host 0:0 0 /backup/../bcm2835-rpi-cm.dtb" ./u-boot -c "host bind 0 ../sd-p1.bin; load host 0:0 0 /extlinux/..backup/../bcm2835-rpi-cm.dtb" ./u-boot -c "host bind 0 ../sd-p1.bin; load host 0:0 0 /extlinux/../backup/../bcm2835-rpi-cm.dtb" (/extlinux and /backup are in different sectors so trigger some different cases, and bcm2835-rpi-cm.dtb is in a sector of the root directory other than the first). In all honesty, this change is a bit of a hack, using goto and all. However, as demonstrated above it appears to work well in practice, is quite minimal, likely doesn't introduce any risk of regressions, and hopefully doesn't introduce any maintenance issues. The correct fix would be to collapse the root and non-root loops in do_fat_read_at() and get_dentfromdir() into a single loop that has a small special-case when moving from one sector to the next, to handle the layout difference of root/non-root directories. AFAIK all other aspects of directory parsing are identical. However, that's a much larger change which needs significantly more thought before it's implemented. Signed-off-by: Stephen Warren <>
* fs: fat: read: fix fat16 ls/read issuePrzemyslaw Marczak2015-01-051-18/+51
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The present fat implementation ignores FAT16 long name directory entries which aren't placed in a single sector. This was becouse of the buffer was always filled by the two sectors, and the loop was made also for two sectors. If some file long name entries are stored in two sectors, the we have two cases: Case 1: Both of sectors are in the buffer - all required data for long file name is in the buffer. - Read OK! Case 2: The current directory entry is placed at the end of the second buffered sector. And the next entries are placed in a sector which is not buffered yet. Then two next sectors are buffered and the mentioned entry is ignored. - Read fail! This commit fixes this issue by: - read two sectors after loop on each single is done - keep the last used sector as a first in the buffer before the read of two next The commit doesn't affects the fat32 imlementation, which works good as previous. Signed-off-by: Przemyslaw Marczak <> Cc: Mikhail Zolotaryov <> Cc: Tom Rini <> Cc: Stephen Warren <> Cc: Simon Glass <> Cc: Suriyan Ramasami <> Cc: Lukasz Majewski <> Cc: Wolfgang Denk <> Tested-by: Simon Glass <>
* fs: API changes enabling extra parameter to return size of type loff_tSuriyan Ramasami2014-11-231-16/+7
| | | | | | | | | | | | | | | The sandbox/ext4/fat/generic fs commands do not gracefully deal with files greater than 2GB. Negative values are returned in such cases. To handle this, the fs functions have been modified to take an additional parameter of type "* loff_t" which is then populated. The return value of the fs functions are used only for error conditions. Signed-off-by: Suriyan Ramasami <> Acked-by: Simon Glass <> [trini: Update board/gdsys/p1022/controlcenterd-id.c, drivers/fpga/zynqpl.c for changes] Signed-off-by: Tom Rini <>
* fat: Prepare API change for files greater than 2GBSuriyan Ramasami2014-11-231-57/+78
| | | | | | | | | Change the internal FAT functions to use loff_t for offsets. Signed-off-by: Suriyan Ramasami <> Acked-by: Simon Glass <> [trini: Fix fs/fat/fat.c for min3 updates] Signed-off-by: Tom Rini <>
* linux/kernel.h: sync min, max, min3, max3 macros with LinuxMasahiro Yamada2014-11-231-1/+1
| | | | | | | | | | | | | | | | | | | | U-Boot has never cared about the type when we get max/min of two values, but Linux Kernel does. This commit gets min, max, min3, max3 macros synced with the kernel introducing type checks. Many of references of those macros must be fixed to suppress warnings. We have two options: - Use min, max, min3, max3 only when the arguments have the same type (or add casts to the arguments) - Use min_t/max_t instead with the appropriate type for the first argument Signed-off-by: Masahiro Yamada <> Acked-by: Pavel Machek <> Acked-by: Lukasz Majewski <> Tested-by: Lukasz Majewski <> [trini: Fixup arch/blackfin/lib/string.c] Signed-off-by: Tom Rini <>
* fs: implement size/fatsize/ext4sizeStephen Warren2014-08-091-0/+5
| | | | | | | | | | These commands may be used to determine the size of a file without actually reading the whole file content into memory. This may be used to determine if the file will fit into the memory buffer that will contain it. In particular, the DFU code will use it for this purpose in the next commit. Signed-off-by: Stephen Warren <>
* fat: implement exists() for FAT fsStephen Warren2014-02-191-4/+14
| | | | | | | | This hooks into the generic "file exists" support added in an earlier patch, and provides an implementation for the FAT filesystem. Signed-off-by: Stephen Warren <> Acked-by: Simon Glass <>
* Add GPL-2.0+ SPDX-License-Identifier to source filesWolfgang Denk2013-07-241-17/+1
| | | | | | Signed-off-by: Wolfgang Denk <> [trini: Fixup common/cmd_io.c] Signed-off-by: Tom Rini <>
* fs: Move ls and read methods into ext4, fatSimon Glass2013-03-041-0/+17
| | | | | | | | | It doesn't make a lot of sense to have these methods in fs.c. They are filesystem-specific, not generic code. Add each to the relevant filesystem and remove the associated #ifdefs in fs.c. Signed-off-by: Simon Glass <> Reviewed-by: Tom Rini <>
* FAT: remove ifdefs to make the code more readableRichard Genoud2013-02-041-26/+29
| | | | | | | | | | | | ifdefs in the code are making it harder to read. The use of simple if(vfat_enabled) makes no more code and is cleaner. (the code is discarded by the compiler instead of the preprocessor.) NB: if -O0 is used, the code won't be discarded and bonus, now the code compiles even if CONFIG_SUPPORT_VFAT is not defined. Signed-off-by: Richard Genoud <>
* FAT: use toupper/tolower instead of recoding themRichard Genoud2013-02-041-1/+2
| | | | | | | | toupper/tolower function are already declared, so use them. Signed-off-by: Richard Genoud <> Acked-by: Marek Vasut <> Acked-by: Stefano Babic <>
* vfat: Fix mkcksum argument sizesMarek Vasut2013-01-311-2/+2
| | | | | | | | | | | | | | | | In case a function argument is known/fixed size array in C, the argument is still decoyed as pointer instead ( T f(U n[k]) ~= T fn(U *n) ) and therefore calling sizeof on the function argument will result in the size of the pointer, not the size of the array. The VFAT code contains such a bug, this patch fixes it. Reported-by: Aaron Williams <> Signed-off-by: Marek Vasut <> Cc: Tom Rini <> Cc: Aaron Williams <> Tested-by: Michal Simek <> Reviewed-by: Joe Hershberger <>
* FAT: implement fat_set_blk_dev(), convert cmd_fat.cStephen Warren2012-10-251-35/+31
| | | | | | | | | | | | | This makes the FAT filesystem API more consistent with other block-based filesystems. If in the future standard multi-filesystem commands such as "ls" or "load" are implemented, having FAT work the same way as other filesystems will be necessary. Convert cmd_fat.c to the new API, so the code looks more like other files implementing the same commands for other filesystems. Signed-off-by: Stephen Warren <> Reviewed-by: Benoît Thébaudeau <>
* FAT: initialize all fields in cur_part_info, simplify initStephen Warren2012-10-251-2/+6
| | | | | | | | | | | | | | cur_part_info.{name,type} are strings. So, we don't need to memset() the entire thing, just put the NULL-termination in the first byte. Add missing initialization of the bootable and uuid fields. None of these fields are actually used by fat.c. However, since it stores the entire disk_partition_t, we should make sure that all fields are valid. Signed-off-by: Stephen Warren <> Reviewed-by: Benoît Thébaudeau <>
* FAT: remove cur_part_nrStephen Warren2012-10-251-7/+2
| | | | | | | | | | | | | | | A future patch will implement the more standard filesystem API fat_set_blk_dev(). This API has no way to know which partition number the partition represents. Equally, future DM rework will make the concept of partition number harder to pass around. So, simply remove cur_part_nr from fat.c; its only use is in a diagnostic printf, and the context where it's printed should make it obvious which partition is referred to anyway (since the partition ID would come from the user command-line that caused it). Signed-off-by: Stephen Warren <> Reviewed-by: Benoît Thébaudeau <>
* fs: fat: Fix mkcksum() function parametersMarek Vasut2012-10-171-8/+12
| | | | | | | | | | | | | | | | | | | | The mkcksum() function now takes one parameter, the pointer to 11-byte wide character array, which it then operates on. Currently, the function is wrongly passed (dir_entry)->name, which is only 8-byte wide character array. Though by further inspecting the dir_entry structure, it can be noticed that the name[8] entry is immediatelly followed by ext[3] entry. Thus, name[8] and ext[3] in the dir_entry structure actually work as this 11-byte wide array since they're placed right next to each other by current compiler behavior. Depending on this is obviously wrong, thus fix this by correctly passing both (dir_entry)->name and (dir_entry)->ext to the mkcksum() function and adjust the function appropriately. Signed-off-by: Marek Vasut <> Cc: Tom Rini <>
* FAT: check for partition 0 not 1 for whole-disk fsStephen Warren2012-10-081-1/+1
| | | | | | | | | | | | | | | | | | | | | The recent switch to use get_device_and_partition() from do_fat_ls() broke the ability to access a FAT filesystem directly on a whole device; FAT only works within a partition on a device. This change makes e.g. "fatls mmc 0:0" work; explicitly requesting partition ID 0 is something that get_device_and_partition() fully supports. However, fat_register_device() expects partition ID 1 to be used in the full-disk case; partition ID 1 was previously implicitly specified when the user didn't actually specify a partition ID. Update fat_register_device() to expect the correct ID. This change does imply that if a user explicitly executes "fatls mmc 0:1" then this will fail, and may be a change in behaviour. Note that this still prevents "fatls mmc 0:auto" from working. The next patch will fix that. Signed-off-by: Stephen Warren <>
* FAT: Make it possible to read from any file positionBenoît Thébaudeau2012-09-261-19/+79
| | | | | | | | | | | | | | | When storage devices contain files larger than the embedded RAM, it is useful to be able to read these files by chunks, e.g. for a software update to the embedded NAND Flash from an external storage device (USB stick, SD card, etc.). Hence, this patch makes it possible by adding a new FAT API to read files from a given position. This patch also adds this feature to the fatload command. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <> Signed-off-by: Tom Rini <>
* FAT: Fix file contents listed as directoryBenoît Thébaudeau2012-09-181-4/+4
| | | | | | | | | | | | | With: fatls mmc 0 /dir/file dir: regular directory file: regular file The previous code read the contents of file as if it were directory entries to list. This patch refuses to list file contents as if it were a folder. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* FAT: Simplify get_contentsBenoît Thébaudeau2012-09-021-13/+1
| | | | | | | | One call to get_cluster can be factorized with another, so avoid duplicating code. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* FAT: get_cluster: Add buffer bouncingBenoît Thébaudeau2012-09-021-12/+30
| | | | | | | | | | Add a buffer bouncing mechanism to get_cluster. This can be useful for misaligned applicative buffers passed through get_contents. This is required for the following patches in the case of data aligned differently relatively to buffers and clusters. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* FAT: Fix redundant sector readBenoît Thébaudeau2012-09-021-26/+33
| | | | | | | | | With the previous code, the remaining prefetched sectors were read again after each sector. With this patch, each sector is read only once, thus making the prefetch useful. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* FAT: cosmetic: Remove useless assignmentBenoît Thébaudeau2012-09-021-1/+0
| | | | | | | | fatlength is not used after this assignment, so it is useless and can be removed. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* FAT: get_fatent: Fix FAT boundary checkBenoît Thébaudeau2012-09-021-2/+2
| | | | | | | | startblock must be taken into account in order not to read past the end of the FAT. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* FAT: cosmetic: Remove extra spacesBenoît Thébaudeau2012-09-021-23/+21
| | | | | | | Remove spaces before opening parentheses in function calls. Signed-off-by: Benoît Thébaudeau <> Cc: Wolfgang Denk <>
* Block: Remove MG DISK supportMarek Vasut2012-06-211-2/+0
| | | | | | | | This driver is unused and obsolete. Signed-off-by: Marek Vasut <> Cc: Wolfgang Denk <> Cc: unsik Kim <>
* fs/fat: align disk buffers on cache line to enable DMA and cacheEric Nelson2012-04-301-10/+12
| | | | | Signed-off-by: Eric Nelson <> Acked-by: Mike Frysinger <>
* fs/fat: Improve error handlingKyle Moffett2012-01-051-4/+14
| | | | | | | | | | | | | | | | | | | | The FAT filesystem fails silently in inexplicable ways when given a filesystem with a block-size that does not match the device sector size. In theory this is not an unsupportable combination but requires a major rewrite of a lot of the filesystem. Until that occurs, the filesystem should detect that scenario and display a helpful error message. This scenario in particular occurred on a 512-byte blocksize FAT fs stored in an El-Torito boot volume on a CD-ROM (2048-byte sector size). Additionally, in many circumstances the ->block_read method will not return a negative number to indicate an error but instead return 0 to indicate the number of blocks successfully read (IE: None). The FAT filesystem should defensively check to ensure that it got all of the sectors that it asked for when reading. Signed-off-by: Kyle Moffett <>
* fs/fat: Fix FAT detection to support non-DOS partition tablesKyle Moffett2012-01-051-63/+52
| | | | | | | | | | | | | | | | | | | The FAT filesystem code currently ends up requiring that the partition table be a DOS MBR, as it checks for the DOS 0x55 0xAA signature on the partition table (which may be Mac, EFI, ISO9660, etc) before actually computing the partition offset. This fixes support for accessing a FAT filesystem in an ISO9660 boot volume (El-Torito format) by reordering the filesystem checks and reading the 0x55 0xAA "DOS boot signature" and FAT/FAT32 magic number from the first sector of the partition instead of from sector 0. Signed-off-by: Kyle Moffett <> Fix build warning: fat.c: In function 'fat_register_device': fat.c:66:15: warning: variable 'found_partition' set but not used [-Wunused-but-set-variable] Signed-off-by: Wolfgang Denk <>
* fat: reset VFAT short alias checksum on first matchSergei Shtylyov2012-01-051-0/+2
| | | | | | | | | | The VFAT short alias checksum read from a long file name is only overwritten when another long file name appears in a directory list. Until then it renders short file names invisible that have the same checksum. Reset the checksum on first match. Signed-off-by: Sergei Shtylyov <> Signed-off-by: Martin Mueller <>
* fat.c: fix printf() length modifierAndreas Bießmann2011-12-171-1/+1
| | | | | | | | | | | | | | | | | | | | The DIRENTSPERBLOCK utilizes sizeof() which will return a size_t which has no fixed size. Therefor use correct length modifer for printf() statement to prevent compiler warnings. This patch fixes following warning: ---8<--- fat.c: In function 'do_fat_read': fat.c:879: warning: format '%d' expects type 'int', but argument 4 has type 'long unsigned int' --->8--- Signed-off-by: Andreas Bießmann <> cc: Mike Frysinger <> cc: Thomas Chou <> cc: cc: Acked-by: Mike Frysinger <>
* fs/fat/fat.c: Fix GCC 4.6 build warningWolfgang Denk2011-11-071-16/+19
| | | | | | | | | Fix: fat.c: In function 'fat_register_device': fat.c:74:19: warning: variable 'info' set but not used [-Wunused-but-set-variable] Signed-off-by: Wolfgang Denk <>
* fat: correct ATTR_VFAT checkJ. Vijayanand2011-10-271-3/+3
| | | | | | | | | ATTR_VFAT condition requires multiple bits to be set but the present condition checking in do_fat_read() & get_dentfromdir() ends up passing on even a single bit being set. Signed-off-by: J. Vijayanand <> Signed-off-by: Sergei Shtylyov <>
* fs/fat/fat.c: fix warning: 'part_size' defined but not usedWolfgang Denk2011-10-271-2/+0
| | | | | | | | | Commit c30a15e "FAT: Add FAT write feature" introduced a compiler warning. Fix this. Signed-off-by: Wolfgang Denk <> Cc: Donggeun Kim <> Cc: Kyungmin Park <>
* FAT: Add FAT write featureDonggeun Kim2011-10-261-0/+2
| | | | | | | | | | | | | | In some cases, saving data in RAM as a file with FAT format is required. This patch allows the file to be written in FAT formatted partition. The usage is similar with reading a file. First, fat_register_device function is called before file_fat_write function in order to set target partition. Then, file_fat_write function is invoked with desired file name, start ram address for writing data, and file size. Signed-off-by: Donggeun Kim <> Signed-off-by: Kyungmin Park <>
* fat: replace LINEAR_PREFETCH_SIZE with PREFETCH_BLOCKSSergei Shtylyov2011-10-011-5/+4
| | | | | | | | | Currently in do_fat_read() when reading FAT sectors, we have to divide down LINEAR_PREFETCH_SIZE by the sector size, whereas it's defined as 2 sectors worth of bytes. In order to avoid redundant multiplication/division, introduce #define PREFETCH_BLOCKS instead of #define LINEAR_PREFETCH_SIZE. Signed-off-by: Sergei Shtylyov <>
* fat: root directory cluster only makes sense for FAT32Sergei Shtylyov2011-10-011-8/+6
| | | | | | | | | The root directory cluster field only exists in a FAT32 boot sector, so the 'root_cluster' variable in do_fat_read() contains garbage in case of FAT12/16. Make it contain 0 instead as this is what is passed to get_vfatname() in that case anyway. Signed-off-by: Sergei Shtylyov <>
* fat: cannot compare bytes and sectorsSergei Shtylyov2011-10-011-3/+4
| | | | | | | | | The code multiples the FAT size in sectors by the sector size and then tries to compare that to the number of sectors in the 'getsize' variable. While fixing this, also change the initial value of 'getsize' as the division of FATBUFSIZE by the sector size gets us FATBUFBLOCKS. Signed-off-by: Sergei Shtylyov <>
* fat: fix crash with big sector sizeSergei Shtylyov2011-10-011-37/+60
| | | | | | | | Apple iPod nanos have sector sizes of 2 or 4 KiB, which crashes U-Boot when it tries to read the boot sector into 512-byte buffer situated on stack. Make the FAT code indifferent to the sector size. Signed-off-by: Sergei Shtylyov <>
* fat32 root directory handlingErik Hansen2011-04-021-14/+23
| | | | | | | | | | | | | | | Fat directory handling didn't check reaching the end of the root directory. It relied on a stop condition based on a directory entry with a name starting with a '\0' character. This check in itself is wrong ('\0' indicates free entry, not end_of_directory) but outside the scope of this fix. For FAT32, the end of the rootdir is reached when the end of the cluster chain is reached. The code didn't check this condition and started to read an incorrect cluster. This caused a subsequent read request of a sector outside the range of the usb stick in use. On its turn, the usb stick protested with a stall handshake. Both FAT32 and non-FAT32 (FAT16/FAT12) end or rootdir checks have been put in. Signed-off-by: Erik Hansen <>
* FAT: buffer overflow with FAT12/16Stefano Babic2010-10-201-1/+1
| | | | | | | | | | | | | Last commit 3831530dcb7b71329c272ccd6181f8038b6a6dd0a was intended "explicitly specify FAT12/16 root directory parsing buffer size, instead of relying on cluster size". Howver, the underlying function requires the size of the buffer in blocks, not in bytes, and instead of passing a double sector size a request for 1024 blocks is sent. This generates a buffer overflow with overwriting of other structure (in the case seen, USB structures were overwritten). Signed-off-by: Stefano Babic <> CC: Mikhail Zolotaryov <>
* VFAT: fix processing of scattered long file name entriesMikhail Zolotaryov2010-10-121-12/+37
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The U-Boot code has the following bugs related to the processing of Long File Name (LFN) entries scattered across several clusters/sectors : 1) get_vfatname() function is designed to gather scattered LFN entries by cluster chain processing - that doesn't work for FAT12/16 root directory. In other words, the function expects the following input data: 1.1) FAT32 directory (which is cluster chain based); OR 1.2) FAT12/16 non-root directory (which is also cluster chain based); OR 1.3) FAT12/16 root directory (allocated as contiguous sectors area), but all necessary information MUST be within the input buffer of filesystem cluster size (thus cluster-chain jump is never initiated). In order to accomplish the last condition, root directory parsing code in do_fat_read() uses the following trick: read-out cluster-size block, process only first sector (512 bytes), then shift 512 forward, read-out cluster-size block and so on. This works great unless cluster size is equal to 512 bytes (in a case you have a small partition), or long file name entries are scattered across three sectors, see 4) for details. 2) Despite of the fact that get_vfatname() supports FAT32 root directory browsing, do_fat_read() function doesn't send current cluster number correctly, so root directory look-up doesn't work correctly. 3) get_vfatname() doesn't gather scattered entries correctly also is the case when all LFN entries are located at the end of the source cluster, but real directory entry (which must be returned) is at the only beginning of the next one. No error detected, the resulting directory entry returned contains a semi-random information (wrong size, wrong start cluster number and so on) i.e. the entry is not accessible. 4) LFN (VFAT) allows up to 20 entries (slots) each containing 26 bytes (13 UTF-16 code units) to represent a single long file name i.e. up to 520 bytes. U-Boot allocates 256 bytes buffer instead, i.e. 10 or more LFN slots record may cause buffer overflow / memory corruption. Also, it's worth to mention that 20+1 slots occupy 672 bytes space which may take more than one cluster of 512 bytes (medium-size FAT32 or small FAT16 partition) - get_vfatname() function doesn't support such case as well. The patch attached fixes these problems in the following way: - keep using 256 bytes buffer for a long file name, but safely prevent a possible buffer overflow (skip LFN processing, if it contains 10 or more slots). - explicitly specify FAT12/16 root directory parsing buffer size, instead of relying on cluster size. The value used is a double sector size (to store current sector and the next one). This fixes the first problem and increases performance on big FAT12/16 partitions; - send current cluster number (FAT32) to get_vfatname() during root directory processing; - use LFN counter to seek the real directory entry in get_vfatname() - fixes the third problem; - skip deleted entries in the root directory (to prevent bogus buffer overflow detection and LFN counter steps). Note: it's not advised to split up the patch, because a separate part may operate incorrectly. Signed-off-by: Mikhail Zolotaryov <>
OpenPOWER on IntegriCloud