[U-Boot] [PATCH] FAT: split block device interactions from filesystem logic

Pavel Herrmann morpheus.ibis at gmail.com
Wed Sep 19 16:34:02 CEST 2012


Put block device interaction code into separate file from filesystem logic.
This makes it easier to change block device API, and is similar to what other
filesystems do.
Cleanup some logic inconsistencies as well.

Signed-off-by: Pavel Herrmann <morpheus.ibis at gmail.com>
---
 fs/fat/Makefile    |   4 +-
 fs/fat/dev.c       | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/fat/fat.c       | 175 ++++++------------------------------------------
 fs/fat/fat_write.c |  21 +++---
 include/fat.h      |   7 ++
 5 files changed, 228 insertions(+), 170 deletions(-)
 create mode 100644 fs/fat/dev.c

diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 9635d36..5d10b24 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -24,8 +24,8 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libfat.o
 
 AOBJS	=
-COBJS-$(CONFIG_CMD_FAT)	:= fat.o
-COBJS-$(CONFIG_FAT_WRITE):= fat_write.o
+COBJS-$(CONFIG_CMD_FAT)	:= fat.o dev.o
+COBJS-$(CONFIG_FAT_WRITE) := fat_write.o dev.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_CMD_FAT)	+= file.o
diff --git a/fs/fat/dev.c b/fs/fat/dev.c
new file mode 100644
index 0000000..d5ff0c5
--- /dev/null
+++ b/fs/fat/dev.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis at gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <fat.h>
+#include <part.h>
+#include <errno.h>
+
+#define DOS_BOOT_MAGIC_OFFSET   0x1fe
+#define DOS_FS_TYPE_OFFSET      0x36
+#define DOS_FS32_TYPE_OFFSET    0x52
+
+static block_dev_desc_t *cur_dev;
+static unsigned int cur_part_nr;
+static disk_partition_t cur_part_info;
+
+int fat_disk_read(__u32 block, __u32 nr_blocks, void *buf)
+{
+	if (!cur_dev || !cur_dev->block_read)
+		return -1;
+
+	return cur_dev->block_read(cur_dev->dev,
+		cur_part_info.start + block, nr_blocks, buf);
+}
+
+int fat_disk_write(__u32 block, __u32 nr_blocks, void *buf)
+{
+	if (!cur_dev || !cur_dev->block_read)
+		return -1;
+
+	return cur_dev->block_read(cur_dev->dev,
+		cur_part_info.start + block, nr_blocks, buf);
+}
+
+int fat_get_blksz(void)
+{
+	if (cur_dev == NULL)
+		return -EINVAL;
+	return cur_dev->blksz;
+}
+
+int fat_get_partsize(void)
+{
+	if (cur_dev == NULL)
+		return -EINVAL;
+	return cur_part_info.size;
+}
+
+int fat_register_device(block_dev_desc_t *dev_desc, int part_no)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
+
+	/* First close any currently found FAT filesystem */
+	cur_dev = NULL;
+
+#if (defined(CONFIG_CMD_IDE) || \
+	defined(CONFIG_CMD_SATA) || \
+	defined(CONFIG_CMD_SCSI) || \
+	defined(CONFIG_CMD_USB) || \
+	defined(CONFIG_MMC) || \
+	defined(CONFIG_SYSTEMACE))
+
+	/* 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);
+			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));
+	}
+
+	/* Make sure it has a valid FAT header */
+	if (fat_disk_read(0, 1, buffer) != 1) {
+		cur_dev = NULL;
+		return -1;
+	}
+
+	/* 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;
+}
+
+int file_fat_detectfs(void)
+{
+	boot_sector bs;
+	volume_info volinfo;
+	int fatsize;
+	char vol_label[12];
+
+	if (cur_dev == NULL) {
+		printf("No current device\n");
+		return 1;
+	}
+
+#if defined(CONFIG_CMD_IDE) || \
+	defined(CONFIG_CMD_SATA) || \
+	defined(CONFIG_CMD_SCSI) || \
+	defined(CONFIG_CMD_USB) || \
+	defined(CONFIG_MMC)
+	printf("Interface:  ");
+	switch (cur_dev->if_type) {
+	case IF_TYPE_IDE:
+		printf("IDE");
+		break;
+	case IF_TYPE_SATA:
+		printf("SATA");
+		break;
+	case IF_TYPE_SCSI:
+		printf("SCSI");
+		break;
+	case IF_TYPE_ATAPI:
+		printf("ATAPI");
+		break;
+	case IF_TYPE_USB:
+		printf("USB");
+		break;
+	case IF_TYPE_DOC:
+		printf("DOC");
+		break;
+	case IF_TYPE_MMC:
+		printf("MMC");
+		break;
+	default:
+		printf("Unknown");
+	}
+
+	printf("\n  Device %d: ", cur_dev->dev);
+	dev_print(cur_dev);
+#endif
+
+	if (fat_read_bootsectandvi(&bs, &volinfo, &fatsize)) {
+		printf("\nNo valid FAT fs found\n");
+		return 1;
+	}
+
+	memcpy(vol_label, volinfo.volume_label, 11);
+	vol_label[11] = '\0';
+	volinfo.fs_type[5] = '\0';
+
+	printf("Partition %d: Filesystem: %s \"%s\"\n", cur_part_nr,
+		volinfo.fs_type, vol_label);
+
+	return 0;
+}
+
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 19f6a8c..a13c62b 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -45,84 +45,6 @@ static void downcase(char *str)
 	}
 }
 
-static block_dev_desc_t *cur_dev;
-static unsigned int cur_part_nr;
-static disk_partition_t cur_part_info;
-
-#define DOS_BOOT_MAGIC_OFFSET	0x1fe
-#define DOS_FS_TYPE_OFFSET	0x36
-#define DOS_FS32_TYPE_OFFSET	0x52
-
-static int disk_read(__u32 block, __u32 nr_blocks, void *buf)
-{
-	if (!cur_dev || !cur_dev->block_read)
-		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)
-{
-	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
-
-	/* First close any currently found FAT filesystem */
-	cur_dev = NULL;
-
-#if (defined(CONFIG_CMD_IDE) || \
-     defined(CONFIG_CMD_SATA) || \
-     defined(CONFIG_CMD_SCSI) || \
-     defined(CONFIG_CMD_USB) || \
-     defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) )
-
-	/* 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);
-			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));
-	}
-
-	/* Make sure it has a valid FAT header */
-	if (disk_read(0, 1, buffer) != 1) {
-		cur_dev = NULL;
-		return -1;
-	}
-
-	/* 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.
@@ -212,7 +134,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
 
 		startblock += mydata->fat_sect;	/* Offset from start of disk */
 
