diff options
| -rw-r--r-- | fs/fat/fat.c | 113 | 
1 files changed, 51 insertions, 62 deletions
| diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 1542194a1..2bb7adfcf 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -43,50 +43,30 @@ static void downcase (char *str)  	}  } -static block_dev_desc_t *cur_dev = NULL; +static block_dev_desc_t *cur_dev; +static unsigned int cur_part_nr; +static disk_partition_t cur_part_info; -static unsigned long part_offset = 0; - -static int cur_part = 1; - -#define DOS_PART_TBL_OFFSET	0x1be -#define DOS_PART_MAGIC_OFFSET	0x1fe +#define DOS_BOOT_MAGIC_OFFSET	0x1fe  #define DOS_FS_TYPE_OFFSET	0x36  #define DOS_FS32_TYPE_OFFSET	0x52 -static int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr) +static int disk_read(__u32 block, __u32 nr_blocks, void *buf)  { -	if (cur_dev == NULL) +	if (!cur_dev || !cur_dev->block_read)  		return -1; -	startblock += part_offset; - -	if (cur_dev->block_read) { -		return cur_dev->block_read(cur_dev->dev, startblock, getsize, -					   (unsigned long *) bufptr); -	} -	return -1; +	return cur_dev->block_read(cur_dev->dev, +			cur_part_info.start + block, nr_blocks, buf);  }  int fat_register_device (block_dev_desc_t * dev_desc, int part_no)  {  	unsigned char buffer[dev_desc->blksz]; -	if (!dev_desc->block_read) -		return -1; +	/* First close any currently found FAT filesystem */ +	cur_dev = NULL; -	cur_dev = dev_desc; -	/* check if we have a MBR (on floppies we have only a PBR) */ -	if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)buffer) != 1) { -		printf("** Can't read from device %d **\n", -			dev_desc->dev); -		return -1; -	} -	if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 || -	    buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) { -		/* no signature found */ -		return -1; -	}  #if (defined(CONFIG_CMD_IDE) || \       defined(CONFIG_CMD_MG_DISK) || \       defined(CONFIG_CMD_SATA) || \ @@ -94,45 +74,54 @@ int fat_register_device (block_dev_desc_t * dev_desc, int part_no)       defined(CONFIG_CMD_USB) || \       defined(CONFIG_MMC) || \       defined(CONFIG_SYSTEMACE) ) -	{ -		disk_partition_t info; -		/* First we assume there is a MBR */ -		if (!get_partition_info(dev_desc, part_no, &info)) { -			part_offset = info.start; -			cur_part = part_no; -		} else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], -				    "FAT", 3) == 0) || -			   (strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET], -				    "FAT32", 5) == 0)) { -			/* ok, we assume we are on a PBR only */ -			cur_part = 1; -			part_offset = 0; -		} else { +	/* Read the partition table, if present */ +	if (!get_partition_info(dev_desc, part_no, &cur_part_info)) { +		cur_dev = dev_desc; +		cur_part_nr = part_no; +	} +#endif + +	/* Otherwise it might be a superfloppy (whole-disk FAT filesystem) */ +	if (!cur_dev) { +		if (part_no != 1) {  			printf("** Partition %d not valid on device %d **\n", -				part_no, dev_desc->dev); +					part_no, dev_desc->dev);  			return -1;  		} + +		cur_dev = dev_desc; +		cur_part_nr = 1; +		cur_part_info.start = 0; +		cur_part_info.size = dev_desc->lba; +		cur_part_info.blksz = dev_desc->blksz; +		memset(cur_part_info.name, 0, sizeof(cur_part_info.name)); +		memset(cur_part_info.type, 0, sizeof(cur_part_info.type));  	} -#else -	if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3) == 0) || -	    (strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET], "FAT32", 5) == 0)) { -		/* ok, we assume we are on a PBR only */ -		cur_part = 1; -		part_offset = 0; -	} else { -		/* FIXME we need to determine the start block of the -		 * partition where the DOS FS resides. This can be done -		 * by using the get_partition_info routine. For this -		 * purpose the libpart must be included. -		 */ -		part_offset = 32; -		cur_part = 1; + +	/* Make sure it has a valid FAT header */ +	if (disk_read(0, 1, buffer) != 1) { +		cur_dev = NULL; +		return -1;  	} -#endif -	return 0; + +	/* Check if it's actually a DOS volume */ +	if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) { +		cur_dev = NULL; +		return -1; +	} + +	/* Check for FAT12/FAT16/FAT32 filesystem */ +	if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3)) +		return 0; +	if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5)) +		return 0; + +	cur_dev = NULL; +	return -1;  } +  /*   * Get the first occurence of a directory delimiter ('/' or '\') in a string.   * Return index into string if found, -1 otherwise. @@ -1172,7 +1161,7 @@ int file_fat_detectfs (void)  	vol_label[11] = '\0';  	volinfo.fs_type[5] = '\0'; -	printf("Partition %d: Filesystem: %s \"%s\"\n", cur_part, +	printf("Partition %d: Filesystem: %s \"%s\"\n", cur_part_nr,  		volinfo.fs_type, vol_label);  	return 0; |