Add a file that converts all the FAT-related APIs used by U-Boot into ff.c calls. This allows ff.c to provide the FAT implementation for U-Boot.
Signed-off-by: Stephen Warren <swar...@wwwdotorg.org> --- v2: * Implement fat_register_device(), file_fat_read() for SPL FAT usage. * Use _MAX_LFN to define size of lfname[] in file_fat_ls(). --- fs/fat/Kconfig | 0 fs/fat/Makefile | 7 + fs/fat/ff-uboot.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 fs/fat/Kconfig create mode 100644 fs/fat/Makefile create mode 100644 fs/fat/ff-uboot.c diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/fs/fat/Makefile b/fs/fat/Makefile new file mode 100644 index 000000000000..c527fc2bb401 --- /dev/null +++ b/fs/fat/Makefile @@ -0,0 +1,7 @@ +# +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_FS_FAT) += ff.o +obj-$(CONFIG_FS_FAT) += ff-uboot.o diff --git a/fs/fat/ff-uboot.c b/fs/fat/ff-uboot.c new file mode 100644 index 000000000000..0003db79ac64 --- /dev/null +++ b/fs/fat/ff-uboot.c @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2015 Stephen Warren <swar...@wwwdotorg.org> + * (GPL-2.0+) + * + * Portions taken from U-Boot's previous FAT implementation + * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg + * 2002-07-28 - rjo...@nexus-tech.net - ported to ppcboot v1.1.6 + * 2003-03-10 - khar...@nexus-tech.net - ported to uboot + * + * Small portions taken from Barebox v2015.07.0 + * Copyright (c) 2007 Sascha Hauer <s.ha...@pengutronix.de>, Pengutronix + * (GPL-2.0) + * + * SPDX-License-Identifier: GPL-2.0+ GPL-2.0 + */ + +#include <common.h> +#include <fat.h> +#include <linux/ctype.h> +#include <part.h> +#include "diskio.h" +#include "ff.h" + +static block_dev_desc_t *fat_dev; +static disk_partition_t *fat_part; +static FATFS fat_ff_fs; + +/* Functions called by ff.c */ + +DSTATUS disk_initialize(BYTE pdrv) +{ + return 0; +} + +DSTATUS disk_status(BYTE pdrv) +{ + return 0; +} + +DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +{ + int ret; + + debug("%s(sector=%d, count=%u)\n", __func__, sector, count); + + ret = fat_dev->block_read(fat_dev->dev, fat_part->start + sector, + count, buff); + if (ret != count) + return RES_ERROR; + + return RES_OK; +} + +DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +{ + int ret; + + debug("%s(sector=%d, count=%u)\n", __func__, sector, count); + + ret = fat_dev->block_write(fat_dev->dev, fat_part->start + sector, + count, buff); + if (ret != count) + return RES_ERROR; + + return RES_OK; +} + +DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) +{ + debug("%s(cmd=%d)\n", __func__, (int)cmd); + + switch (cmd) { + case CTRL_SYNC: + return RES_OK; + default: + return RES_ERROR; + } +} + +/* From Barebox v2015.07.0 fs/fat/fat.c */ +WCHAR ff_convert(WCHAR src, UINT dir) +{ + if (src <= 0x80) + return src; + else + return '?'; +} + +/* From Barebox v2015.07.0 fs/fat/fat.c */ +WCHAR ff_wtoupper(WCHAR chr) +{ + if (chr <= 0x80) + return toupper(chr); + else + return '?'; +} + +/* Functions that call into ff.c */ + +int fat_set_blk_dev(block_dev_desc_t *dev, disk_partition_t *part) +{ + FRESULT ff_ret; + + debug("%s()\n", __func__); + + fat_dev = dev; + fat_part = part; + + ff_ret = f_mount(&fat_ff_fs, "0:", 1); + if (ff_ret != FR_OK) { + debug("f_mount() failed: %d\n", ff_ret); + fat_dev = NULL; + fat_part = NULL; + return -1; + } + + debug("f_mount() succeeded\n"); + return 0; +} + +int fat_register_device(block_dev_desc_t *dev_desc, int part_no) +{ + disk_partition_t info; + + /* First unregister any current FAT filesystem */ + fat_dev = NULL; + fat_part = NULL; + + /* Read the partition table, if present */ + if (get_partition_info(dev_desc, part_no, &info)) { + if (part_no != 0) { + printf("** Partition %d not valid on device %d **\n", + part_no, dev_desc->dev); + return -1; + } + + info.start = 0; + info.size = dev_desc->lba; + info.blksz = dev_desc->blksz; + info.name[0] = 0; + info.type[0] = 0; + info.bootable = 0; +#ifdef CONFIG_PARTITION_UUIDS + info.uuid[0] = 0; +#endif + } + + return fat_set_blk_dev(dev_desc, &info); +} + +int file_fat_detectfs(void) +{ + FRESULT ff_ret; + TCHAR label[12]; + DWORD vsn; + + debug("%s()\n", __func__); + + if (!fat_dev) { + printf("No current device\n"); + return 1; + } + +#ifdef HAVE_BLOCK_DEVICE + printf(" Device %d: ", fat_dev->dev); + dev_print(fat_dev); +#endif + + ff_ret = f_getlabel("0:", label, &vsn); + if (ff_ret != FR_OK) { + debug("f_getlabel() failed: %d\n", ff_ret); + return -1; + } + + printf("Filesystem: "); + switch (fat_ff_fs.fs_type) { + case FS_FAT12: + puts("FAT12\n"); + break; + case FS_FAT16: + puts("FAT16\n"); + break; + case FS_FAT32: + puts("FAT32\n"); + break; + default: + puts("<<unknown>>\n"); + break; + } + + printf("Volume label: "); + if (!label[0]) { + puts("<<no label>>\n"); + } else { + puts(label); + puts("\n"); + } + + printf("Volume serial: %08x\n", vsn); + + return 0; +} + +int fat_exists(const char *filename) +{ + loff_t size; + int ret; + + debug("%s(filename=%s)\n", __func__, filename); + + ret = fat_size(filename, &size); + if (ret) + return 0; + + return 1; +} + +int fat_size(const char *filename, loff_t *size) +{ + FRESULT ff_ret; + FILINFO finfo; + + debug("%s(filename=%s)\n", __func__, filename); + + memset(&finfo, 0, sizeof(finfo)); + + ff_ret = f_stat(filename, &finfo); + if (ff_ret != FR_OK) { + debug("f_stat() failed: %d\n", ff_ret); + return -1; + } + + *size = finfo.fsize; + + return 0; +} + +int file_fat_ls(const char *dir) +{ + FRESULT ff_ret; + DIR d; + FILINFO finfo; + char lfname[_MAX_LFN + 1]; + TCHAR *fname; + + debug("%s()\n", __func__); + + memset(&finfo, 0, sizeof(finfo)); + finfo.lfname = lfname; + finfo.lfsize = sizeof(lfname); + + ff_ret = f_opendir(&d, dir); + if (ff_ret != FR_OK) { + debug("f_opendir() failed: %d\n", ff_ret); + goto err; + } + + for (;;) { + ff_ret = f_readdir(&d, &finfo); + if (ff_ret != FR_OK) { + debug("f_readdir() failed: %d\n", ff_ret); + goto err; + } + if (!finfo.fname[0]) + break; + + if (*finfo.lfname) + fname = finfo.lfname; + else + fname = finfo.fname; + + if (finfo.fattrib & AM_DIR) + printf(" %s/\n", fname); + else + printf(" %8u %s\n", finfo.fsize, fname); + } + + ff_ret = f_closedir(&d); + if (ff_ret != FR_OK) { + debug("f_closedir() failed: %d\n", ff_ret); + goto err; + } + + return 0; + +err: + printf("** Unable to read dir %s **\n", dir); + return -1; +} + +int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actread) +{ + FRESULT ff_ret; + FIL fil; + UINT ff_actread; + + debug("%s(filename=%s, offset=%d, len=%d)\n", __func__, filename, + (int)offset, (int)len); + + if (!len) + len = -1; + + ff_ret = f_open(&fil, filename, FA_READ); + if (ff_ret != FR_OK) { + debug("f_open() failed: %d\n", ff_ret); + goto err; + } + + ff_ret = f_lseek(&fil, offset); + if (ff_ret != FR_OK) { + debug("f_lseek() failed: %d\n", ff_ret); + goto err; + } + + ff_ret = f_read(&fil, buf, len, &ff_actread); + if (ff_ret != FR_OK) { + debug("f_read() failed: %d\n", ff_ret); + goto err; + } + debug("f_read() read %u bytes\n", ff_actread); + *actread = ff_actread; + + ff_ret = f_close(&fil); + if (ff_ret != FR_OK) { + debug("f_close() failed: %d\n", ff_ret); + goto err; + } + + return 0; + +err: + printf("** Unable to read file %s **\n", filename); + return -1; +} + +int file_fat_read(const char *filename, void *buffer, int maxsize) +{ + loff_t actread; + int ret; + + ret = fat_read_file(filename, buffer, 0, maxsize, &actread); + if (ret) + return ret; + else + return actread; +} + +#ifdef CONFIG_FAT_WRITE +int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actwrite) +{ + FRESULT ff_ret; + FIL fil; + UINT ff_actwrite; + + debug("%s(filename=%s, offset=%d, len=%d)\n", __func__, filename, + (int)offset, (int)len); + + if (!len) + len = -1; + + ff_ret = f_open(&fil, filename, FA_WRITE | FA_OPEN_ALWAYS); + if (ff_ret != FR_OK) { + debug("f_open() failed: %d\n", ff_ret); + goto err; + } + + ff_ret = f_lseek(&fil, offset); + if (ff_ret != FR_OK) { + debug("f_lseek() failed: %d\n", ff_ret); + goto err; + } + + ff_ret = f_write(&fil, buf, len, &ff_actwrite); + if (ff_ret != FR_OK) { + debug("f_write() failed: %d\n", ff_ret); + goto err; + } + debug("f_read() read %u bytes\n", ff_actwrite); + *actwrite = ff_actwrite; + + ff_ret = f_close(&fil); + if (ff_ret != FR_OK) { + debug("f_close() failed: %d\n", ff_ret); + goto err; + } + + return 0; + +err: + printf("** Unable to write file %s **\n", filename); + return -1; +} +#endif + +void fat_close(void) +{ + debug("%s()\n", __func__); + + fat_dev = NULL; + fat_part = NULL; +} -- 1.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot