mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/2] [v4] filetype: Improve FAT detection
@ 2012-09-19 11:09 Franck Jullien
  2012-09-19 11:09 ` [PATCH 2/2] [v2] fs/fat: Handle MBR on the first sector Franck Jullien
  2012-09-20  7:03 ` [PATCH 1/2] [v4] filetype: Improve FAT detection Sascha Hauer
  0 siblings, 2 replies; 3+ messages in thread
From: Franck Jullien @ 2012-09-19 11:09 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_or_mbr to check if a buffer is a FAT boot
or MBR sector

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 common/filetype.c  |   60 +++++++++++++++++++++++++++++++++++++++++----------
 include/filetype.h |    2 +
 2 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/common/filetype.c b/common/filetype.c
index e736d43..b139d78 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",
@@ -42,6 +44,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 +55,43 @@ 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;
+
+	/* Check record signature (always placed at offset 510 even if the sector size is>512) */
+	if (get_unaligned_le16(&sector[BS_55AA]) != 0xAA55)
+		return filetype_unknown;
+
+	/* Check "FAT" string */
+	if ((get_unaligned_le32(&sector[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
+		return filetype_fat;
 
-	/* FAT */
-	if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146)
-		return 1;
+	if ((get_unaligned_le32(&sector[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
+		return filetype_fat;
 
-	/* 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(&sector[MBR_Table + MBR_StartSector]);
 
-	return 0;
+	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 +119,10 @@ 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 +132,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 +146,19 @@ 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);
diff --git a/include/filetype.h b/include/filetype.h
index 179ec0f..37eb620 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -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 */
-- 
1.7.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/2] [v2] fs/fat: Handle MBR on the first sector
  2012-09-19 11:09 [PATCH 1/2] [v4] filetype: Improve FAT detection Franck Jullien
@ 2012-09-19 11:09 ` Franck Jullien
  2012-09-20  7:03 ` [PATCH 1/2] [v4] filetype: Improve FAT detection Sascha Hauer
  1 sibling, 0 replies; 3+ messages in thread
From: Franck Jullien @ 2012-09-19 11:09 UTC (permalink / raw)
  To: barebox

Use filetype to detect FAT boot sector.
Add support for disk with MBR on the first sector.

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 fs/fat/ff.c |   37 +++++++++++++++++++------------------
 1 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/fs/fat/ff.c b/fs/fat/ff.c
index 66db1d6..33f8b61 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 */
 
@@ -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;
-
-	/* 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 filetype_unknown;
 
-	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 */
 
-- 
1.7.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/2] [v4] filetype: Improve FAT detection
  2012-09-19 11:09 [PATCH 1/2] [v4] filetype: Improve FAT detection Franck Jullien
  2012-09-19 11:09 ` [PATCH 2/2] [v2] fs/fat: Handle MBR on the first sector Franck Jullien
@ 2012-09-20  7:03 ` Sascha Hauer
  1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2012-09-20  7:03 UTC (permalink / raw)
  To: Franck Jullien; +Cc: barebox

On Wed, Sep 19, 2012 at 01:09:01PM +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_or_mbr to check if a buffer is a FAT boot
> or MBR sector
> 
> Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
> ---
>  common/filetype.c  |   60 +++++++++++++++++++++++++++++++++++++++++----------
>  include/filetype.h |    2 +
>  2 files changed, 50 insertions(+), 12 deletions(-)
> 
> diff --git a/common/filetype.c b/common/filetype.c
> index e736d43..b139d78 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>

Dropped this after compile testing. Probably your first idea was to add
the the FAT defines below to that file.

Sascha

> +#include <errno.h>
>  
>  static const char *filetype_str[] = {
>  	[filetype_unknown] = "unknown",
> @@ -42,6 +44,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 +55,43 @@ 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;
> +
> +	/* Check record signature (always placed at offset 510 even if the sector size is>512) */
> +	if (get_unaligned_le16(&sector[BS_55AA]) != 0xAA55)
> +		return filetype_unknown;
> +
> +	/* Check "FAT" string */
> +	if ((get_unaligned_le32(&sector[BS_FilSysType]) & 0xFFFFFF) == 0x544146)
> +		return filetype_fat;
>  
> -	/* FAT */
> -	if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146)
> -		return 1;
> +	if ((get_unaligned_le32(&sector[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
> +		return filetype_fat;
>  
> -	/* 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(&sector[MBR_Table + MBR_StartSector]);
>  
> -	return 0;
> +	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 +119,10 @@ 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 +132,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 +146,19 @@ 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);
> diff --git a/include/filetype.h b/include/filetype.h
> index 179ec0f..37eb620 100644
> --- a/include/filetype.h
> +++ b/include/filetype.h
> @@ -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 */
> -- 
> 1.7.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
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] 3+ messages in thread

end of thread, other threads:[~2012-09-20  7:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-19 11:09 [PATCH 1/2] [v4] filetype: Improve FAT detection Franck Jullien
2012-09-19 11:09 ` [PATCH 2/2] [v2] fs/fat: Handle MBR on the first sector Franck Jullien
2012-09-20  7:03 ` [PATCH 1/2] [v4] filetype: Improve FAT detection Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox