Update FatFS port to version 0.13

- Update FatFS port from 0.07e to 0.13
- Multi-device support
- Basic test at run/fatfs
- Adaption of existing components

Note, ffat is now consistently renamed to fatfs.

Ref #2410
This commit is contained in:
Emery Hemingway 2017-05-16 13:59:37 -05:00 committed by Christian Helmuth
parent 473aa3454d
commit f09fc4a5a2
35 changed files with 767 additions and 647 deletions

View File

@ -11,16 +11,16 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__FFAT__BLOCK_H_
#define _INCLUDE__FFAT__BLOCK_H_
#ifndef _INCLUDE__FATFS__BLOCK_H_
#define _INCLUDE__FATFS__BLOCK_H_
namespace Genode {
struct Env;
struct Allocator;
}
namespace Ffat {
namespace Fatfs {
void block_init(Genode::Env &, Genode::Allocator &heap);
}
#endif /* _INCLUDE__FFAT__BLOCK_H_ */
#endif /* _INCLUDE__FATFS__BLOCK_H_ */

View File

@ -0,0 +1 @@
INC_DIR += $(call select_from_ports,fatfs)/include

View File

@ -1 +0,0 @@
INC_DIR += $(call select_from_ports,ffat)/include

View File

@ -0,0 +1,17 @@
#
# FAT File System Module using a Block session as disk I/O backend
#
FATFS_PORT_DIR := $(call select_from_ports,fatfs)
FATFS_PORT_SRC_DIR := $(FATFS_PORT_DIR)/src/lib/fatfs/source
FATFS_LOCAL_SRC_DIR := $(REP_DIR)/src/lib/fatfs
INC_DIR += $(REP_DIR)/include/fatfs $(FATFS_PORT_DIR)/include
SRC_C = ff.c ffunicode.c
SRC_CC = diskio_block.cc
CC_OPT += -Wno-unused-variable
vpath % $(FATFS_LOCAL_SRC_DIR)
vpath % $(FATFS_PORT_SRC_DIR)

View File

@ -1,16 +0,0 @@
#
# FAT File System Module using a Block session as disk I/O backend
#
FFAT_PORT_DIR := $(call select_from_ports,ffat)
INC_DIR += $(FFAT_PORT_DIR)/include
FFAT_DIR := $(FFAT_PORT_DIR)/src/lib/ffat
SRC_C = ff.c ccsbcs.c
SRC_CC = diskio_block.cc
vpath % $(REP_DIR)/src/lib/ffat/
vpath % $(FFAT_DIR)/src
vpath % $(FFAT_DIR)/src/option

View File

@ -0,0 +1,6 @@
SRC_CC = plugin.cc
LIBS += libc fatfs_block
vpath plugin.cc $(REP_DIR)/src/lib/libc_fatfs
SHARED_LIB = yes

View File

@ -1,6 +0,0 @@
SRC_CC = plugin.cc
LIBS += libc ffat_block
vpath plugin.cc $(REP_DIR)/src/lib/libc_ffat
SHARED_LIB = yes

View File

@ -0,0 +1 @@
4ca5681b074e2b5f64454b4065faab28b33f2cc5

View File

@ -0,0 +1,13 @@
LICENSE := BSD
VERSION := 0.13
DOWNLOADS := fatfs.archive
URL(fatfs) := http://www.elm-chan.org/fsw/ff/arc/ff13.zip
SHA(fatfs) := 8ce22f86e339b0fc59c8c69941fbaf86e5cf9364
DIR(fatfs) := src/lib/fatfs
PATCHES := src/lib/fatfs/ffconf.patch src/lib/fatfs/integer.patch
DIRS := include/fatfs
DIR_CONTENT(include/fatfs) := \
$(addprefix src/lib/fatfs/source/, ff.h ffconf.h diskio.h integer.h)

View File

@ -1 +0,0 @@
c77033bdfb9e0e291b2a6bcf3b168e5823235649

View File

@ -1,18 +0,0 @@
LICENSE := BSD
VERSION := 0.07e
DOWNLOADS := ffat.archive
#
# Download archive from genode.org instead of the original location
# 'http://elm-chan.org/fsw/ff/ff007e.zip' because the elm-chan webserver
# does not like wget.
#
URL(ffat) := https://genode.org/files/ff007e.zip
SHA(ffat) := 3379ad817e1c4f9993ae2722e86235ec85d7e36d
DIR(ffat) := src/lib/ffat
PATCHES := src/lib/ffat/config.patch
DIRS := include/ffat
DIR_CONTENT(include/ffat) := $(addprefix src/lib/ffat/src/,\
ff.h diskio.h integer.h ffconf.h)

View File

@ -0,0 +1,148 @@
#
# \brief Test of FatFS blkio implementation
# \author Emery Hemingway
# \date 2017-07-31
#
if {[have_spec odroid_xu] || [have_spec zynq]} {
puts "Run script does not support this platform."
exit 0
}
# use SD on ARM
set use_sd_card_drv [expr [have_spec omap4] || [have_spec arndale] || [have_spec pl180]]
# use AHCI on x86
set use_ahci [expr [have_spec x86] && ![have_spec linux]]
# use ram_blk on Linux
set use_ram_blk [have_spec linux]
if {[expr ![have_include "power_on/qemu"] && !$use_ram_blk]} {
puts "\nPlease setup your native sd or hard drive. Remove this fail stop";
puts "check when you have prepared your native environment.\n";
exit 0
}
#
# Build
#
set build_components {
test/fatfs_blkio
}
lappend_if $use_sd_card_drv build_components drivers/sd_card
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
set depot_pkgs "genodelabs/src/[base_src] genodelabs/src/init"
lappend_if $use_ahci depot_pkgs genodelabs/src/ahci_drv
lappend_if $use_ram_blk depot_pkgs genodelabs/src/ram_blk
import_from_depot {*}$depot_pkgs
#
# Generate config
#
append config {
<config>
<parent-provides>
<service name="CPU"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="IRQ"/>
<service name="LOG"/>
<service name="PD"/>
<service name="RAM"/>
<service name="RM"/>
<service name="ROM"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="128"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="test-fatfs_blkio">
<resource name="RAM" quantum="10M"/>
<config ld_verbose="true">
<libc stdout="/log" stderr="/log"/>
<vfs> <log/> </vfs>
</config>
</start>}
append_platform_drv_config
append_if $use_ahci config {
<start name="ahci_drv">
<resource name="RAM" quantum="10M" />
<provides><service name="Block" /></provides>
<route>
<any-service> <parent /> <any-child /></any-service>
</route>
<config>
<policy label_prefix="test-fatfs_blkio" device="0"/>
</config>
</start>}
append_if $use_sd_card_drv config {
<start name="sd_card_drv">
<resource name="RAM" quantum="1M" />
<provides><service name="Block"/></provides>
</start>
}
append_if $use_ram_blk config {
<start name="ram_blk">
<resource name="RAM" quantum="4M" />
<provides><service name="Block"/></provides>
<config size="1M" block_size="512"/>
</start>}
append config {
</config>
}
install_config $config
#
# Boot modules
#
set disk_image "bin/test.hda"
set cmd "dd if=/dev/zero of=$disk_image bs=512 count=4096"
puts "creating disk image: $cmd"
catch { exec sh -c $cmd }
# generic modules
set boot_modules {
libc.lib.so
libm.lib.so
test-fatfs_blkio
}
lappend_if $use_sd_card_drv boot_modules sd_card_drv
lappend_if $use_ram_blk boot_modules test.hda
append_platform_drv_boot_modules
build_boot_image $boot_modules
#
# Qemu
#
append qemu_args " -nographic "
append_if $use_ahci qemu_args " -drive id=disk,file=$disk_image,format=raw,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
append_if $use_sd_card_drv qemu_args " -drive file=$disk_image,format=raw,if=sd,cache=writeback "
run_genode_until {.*child "test-fatfs_blkio" exited with exit value 0.*} 60
exec rm -f $disk_image

View File

@ -1,9 +1,9 @@
set mkfs_cmd [check_installed mkfs.vfat]
set mkfs_opts "-F32"
set filesystem ffat
set filesystem fatfs
#
# The ffat_libc plugin opens a block session directly. If the VFS opened
# The fatfs_libc plugin opens a block session directly. If the VFS opened
# the block session, the plugin would try to open a second one, which
# would get denied by the block driver.
#

View File

@ -1,5 +1,5 @@
#
# \brief Test for using the libc_ffat plugin
# \brief Test for using file systems in the libc
# \author Christian Prochaska
# \date 2011-05-27
#

View File

@ -1,5 +1,5 @@
set build_component server/ffat_fs
set binary ffat_fs
set build_component server/fatfs_fs
set binary fatfs_fs
set mkfs_cmd mkfs.vfat
set mkfs_opts "-F32"
set vfs_dev_blkdev ""

View File

@ -22,7 +22,7 @@ lappend_if $use_sd_card_driver build_components drivers/sd_card
lappend_if $use_ahci_driver build_components drivers/ahci
lappend_if [have_spec acpi] build_components drivers/acpi
lappend_if [have_spec linux] build_components server/ram_fs
lappend_if [expr ![have_spec linux]] build_components server/ffat_fs
lappend_if [expr ![have_spec linux]] build_components server/fatfs_fs
build $build_components
@ -55,7 +55,7 @@ append_if $use_ahci_driver config {
<resource name="RAM" quantum="5M"/>
<provides> <service name="Block"/> </provides>
<config>
<policy label_prefix="ffat_fs" device="0" />
<policy label_prefix="fatfs_fs" device="0" />
</config>
</start>}
@ -77,7 +77,7 @@ append_if [have_spec linux] config {
</start>}
append_if [expr ![have_spec linux]] config {
<start name="ffat_fs">
<start name="fatfs_fs">
<resource name="RAM" quantum="10M"/>
<provides><service name="File_system"/></provides>
<config>
@ -146,7 +146,7 @@ append boot_modules {
# platform-specific modules
lappend_if [have_spec linux] boot_modules ram_fs
lappend_if [expr ![have_spec linux]] boot_modules ffat_fs
lappend_if [expr ![have_spec linux]] boot_modules fatfs_fs
lappend_if $use_sd_card_driver boot_modules sd_card_drv
lappend_if $use_ahci_driver boot_modules ahci_drv

View File

@ -0,0 +1,215 @@
/*
* \brief Low level disk I/O module using a Block session
* \author Christian Prochaska
* \date 2011-05-30
*
* See doc/en/appnote.html in the FatFS source.
*/
/*
* Copyright (C) 2011-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <block_session/connection.h>
#include <base/allocator_avl.h>
#include <base/log.h>
/* Genode block backend */
#include <fatfs/block.h>
namespace Fatfs {
extern "C" {
/* fatfs includes */
#include <fatfs/diskio.h>
}
using namespace Genode;
struct Drive;
struct Platform
{
Genode::Env &env;
Genode::Allocator &alloc;
Genode::Allocator_avl tx_alloc { &alloc };
enum { MAX_DEV_NUM = 8 };
/* XXX: could make a tree... */
Drive* drives[MAX_DEV_NUM];
Platform(Genode::Env &env, Genode::Allocator &alloc)
: env(env), alloc(alloc)
{
for (int i = 0; i < MAX_DEV_NUM; ++i)
drives[i] = nullptr;
}
};
static Constructible<Platform> _platform;
void block_init(Genode::Env &env, Genode::Allocator &alloc) {
_platform.construct(env, alloc); }
struct Drive : Block::Connection
{
Block::sector_t block_count;
Genode::size_t block_size;
Block::Session::Operations ops;
Drive(Platform &platform, char const *label)
: Block::Connection(platform.env, &platform.tx_alloc, 128*1024, label)
{
info(&block_count, &block_size, &ops);
}
};
}
using namespace Fatfs;
extern "C" Fatfs::DSTATUS disk_initialize (BYTE drv)
{
if (drv >= Platform::MAX_DEV_NUM) {
Genode::error("only ", (int)Platform::MAX_DEV_NUM," supported");
return STA_NODISK;
}
if (_platform->drives[drv]) {
destroy(_platform->alloc, _platform->drives[drv]);
_platform->drives[drv] = nullptr;
}
try {
String<2> label(drv);
_platform->drives[drv] = new (_platform->alloc) Drive(*_platform, label.string());
} catch(Service_denied) {
Genode::error("could not open block connection for drive ", drv);
return STA_NODISK;
}
Drive &drive = *_platform->drives[drv];
/* check for read- and write-capability */
if (!drive.ops.supported(Block::Packet_descriptor::READ)) {
Genode::error("drive ", drv, " not readable!");
destroy(_platform->alloc, _platform->drives[drv]);
_platform->drives[drv] = nullptr;
return STA_NOINIT;
}
if (!drive.ops.supported(Block::Packet_descriptor::WRITE))
return STA_PROTECT;
return 0;
}
extern "C" DSTATUS disk_status (BYTE drv)
{
if (_platform->drives[drv]) {
if (_platform->drives[drv]->ops.supported(Block::Packet_descriptor::WRITE))
return 0;
return STA_PROTECT;
}
return STA_NOINIT;
}
extern "C" DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count)
{
if (!_platform->drives[pdrv])
return RES_NOTRDY;
Drive &drive = *_platform->drives[pdrv];
Genode::size_t const op_len = drive.block_size*count;
/* allocate packet-descriptor for reading */
Block::Packet_descriptor p(drive.tx()->alloc_packet(op_len),
Block::Packet_descriptor::READ, sector, count);
drive.tx()->submit_packet(p);
p = drive.tx()->get_acked_packet();
DRESULT res;
if (p.succeeded() && p.size() >= op_len) {
Genode::memcpy(buff, drive.tx()->packet_content(p), op_len);
res = RES_OK;
} else {
Genode::error(__func__, " failed at sector ", sector, ", count ", count);
res = RES_ERROR;
}
drive.tx()->release_packet(p);
return res;
}
#if _READONLY == 0
extern "C" DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count)
{
if (!_platform->drives[pdrv])
return RES_NOTRDY;
Drive &drive = *_platform->drives[pdrv];
Genode::size_t const op_len = drive.block_size*count;
/* allocate packet-descriptor for writing */
Block::Packet_descriptor p(drive.tx()->alloc_packet(op_len),
Block::Packet_descriptor::WRITE, sector, count);
Genode::memcpy(drive.tx()->packet_content(p), buff, op_len);
drive.tx()->submit_packet(p);
p = drive.tx()->get_acked_packet();
DRESULT res;
if (p.succeeded()) {
res = RES_OK;
} else {
Genode::error(__func__, " failed at sector ", sector, ", count ", count);
res = RES_ERROR;
}
drive.tx()->release_packet(p);
return res;
}
#endif /* _READONLY */
extern "C" DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff)
{
if (!_platform->drives[pdrv])
return RES_NOTRDY;
Drive &drive = *_platform->drives[pdrv];
switch (cmd) {
case CTRL_SYNC:
drive.sync();
return RES_OK;
case GET_SECTOR_COUNT:
*((DWORD*)buff) = drive.block_count;
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD*)buff) = drive.block_size;
return RES_OK;
case GET_BLOCK_SIZE :
*((DWORD*)buff) = 1;
return RES_OK;
default:
return RES_PARERR;
}
}

