mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 07:46:42 +00:00
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: ! <config file="image.iso" block_size="2048"/> To use a empty RAM dataspace that is 256MiB large and has a block size of 4KiB the configuration looks like this: ! <config size="256M" block_size="4096"/> Either 'size' or 'file' has to specified. If both are declared the 'file' attribute is soley evaluated. Issue #1987. Fixes #2031.
This commit is contained in:
parent
a5dd3fa1e9
commit
c25c4e3411
@ -1,6 +1,14 @@
|
|||||||
RAM loop device is an implementation of the block-session interface
|
RAM block 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
|
running as a client of a RAM session. It either populates the RAM dataspace
|
||||||
block device, similiar to loop devices known in Linux. The example shows how
|
by using a ROM dataspace, similiar to loop devices. For example to use
|
||||||
to choose the right ROM file in its configuration and how to configure the exported block size.
|
an ISO file the component has to be configured as follows:
|
||||||
|
|
||||||
! <config file="image.iso" block_size="2048"/>
|
! <config file="image.iso" block_size="2048"/>
|
||||||
|
|
||||||
|
To use a empty RAM dataspace that is 256MiB large and has a block size
|
||||||
|
of 4KiB the configuration looks like this:
|
||||||
|
|
||||||
|
! <config size="256M" block_size="4096"/>
|
||||||
|
|
||||||
|
Either 'size' or 'file' has to specified. If both are declared the 'file'
|
||||||
|
attribute is soley evaluated.
|
||||||
|
@ -1,39 +1,45 @@
|
|||||||
/*
|
/*
|
||||||
* \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 Stefan Kalkowski
|
||||||
* \author Sebastian Sumpf
|
* \author Sebastian Sumpf
|
||||||
|
* \author Josef Soentgen
|
||||||
* \date 2010-07-07
|
* \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
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/attached_ram_dataspace.h>
|
||||||
|
#include <base/attached_rom_dataspace.h>
|
||||||
|
#include <base/component.h>
|
||||||
#include <base/exception.h>
|
#include <base/exception.h>
|
||||||
#include <base/printf.h>
|
#include <base/heap.h>
|
||||||
#include <os/attached_ram_dataspace.h>
|
#include <base/log.h>
|
||||||
#include <os/attached_rom_dataspace.h>
|
|
||||||
#include <os/config.h>
|
|
||||||
#include <os/server.h>
|
|
||||||
#include <rom_session/connection.h>
|
|
||||||
#include <block/component.h>
|
#include <block/component.h>
|
||||||
#include <block/driver.h>
|
#include <block/driver.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
class Ram_blk : public Block::Driver
|
class Ram_blk : public Block::Driver
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Attached_rom_dataspace _rom_ds;
|
Env &_env;
|
||||||
size_t _file_sz; /* file size */
|
Allocator *_alloc { nullptr };
|
||||||
size_t _blk_sz; /* block size */
|
|
||||||
size_t _blk_cnt; /* block count */
|
Attached_rom_dataspace *_rom_ds { nullptr };
|
||||||
Attached_ram_dataspace _file_ds; /* copy of rom file */
|
size_t _size;
|
||||||
addr_t _file_addr; /* start address of attached file */
|
size_t _block_size;
|
||||||
|
size_t _block_count;
|
||||||
|
Attached_ram_dataspace _ram_ds;
|
||||||
|
addr_t _ram_addr;
|
||||||
|
|
||||||
void _io(Block::sector_t block_number,
|
void _io(Block::sector_t block_number,
|
||||||
size_t block_count,
|
size_t block_count,
|
||||||
@ -42,17 +48,17 @@ class Ram_blk : public Block::Driver
|
|||||||
bool read)
|
bool read)
|
||||||
{
|
{
|
||||||
/* sanity check block number */
|
/* sanity check block number */
|
||||||
if (block_number + block_count > _file_sz / _blk_sz) {
|
if (block_number + block_count > _block_count) {
|
||||||
PWRN("requested blocks %lld-%lld out of range!",
|
Genode::warning("requested blocks ", block_number, "-",
|
||||||
block_number, block_number + block_count);
|
block_number + block_count," out of range!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t offset = (size_t) block_number * _blk_sz;
|
size_t offset = (size_t) block_number * _block_size;
|
||||||
size_t size = block_count * _blk_sz;
|
size_t size = block_count * _block_size;
|
||||||
|
|
||||||
void *src = read ? (void *)(_file_addr + offset) : (void *)buffer;
|
void *src = read ? (void *)(_ram_addr + offset) : (void *)buffer;
|
||||||
void *dst = read ? (void *)buffer : (void *)(_file_addr + offset);
|
void *dst = read ? (void *)buffer : (void *)(_ram_addr + offset);
|
||||||
/* copy file content to packet payload */
|
/* copy file content to packet payload */
|
||||||
memcpy(dst, src, size);
|
memcpy(dst, src, size);
|
||||||
|
|
||||||
@ -61,24 +67,46 @@ class Ram_blk : public Block::Driver
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Ram_blk(const char *name, size_t blk_sz)
|
/**
|
||||||
: _rom_ds(name),
|
* Construct populated RAM dataspace
|
||||||
_file_sz(_rom_ds.size()),
|
*/
|
||||||
_blk_sz(blk_sz),
|
Ram_blk(Env &env, Allocator &alloc,
|
||||||
_blk_cnt(_file_sz/_blk_sz),
|
const char *name, size_t block_size)
|
||||||
_file_ds(env()->ram_session(), _file_sz),
|
:
|
||||||
_file_addr((addr_t)_file_ds.local_addr<addr_t>())
|
_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<addr_t>())
|
||||||
{
|
{
|
||||||
memcpy(_file_ds.local_addr<void>(), _rom_ds.local_addr<void>(), _file_sz);
|
/* populate backing store from file */
|
||||||
|
memcpy(_ram_ds.local_addr<void>(), _rom_ds->local_addr<void>(), _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<addr_t>())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Ram_blk() { destroy(_alloc, _rom_ds); }
|
||||||
|
|
||||||
|
|
||||||
/****************************
|
/****************************
|
||||||
** Block-driver interface **
|
** Block-driver interface **
|
||||||
****************************/
|
****************************/
|
||||||
|
|
||||||
Genode::size_t block_size() { return _blk_sz; }
|
size_t block_size() { return _block_size; }
|
||||||
Block::sector_t block_count() { return _blk_cnt; }
|
Block::sector_t block_count() { return _block_count; }
|
||||||
|
|
||||||
Block::Session::Operations ops()
|
Block::Session::Operations ops()
|
||||||
{
|
{
|
||||||
@ -97,7 +125,7 @@ class Ram_blk : public Block::Driver
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write(Block::sector_t block_number,
|
void write(Block::sector_t block_number,
|
||||||
Genode::size_t block_count,
|
size_t block_count,
|
||||||
const char * buffer,
|
const char * buffer,
|
||||||
Block::Packet_descriptor &packet)
|
Block::Packet_descriptor &packet)
|
||||||
{
|
{
|
||||||
@ -108,50 +136,78 @@ class Ram_blk : public Block::Driver
|
|||||||
|
|
||||||
struct Main
|
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
|
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()
|
Block::Driver *create()
|
||||||
{
|
{
|
||||||
char file[64];
|
|
||||||
size_t blk_sz = 512;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
config()->xml_node().attribute("file").value(file, sizeof(file));
|
if (use_file) {
|
||||||
config()->xml_node().attribute("block_size").value(&blk_sz);
|
Genode::log("Creating RAM-basd block device populated by file='",
|
||||||
}
|
(char const*)file, "' with block size ", block_size);
|
||||||
catch (...) { }
|
return new (&alloc) Ram_blk(env, alloc, file, block_size);
|
||||||
|
} else {
|
||||||
PINF("Using file=%s as device with block size %zd.", file, blk_sz);
|
Genode::log("Creating RAM-based block device with size ",
|
||||||
|
size, " and block size ", block_size);
|
||||||
try {
|
return new (&alloc) Ram_blk(env, size, block_size);
|
||||||
return new (Genode::env()->heap()) Ram_blk(file, blk_sz);
|
|
||||||
} catch(Rom_connection::Rom_connection_failed) {
|
|
||||||
PERR("Cannot open file %s.", file);
|
|
||||||
}
|
}
|
||||||
|
} catch (...) {
|
||||||
throw Root::Unavailable();
|
throw Root::Unavailable();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void destroy(Block::Driver *driver) {
|
void destroy(Block::Driver *driver) {
|
||||||
Genode::destroy(env()->heap(), driver); }
|
Genode::destroy(&alloc, driver); }
|
||||||
} factory;
|
} factory { env, heap, config_rom.xml() };
|
||||||
|
|
||||||
Block::Root root;
|
Block::Root root { env.ep(), &heap, factory };
|
||||||
|
|
||||||
Main(Server::Entrypoint &ep)
|
Main(Env &env) : env(env)
|
||||||
: ep(ep), root(ep, Genode::env()->heap(), factory) {
|
{
|
||||||
Genode::env()->parent()->announce(ep.manage(root)); }
|
env.parent().announce(env.ep().manage(root));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/************
|
/***************
|
||||||
** Server **
|
** Component **
|
||||||
************/
|
***************/
|
||||||
|
|
||||||
namespace Server {
|
namespace Component {
|
||||||
char const *name() { return "rom_blk_ep"; }
|
Genode::size_t stack_size() { return 2*1024*sizeof(long); }
|
||||||
size_t stack_size() { return 2*1024*sizeof(long); }
|
void construct(Genode::Env &env) { static Main server(env); }
|
||||||
void construct(Entrypoint &ep) { static Main server(ep); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
TARGET = ram_blk
|
TARGET = ram_blk
|
||||||
SRC_CC = main.cc
|
SRC_CC = main.cc
|
||||||
LIBS = base config server
|
LIBS = base config
|
||||||
|
Loading…
Reference in New Issue
Block a user