-		if (disk_read(startblock, getsize, bufptr) < 0) {
+		if (fat_disk_read(startblock, getsize, bufptr) < 0) {
 			debug("Error reading FAT blocks\n");
 			return ret;
 		}
@@ -290,7 +212,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
 		printf("FAT: Misaligned buffer address (%p)\n", buffer);
 
 		while (size >= mydata->sect_size) {
-			ret = disk_read(startsect++, 1, tmpbuf);
+			ret = fat_disk_read(startsect++, 1, tmpbuf);
 			if (ret != 1) {
 				debug("Error reading data (got %d)\n", ret);
 				return -1;
@@ -302,7 +224,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
 		}
 	} else {
 		idx = size / mydata->sect_size;
-		ret = disk_read(startsect, idx, buffer);
+		ret = fat_disk_read(startsect, idx, buffer);
 		if (ret != idx) {
 			debug("Error reading data (got %d)\n", ret);
 			return -1;
@@ -315,7 +237,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
 	if (size) {
 		ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
 
-		ret = disk_read(startsect, 1, tmpbuf);
+		ret = fat_disk_read(startsect, 1, tmpbuf);
 		if (ret != 1) {
 			debug("Error reading data (got %d)\n", ret);
 			return -1;
@@ -702,25 +624,28 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
 /*
  * Read boot sector and volume info from a FAT filesystem
  */
-static int
-read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
+int
+fat_read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
 {
 	__u8 *block;
 	volume_info *vistart;
 	int ret = 0;
+	int blksz;
 
-	if (cur_dev == NULL) {
+	blksz = fat_get_blksz();
+	if (blksz <= 0) {
+		/*this means the device is NULL, or otherwise unavailable*/
 		debug("Error: no device selected\n");
 		return -1;
 	}
 
-	block = memalign(ARCH_DMA_MINALIGN, cur_dev->blksz);
+	block = memalign(ARCH_DMA_MINALIGN, blksz);
 	if (block == NULL) {
 		debug("Error: allocating block\n");
 		return -1;
 	}
 
-	if (disk_read(0, 1, block) < 0) {
+	if (fat_disk_read(0, 1, block) < 0) {
 		debug("Error: reading block\n");
 		goto fail;
 	}
@@ -792,11 +717,14 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
 	__u32 root_cluster = 0;
 	int rootdir_size = 0;
 	int j;
+	int blksz;
 
-	if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
+	if (fat_read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
 		debug("Error: reading boot sector\n");
 		return -1;
 	}
+	/*this will always succeed, because it did in above call*/
+	blksz = fat_get_blksz();
 
 	if (mydata->fatsize == 32) {
 		root_cluster = bs.root_cluster;
@@ -812,9 +740,9 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
 
 	mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
 	mydata->clust_size = bs.cluster_size;
-	if (mydata->sect_size != cur_part_info.blksz) {
-		printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n",
-				mydata->sect_size, cur_part_info.blksz);
+	if (mydata->sect_size != blksz) {
+		printf("Error: FAT sector size mismatch (fs=%hu, dev=%d)\n",
+				mydata->sect_size, blksz);
 		return -1;
 	}
 
@@ -884,7 +812,7 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
 			debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
 				cursect, mydata->clust_size, DIRENTSPERBLOCK);
 
-			if (disk_read(cursect,
+			if (fat_disk_read(cursect,
 					(mydata->fatsize == 32) ?
 					(mydata->clust_size) :
 					PREFETCH_BLOCKS,
@@ -1124,69 +1052,6 @@ exit:
 	return ret;
 }
 
-int file_fat_detectfs(void)
-{
-	boot_sector bs;
-	volume_info volinfo;
-	int fatsize;
-	char vol_label[12];
-
-	if (cur_dev == NULL) {
-		printf("No current device\n");
-		return 1;
-	}
-
-#if defined(CONFIG_CMD_IDE) || \
-    defined(CONFIG_CMD_SATA) || \
-    defined(CONFIG_CMD_SCSI) || \
-    defined(CONFIG_CMD_USB) || \
-    defined(CONFIG_MMC)
-	printf("Interface:  ");
-	switch (cur_dev->if_type) {
-	case IF_TYPE_IDE:
-		printf("IDE");
-		break;
-	case IF_TYPE_SATA:
-		printf("SATA");
-		break;
-	case IF_TYPE_SCSI:
-		printf("SCSI");
-		break;
-	case IF_TYPE_ATAPI:
-		printf("ATAPI");
-		break;
-	case IF_TYPE_USB:
-		printf("USB");
-		break;
-	case IF_TYPE_DOC:
-		printf("DOC");
-		break;
-	case IF_TYPE_MMC:
-		printf("MMC");
-		break;
-	default:
-		printf("Unknown");
-	}
-
-	printf("\n  Device %d: ", cur_dev->dev);
-	dev_print(cur_dev);
-#endif
-
-	if (read_bootsectandvi(&bs, &volinfo, &fatsize)) {
-		printf("\nNo valid FAT fs found\n");
-		return 1;
-	}
-
-	memcpy(vol_label, volinfo.volume_label, 11);
-	vol_label[11] = '\0';
-	volinfo.fs_type[5] = '\0';
-
-	printf("Partition %d: Filesystem: %s \"%s\"\n", cur_part_nr,
-		volinfo.fs_type, vol_label);
-
-	return 0;
-}
-
 int file_fat_ls(const char *dir)
 {
 	return do_fat_read(dir, NULL, 0, LS_YES);
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index a6181e7..2e5bda9 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -43,17 +43,12 @@ static void uppercase(char *str, int len)
 static int total_sector;
 static int disk_write(__u32 block, __u32 nr_blocks, void *buf)
 {
-	if (!cur_dev || !cur_dev->block_write)
-		return -1;
-
-	if (cur_part_info.start + block + nr_blocks >
-		cur_part_info.start + total_sector) {
+	if (block + nr_blocks > total_sector) {
 		printf("error: overflow occurs\n");
 		return -1;
 	}
 
-	return cur_dev->block_write(cur_dev->dev,
-			cur_part_info.start + block, nr_blocks,	buf);
+	return fat_disk_write(block, nr_blocks, buf);
 }
 
 /*
@@ -196,7 +191,7 @@ static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
 				return -1;
 		}
 
-		if (disk_read(startblock, getsize, bufptr) < 0) {
+		if (fat_disk_read(startblock, getsize, bufptr) < 0) {
 			debug("Error reading FAT blocks\n");
 			return ret;
 		}
@@ -509,7 +504,7 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
 				return -1;
 		}
 
-		if (disk_read(startblock, getsize, bufptr) < 0) {
+		if (fat_disk_read(startblock, getsize, bufptr) < 0) {
 			debug("Error reading FAT blocks\n");
 			return -1;
 		}
@@ -793,7 +788,7 @@ static int check_overflow(fsdata *mydata, __u32 clustnum, unsigned long size)
 	if (size % mydata->sect_size)
 		sect_num++;
 
-	if (startsect + sect_num > cur_part_info.start + total_sector)
+	if (startsect + sect_num > total_sector)
 		return -1;
 
 	return 0;
@@ -932,14 +927,14 @@ static int do_fat_write(const char *filename, void *buffer,
 
 	dir_curclust = 0;
 
-	if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
+	if (fat_read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
 		debug("error: reading boot sector\n");
 		return -1;
 	}
 
 	total_sector = bs.total_sect;
 	if (total_sector == 0)
-		total_sector = cur_part_info.size;
+		total_sector = fat_get_partsize();
 
 	if (mydata->fatsize == 32)
 		mydata->fatlength = bs.fat32_length;
@@ -977,7 +972,7 @@ static int do_fat_write(const char *filename, void *buffer,
 		return -1;
 	}
 
-	if (disk_read(cursect,
+	if (fat_disk_read(cursect,
 		(mydata->fatsize == 32) ?
 		(mydata->clust_size) :
 		PREFETCH_BLOCKS, do_fat_read_block) < 0) {
diff --git a/include/fat.h b/include/fat.h
index f1b4a0d..98f77a5 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -213,4 +213,11 @@ const char *file_getfsname(int idx);
 int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
 
 int file_fat_write(const char *filename, void *buffer, unsigned long maxsize);
+
+/*internal functions for fs/blockdev API abstraction*/
+int fat_disk_read(__u32 block, __u32 nr_blocks, void *buf);
+int fat_disk_write(__u32 block, __u32 nr_blocks, void *buf);
+int fat_read_bootsectandvi(boot_sector *bs, volume_info *vi, int *fatsize);
+int fat_get_blksz(void);
+int fat_get_partsize(void);
 #endif /* _FAT_H_ */
-- 
1.7.12



More information about the U-Boot mailing list