View File

@ -0,0 +1,72 @@
--- src/lib/fatfs/source/ffconf.h
+++ src/lib/fatfs/source/ffconf.h
@@ -55,7 +55,7 @@
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
-#define FF_USE_LABEL 0
+#define FF_USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
@@ -68,7 +68,7 @@
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
-#define FF_CODE_PAGE 932
+#define FF_CODE_PAGE 0
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
@@ -97,7 +97,7 @@
*/
-#define FF_USE_LFN 0
+#define FF_USE_LFN 2
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
@@ -135,7 +135,7 @@
*/
-#define FF_FS_RPATH 0
+#define FF_FS_RPATH 1
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
@@ -148,7 +148,7 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
-#define FF_VOLUMES 1
+#define FF_VOLUMES 10
/* Number of volumes (logical drives) to be used. (1-10) */
@@ -171,7 +171,7 @@
#define FF_MIN_SS 512
-#define FF_MAX_SS 512
+#define FF_MAX_SS 4096
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
@@ -210,13 +210,13 @@
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
-#define FF_FS_EXFAT 0
+#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled.
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
-#define FF_FS_NORTC 0
+#define FF_FS_NORTC 1
#define FF_NORTC_MON 5
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2017

View File

@ -0,0 +1,36 @@
--- src/lib/fatfs/source/integer.h 2017-05-21 13:10:48.000000000 -0500
+++ src/lib/fatfs/source/integer.h 2017-07-22 10:59:54.856013544 -0500
@@ -14,24 +14,26 @@
#else /* Embedded platform */
+#include <base/fixed_stdint.h>
+
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
-typedef unsigned char BYTE;
+typedef genode_uint8_t BYTE;
/* These types MUST be 16-bit */
-typedef short SHORT;
-typedef unsigned short WORD;
-typedef unsigned short WCHAR;
+typedef genode_int16_t SHORT;
+typedef genode_uint16_t WORD;
+typedef genode_uint16_t WCHAR;
/* These types MUST be 32-bit */
-typedef long LONG;
-typedef unsigned long DWORD;
+typedef genode_int32_t LONG;
+typedef genode_uint32_t DWORD;
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
-typedef unsigned long long QWORD;
+typedef genode_uint64_t QWORD;
#endif

