Skip to content

Commit

Permalink
Libc plugin for using file I/O on ROM dataspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
nfeske committed Feb 14, 2012
1 parent dc4f687 commit 54cb495
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 0 deletions.
6 changes: 6 additions & 0 deletions libports/lib/mk/libc_rom.mk
@@ -0,0 +1,6 @@
SRC_CC = plugin.cc
LIBS += libc

vpath plugin.cc $(REP_DIR)/src/lib/libc_rom

SHARED_LIB = yes
5 changes: 5 additions & 0 deletions libports/src/lib/libc_rom/README
@@ -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.
172 changes: 172 additions & 0 deletions libports/src/lib/libc_rom/plugin.cc
@@ -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;
}

0 comments on commit 54cb495

Please sign in to comment.