mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
parent
9646c17f2e
commit
f9c2e0e21c
59
repos/os/run/lx_block.run
Normal file
59
repos/os/run/lx_block.run
Normal file
@ -0,0 +1,59 @@
|
||||
#
|
||||
# Test runs only on Linux
|
||||
#
|
||||
assert_spec linux
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
build { core init drivers/timer server/lx_block test/blk/bench }
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="TRACE"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="lx_block">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Block"/> </provides>
|
||||
<config file="lx_block.img" block_size="4K" writeable="yes"/>
|
||||
</start>
|
||||
<start name="test-blk-bench">
|
||||
<resource name="RAM" quantum="24M"/>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
#
|
||||
# Create test file
|
||||
#
|
||||
catch { exec dd if=/dev/zero of=bin/lx_block.img bs=1M count=64 }
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
build_boot_image { core ld.lib.so init timer lx_block lx_block.img test-blk-bench }
|
||||
|
||||
run_genode_until "Done.*\n" 100
|
||||
|
||||
exec rm -f bin/lx_block.img
|
22
repos/os/src/server/lx_block/README
Normal file
22
repos/os/src/server/lx_block/README
Normal file
@ -0,0 +1,22 @@
|
||||
This directory contains an Genode Block service that uses a file on
|
||||
a Linux system as backing store.
|
||||
|
||||
Configuration
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The backing store is specified by the 'file' attribute. The pretended
|
||||
block size is specified by the 'block_size' attribute. In case it is
|
||||
omitted, a default block size of 512 bytes is used. To allow write
|
||||
access, the 'writeable' attribute must be set to 'yes'. By default only
|
||||
read-only access it allowed.
|
||||
|
||||
An example configuration is shown in the the following config snippet:
|
||||
|
||||
!<config file="/foo/bar/block.img" block_size="512" writeable="yes"/>
|
||||
|
||||
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
The backing file is opened with blocking semantics and thereby the block
|
||||
session is used synchronously.
|
194
repos/os/src/server/lx_block/main.cc
Normal file
194
repos/os/src/server/lx_block/main.cc
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* \brief Linux file as a block session
|
||||
* \author Josef Soentgen
|
||||
* \date 2017-07-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 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 <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/log.h>
|
||||
#include <block/component.h>
|
||||
#include <block/driver.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h> /* perror */
|
||||
|
||||
|
||||
static bool xml_attr_ok(Genode::Xml_node node, char const *attr)
|
||||
{
|
||||
return node.attribute_value(attr, false);
|
||||
}
|
||||
|
||||
|
||||
class Lx_block_driver : public Block::Driver
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
Block::sector_t _block_count { 0 };
|
||||
Genode::size_t _block_size { 512 };
|
||||
Block::Session::Operations _block_ops;
|
||||
|
||||
int _fd { -1 };
|
||||
|
||||
public:
|
||||
|
||||
struct Could_not_open_file : Genode::Exception { };
|
||||
|
||||
Lx_block_driver(Genode::Env &env, Genode::Xml_node config)
|
||||
: Block::Driver(env.ram()), _env(env)
|
||||
{
|
||||
Genode::String<256> file;
|
||||
try {
|
||||
config.attribute("file").value(&file);
|
||||
} catch (...) {
|
||||
Genode::error("mandatory file attribute missing");
|
||||
throw Could_not_open_file();
|
||||
}
|
||||
|
||||
try {
|
||||
Genode::Number_of_bytes bytes;
|
||||
config.attribute("block_size").value(&bytes);
|
||||
_block_size = bytes;
|
||||
} catch (...) {
|
||||
Genode::warning("block size missing, assuming 512b");
|
||||
}
|
||||
|
||||
bool const writeable = xml_attr_ok(config, "writeable");
|
||||
|
||||
struct stat st;
|
||||
if (stat(file.string(), &st)) {
|
||||
perror("stat");
|
||||
throw Could_not_open_file();
|
||||
}
|
||||
|
||||
_block_count = st.st_size / _block_size;
|
||||
|
||||
/* open file */
|
||||
_fd = open(file.string(), writeable ? O_RDWR : O_RDONLY);
|
||||
if (_fd == -1) {
|
||||
perror("open");
|
||||
throw Could_not_open_file();
|
||||
}
|
||||
|
||||
_block_ops.set_operation(Block::Packet_descriptor::READ);
|
||||
if (writeable) {
|
||||
_block_ops.set_operation(Block::Packet_descriptor::WRITE);
|
||||
}
|
||||
|
||||
Genode::log("Provide '", file.string(), "' as block device "
|
||||
"block_size: ", _block_size, " block_count: ",
|
||||
_block_count, " writeable: ", writeable ? "yes" : "no");
|
||||
}
|
||||
|
||||
~Lx_block_driver() { close(_fd); }
|
||||
|
||||
|
||||
/*****************************
|
||||
** Block::Driver interface **
|
||||
*****************************/
|
||||
|
||||
Genode::size_t block_size() override { return _block_size; }
|
||||
Block::sector_t block_count() override { return _block_count; }
|
||||
Block::Session::Operations ops() override { return _block_ops; }
|
||||
|
||||
void read(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char *buffer,
|
||||
Block::Packet_descriptor &packet) override
|
||||
{
|
||||
/* range check is done by Block::Driver */
|
||||
if (!_block_ops.supported(Block::Packet_descriptor::READ)) {
|
||||
throw Io_error();
|
||||
}
|
||||
|
||||
off_t const offset = block_number * _block_size;
|
||||
size_t const count = block_count * _block_size;
|
||||
|
||||
ssize_t const n = pread(_fd, buffer, count, offset);
|
||||
if (n == -1) {
|
||||
perror("pread");
|
||||
throw Io_error();
|
||||
}
|
||||
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
void write(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char const *buffer,
|
||||
Block::Packet_descriptor &packet) override
|
||||
{
|
||||
/* range check is done by Block::Driver */
|
||||
if (!_block_ops.supported(Block::Packet_descriptor::WRITE)) {
|
||||
throw Io_error();
|
||||
}
|
||||
|
||||
off_t const offset = block_number * _block_size;
|
||||
size_t const count = block_count * _block_size;
|
||||
|
||||
ssize_t const n = pwrite(_fd, buffer, count, offset);
|
||||
if (n == -1) {
|
||||
perror("pwrite");
|
||||
throw Io_error();
|
||||
}
|
||||
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
void sync() { }
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Genode::Env &_env;
|
||||
Genode::Heap _heap { _env.ram(), _env.rm() };
|
||||
|
||||
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
|
||||
struct Factory : Block::Driver_factory
|
||||
{
|
||||
Genode::Constructible<Lx_block_driver> _driver;
|
||||
|
||||
Factory(Genode::Env &env, Genode::Xml_node config)
|
||||
{
|
||||
_driver.construct(env, config);
|
||||
}
|
||||
|
||||
~Factory() { _driver.destruct(); }
|
||||
|
||||
/***********************
|
||||
** Factory interface **
|
||||
***********************/
|
||||
|
||||
Block::Driver *create() { return &*_driver; }
|
||||
void destroy(Block::Driver *) { }
|
||||
} factory { _env, _config_rom.xml() };
|
||||
|
||||
Block::Root root { _env.ep(), _heap, _env.rm(), factory,
|
||||
xml_attr_ok(_config_rom.xml(), "writeable") };
|
||||
|
||||
Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
_env.parent().announce(_env.ep().manage(root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Main main(env); }
|
7
repos/os/src/server/lx_block/target.mk
Normal file
7
repos/os/src/server/lx_block/target.mk
Normal file
@ -0,0 +1,7 @@
|
||||
TARGET = lx_block
|
||||
REQUIRES = linux
|
||||
|
||||
SRC_CC = main.cc
|
||||
LIBS = lx_hybrid
|
||||
|
||||
INC_DIR += $(PRG_DIR) /usr/include
|
Loading…
Reference in New Issue
Block a user