mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	fs: fat: calculate FAT type based on cluster count
This fixes an issue where the FAT type (FAT12, FAT16) is not correctly detected, e.g. when the BPB field BS_FilSysType contains the valid value "FAT ". According to the FAT spec the field BS_FilSysType has only informational character and does not determine the FAT type. The logic of this code is based on the linux kernel implementation from the file fs/fat/inode.c function fat_fill_super(). For details about FAT see http://elm-chan.org/docs/fat_e.html Signed-off-by: Christian Taedcke <christian.taedcke@weidmueller.com>
This commit is contained in:
		
							parent
							
								
									601d33f31a
								
							
						
					
					
						commit
						08f622a127
					
				
							
								
								
									
										46
									
								
								fs/fat/fat.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								fs/fat/fat.c
									
									
									
									
									
								
							@ -26,6 +26,9 @@
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
#include <linux/ctype.h>
 | 
			
		||||
 | 
			
		||||
/* maximum number of clusters for FAT12 */
 | 
			
		||||
#define MAX_FAT12	0xFF4
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Convert a string to lowercase.  Converts at most 'len' characters,
 | 
			
		||||
 * 'len' may be larger than the length of 'str' if 'str' is NULL
 | 
			
		||||
@ -484,6 +487,27 @@ static __u8 mkcksum(struct nameext *nameext)
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Determine if the FAT type is FAT12 or FAT16
 | 
			
		||||
 *
 | 
			
		||||
 * Based on fat_fill_super() from the Linux kernel's fs/fat/inode.c
 | 
			
		||||
 */
 | 
			
		||||
static int determine_legacy_fat_bits(const boot_sector *bs)
 | 
			
		||||
{
 | 
			
		||||
	u16 fat_start = bs->reserved;
 | 
			
		||||
	u32 dir_start = fat_start + bs->fats * bs->fat_length;
 | 
			
		||||
	u32 rootdir_sectors = get_unaligned_le16(bs->dir_entries) *
 | 
			
		||||
			      sizeof(dir_entry) /
 | 
			
		||||
			      get_unaligned_le16(bs->sector_size);
 | 
			
		||||
	u32 data_start = dir_start + rootdir_sectors;
 | 
			
		||||
	u16 sectors = get_unaligned_le16(bs->sectors);
 | 
			
		||||
	u32 total_sectors = sectors ? sectors : bs->total_sect;
 | 
			
		||||
	u32 total_clusters = (total_sectors - data_start) /
 | 
			
		||||
			     bs->cluster_size;
 | 
			
		||||
 | 
			
		||||
	return (total_clusters > MAX_FAT12) ? 16 : 12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Read boot sector and volume info from a FAT filesystem
 | 
			
		||||
 */
 | 
			
		||||
@ -518,7 +542,7 @@ read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
 | 
			
		||||
	bs->total_sect = FAT2CPU32(bs->total_sect);
 | 
			
		||||
 | 
			
		||||
	/* FAT32 entries */
 | 
			
		||||
	if (bs->fat_length == 0) {
 | 
			
		||||
	if (!bs->fat_length && bs->fat32_length) {
 | 
			
		||||
		/* Assume FAT32 */
 | 
			
		||||
		bs->fat32_length = FAT2CPU32(bs->fat32_length);
 | 
			
		||||
		bs->flags = FAT2CPU16(bs->flags);
 | 
			
		||||
@ -529,25 +553,10 @@ read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
 | 
			
		||||
		*fatsize = 32;
 | 
			
		||||
	} else {
 | 
			
		||||
		vistart = (volume_info *)&(bs->fat32_length);
 | 
			
		||||
		*fatsize = 0;
 | 
			
		||||
		*fatsize = determine_legacy_fat_bits(bs);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(volinfo, vistart, sizeof(volume_info));
 | 
			
		||||
 | 
			
		||||
	if (*fatsize == 32) {
 | 
			
		||||
		if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0)
 | 
			
		||||
	goto exit;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) {
 | 
			
		||||
			*fatsize = 12;
 | 
			
		||||
			goto exit;
 | 
			
		||||
		}
 | 
			
		||||
		if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) {
 | 
			
		||||
			*fatsize = 16;
 | 
			
		||||
			goto exit;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	debug("Error: broken fs_type sign\n");
 | 
			
		||||
fail:
 | 
			
		||||
	ret = -1;
 | 
			
		||||
exit:
 | 
			
		||||
@ -1157,9 +1166,8 @@ int file_fat_detectfs(void)
 | 
			
		||||
 | 
			
		||||
	memcpy(vol_label, volinfo.volume_label, 11);
 | 
			
		||||
	vol_label[11] = '\0';
 | 
			
		||||
	volinfo.fs_type[5] = '\0';
 | 
			
		||||
 | 
			
		||||
	printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label);
 | 
			
		||||
	printf("Filesystem: FAT%d \"%s\"\n", fatsize, vol_label);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,12 +34,6 @@ struct disk_partition;
 | 
			
		||||
/* Maximum number of entry for long file name according to spec */
 | 
			
		||||
#define MAX_LFN_SLOT	20
 | 
			
		||||
 | 
			
		||||
/* Filesystem identifiers */
 | 
			
		||||
#define FAT12_SIGN	"FAT12   "
 | 
			
		||||
#define FAT16_SIGN	"FAT16   "
 | 
			
		||||
#define FAT32_SIGN	"FAT32   "
 | 
			
		||||
#define SIGNLEN		8
 | 
			
		||||
 | 
			
		||||
/* File attributes */
 | 
			
		||||
#define ATTR_RO	1
 | 
			
		||||
#define ATTR_HIDDEN	2
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user