Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Libc plugin for using file I/O on ROM dataspaces
- Loading branch information
Showing
3 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
SRC_CC = plugin.cc | ||
LIBS += libc | ||
|
||
vpath plugin.cc $(REP_DIR)/src/lib/libc_rom | ||
|
||
SHARED_LIB = yes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
The 'libc_rom' plugin allows the use of Genode's ROM-session interface via file | ||
operations of the C library. | ||
|
||
This implementation is very preliminary. It supports no file operations other | ||
than open and read. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* \brief Libc plugin that uses Genode's ROM session | ||
* \author Norman Feske | ||
* \date 2012-01-09 | ||
*/ | ||
|
||
/* | ||
* Copyright (C) 2011-2012 Genode Labs GmbH | ||
* | ||
* This file is part of the Genode OS framework, which is distributed | ||
* under the terms of the GNU General Public License version 2. | ||
*/ | ||
|
||
/* libc plugin interface */ | ||
#include <libc-plugin/plugin.h> | ||
#include <libc-plugin/fd_alloc.h> | ||
|
||
/* libc includes */ | ||
#include <unistd.h> | ||
#include <errno.h> | ||
#include <string.h> | ||
|
||
/* Genode includes */ | ||
#include <os/attached_rom_dataspace.h> | ||
#include <util/misc_math.h> | ||
#include <base/printf.h> | ||
#include <base/env.h> | ||
|
||
|
||
namespace { | ||
|
||
/** | ||
* An open file descriptor for this plugin corresponds to a ROM connection | ||
* | ||
* The connection is created along with the context. | ||
*/ | ||
struct Plugin_context : Libc::Plugin_context, Genode::Attached_rom_dataspace | ||
{ | ||
Genode::off_t read_offset; | ||
|
||
Plugin_context(char const *filename) | ||
: Genode::Attached_rom_dataspace(filename), read_offset(0) { } | ||
}; | ||
|
||
|
||
static inline Plugin_context *context(Libc::File_descriptor *fd) | ||
{ | ||
return static_cast<Plugin_context *>(fd->context); | ||
} | ||
|
||
|
||
class Plugin : public Libc::Plugin | ||
{ | ||
private: | ||
|
||
bool _probe_rom(char const *filename) | ||
{ | ||
try { | ||
/* | ||
* Create ROM connection as local variable. The connection | ||
* gets closed automatically when leaving the scope of this | ||
* function. | ||
*/ | ||
Genode::Rom_connection rom(filename); | ||
return true; | ||
} catch (...) { | ||
return false; | ||
} | ||
} | ||
|
||
public: | ||
|
||
/** | ||
* Constructor | ||
*/ | ||
Plugin() | ||
{ } | ||
|
||
bool supports_open(const char *path, int flags) | ||
{ | ||
return _probe_rom(path); | ||
} | ||
|
||
Libc::File_descriptor *open(const char *pathname, int flags) | ||
{ | ||
Plugin_context *context = new (Genode::env()->heap()) | ||
Plugin_context(pathname); | ||
return Libc::file_descriptor_allocator()->alloc(this, context); | ||
} | ||
|
||
int close(Libc::File_descriptor *fd) | ||
{ | ||
Genode::destroy(Genode::env()->heap(), context(fd)); | ||
Libc::file_descriptor_allocator()->free(fd); | ||
return 0; | ||
} | ||
|
||
ssize_t read(Libc::File_descriptor *fd, void *buf, ::size_t count) | ||
{ | ||
Plugin_context *rom = context(fd); | ||
|
||
/* file read limit is the size of data space */ | ||
Genode::size_t const max_size = rom->size(); | ||
|
||
/* shortcut to current read offset */ | ||
Genode::off_t &read_offset = rom->read_offset; | ||
|
||
/* maximum read offset, clamped to dataspace size */ | ||
Genode::off_t const end_offset = Genode::min(count + read_offset, max_size); | ||
|
||
/* source address within the dataspace */ | ||
char const *src = rom->local_addr<char>() + read_offset; | ||
|
||
/* check if end of file is reached */ | ||
if (read_offset >= end_offset) | ||
return 0; | ||
|
||
/* copy-out bytes from ROM dataspace */ | ||
Genode::off_t num_bytes = end_offset - read_offset; | ||
memcpy(buf, src, num_bytes); | ||
|
||
/* advance read offset */ | ||
read_offset += num_bytes; | ||
|
||
return num_bytes; | ||
} | ||
|
||
::off_t lseek(Libc::File_descriptor *fd, ::off_t offset, int whence) | ||
{ | ||
Plugin_context *rom = context(fd); | ||
|
||
switch (whence) { | ||
|
||
case SEEK_CUR: | ||
|
||
offset += rom->read_offset; | ||
|
||
/* | ||
* falling through... | ||
*/ | ||
|
||
case SEEK_SET: | ||
|
||
if (offset > rom->size()) { | ||
errno = EINVAL; | ||
return (::off_t)(-1); | ||
} | ||
|
||
rom->read_offset = offset; | ||
break; | ||
|
||
case SEEK_END: | ||
|
||
rom->read_offset = rom->size(); | ||
break; | ||
|
||
default: | ||
errno = EINVAL; | ||
return (::off_t)(-1); | ||
} | ||
|
||
return rom->read_offset; | ||
} | ||
}; | ||
|
||
} /* unnamed namespace */ | ||
|
||
|
||
void __attribute__((constructor)) init_libc_rom(void) | ||
{ | ||
static Plugin plugin; | ||
} |