From ce27985b8a0f57f21ebe323c3e99fb344a9f9fbf Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Wed, 18 Dec 2013 12:27:29 +0100 Subject: [PATCH] ram_blk: Writable loopback device Issue #1048 --- os/src/server/ram_blk/README | 6 ++ os/src/server/ram_blk/main.cc | 158 ++++++++++++++++++++++++++++++++ os/src/server/ram_blk/target.mk | 3 + 3 files changed, 167 insertions(+) create mode 100644 os/src/server/ram_blk/README create mode 100644 os/src/server/ram_blk/main.cc create mode 100644 os/src/server/ram_blk/target.mk diff --git a/os/src/server/ram_blk/README b/os/src/server/ram_blk/README new file mode 100644 index 0000000000..96e2ebe8d7 --- /dev/null +++ b/os/src/server/ram_blk/README @@ -0,0 +1,6 @@ +RAM loop device is an implementation of the block-session interface +running as a client of a RAM session. It exports the requested ROM file as a +block device, similiar to loop devices known in Linux. The example shows how +to choose the right ROM file in its configuration and how to configure the exported block size. + +! diff --git a/os/src/server/ram_blk/main.cc b/os/src/server/ram_blk/main.cc new file mode 100644 index 0000000000..63bea1dcab --- /dev/null +++ b/os/src/server/ram_blk/main.cc @@ -0,0 +1,158 @@ +/* + * \brief Provide a rom-file as writable block device (aka loop devices) + * \author Stefan Kalkowski + * \author Sebastian Sumpf + * \date 2010-07-07 + */ + +/* + * Copyright (C) 2010-2013 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Genode; + +class Ram_blk : public Block::Driver +{ + private: + + Attached_rom_dataspace _rom_ds; + size_t _file_sz; /* file size */ + size_t _blk_sz; /* block size */ + size_t _blk_cnt; /* block count */ + Attached_ram_dataspace _file_ds; /* copy of rom file */ + addr_t _file_addr; /* start address of attached file */ + + void _io(Block::sector_t block_number, + size_t block_count, + char* buffer, + Block::Packet_descriptor &packet, + bool read) + { + /* sanity check block number */ + if ((block_number + block_count > _file_sz / _blk_sz) + || block_number < 0) { + PWRN("requested blocks %lld-%lld out of range!", + block_number, block_number + block_count); + return; + } + + size_t offset = (size_t) block_number * _blk_sz; + size_t size = block_count * _blk_sz; + + void *src = read ? (void *)(_file_addr + offset) : (void *)buffer; + void *dst = read ? (void *)buffer : (void *)(_file_addr + offset); + /* copy file content to packet payload */ + memcpy(dst, src, size); + + ack_packet(packet); + } + + public: + + Ram_blk(const char *name, size_t blk_sz) + : _rom_ds(name), + _file_sz(_rom_ds.size()), + _blk_sz(blk_sz), + _blk_cnt(_file_sz/_blk_sz), + _file_ds(env()->ram_session(), _file_sz), + _file_addr((addr_t)_file_ds.local_addr()) + { + memcpy(_file_ds.local_addr(), _rom_ds.local_addr(), _file_sz); + } + + + /**************************** + ** Block-driver interface ** + ****************************/ + + Genode::size_t block_size() { return _blk_sz; } + Block::sector_t block_count() { return _blk_cnt; } + + Block::Session::Operations ops() + { + Block::Session::Operations o; + o.set_operation(Block::Packet_descriptor::READ); + o.set_operation(Block::Packet_descriptor::WRITE); + return o; + } + + void read(Block::sector_t block_number, + size_t block_count, + char* buffer, + Block::Packet_descriptor &packet) + { + _io(block_number, block_count, buffer, packet, true); + } + + void write(Block::sector_t block_number, + Genode::size_t block_count, + const char * buffer, + Block::Packet_descriptor &packet) + { + _io(block_number, block_count, const_cast(buffer), packet, false); + } +}; + + +struct Main +{ + Server::Entrypoint &ep; + + struct Factory : Block::Driver_factory + { + Block::Driver *create() + { + char file[64]; + size_t blk_sz = 512; + + try { + config()->xml_node().attribute("file").value(file, sizeof(file)); + config()->xml_node().attribute("block_size").value(&blk_sz); + } + catch (...) { } + + PINF("Using file=%s as device with block size %zx.", file, blk_sz); + + try { + return new (Genode::env()->heap()) Ram_blk(file, blk_sz); + } catch(Rom_connection::Rom_connection_failed) { + PERR("Cannot open file %s.", file); + } + throw Root::Unavailable(); + } + + void destroy(Block::Driver *driver) { + Genode::destroy(env()->heap(), driver); } + } factory; + + Block::Root root; + + Main(Server::Entrypoint &ep) + : ep(ep), root(ep, Genode::env()->heap(), factory) { + Genode::env()->parent()->announce(ep.manage(root)); } +}; + + +/************ + ** Server ** + ************/ + +namespace Server { + char const *name() { return "rom_blk_ep"; } + size_t stack_size() { return 2*1024*sizeof(long); } + void construct(Entrypoint &ep) { static Main server(ep); } +} + diff --git a/os/src/server/ram_blk/target.mk b/os/src/server/ram_blk/target.mk new file mode 100644 index 0000000000..9c1d8f80c4 --- /dev/null +++ b/os/src/server/ram_blk/target.mk @@ -0,0 +1,3 @@ +TARGET = ram_blk +SRC_CC = main.cc +LIBS = base config server