From c25c4e34118cee24b3d1f5ffe4416fe161143ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Tue, 5 Jul 2016 11:40:26 +0200 Subject: [PATCH] ram_blk: transition to the new base API In addition to modernizing the component now also supports using empty RAM dataspace as backing store. 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. Issue #1987. Fixes #2031. --- repos/os/src/server/ram_blk/README | 16 ++- repos/os/src/server/ram_blk/main.cc | 188 +++++++++++++++++--------- repos/os/src/server/ram_blk/target.mk | 2 +- 3 files changed, 135 insertions(+), 71 deletions(-) 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