View File

@ -1,37 +0,0 @@
+++ src/lib/ffat/src/ffconf.h 2012-07-09 13:08:03.000000000 +0200
@@ -40,7 +40,7 @@
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
-#define _USE_MKFS 0 /* 0 or 1 */
+#define _USE_MKFS 1 /* 0 or 1 */
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
@@ -53,7 +53,7 @@
/ Locale and Namespace Configurations
/----------------------------------------------------------------------------*/
-#define _CODE_PAGE 932
+#define _CODE_PAGE 858
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
@@ -86,7 +86,7 @@
*/
-#define _USE_LFN 0 /* 0, 1 or 2 */
+#define _USE_LFN 1 /* 0, 1 or 2 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
@@ -105,7 +105,7 @@
*/
-#define _FS_RPATH 0 /* 0 or 1 */
+#define _FS_RPATH 1 /* 0 or 1 */
/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir,
/ f_chdrive function are available.
/ Note that output of the f_readdir fnction is affected by this option. */

View File

@ -1,146 +0,0 @@
/*
* \brief Low level disk I/O module
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
* \date 2009-11-20
*/
/*
* Copyright (C) 2009-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <ffat/diskio.h>
#include <dde_linux26/block.h>
typedef __SIZE_TYPE__ size_t;
extern void *memcpy(void *dest, const void *src, size_t n);
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
if (dde_linux26_block_present((int)drv))
return 0;
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
if (dde_linux26_block_present((int)drv))
return 0;
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
int result;
BYTE i;
void * dma_buf = dde_linux26_block_malloc(512);
for (i = 0; i < count; i++) {
result = dde_linux26_block_read((int)drv, (unsigned long)(sector + i), dma_buf);
switch (result) {
case -EBLK_NODEV: return RES_NOTRDY;
case -EBLK_FAULT: return RES_PARERR;
}
memcpy(buff + (i * 512), dma_buf, 512);
}
dde_linux26_block_free(dma_buf);
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
int result;
BYTE i;
void * dma_buf = dde_linux26_block_malloc(512);
for (i = 0; i < count; i++) {
result = dde_linux26_block_write((int)drv, (unsigned long)(sector + i), dma_buf);
switch (result) {
case -EBLK_NODEV: return RES_NOTRDY;
case -EBLK_FAULT: return RES_PARERR;
}
memcpy(dma_buf, buff + (i * 512), 512);
}
dde_linux26_block_free(dma_buf);
return RES_OK;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
int result;
DWORD dresult = 1;
if(!dde_linux26_block_present((int)drv))
return RES_PARERR;
switch (ctrl) {
case CTRL_SYNC:
break;
case GET_SECTOR_SIZE:
result = dde_linux26_block_size((int)drv);
if (result < 0)
return RES_ERROR;
memcpy(buff, &result, sizeof(int));
break;
case GET_SECTOR_COUNT:
result = dde_linux26_block_count((int)drv);
if(result < 0)
return RES_ERROR;
memcpy(buff, &result, sizeof(int));
break;
case GET_BLOCK_SIZE:
memcpy(buff, &dresult, sizeof(DWORD));
break;
}
return RES_OK;
}
DWORD get_fattime(void)
{
return 0;
}

View File

@ -1,188 +0,0 @@
/*
* \brief Low level disk I/O module using a Block session
* \author Christian Prochaska
* \date 2011-05-30
*/
/*
* Copyright (C) 2011-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/allocator_avl.h>
#include <base/log.h>
#include <block_session/connection.h>
/* Genode block backend */
#include <ffat/block.h>
/* Ffat includes */
extern "C" {
#include <ffat/diskio.h>
}
namespace Ffat {
void block_init(Genode::Env &, Genode::Allocator &alloc);
}
using namespace Genode;
static bool const verbose = false;
static Constructible<Genode::Allocator_avl> _block_alloc;
static Constructible<Block::Connection> _block_connection;
static size_t _blk_size = 0;
static Block::sector_t _blk_cnt = 0;
static Block::Session::Tx::Source *_source;
static Genode::Env *_global_env;
void Ffat::block_init(Genode::Env &env, Genode::Allocator &alloc)
{
_global_env = &env;
_block_alloc.construct(&alloc);
}
extern "C" DSTATUS disk_initialize (BYTE drv)
{
static bool initialized = false;
if (verbose)
Genode::log("disk_initialize(drv=", drv, ") called.");
if (drv != 0) {
Genode::error("only one disk drive is supported at this time.");
return STA_NOINIT;
}
if (initialized) {
Genode::error("drv 0 has already been initialized.");
return STA_NOINIT;
}
try {
_block_connection.construct(*_global_env, &*_block_alloc);
} catch(...) {
Genode::error("could not open block connection");
return STA_NOINIT;
}
_source = _block_connection->tx();
Block::Session::Operations ops;
_block_connection->info(&_blk_cnt, &_blk_size, &ops);
/* check for read- and write-capability */
if (!ops.supported(Block::Packet_descriptor::READ)) {
Genode::error("block device not readable!");
_block_connection.destruct();
return STA_NOINIT;
}
if (!ops.supported(Block::Packet_descriptor::WRITE)) {
Genode::warning("block device not writeable!");
}
if (verbose)
Genode::log(__func__, ": We have ", _blk_cnt, " blocks with a "
"size of ", _blk_size, " bytes");
initialized = true;
return 0;
}
extern "C" DSTATUS disk_status (BYTE drv)
{
if (drv != 0) {
Genode::error("only one disk drive is supported at this time.");
return STA_NODISK;
}
return 0;
}
extern "C" DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, BYTE count)
{
if (verbose)
Genode::log(__func__, ": disk_read(drv=", drv, ", buff=", buff, ", "
"sector=", sector, ", count=", count, ") called.");
if (drv != 0) {
Genode::error("only one disk drive is supported at this time.");
return RES_ERROR;
}
/* allocate packet-descriptor for reading */
Block::Packet_descriptor p(_source->alloc_packet(_blk_size),
Block::Packet_descriptor::READ, sector, count);
_source->submit_packet(p);
p = _source->get_acked_packet();
/* check for success of operation */
if (!p.succeeded()) {
Genode::error("could not read block(s)");
_source->release_packet(p);
return RES_ERROR;
}
memcpy(buff, _source->packet_content(p), count * _blk_size);
_source->release_packet(p);
return RES_OK;
}
#if _READONLY == 0
extern "C" DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, BYTE count)
{
if (verbose)
Genode::log(__func__, ": disk_write(drv=", drv, ", buff=", buff, ", "
"sector=", sector, ", count=", count, ") called.");
if (drv != 0) {
Genode::error("only one disk drive is supported at this time.");
return RES_ERROR;
}
/* allocate packet-descriptor for writing */
Block::Packet_descriptor p(_source->alloc_packet(_blk_size),
Block::Packet_descriptor::WRITE, sector, count);
memcpy(_source->packet_content(p), buff, count * _blk_size);
_source->submit_packet(p);
p = _source->get_acked_packet();
/* check for success of operation */
if (!p.succeeded()) {
Genode::error("could not write block(s)");
_source->release_packet(p);
return RES_ERROR;
}
_source->release_packet(p);
return RES_OK;
}
#endif /* _READONLY */
extern "C" DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void *buff)
{
Genode::warning(__func__, "(drv=", drv, ", ctrl=", ctrl, ", buff=", buff, ") "
"called - not yet implemented.");
return RES_OK;
}
extern "C" DWORD get_fattime(void)
{
Genode::warning(__func__, "() called - not yet implemented.");
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* \brief FFAT libc plugin
* \brief FATFS libc plugin
* \author Christian Prochaska
* \date 2011-05-27
*/
@ -29,21 +29,12 @@
#include <libc-plugin/plugin.h>
#include <libc-plugin/fd_alloc.h>
/* Genode block backend */
#include <ffat/block.h>
#include <fatfs/block.h>
/* ffat includes */
namespace Ffat { extern "C" {
#include <ffat/ff.h>
namespace Fatfs { extern "C" {
#include <fatfs/ff.h>
} }
/*
* These macros are defined in later versions of the FatFs lib, but not in the
* one currently used for Genode.
*/
#define f_size(fp) ((fp)->fsize)
#define f_tell(fp) ((fp)->fptr)
static bool const verbose = false;
@ -98,7 +89,7 @@ class File_plugin_context : public Plugin_context
{
private:
Ffat::FIL _ffat_file;
Fatfs::FIL _fatfs_file;
public:
@ -106,13 +97,13 @@ class File_plugin_context : public Plugin_context
* Constructor
*
* \param filename
* \param ffat_file file object used for interacting with the
* file API of ffat
* \param fatfs_file file object used for interacting with the
* file API of fatfs
*/
File_plugin_context(const char *filename, Ffat::FIL ffat_file) :
Plugin_context(filename), _ffat_file(ffat_file) { }
File_plugin_context(const char *filename, Fatfs::FIL fatfs_file) :
Plugin_context(filename), _fatfs_file(fatfs_file) { }
Ffat::FIL *ffat_file() { return &_ffat_file; }
Fatfs::FIL *fatfs_file() { return &_fatfs_file; }
};
@ -120,7 +111,7 @@ class Directory_plugin_context : public Plugin_context
{
private:
Ffat::DIR _ffat_dir;
Fatfs::DIR _fatfs_dir;
public:
@ -128,13 +119,13 @@ class Directory_plugin_context : public Plugin_context
* Constructor
*
* \param filename
* \param ffat_dir dir object used for interacting with the
* file API of ffat
* \param fatfs_dir dir object used for interacting with the
* file API of fatfs
*/
Directory_plugin_context(const char *filename, Ffat::DIR ffat_dir) :
Plugin_context(filename), _ffat_dir(ffat_dir) { }
Directory_plugin_context(const char *filename, Fatfs::DIR fatfs_dir) :
Plugin_context(filename), _fatfs_dir(fatfs_dir) { }
Ffat::DIR *ffat_dir() { return &_ffat_dir; }
Fatfs::DIR *fatfs_dir() { return &_fatfs_dir; }
};
@ -144,26 +135,26 @@ class Plugin : public Libc::Plugin
Genode::Constructible<Genode::Heap> _heap;
Ffat::FATFS _fatfs;
Fatfs::FATFS _fatfs;
Ffat::FIL *_get_ffat_file(Libc::File_descriptor *fd)
Fatfs::FIL *_get_fatfs_file(Libc::File_descriptor *fd)
{
File_plugin_context *file_plugin_context =
dynamic_cast<File_plugin_context*>(context(fd));
if (!file_plugin_context) {
return 0;
}
return file_plugin_context->ffat_file();
return file_plugin_context->fatfs_file();
}
Ffat::DIR *_get_ffat_dir(Libc::File_descriptor *fd)
Fatfs::DIR *_get_fatfs_dir(Libc::File_descriptor *fd)
{
Directory_plugin_context *directory_plugin_context =
dynamic_cast<Directory_plugin_context*>(context(fd));
if (!directory_plugin_context) {
return 0;
}
return directory_plugin_context->ffat_dir();
return directory_plugin_context->fatfs_dir();
}
/*
@ -181,20 +172,20 @@ class Plugin : public Libc::Plugin
~Plugin()
{
/* unmount the file system */
Ffat::f_mount(0, NULL);
Fatfs::f_unmount("");
}
void init(Genode::Env &env) override
{
_heap.construct(env.ram(), env.rm());
Ffat::block_init(env, *_heap);
Fatfs::block_init(env, *_heap);
/* mount the file system */
if (verbose)
Genode::log(__func__, ": mounting device ...");
if (f_mount(0, &_fatfs) != Ffat::FR_OK) {
if (f_mount(&_fatfs, "", 0) != Fatfs::FR_OK) {
Genode::error("mount failed");
}
}
@ -248,7 +239,7 @@ class Plugin : public Libc::Plugin
bool supports_symlink(const char *, const char *) override
{
/*
* Even though FFAT does not support symlinks, we still want
* Even though FATFS does not support symlinks, we still want
* to capture calls of 'symlink' to return ENOSYS, which is
* checked in the file-system test.
*/
@ -257,18 +248,18 @@ class Plugin : public Libc::Plugin
int close(Libc::File_descriptor *fd) override
{
using namespace Ffat;
using namespace Fatfs;
FIL *ffat_file = _get_ffat_file(fd);
FIL *fatfs_file = _get_fatfs_file(fd);
if (!ffat_file){
if (!fatfs_file){
/* directory */
Genode::destroy(&*_heap, context(fd));
Libc::file_descriptor_allocator()->free(fd);
return 0;
}
FRESULT res = f_close(ffat_file);
FRESULT res = f_close(fatfs_file);
Genode::destroy(&*_heap, context(fd));
Libc::file_descriptor_allocator()->free(fd);
@ -283,7 +274,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_close() returned an unexpected error code");
return -1;
}
@ -314,9 +305,9 @@ class Plugin : public Libc::Plugin
int fsync(Libc::File_descriptor *fd) override
{
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_sync(_get_ffat_file(fd));
FRESULT res = f_sync(_get_fatfs_file(fd));
switch(res) {
case FR_OK:
@ -328,7 +319,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_sync() returned an unexpected error code");
return -1;
}
@ -336,14 +327,14 @@ class Plugin : public Libc::Plugin
int ftruncate(Libc::File_descriptor *fd, ::off_t length) override
{
using namespace Ffat;
using namespace Fatfs;
/* 'f_truncate()' truncates to the current seek pointer */
if (lseek(fd, length, SEEK_SET) == -1)
return -1;
FRESULT res = f_truncate(_get_ffat_file(fd));
FRESULT res = f_truncate(_get_fatfs_file(fd));
switch(res) {
case FR_OK:
@ -355,7 +346,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_truncate() returned an unexpected error code");
return -1;
}
@ -364,7 +355,7 @@ class Plugin : public Libc::Plugin
ssize_t getdirentries(Libc::File_descriptor *fd, char *buf,
::size_t nbytes, ::off_t *basep) override
{
using namespace Ffat;
using namespace Fatfs;
if (nbytes < sizeof(struct dirent)) {
Genode::error(__func__, ": buf too small");
@ -375,11 +366,9 @@ class Plugin : public Libc::Plugin
struct dirent *dirent = (struct dirent *)buf;
::memset(dirent, 0, sizeof(struct dirent));
FILINFO ffat_file_info;
ffat_file_info.lfname = dirent->d_name;
ffat_file_info.lfsize = sizeof(dirent->d_name);
FILINFO fatfs_file_info;
FRESULT res = f_readdir(_get_ffat_dir(fd), &ffat_file_info);
FRESULT res = f_readdir(_get_fatfs_dir(fd), &fatfs_file_info);
switch(res) {
case FR_OK:
break;
@ -390,12 +379,12 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_readdir() returned an unexpected error code");
return -1;
}
if (ffat_file_info.fname[0] == 0) { /* no (more) entries */
if (fatfs_file_info.fname[0] == 0) { /* no (more) entries */
if (verbose)
Genode::log(__func__, ": no more dir entries");
/* TODO: reset the f_readdir() index? */
@ -404,16 +393,14 @@ class Plugin : public Libc::Plugin
dirent->d_ino = 1; /* libc's readdir() wants an inode number */
if ((ffat_file_info.fattrib & AM_DIR) == AM_DIR)
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR)
dirent->d_type = DT_DIR;
else
dirent->d_type = DT_REG;
dirent->d_reclen = sizeof(struct dirent);
if (dirent->d_name[0] == 0) /* use short file name */
::strncpy(dirent->d_name, ffat_file_info.fname,
sizeof(dirent->d_name));
::strncpy(dirent->d_name, fatfs_file_info.fname, sizeof(dirent->d_name));
dirent->d_namlen = ::strlen(dirent->d_name);
@ -426,25 +413,25 @@ class Plugin : public Libc::Plugin
::off_t lseek(Libc::File_descriptor *fd, ::off_t offset, int whence) override
{
using namespace Ffat;
using namespace Fatfs;
switch(whence) {
case SEEK_CUR:
offset += f_tell(_get_ffat_file(fd));
offset += f_tell(_get_fatfs_file(fd));
break;
case SEEK_END:
offset += f_size(_get_ffat_file(fd));
offset += f_size(_get_fatfs_file(fd));
break;
default:
break;
}
FRESULT res = f_lseek(_get_ffat_file(fd), offset);
FRESULT res = f_lseek(_get_fatfs_file(fd), offset);
switch(res) {
case FR_OK:
/* according to the FatFs documentation this can happen */
if ((off_t)f_tell(_get_ffat_file(fd)) != offset) {
if ((off_t)f_tell(_get_fatfs_file(fd)) != offset) {
errno = EINVAL;
return -1;
}
@ -456,7 +443,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_lseek() returned an unexpected error code");
return -1;
}
@ -464,7 +451,7 @@ class Plugin : public Libc::Plugin
int mkdir(const char *path, mode_t mode) override
{
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_mkdir(path);
@ -491,7 +478,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_mkdir() returned an unexpected error code");
return -1;
}
@ -499,34 +486,34 @@ class Plugin : public Libc::Plugin
Libc::File_descriptor *open(const char *pathname, int flags) override
{
using namespace Ffat;
using namespace Fatfs;
if (verbose)
Genode::log(__func__, ": pathname=", pathname);
FIL ffat_file;
BYTE ffat_flags = 0;
FIL fatfs_file;
BYTE fatfs_flags = 0;
/* convert libc flags to libffat flags */
/* convert libc flags to fatfs flags */
if (((flags & O_RDONLY) == O_RDONLY) || ((flags & O_RDWR) == O_RDWR))
ffat_flags |= FA_READ;
fatfs_flags |= FA_READ;
if (((flags & O_WRONLY) == O_WRONLY) || ((flags & O_RDWR) == O_RDWR))
ffat_flags |= FA_WRITE;
fatfs_flags |= FA_WRITE;
if ((flags & O_CREAT) == O_CREAT) {
if ((flags & O_EXCL) == O_EXCL)
ffat_flags |= FA_CREATE_NEW;
fatfs_flags |= FA_CREATE_NEW;
else
ffat_flags |= FA_OPEN_ALWAYS;
fatfs_flags |= FA_OPEN_ALWAYS;
}
FRESULT res = f_open(&ffat_file, pathname, ffat_flags);
FRESULT res = f_open(&fatfs_file, pathname, fatfs_flags);
switch(res) {
case FR_OK: {
Plugin_context *context = new (&*_heap)
File_plugin_context(pathname, ffat_file);
File_plugin_context(pathname, fatfs_file);
context->status_flags(flags);
Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->alloc(this, context);
if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1))
@ -539,14 +526,14 @@ class Plugin : public Libc::Plugin
* that's not supported by f_open(). So we call
* f_opendir() in case the file is a directory.
*/
Ffat::DIR ffat_dir;
FRESULT f_opendir_res = f_opendir(&ffat_dir, pathname);
Fatfs::DIR fatfs_dir;
FRESULT f_opendir_res = f_opendir(&fatfs_dir, pathname);
if (verbose)
Genode::log(__func__, ": opendir res=", (int)f_opendir_res);
switch(f_opendir_res) {
case FR_OK: {
Plugin_context *context = new (&*_heap)
Directory_plugin_context(pathname, ffat_dir);
Directory_plugin_context(pathname, fatfs_dir);
context->status_flags(flags);
Libc::File_descriptor *f =
Libc::file_descriptor_allocator()->alloc(this, context);
@ -568,7 +555,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_opendir() returned an unexpected error code");
return 0;
}
@ -593,7 +580,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_open() returned an unexpected error code");
return 0;
}
@ -601,10 +588,16 @@ class Plugin : public Libc::Plugin
int rename(const char *oldpath, const char *newpath) override
{
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_rename(oldpath, newpath);
/* if newpath already exists - try to unlink it once */
if (res == FR_EXIST) {
f_unlink(newpath);
res = f_rename(oldpath, newpath);
}
switch(res) {
case FR_OK:
return 0;
@ -616,7 +609,7 @@ class Plugin : public Libc::Plugin
return 0;
case FR_EXIST:
errno = EEXIST;
return 0;
return -1;
case FR_DENIED:
case FR_WRITE_PROTECTED:
errno = EACCES;
@ -629,7 +622,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_rename() returned an unexpected error code");
return -1;
}
@ -637,10 +630,10 @@ class Plugin : public Libc::Plugin
ssize_t read(Libc::File_descriptor *fd, void *buf, ::size_t count) override
{
using namespace Ffat;
using namespace Fatfs;
UINT result;
FRESULT res = f_read(_get_ffat_file(fd), buf, count, &result);
FRESULT res = f_read(_get_fatfs_file(fd), buf, count, &result);
switch(res) {
case FR_OK:
@ -655,7 +648,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_read() returned an unexpected error code");
return -1;
}
@ -663,12 +656,9 @@ class Plugin : public Libc::Plugin
int stat(const char *path, struct stat *buf) override
{
using namespace Ffat;
using namespace Fatfs;
FILINFO file_info;
/* the long file name is not used in this function */
file_info.lfname = 0;
file_info.lfsize = 0;
::memset(buf, 0, sizeof(struct stat));
@ -697,7 +687,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_stat() returned an unexpected error code");
return -1;
}
@ -741,7 +731,7 @@ class Plugin : public Libc::Plugin
int unlink(const char *path) override
{
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_unlink(path);
@ -766,7 +756,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_unlink() returned an unexpected error code");
return -1;
}
@ -779,10 +769,10 @@ class Plugin : public Libc::Plugin
ssize_t write(Libc::File_descriptor *fd, const void *buf, ::size_t count) override
{
using namespace Ffat;
using namespace Fatfs;
UINT result;
FRESULT res = f_write(_get_ffat_file(fd), buf, count, &result);
FRESULT res = f_write(_get_fatfs_file(fd), buf, count, &result);
switch(res) {
case FR_OK:
@ -797,7 +787,7 @@ class Plugin : public Libc::Plugin
errno = EIO;
return -1;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_write() returned an unexpected error code");
return -1;
}
@ -814,7 +804,7 @@ class Plugin : public Libc::Plugin
} /* unnamed namespace */
void __attribute__((constructor)) init_libc_ffat(void)
void __attribute__((constructor)) init_libc_fatfs(void)
{
static Plugin plugin;
}

View File

@ -1,5 +1,5 @@
/*
* \brief FFAT file-system directory node
* \brief FATFS file-system directory node
* \author Christian Prochaska
* \date 2012-07-04
*/
@ -14,25 +14,25 @@
#ifndef _DIRECTORY_H_
#define _DIRECTORY_H_
/* ffat includes */
namespace Ffat { extern "C" {
#include <ffat/ff.h>
/* fatfs includes */
namespace Fatfs { extern "C" {
#include <fatfs/ff.h>
} }
/* local includes */
#include <node.h>
namespace Ffat_fs {
namespace Fatfs_fs {
using namespace Genode;
class Directory;
}
class Ffat_fs::Directory : public Node
class Fatfs_fs::Directory : public Node
{
private:
Ffat::DIR _ffat_dir;
Fatfs::DIR _fatfs_dir;
int64_t _prev_index;
public:
@ -41,8 +41,8 @@ class Ffat_fs::Directory : public Node
: Node(name),
_prev_index(-1) { }
void ffat_dir(Ffat::DIR ffat_dir) { _ffat_dir = ffat_dir; }
Ffat::DIR *ffat_dir() { return &_ffat_dir; }
void fatfs_dir(Fatfs::DIR fatfs_dir) { _fatfs_dir = fatfs_dir; }
Fatfs::DIR *fatfs_dir() { return &_fatfs_dir; }
size_t read(char *dst, size_t len, seek_off_t seek_offset)
{
@ -58,24 +58,22 @@ class Ffat_fs::Directory : public Node
Directory_entry *e = (Directory_entry *)(dst);
using namespace Ffat;
using namespace Fatfs;
FILINFO ffat_file_info;
ffat_file_info.lfname = e->name;
ffat_file_info.lfsize = sizeof(e->name);
FILINFO fatfs_file_info;
int64_t index = seek_offset / sizeof(Directory_entry);
if (index != (_prev_index + 1)) {
/* rewind and iterate from the beginning */
f_readdir(&_ffat_dir, 0);
f_readdir(&_fatfs_dir, 0);
for (int i = 0; i < index; i++)
f_readdir(&_ffat_dir, &ffat_file_info);
f_readdir(&_fatfs_dir, &fatfs_file_info);
}
_prev_index = index;
FRESULT res = f_readdir(&_ffat_dir, &ffat_file_info);
FRESULT res = f_readdir(&_fatfs_dir, &fatfs_file_info);
switch(res) {
case FR_OK:
break;
@ -92,19 +90,18 @@ class Ffat_fs::Directory : public Node
error("f_readdir() failed with error code FR_NOT_READY");
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the libfatfs documentation */
error("f_readdir() returned an unexpected error code");
return 0;
}
if (ffat_file_info.fname[0] == 0) { /* no (more) entries */
if (fatfs_file_info.fname[0] == 0) { /* no (more) entries */
return 0;
}
if (e->name[0] == 0) /* use short file name */
strncpy(e->name, ffat_file_info.fname, sizeof(e->name));
strncpy(e->name, fatfs_file_info.fname, sizeof(e->name));
if ((ffat_file_info.fattrib & AM_DIR) == AM_DIR)
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR)
e->type = Directory_entry::TYPE_DIRECTORY;
else
e->type = Directory_entry::TYPE_FILE;

View File

@ -1,5 +1,5 @@
/*
* \brief FFAT file-system file node
* \brief FATFS file-system file node
* \author Christian Prochaska
* \date 2012-07-04
*/
@ -14,24 +14,24 @@
#ifndef _FILE_H_
#define _FILE_H_
/* ffat includes */
namespace Ffat { extern "C" {
#include <ffat/ff.h>
/* fatfs includes */
namespace Fatfs { extern "C" {
#include <fatfs/ff.h>
} }
/* local includes */
#include <node.h>
namespace Ffat_fs {
namespace Fatfs_fs {
class File;
}
class Ffat_fs::File : public Node
class Fatfs_fs::File : public Node
{
private:
Ffat::FIL _ffat_fil;
Fatfs::FIL _fatfs_fil;
public:
@ -39,9 +39,9 @@ class Ffat_fs::File : public Node
~File()
{
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_close(&_ffat_fil);
FRESULT res = f_close(&_fatfs_fil);
switch(res) {
case FR_OK:
@ -59,25 +59,29 @@ class Ffat_fs::File : public Node
error("f_close() failed with error code FR_NOT_READY");
return;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_close() returned an unexpected error code");
return;
}
}
void ffat_fil(Ffat::FIL ffat_fil) { _ffat_fil = ffat_fil; }
Ffat::FIL *ffat_fil() { return &_ffat_fil; }
void fatfs_fil(Fatfs::FIL fatfs_fil) { _fatfs_fil = fatfs_fil; }
Fatfs::FIL *fatfs_fil() { return &_fatfs_fil; }
size_t read(char *dst, size_t len, seek_off_t seek_offset) override
{
using namespace Ffat;
using namespace Fatfs;
UINT result;
if (seek_offset == (seek_off_t)(~0))
seek_offset = _ffat_fil.fsize;
if (seek_offset == (seek_off_t)(~0)) {
FILINFO file_info;
f_stat(name(), &file_info);
FRESULT res = f_lseek(&_ffat_fil, seek_offset);
seek_offset = file_info.fsize;
}
FRESULT res = f_lseek(&_fatfs_fil, seek_offset);
switch(res) {
case FR_OK:
@ -95,12 +99,12 @@ class Ffat_fs::File : public Node
Genode::error("f_lseek() failed with error code FR_NOT_READY");
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_lseek() returned an unexpected error code");
return 0;
}
res = f_read(&_ffat_fil, dst, len, &result);
res = f_read(&_fatfs_fil, dst, len, &result);
switch(res) {
case FR_OK:
@ -121,7 +125,7 @@ class Ffat_fs::File : public Node
Genode::error("f_read() failed with error code FR_NOT_READY");
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_read() returned an unexpected error code");
return 0;
}
@ -129,14 +133,18 @@ class Ffat_fs::File : public Node
size_t write(char const *src, size_t len, seek_off_t seek_offset) override
{
using namespace Ffat;
using namespace Fatfs;
UINT result;
if (seek_offset == (seek_off_t)(~0))
seek_offset = _ffat_fil.fsize;
if (seek_offset == (seek_off_t)(~0)) {
FILINFO file_info;
f_stat(name(), &file_info);
FRESULT res = f_lseek(&_ffat_fil, seek_offset);
seek_offset = file_info.fsize;
}
FRESULT res = f_lseek(&_fatfs_fil, seek_offset);
switch(res) {
case FR_OK:
@ -154,12 +162,12 @@ class Ffat_fs::File : public Node
Genode::error("f_lseek() failed with error code FR_NOT_READY");
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_lseek() returned an unexpected error code");
return 0;
}
res = f_write(&_ffat_fil, src, len, &result);
res = f_write(&_fatfs_fil, src, len, &result);
switch(res) {
case FR_OK:
@ -180,7 +188,7 @@ class Ffat_fs::File : public Node
Genode::error("f_write() failed with error code FR_NOT_READY");
return 0;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
Genode::error("f_write() returned an unexpected error code");
return 0;
}
@ -188,7 +196,7 @@ class Ffat_fs::File : public Node
void truncate(file_size_t size) override
{
using namespace Ffat;
using namespace Fatfs;
/*
* This macro is defined in later versions of the FatFs lib, but not in the
@ -198,12 +206,12 @@ class Ffat_fs::File : public Node
/* 'f_truncate()' truncates to the current seek pointer */
FRESULT res = f_lseek(&_ffat_fil, size);
FRESULT res = f_lseek(&_fatfs_fil, size);
switch(res) {
case FR_OK:
/* according to the FatFs documentation this can happen */
if (f_tell(&_ffat_fil) != size) {
if (f_tell(&_fatfs_fil) != size) {
error("f_lseek() could not seek to offset ", size);
return;
}
@ -221,12 +229,12 @@ class Ffat_fs::File : public Node
error("f_lseek() failed with error code FR_INVALID_OBJECT");
throw Invalid_handle();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_lseek() returned an unexpected error code");
return;
}
res = f_truncate(&_ffat_fil);
res = f_truncate(&_fatfs_fil);
switch(res) {
case FR_OK:
@ -247,7 +255,7 @@ class Ffat_fs::File : public Node
error("f_truncate() failed with error code FR_TIMEOUT");
return;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_truncate() returned an unexpected error code");
return;
}

View File

@ -1,5 +1,5 @@
/*
* \brief FFAT file system
* \brief FATFS file system
* \author Christian Prochaska
* \date 2012-07-03
*/
@ -28,11 +28,11 @@
#include <util.h>
/* Genode block backend */
#include <ffat/block.h>
#include <fatfs/block.h>
/* ffat includes */
namespace Ffat { extern "C" {
#include <ffat/ff.h>
/* fatfs includes */
namespace Fatfs { extern "C" {
#include <fatfs/ff.h>
} }
@ -40,7 +40,7 @@ namespace Ffat { extern "C" {
** File-system service **
*************************/
namespace Ffat_fs {
namespace Fatfs_fs {
using namespace Genode;
using File_system::Exception;
@ -52,7 +52,7 @@ namespace Ffat_fs {
struct Main;
}
class Ffat_fs::Session_component : public Session_rpc_object
class Fatfs_fs::Session_component : public Session_rpc_object
{
private:
@ -222,23 +222,23 @@ class Ffat_fs::Session_component : public Session_rpc_object
auto file_fn = [&] (Open_node &open_node) {
using namespace Ffat;
using namespace Fatfs;
FIL ffat_fil;
BYTE ffat_flags = 0;
FIL fatfs_fil;
BYTE fatfs_flags = 0;
if (!_writable)
if (create || (mode != STAT_ONLY && mode != READ_ONLY))
throw Permission_denied();
if (create)
ffat_flags |= FA_CREATE_NEW;
fatfs_flags |= FA_CREATE_NEW;
if ((mode == READ_ONLY) || (mode == READ_WRITE))
ffat_flags |= FA_READ;
fatfs_flags |= FA_READ;
if ((mode == WRITE_ONLY) || (mode == READ_WRITE))
ffat_flags |= FA_WRITE;
fatfs_flags |= FA_WRITE;
Absolute_path absolute_path(_root.name());
@ -250,12 +250,12 @@ class Ffat_fs::Session_component : public Session_rpc_object
throw Invalid_name();
}
FRESULT res = f_open(&ffat_fil, absolute_path.base(), ffat_flags);
FRESULT res = f_open(&fatfs_fil, absolute_path.base(), fatfs_flags);
switch(res) {
case FR_OK: {
File *file_node = new (&_heap) File(absolute_path.base());
file_node->ffat_fil(ffat_fil);
file_node->fatfs_fil(fatfs_fil);
Open_node *open_file =
new (_heap) Open_node(*file_node, _open_node_registry);
@ -289,7 +289,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_open() failed with error code FR_NO_FILESYSTEM");
throw Lookup_failed();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_open() returned an unexpected error code");
throw Lookup_failed();
}
@ -323,7 +323,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
*/
Directory *dir_node = new (&_heap) Directory(path.string());
using namespace Ffat;
using namespace Fatfs;
Absolute_path absolute_path(_root.name());
@ -372,7 +372,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_mkdir() failed with error code FR_NO_FILESYSTEM");
throw Lookup_failed();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_mkdir() returned an unexpected error code");
throw Lookup_failed();
}
@ -382,13 +382,13 @@ class Ffat_fs::Session_component : public Session_rpc_object
}
}
Ffat::DIR ffat_dir;
FRESULT f_opendir_res = f_opendir(&ffat_dir, absolute_path.base());
Fatfs::DIR fatfs_dir;
FRESULT f_opendir_res = f_opendir(&fatfs_dir, absolute_path.base());
try {
switch(f_opendir_res) {
case FR_OK: {
dir_node->ffat_dir(ffat_dir);
dir_node->fatfs_dir(fatfs_dir);
Open_node *open_dir =
new (_heap) Open_node(*dir_node, _open_node_registry);
@ -417,7 +417,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_opendir() failed with error code FR_NO_FILESYSTEM");
throw Lookup_failed();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_opendir() returned an unexpected error code");
throw Lookup_failed();
}
@ -446,12 +446,9 @@ class Ffat_fs::Session_component : public Session_rpc_object
/* f_stat() does not work for "/" */
if (!is_root(node->name())) {
using namespace Ffat;
using namespace Fatfs;
FILINFO file_info;
/* the long file name is not used in this function */
file_info.lfname = 0;
file_info.lfsize = 0;
FRESULT res = f_stat(node->name(), &file_info);
@ -481,7 +478,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_stat() failed with error code FR_NO_FILESYSTEM");
throw Lookup_failed();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_stat() returned an unexpected error code");
throw Lookup_failed();
}
@ -523,17 +520,14 @@ class Ffat_fs::Session_component : public Session_rpc_object
Node &node = open_node.node();
using namespace Ffat;
using namespace Fatfs;
/* f_stat() does not work for the '/' directory */
if (!is_root(node.name())) {
FILINFO ffat_file_info;
/* the long file name is not used in this function */
ffat_file_info.lfname = 0;
ffat_file_info.lfsize = 0;
FILINFO fatfs_file_info;
FRESULT res = f_stat(node.name(), &ffat_file_info);
FRESULT res = f_stat(node.name(), &fatfs_file_info);
switch(res) {
case FR_OK:
@ -566,16 +560,16 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_stat() failed with error code FR_NO_FILESYSTEM");
return status;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_stat() returned an unexpected error code");
return status;
}
if ((ffat_file_info.fattrib & AM_DIR) == AM_DIR) {
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR) {
status.mode = File_system::Status::MODE_DIRECTORY; }
else {
status.mode = File_system::Status::MODE_FILE;
status.size = ffat_file_info.fsize;
status.size = fatfs_file_info.fsize;
}
} else {
@ -586,24 +580,21 @@ class Ffat_fs::Session_component : public Session_rpc_object
/* determine the number of directory entries */
Ffat::DIR ffat_dir;
FRESULT f_opendir_res = f_opendir(&ffat_dir, node.name());
Fatfs::DIR fatfs_dir;
FRESULT f_opendir_res = f_opendir(&fatfs_dir, node.name());
if (f_opendir_res != FR_OK)
return status;
FILINFO ffat_file_info;
/* the long file name is not used in this function */
ffat_file_info.lfname = 0;
ffat_file_info.lfsize = 0;
FILINFO fatfs_file_info;
int num_direntries = -1;
do {
++num_direntries;
FRESULT res = f_readdir(&ffat_dir, &ffat_file_info);
FRESULT res = f_readdir(&fatfs_dir, &fatfs_file_info);
if (res != FR_OK)
return status;
} while (ffat_file_info.fname[0] != 0);
} while (fatfs_file_info.fname[0] != 0);
status.size = num_direntries * sizeof(Directory_entry);
}
@ -630,7 +621,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
auto unlink_fn = [&] (Open_node &open_node) {
using namespace Ffat;
using namespace Fatfs;
Absolute_path absolute_path(_root.name());
@ -672,7 +663,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_unlink() failed with error code FR_NO_FILESYSTEM");
return;
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_unlink() returned an unexpected error code");
return;
}
@ -731,10 +722,16 @@ class Ffat_fs::Session_component : public Session_rpc_object
throw Invalid_name();
}
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_rename(absolute_from_path.base(), absolute_to_path.base());
/* if newpath already exists - try to unlink it once */
if (res == FR_EXIST) {
f_unlink(absolute_to_path.base());
res = f_rename(absolute_from_path.base(), absolute_to_path.base());
}
switch(res) {
case FR_OK:
break;
@ -766,7 +763,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
error("f_rename() failed with error code FR_NO_FILESYSTEM");
throw Lookup_failed();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_rename() returned an unexpected error code");
throw Lookup_failed();
}
@ -793,7 +790,7 @@ class Ffat_fs::Session_component : public Session_rpc_object
};
class Ffat_fs::Root : public Root_component<Session_component>
class Fatfs_fs::Root : public Root_component<Session_component>
{
private:
@ -841,7 +838,7 @@ class Ffat_fs::Root : public Root_component<Session_component>
/* Check if the root path exists */
using namespace Ffat;
using namespace Fatfs;
FRESULT res = f_chdir(root);
@ -869,7 +866,7 @@ class Ffat_fs::Root : public Root_component<Session_component>
error("f_chdir() failed with error code FR_NO_FILESYSTEM");
throw Service_denied();
default:
/* not supposed to occur according to the libffat documentation */
/* not supposed to occur according to the fatfs documentation */
error("f_chdir() returned an unexpected error code");
throw Service_denied();
}
@ -940,7 +937,7 @@ class Ffat_fs::Root : public Root_component<Session_component>
};
struct Ffat_fs::Main
struct Fatfs_fs::Main
{
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
@ -949,24 +946,24 @@ struct Ffat_fs::Main
Directory _root_dir { "/" };
Root _root { _env, _sliced_heap, _heap, _root_dir };
Ffat::FATFS _fatfs;
Fatfs::FATFS _fatfs;
Main(Genode::Env &env) : _env(env)
{
Ffat::block_init(_env, _heap);
Fatfs::block_init(_env, _heap);
using namespace File_system;
using namespace Ffat;
using namespace Fatfs;
/* mount the file system */
if (f_mount(0, &_fatfs) != Ffat::FR_OK) {
if (f_mount(&_fatfs, "", 0) != Fatfs::FR_OK) {
error("mount failed");
struct Mount_failed : Genode::Exception { };
throw Mount_failed();
}
Genode::log("--- Starting Ffat_fs ---");
Genode::log("--- Starting Fatfs_fs ---");
_env.parent().announce(_env.ep().manage(_root));
}
@ -978,5 +975,5 @@ void Component::construct(Genode::Env &env)
/* XXX execute constructors of global statics */
env.exec_static_constructors();
static Ffat_fs::Main main(env);
static Fatfs_fs::Main main(env);
}

View File

@ -1,5 +1,5 @@
/*
* \brief FFAT file-system node
* \brief FATFS file-system node
* \author Christian Prochaska
* \date 2012-07-04
*/
@ -19,21 +19,21 @@
#include <base/log.h>
#include <os/path.h>
/* ffat includes */
namespace Ffat { extern "C" {
#include <ffat/ff.h>
/* fatfs includes */
namespace Fatfs { extern "C" {
#include <fatfs/ff.h>
} }
namespace Ffat_fs {
namespace Fatfs_fs {
using namespace File_system;
typedef Genode::Path<_MAX_LFN + 1> Absolute_path;
typedef Genode::Path<FF_MAX_LFN + 1> Absolute_path;
class Node;
}
class Ffat_fs::Node : public Node_base
class Fatfs_fs::Node : public Node_base
{
protected:

View File

@ -0,0 +1,4 @@
TARGET = fatfs_fs
SRC_CC = main.cc
LIBS = base fatfs_block
INC_DIR += $(PRG_DIR)

View File

@ -1,4 +0,0 @@
TARGET = ffat_fs
SRC_CC = main.cc
LIBS = base ffat_block
INC_DIR += $(PRG_DIR)

View File

@ -0,0 +1,17 @@
#include <fatfs/block.h>
#include <base/heap.h>
#include <libc/component.h>
extern int main (int argc, char* argv[]);
void Libc::Component::construct(Libc::Env &env)
{
env.exec_static_constructors();
Genode::Heap heap(env.ram(), env.rm());
Fatfs::block_init(env, heap);
int r = 0;
Libc::with_libc([&r] () { r = main(0, 0); });
env.parent().exit(r);
}

View File

@ -0,0 +1,13 @@
TARGET = test-fatfs_blkio
LIBS = fatfs_block libc
SRC_C = app4.c
SRC_CC = component.cc
CC_DEF += -D_MAX_SS=FF_MAX_SS
CC_WARN += -Wno-pointer-to-int-cast
FATFS_PORT_DIR = $(call select_from_ports,fatfs)
INC_DIR += $(FATFS_PORT_DIR)/include/fatfs
vpath %.c $(FATFS_PORT_DIR)/src/lib/fatfs/documents/res

View File

@ -1,5 +1,5 @@
TARGET = test-libc_ffat
LIBS = libc libc_ffat
TARGET = test-libc_fatfs
LIBS = libc libc_fatfs
SRC_CC = main.cc
# we re-use the libc_vfs test

View File

@ -162,10 +162,12 @@ static void test(Genode::Xml_node node)
/* move file (target does not exist) */
CALL_AND_CHECK(fd, open(file_name5, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name5);
CALL_AND_CHECK(ret, rename(file_name5, "x"), ret == 0, "file_name=%s", file_name5);
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
/* move file (target already exists) */
CALL_AND_CHECK(fd, open(file_name5, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name5);
CALL_AND_CHECK(ret, rename(file_name5, "x"), ret == 0, "file_name=%s", file_name5);
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
/* test 'pread()' and 'pwrite()' */
CALL_AND_CHECK(fd, open(file_name2, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name2);

View File

@ -7,7 +7,7 @@ rom_blk
tar_rom
noux
noux_net_netcat
libc_ffat
libc_fatfs
libc_getenv
libc_pipe
libc_vfs