diff --git a/repos/os/src/server/ram_blk/README b/repos/os/src/server/ram_blk/README index 96e2ebe8d7..4371395075 100644 --- a/repos/os/src/server/ram_blk/README +++ b/repos/os/src/server/ram_blk/README @@ -1,6 +1,14 @@ -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. +RAM block device is an implementation of the block-session interface +running as a client of a RAM session. It either populates the RAM dataspace +by using a ROM dataspace, similiar to loop devices. For example to use +an ISO file the component has to be configured as follows: ! + +To use a empty RAM dataspace that is 256MiB large and has a block size +of 4KiB the configuration looks like this: + +! + +Either 'size' or 'file' has to specified. If both are declared the 'file' +attribute is soley evaluated. diff --git a/repos/os/src/server/ram_blk/main.cc b/repos/os/src/server/ram_blk/main.cc index d3ba6768aa..a74ea7ef6d 100644 --- a/repos/os/src/server/ram_blk/main.cc +++ b/repos/os/src/server/ram_blk/main.cc @@ -1,58 +1,64 @@ /* - * \brief Provide a rom-file as writable block device (aka loop devices) + * \brief Provide a RAM dataspace as writable block device * \author Stefan Kalkowski * \author Sebastian Sumpf + * \author Josef Soentgen * \date 2010-07-07 */ /* - * Copyright (C) 2010-2013 Genode Labs GmbH + * Copyright (C) 2010-2016 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. */ +/* Genode includes */ +#include +#include +#include #include -#include -#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 */ + Env &_env; + Allocator *_alloc { nullptr }; - void _io(Block::sector_t block_number, - size_t block_count, - char* buffer, + Attached_rom_dataspace *_rom_ds { nullptr }; + size_t _size; + size_t _block_size; + size_t _block_count; + Attached_ram_dataspace _ram_ds; + addr_t _ram_addr; + + void _io(Block::sector_t block_number, + size_t block_count, + char* buffer, Block::Packet_descriptor &packet, - bool read) + bool read) { /* sanity check block number */ - if (block_number + block_count > _file_sz / _blk_sz) { - PWRN("requested blocks %lld-%lld out of range!", - block_number, block_number + block_count); + if (block_number + block_count > _block_count) { + Genode::warning("requested blocks ", block_number, "-", + block_number + block_count," out of range!"); return; } - size_t offset = (size_t) block_number * _blk_sz; - size_t size = block_count * _blk_sz; + size_t offset = (size_t) block_number * _block_size; + size_t size = block_count * _block_size; - void *src = read ? (void *)(_file_addr + offset) : (void *)buffer; - void *dst = read ? (void *)buffer : (void *)(_file_addr + offset); + void *src = read ? (void *)(_ram_addr + offset) : (void *)buffer; + void *dst = read ? (void *)buffer : (void *)(_ram_addr + offset); /* copy file content to packet payload */ memcpy(dst, src, size); @@ -61,24 +67,46 @@ class Ram_blk : public Block::Driver 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()) + /** + * Construct populated RAM dataspace + */ + Ram_blk(Env &env, Allocator &alloc, + const char *name, size_t block_size) + : + _env(env), _alloc(&alloc), + _rom_ds(new (_alloc) Attached_rom_dataspace(_env, name)), + _size(_rom_ds->size()), + _block_size(block_size), + _block_count(_size/_block_size), + _ram_ds(_env.ram(), _env.rm(), _size), + _ram_addr((addr_t)_ram_ds.local_addr()) { - memcpy(_file_ds.local_addr(), _rom_ds.local_addr(), _file_sz); + /* populate backing store from file */ + memcpy(_ram_ds.local_addr(), _rom_ds->local_addr(), _size); } + /** + * Construct empty RAM dataspace + */ + Ram_blk(Env &env, size_t size, size_t block_size) + : + _env(env), + _size(size), + _block_size(block_size), + _block_count(_size/_block_size), + _ram_ds(_env.ram(), _env.rm(), _size), + _ram_addr((addr_t)_ram_ds.local_addr()) + { } + + ~Ram_blk() { destroy(_alloc, _rom_ds); } + /**************************** ** Block-driver interface ** ****************************/ - Genode::size_t block_size() { return _blk_sz; } - Block::sector_t block_count() { return _blk_cnt; } + size_t block_size() { return _block_size; } + Block::sector_t block_count() { return _block_count; } Block::Session::Operations ops() { @@ -97,7 +125,7 @@ class Ram_blk : public Block::Driver } void write(Block::sector_t block_number, - Genode::size_t block_count, + size_t block_count, const char * buffer, Block::Packet_descriptor &packet) { @@ -108,50 +136,78 @@ class Ram_blk : public Block::Driver struct Main { - Server::Entrypoint &ep; + Env &env; + Heap heap { env.ram(), env.rm() }; + + Attached_rom_dataspace config_rom { env, "config" }; struct Factory : Block::Driver_factory { + Env &env; + Allocator &alloc; + + bool use_file { false }; + char file[64]; + + size_t size { 0 }; + size_t block_size { 512 }; + + Factory(Env &env, Allocator &alloc, + Xml_node config) + : env(env), alloc(alloc) + { + use_file = config.has_attribute("file"); + if (use_file) { + config.attribute("file").value(file, sizeof(file)); + } else { + try { + Genode::Number_of_bytes bytes; + config.attribute("size").value(&bytes); + size = bytes; + } catch (...) { + error("neither file nor size attribute specified"); + throw Exception(); + } + } + + block_size = config.attribute_value("block_size", block_size); + } + 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); + if (use_file) { + Genode::log("Creating RAM-basd block device populated by file='", + (char const*)file, "' with block size ", block_size); + return new (&alloc) Ram_blk(env, alloc, file, block_size); + } else { + Genode::log("Creating RAM-based block device with size ", + size, " and block size ", block_size); + return new (&alloc) Ram_blk(env, size, block_size); + } + } catch (...) { + throw Root::Unavailable(); } - catch (...) { } - - PINF("Using file=%s as device with block size %zd.", 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; + Genode::destroy(&alloc, driver); } + } factory { env, heap, config_rom.xml() }; - Block::Root root; + Block::Root root { env.ep(), &heap, factory }; - Main(Server::Entrypoint &ep) - : ep(ep), root(ep, Genode::env()->heap(), factory) { - Genode::env()->parent()->announce(ep.manage(root)); } + Main(Env &env) : env(env) + { + env.parent().announce(env.ep().manage(root)); + } }; -/************ - ** Server ** - ************/ +/*************** + ** Component ** + ***************/ -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); } +namespace Component { + Genode::size_t stack_size() { return 2*1024*sizeof(long); } + void construct(Genode::Env &env) { static Main server(env); } } - diff --git a/repos/os/src/server/ram_blk/target.mk b/repos/os/src/server/ram_blk/target.mk index 9c1d8f80c4..89b54989a2 100644 --- a/repos/os/src/server/ram_blk/target.mk +++ b/repos/os/src/server/ram_blk/target.mk @@ -1,3 +1,3 @@ TARGET = ram_blk SRC_CC = main.cc -LIBS = base config server +LIBS = base config