[U-Boot] [PATCH] FAT: split block device interactions from filesystem logic
Pavel Herrmann
morpheus.ibis at gmail.com
Sun Sep 23 17:28:31 CEST 2012
add some CCs
On Wednesday 19 September 2012 16:34:02 Pavel Herrmann wrote:
> 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_ */
More information about the U-Boot
mailing list