diff options
-rw-r--r-- | fs/fat/fat.c | 115 |
1 files changed, 52 insertions, 63 deletions
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 1542194..2bb7adf 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; |