Merge branch 'for-next/fat-detection'
This commit is contained in:
commit
3b02a1ac3a
|
@ -26,6 +26,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <fs.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
|
||||
static const char *filetype_str[] = {
|
||||
[filetype_unknown] = "unknown",
|
||||
|
@ -42,6 +43,7 @@ static const char *filetype_str[] = {
|
|||
[filetype_sh] = "Bourne Shell",
|
||||
[filetype_mips_barebox] = "MIPS barebox image",
|
||||
[filetype_fat] = "FAT filesytem",
|
||||
[filetype_mbr] = "MBR sector",
|
||||
};
|
||||
|
||||
const char *file_type_to_string(enum filetype f)
|
||||
|
@ -52,26 +54,51 @@ const char *file_type_to_string(enum filetype f)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int is_fat(u8 *buf)
|
||||
#define MBR_StartSector 8 /* MBR: Offset of Starting Sector in Partition Table Entry */
|
||||
#define BS_55AA 510 /* Boot sector signature (2) */
|
||||
#define MBR_Table 446 /* MBR: Partition table offset (2) */
|
||||
#define BS_FilSysType32 82 /* File system type (1) */
|
||||
#define BS_FilSysType 54 /* File system type (1) */
|
||||
|
||||
enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec)
|
||||
{
|
||||
if (get_unaligned_le16(&buf[510]) != 0xAA55)
|
||||
return 0;
|
||||
/*
|
||||
* bootsec can be used to return index of the first sector in the
|
||||
* first partition
|
||||
*/
|
||||
if (bootsec)
|
||||
*bootsec = 0;
|
||||
|
||||
/* FAT */
|
||||
if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146)
|
||||
return 1;
|
||||
/*
|
||||
* Check record signature (always placed at offset 510 even if the
|
||||
* sector size is > 512)
|
||||
*/
|
||||
if (get_unaligned_le16(§or[BS_55AA]) != 0xAA55)
|
||||
return filetype_unknown;
|
||||
|
||||
/* FAT32 */
|
||||
if ((get_unaligned_le32(&buf[82]) & 0xFFFFFF) == 0x544146)
|
||||
return 1;
|
||||
/* Check "FAT" string */
|
||||
if ((get_unaligned_le32(§or[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
|
||||
return filetype_fat;
|
||||
|
||||
return 0;
|
||||
if ((get_unaligned_le32(§or[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
|
||||
return filetype_fat;
|
||||
|
||||
if (bootsec)
|
||||
/*
|
||||
* This must be an MBR, so return the starting sector of the
|
||||
* first partition so we could check if there is a FAT boot
|
||||
* sector there
|
||||
*/
|
||||
*bootsec = get_unaligned_le16(§or[MBR_Table + MBR_StartSector]);
|
||||
|
||||
return filetype_mbr;
|
||||
}
|
||||
|
||||
enum filetype file_detect_type(void *_buf)
|
||||
{
|
||||
u32 *buf = _buf;
|
||||
u8 *buf8 = _buf;
|
||||
enum filetype type;
|
||||
|
||||
if (strncmp(buf8, "#!/bin/sh", 9) == 0)
|
||||
return filetype_sh;
|
||||
|
@ -99,8 +126,9 @@ enum filetype file_detect_type(void *_buf)
|
|||
return filetype_aimage;
|
||||
if (strncmp(buf8 + 0x10, "barebox", 7) == 0)
|
||||
return filetype_mips_barebox;
|
||||
if (is_fat(buf8))
|
||||
return filetype_fat;
|
||||
type = is_fat_or_mbr(buf8, NULL);
|
||||
if (type != filetype_unknown)
|
||||
return type;
|
||||
|
||||
return filetype_unknown;
|
||||
}
|
||||
|
@ -110,6 +138,7 @@ enum filetype file_name_detect_type(const char *filename)
|
|||
int fd, ret;
|
||||
void *buf;
|
||||
enum filetype type = filetype_unknown;
|
||||
unsigned long bootsec;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
|
@ -123,6 +152,21 @@ enum filetype file_name_detect_type(const char *filename)
|
|||
|
||||
type = file_detect_type(buf);
|
||||
|
||||
if (type == filetype_mbr) {
|
||||
/*
|
||||
* Get the first partition start sector
|
||||
* and check for FAT in it
|
||||
*/
|
||||
is_fat_or_mbr(buf, &bootsec);
|
||||
ret = lseek(fd, (bootsec) * 512, SEEK_SET);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
ret = read(fd, buf, 512);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
type = is_fat_or_mbr((u8 *)buf, NULL);
|
||||
}
|
||||
|
||||
err_out:
|
||||
close(fd);
|
||||
free(buf);
|
||||
|
|
37
fs/fat/ff.c
37
fs/fat/ff.c
|
@ -93,6 +93,7 @@
|
|||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <filetype.h>
|
||||
#include "ff.h" /* FatFs configurations and declarations */
|
||||
#include "diskio.h" /* Declarations of low level disk I/O functions */
|
||||
|
||||
|
@ -1531,29 +1532,20 @@ int follow_path ( /* 0(0): successful, !=0: error code */
|
|||
/*
|
||||
* Load boot record and check if it is an FAT boot record
|
||||
*/
|
||||
static int check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
|
||||
static enum filetype check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
|
||||
FATFS *fs, /* File system object */
|
||||
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
|
||||
DWORD sect, /* Sector# (lba) to check if it is an FAT boot record or not */
|
||||
DWORD *bootsec
|
||||
)
|
||||
{
|
||||
int ret;
|
||||
enum filetype ret;
|
||||
|
||||
/* Load boot record */
|
||||
ret = disk_read(fs, fs->win, sect, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Check record signature (always placed at offset 510 even if the sector size is>512) */
|
||||
if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)
|
||||
return -ENODEV;
|
||||
return filetype_unknown;
|
||||
|
||||
/* Check "FAT" string */
|
||||
if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
|
||||
return 0;
|
||||
|
||||
if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
return is_fat_or_mbr(fs->win, bootsec);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1565,8 +1557,10 @@ static int chk_mounted ( /* 0(0): successful, !=0: any error occurred */
|
|||
)
|
||||
{
|
||||
BYTE fmt, b;
|
||||
DWORD first_boot_sect;
|
||||
DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
|
||||
WORD nrsv;
|
||||
enum filetype type;
|
||||
|
||||
INIT_LIST_HEAD(&fs->dirtylist);
|
||||
|
||||
|
@ -1579,9 +1573,16 @@ static int chk_mounted ( /* 0(0): successful, !=0: any error occurred */
|
|||
return -EIO;
|
||||
#endif
|
||||
/* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */
|
||||
fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */
|
||||
if (fmt)
|
||||
return fmt; /* No FAT volume is found */
|
||||
type = check_fs(fs, bsect = 0, &first_boot_sect); /* Check sector 0 if it is a VBR */
|
||||
if (type == filetype_mbr) {
|
||||
/* Sector 0 is an MBR, now check for FAT in the first partition */
|
||||
type = check_fs(fs, bsect = first_boot_sect, NULL);
|
||||
if (type != filetype_fat)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (type == filetype_unknown)
|
||||
return -ENODEV;
|
||||
|
||||
/* Following code initializes the file system object */
|
||||
|
||||
|
|
|
@ -19,10 +19,12 @@ enum filetype {
|
|||
filetype_sh,
|
||||
filetype_mips_barebox,
|
||||
filetype_fat,
|
||||
filetype_mbr,
|
||||
};
|
||||
|
||||
const char *file_type_to_string(enum filetype f);
|
||||
enum filetype file_detect_type(void *_buf);
|
||||
enum filetype file_name_detect_type(const char *filename);
|
||||
enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec);
|
||||
|
||||
#endif /* __FILE_TYPE_H */
|
||||
|
|
Loading…
Reference in New Issue