[U-Boot] [PATCH V3 08/10] fat: add U-Boot to ff.c API conversion wrapper

Stephen Warren swarren at wwwdotorg.org
Fri Oct 2 08:06:11 CEST 2015


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 <swarren at wwwdotorg.org>
---
v3:
* Fix writes to truncate the file to the written length.
* Add error cleanup (e.g. fclose()) to a number of functions.
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 | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 428 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..a97254b8aa19
--- /dev/null
+++ b/fs/fat/ff-uboot.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2015 Stephen Warren <swarren at 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 - rjones at nexus-tech.net - ported to ppcboot v1.1.6
+ * 2003-03-10 - kharris at nexus-tech.net - ported to uboot
+ *
+ * Small portions taken from Barebox v2015.07.0
+ * Copyright (c) 2007 Sascha Hauer <s.hauer at 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;
+	bool d_valid = false;
+	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;
+	}
+	d_valid = true;
+
+	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:
+	if (d_valid)
+		f_closedir(&d);
+	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;
+	bool fil_valid = false;
+	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;
+	}
+	fil_valid = true;
+
+	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:
+	if (fil_valid)
+		f_close(&fil);
+	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;
+	bool fil_valid = false;
+	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;
+	}
+	fil_valid = true;
+
+	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_truncate(&fil);
+	if (ff_ret != FR_OK) {
+		debug("f_truncate() failed: %d\n", ff_ret);
+		goto err;
+	}
+
+	ff_ret = f_close(&fil);
+	if (ff_ret != FR_OK) {
+		debug("f_close() failed: %d\n", ff_ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	if (fil_valid)
+		f_close(&fil);
+	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



More information about the U-Boot mailing list