* [PATCH 1/2] [v2] filetype: Improve FAT detection
@ 2012-09-16 20:33 Franck Jullien
2012-09-16 20:33 ` [PATCH 2/2] fs/fat: Handle MBR on the first sector Franck Jullien
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Franck Jullien @ 2012-09-16 20:33 UTC (permalink / raw)
To: barebox
We may have some disk with MBR as a first sector. In this case, the
current FAT check returns an error. However, the FAT sector exist and
the MBR can tell us where it is.
This patch add to file_name_detect_type function the ability to find
the FAT boot sector on the first sector of the first partition in case
it is not on sector 0.
It also introduce is_fat_boot_sector to check if a buffer is a FAT boot
sector.
Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
common/filetype.c | 58 +++++++++++++++++++++++++++++++++++++++++++---------
include/filetype.h | 1 +
2 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/common/filetype.c b/common/filetype.c
index e736d43..04ed7fe 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -26,6 +26,8 @@
#include <fcntl.h>
#include <fs.h>
#include <malloc.h>
+#include <fat.h>
+#include <errno.h>
static const char *filetype_str[] = {
[filetype_unknown] = "unknown",
@@ -52,20 +54,35 @@ 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) */
+
+int is_fat_boot_sector(unsigned char *sector, unsigned long *bootsec)
{
- if (get_unaligned_le16(&buf[510]) != 0xAA55)
+ if(bootsec)
+ *bootsec = 0;
+
+ /* Check record signature (always placed at offset 510 even if the sector size is>512) */
+ if (get_unaligned_le16(§or[BS_55AA]) != 0xAA55)
+ return -ENODEV;
+
+ /* Check "FAT" string */
+ if ((get_unaligned_le32(§or[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
return 0;
- /* FAT */
- if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146)
- return 1;
+ if ((get_unaligned_le32(§or[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
+ return 0;
- /* FAT32 */
- if ((get_unaligned_le32(&buf[82]) & 0xFFFFFF) == 0x544146)
- return 1;
+ 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 0;
+ return -ENODEV;
}
enum filetype file_detect_type(void *_buf)
@@ -99,7 +116,8 @@ 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))
+
+ if (!is_fat_boot_sector(buf8, NULL))
return filetype_fat;
return filetype_unknown;
@@ -110,6 +128,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 +142,25 @@ enum filetype file_name_detect_type(const char *filename)
type = file_detect_type(buf);
+ /* Let's give FAT another chance */
+ if (type == filetype_unknown) {
+ ret = is_fat_boot_sector((u8 *)buf, &bootsec);
+ if (ret && bootsec != 0) {
+ /* The first sector is an MBR, now check for
+ * FAT in the first partition */
+ lseek(fd, (bootsec) * 512, SEEK_SET);
+ ret = read(fd, buf, 512);
+ if (ret < 0) {
+ type = filetype_unknown;
+ goto err_out;
+ }
+ ret = is_fat_boot_sector((u8 *)buf, NULL);
+ if (!ret)
+ type = filetype_fat;
+ } else
+ type = filetype_fat;
+ }
+
err_out:
close(fd);
free(buf);
diff --git a/include/filetype.h b/include/filetype.h
index 179ec0f..c60f654 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -24,5 +24,6 @@ enum filetype {
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);
+int is_fat_boot_sector(unsigned char *sector, unsigned long *bootsec);
#endif /* __FILE_TYPE_H */
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] fs/fat: Handle MBR on the first sector
2012-09-16 20:33 [PATCH 1/2] [v2] filetype: Improve FAT detection Franck Jullien
@ 2012-09-16 20:33 ` Franck Jullien
2012-09-17 5:49 ` [PATCH 1/2] [v2] filetype: Improve FAT detection Jean-Christophe PLAGNIOL-VILLARD
2012-09-18 8:38 ` Sascha Hauer
2 siblings, 0 replies; 6+ messages in thread
From: Franck Jullien @ 2012-09-16 20:33 UTC (permalink / raw)
To: barebox
Use the new filetype.c file detection function to support disk with MBR on the first
sector.
Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
fs/fat/ff.c | 27 ++++++++++++---------------
1 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/fs/fat/ff.c b/fs/fat/ff.c
index 66db1d6..622845a 100644
--- a/fs/fat/ff.c
+++ b/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 */
@@ -1533,7 +1534,8 @@ int follow_path ( /* 0(0): successful, !=0: error code */
*/
static int 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;
@@ -1542,18 +1544,8 @@ static int check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:
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;
- /* 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_boot_sector(fs->win, bootsec);
}
/*
@@ -1565,6 +1557,7 @@ 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;
@@ -1579,9 +1572,13 @@ 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 */
+ fmt = check_fs(fs, bsect = 0, &first_boot_sect); /* Check sector 0 if it is a VBR */
+ if (fmt && first_boot_sect != 0) {
+ /* Sector 0 is an MBR, now check for FAT in the first partition */
+ fmt = check_fs(fs, bsect = first_boot_sect, NULL);
+ if(fmt)
+ return fmt; /* No FAT volume is found */
+ }
/* Following code initializes the file system object */
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] [v2] filetype: Improve FAT detection
2012-09-16 20:33 [PATCH 1/2] [v2] filetype: Improve FAT detection Franck Jullien
2012-09-16 20:33 ` [PATCH 2/2] fs/fat: Handle MBR on the first sector Franck Jullien
@ 2012-09-17 5:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-09-17 6:08 ` Franck Jullien
2012-09-18 8:38 ` Sascha Hauer
2 siblings, 1 reply; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-17 5:49 UTC (permalink / raw)
To: Franck Jullien; +Cc: barebox
On 22:33 Sun 16 Sep , Franck Jullien wrote:
> We may have some disk with MBR as a first sector. In this case, the
> current FAT check returns an error. However, the FAT sector exist and
> the MBR can tell us where it is.
>
> This patch add to file_name_detect_type function the ability to find
> the FAT boot sector on the first sector of the first partition in case
> it is not on sector 0.
>
> It also introduce is_fat_boot_sector to check if a buffer is a FAT boot
> sector.
can you try
mount /dev/disk0.0 /mnt
does this work?
Best Regards,
J.
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] [v2] filetype: Improve FAT detection
2012-09-17 5:49 ` [PATCH 1/2] [v2] filetype: Improve FAT detection Jean-Christophe PLAGNIOL-VILLARD
@ 2012-09-17 6:08 ` Franck Jullien
0 siblings, 0 replies; 6+ messages in thread
From: Franck Jullien @ 2012-09-17 6:08 UTC (permalink / raw)
To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox
2012/9/17 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>:
> On 22:33 Sun 16 Sep , Franck Jullien wrote:
>> We may have some disk with MBR as a first sector. In this case, the
>> current FAT check returns an error. However, the FAT sector exist and
>> the MBR can tell us where it is.
>>
>> This patch add to file_name_detect_type function the ability to find
>> the FAT boot sector on the first sector of the first partition in case
>> it is not on sector 0.
>>
>> It also introduce is_fat_boot_sector to check if a buffer is a FAT boot
>> sector.
> can you try
>
> mount /dev/disk0.0 /mnt
>
> does this work?
>
> Best Regards,
> J.
Yes it works. However, I don't have partitions, I use mount /dev/disk0 /mnt.
I tested with MBR and FAT as first sector (two different cards) and
with/without -t fat option.
Franck.
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] [v2] filetype: Improve FAT detection
2012-09-16 20:33 [PATCH 1/2] [v2] filetype: Improve FAT detection Franck Jullien
2012-09-16 20:33 ` [PATCH 2/2] fs/fat: Handle MBR on the first sector Franck Jullien
2012-09-17 5:49 ` [PATCH 1/2] [v2] filetype: Improve FAT detection Jean-Christophe PLAGNIOL-VILLARD
@ 2012-09-18 8:38 ` Sascha Hauer
2 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2012-09-18 8:38 UTC (permalink / raw)
To: Franck Jullien; +Cc: barebox
Hi Franck,
On Sun, Sep 16, 2012 at 10:33:32PM +0200, Franck Jullien wrote:
> We may have some disk with MBR as a first sector. In this case, the
> current FAT check returns an error. However, the FAT sector exist and
> the MBR can tell us where it is.
>
> This patch add to file_name_detect_type function the ability to find
> the FAT boot sector on the first sector of the first partition in case
> it is not on sector 0.
>
> It also introduce is_fat_boot_sector to check if a buffer is a FAT boot
> sector.
I think it would be cleaner to introduce a filetype MBR as a first
step...
> @@ -110,6 +128,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 +142,25 @@ enum filetype file_name_detect_type(const char *filename)
>
> type = file_detect_type(buf);
>
> + /* Let's give FAT another chance */
> + if (type == filetype_unknown) {
... then you could check for type == filetype_mbr here instead and
return filetype_mbr when the check for fat below fails.
> + ret = is_fat_boot_sector((u8 *)buf, &bootsec);
> + if (ret && bootsec != 0) {
> + /* The first sector is an MBR, now check for
> + * FAT in the first partition */
> + lseek(fd, (bootsec) * 512, SEEK_SET);
Please check the return value of lseek here. lseek will fail when the file
is on a tftp filesystem or when the file is not large enough.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] filetype: Improve FAT detection
@ 2012-09-16 12:32 Franck Jullien
2012-09-16 12:32 ` [PATCH 2/2] fs/fat: Handle MBR on the first sector Franck Jullien
0 siblings, 1 reply; 6+ messages in thread
From: Franck Jullien @ 2012-09-16 12:32 UTC (permalink / raw)
To: barebox
We may have some disk with MBR as a first sector. In this case, the
current FAT check returns an error. However, the FAT sector exist and
the MBR can tell us where it is.
This patch make the FAT fs try to find the FAT boot sector on the first
sector of the first partition in case it is not on sector 0.
Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
common/filetype.c | 55 +++++++++++++++++++++++++++++++++++++++++----------
include/filetype.h | 1 +
2 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/common/filetype.c b/common/filetype.c
index e736d43..d07505b 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -26,6 +26,8 @@
#include <fcntl.h>
#include <fs.h>
#include <malloc.h>
+#include <fat.h>
+#include <errno.h>
static const char *filetype_str[] = {
[filetype_unknown] = "unknown",
@@ -52,26 +54,45 @@ const char *file_type_to_string(enum filetype f)
return NULL;
}
-static int is_fat(u8 *buf)
+int fd;
+
+#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) */
+
+int is_fat_boot_sector(unsigned char *sector, unsigned long *bootsec)
{
- if (get_unaligned_le16(&buf[510]) != 0xAA55)
+ if(bootsec)
+ *bootsec = 0;
+
+ /* Check record signature (always placed at offset 510 even if the sector size is>512) */
+ if (get_unaligned_le16(§or[BS_55AA]) != 0xAA55)
+ return -ENODEV;
+
+ /* Check "FAT" string */
+ if ((get_unaligned_le32(§or[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
return 0;
- /* FAT */
- if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146)
- return 1;
+ if ((get_unaligned_le32(§or[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
+ return 0;
- /* FAT32 */
- if ((get_unaligned_le32(&buf[82]) & 0xFFFFFF) == 0x544146)
- return 1;
+ 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 0;
+ return -ENODEV;
}
enum filetype file_detect_type(void *_buf)
{
u32 *buf = _buf;
u8 *buf8 = _buf;
+ unsigned long bootsec;
+ int ret;
if (strncmp(buf8, "#!/bin/sh", 9) == 0)
return filetype_sh;
@@ -99,7 +120,19 @@ 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))
+
+ ret = is_fat_boot_sector(buf8, &bootsec);
+ if (ret && bootsec != 0) {
+ /* The first sector is an MBR, now check for FAT in
+ * the first partition */
+ lseek(fd, (bootsec) * 512, SEEK_SET);
+ ret = read(fd, buf, 512);
+ if (ret < 0)
+ return filetype_unknown;
+ ret = is_fat_boot_sector(buf8, NULL);
+ if (!ret)
+ return filetype_fat;
+ } else
return filetype_fat;
return filetype_unknown;
@@ -107,7 +140,7 @@ enum filetype file_detect_type(void *_buf)
enum filetype file_name_detect_type(const char *filename)
{
- int fd, ret;
+ int ret;
void *buf;
enum filetype type = filetype_unknown;
diff --git a/include/filetype.h b/include/filetype.h
index 179ec0f..c60f654 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -24,5 +24,6 @@ enum filetype {
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);
+int is_fat_boot_sector(unsigned char *sector, unsigned long *bootsec);
#endif /* __FILE_TYPE_H */
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] fs/fat: Handle MBR on the first sector
2012-09-16 12:32 [PATCH 1/2] " Franck Jullien
@ 2012-09-16 12:32 ` Franck Jullien
0 siblings, 0 replies; 6+ messages in thread
From: Franck Jullien @ 2012-09-16 12:32 UTC (permalink / raw)
To: barebox
Use the new filetype.c file detection function to support disk with MBR on the first
sector.
Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
fs/fat/ff.c | 27 ++++++++++++---------------
1 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/fs/fat/ff.c b/fs/fat/ff.c
index 66db1d6..622845a 100644
--- a/fs/fat/ff.c
+++ b/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 */
@@ -1533,7 +1534,8 @@ int follow_path ( /* 0(0): successful, !=0: error code */
*/
static int 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;
@@ -1542,18 +1544,8 @@ static int check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:
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;
- /* 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_boot_sector(fs->win, bootsec);
}
/*
@@ -1565,6 +1557,7 @@ 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;
@@ -1579,9 +1572,13 @@ 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 */
+ fmt = check_fs(fs, bsect = 0, &first_boot_sect); /* Check sector 0 if it is a VBR */
+ if (fmt && first_boot_sect != 0) {
+ /* Sector 0 is an MBR, now check for FAT in the first partition */
+ fmt = check_fs(fs, bsect = first_boot_sect, NULL);
+ if(fmt)
+ return fmt; /* No FAT volume is found */
+ }
/* Following code initializes the file system object */
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-09-18 8:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-16 20:33 [PATCH 1/2] [v2] filetype: Improve FAT detection Franck Jullien
2012-09-16 20:33 ` [PATCH 2/2] fs/fat: Handle MBR on the first sector Franck Jullien
2012-09-17 5:49 ` [PATCH 1/2] [v2] filetype: Improve FAT detection Jean-Christophe PLAGNIOL-VILLARD
2012-09-17 6:08 ` Franck Jullien
2012-09-18 8:38 ` Sascha Hauer
-- strict thread matches above, loose matches on Subject: below --
2012-09-16 12:32 [PATCH 1/2] " Franck Jullien
2012-09-16 12:32 ` [PATCH 2/2] fs/fat: Handle MBR on the first sector Franck Jullien
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox