part_blk: transition to the new base API

Ref #1987
Ref #2051
This commit is contained in:
Stefan Kalkowski
2016-08-03 10:35:32 +02:00
committed by Christian Helmuth
parent d4879f04a6
commit ef7c51548d
6 changed files with 192 additions and 197 deletions

View File

@ -14,8 +14,9 @@
#ifndef _PART_BLK__COMPONENT_H_ #ifndef _PART_BLK__COMPONENT_H_
#define _PART_BLK__COMPONENT_H_ #define _PART_BLK__COMPONENT_H_
#include <os/session_policy.h>
#include <base/exception.h> #include <base/exception.h>
#include <base/component.h>
#include <os/session_policy.h>
#include <root/component.h> #include <root/component.h>
#include <block_session/rpc_object.h> #include <block_session/rpc_object.h>
@ -36,15 +37,16 @@ class Block::Session_component : public Block::Session_rpc_object,
{ {
private: private:
Ram_dataspace_capability _rq_ds; Ram_dataspace_capability _rq_ds;
addr_t _rq_phys; addr_t _rq_phys;
Partition *_partition; Partition *_partition;
Signal_dispatcher<Session_component> _sink_ack; Signal_handler<Session_component> _sink_ack;
Signal_dispatcher<Session_component> _sink_submit; Signal_handler<Session_component> _sink_submit;
bool _req_queue_full; bool _req_queue_full;
bool _ack_queue_full; bool _ack_queue_full;
Packet_descriptor _p_to_handle; Packet_descriptor _p_to_handle;
unsigned _p_in_fly; unsigned _p_in_fly;
Block::Driver &_driver;
/** /**
* Acknowledge a packet already handled * Acknowledge a packet already handled
@ -52,7 +54,7 @@ class Block::Session_component : public Block::Session_rpc_object,
inline void _ack_packet(Packet_descriptor &packet) inline void _ack_packet(Packet_descriptor &packet)
{ {
if (!tx_sink()->ready_to_ack()) if (!tx_sink()->ready_to_ack())
PERR("Not ready to ack!"); error("Not ready to ack!");
tx_sink()->acknowledge_packet(packet); tx_sink()->acknowledge_packet(packet);
_p_in_fly--; _p_in_fly--;
@ -83,7 +85,7 @@ class Block::Session_component : public Block::Session_rpc_object,
size_t cnt = _p_to_handle.block_count(); size_t cnt = _p_to_handle.block_count();
void* addr = tx_sink()->packet_content(_p_to_handle); void* addr = tx_sink()->packet_content(_p_to_handle);
try { try {
Driver::driver().io(write, off, cnt, addr, *this, _p_to_handle); _driver.io(write, off, cnt, addr, *this, _p_to_handle);
} catch (Block::Session::Tx::Source::Packet_alloc_failed) { } catch (Block::Session::Tx::Source::Packet_alloc_failed) {
_req_queue_full = true; _req_queue_full = true;
Session_component::wait_queue().insert(this); Session_component::wait_queue().insert(this);
@ -93,7 +95,7 @@ class Block::Session_component : public Block::Session_rpc_object,
/** /**
* Triggered when a packet was placed into the empty submit queue * Triggered when a packet was placed into the empty submit queue
*/ */
void _packet_avail(unsigned) void _packet_avail()
{ {
_ack_queue_full = _p_in_fly >= tx_sink()->ack_slots_free(); _ack_queue_full = _p_in_fly >= tx_sink()->ack_slots_free();
@ -111,7 +113,7 @@ class Block::Session_component : public Block::Session_rpc_object,
/** /**
* Triggered when an ack got removed from the full ack queue * Triggered when an ack got removed from the full ack queue
*/ */
void _ready_to_ack(unsigned) { _packet_avail(0); } void _ready_to_ack() { _packet_avail(); }
public: public:
@ -120,17 +122,18 @@ class Block::Session_component : public Block::Session_rpc_object,
*/ */
Session_component(Ram_dataspace_capability rq_ds, Session_component(Ram_dataspace_capability rq_ds,
Partition *partition, Partition *partition,
Rpc_entrypoint &ep, Genode::Entrypoint &ep,
Signal_receiver &receiver) Block::Driver &driver)
: Session_rpc_object(rq_ds, ep), : Session_rpc_object(rq_ds, ep.rpc_ep()),
_rq_ds(rq_ds), _rq_ds(rq_ds),
_rq_phys(Dataspace_client(_rq_ds).phys_addr()), _rq_phys(Dataspace_client(_rq_ds).phys_addr()),
_partition(partition), _partition(partition),
_sink_ack(receiver, *this, &Session_component::_ready_to_ack), _sink_ack(ep, *this, &Session_component::_ready_to_ack),
_sink_submit(receiver, *this, &Session_component::_packet_avail), _sink_submit(ep, *this, &Session_component::_packet_avail),
_req_queue_full(false), _req_queue_full(false),
_ack_queue_full(false), _ack_queue_full(false),
_p_in_fly(0) _p_in_fly(0),
_driver(driver)
{ {
_tx.sigh_ready_to_ack(_sink_ack); _tx.sigh_ready_to_ack(_sink_ack);
_tx.sigh_packet_avail(_sink_submit); _tx.sigh_packet_avail(_sink_submit);
@ -142,16 +145,16 @@ class Block::Session_component : public Block::Session_rpc_object,
{ {
if (request.operation() == Block::Packet_descriptor::READ) { if (request.operation() == Block::Packet_descriptor::READ) {
void *src = void *src =
Driver::driver().session().tx()->packet_content(reply); _driver.session().tx()->packet_content(reply);
Genode::size_t sz = Genode::size_t sz =
request.block_count() * Driver::driver().blk_size(); request.block_count() * _driver.blk_size();
Genode::memcpy(tx_sink()->packet_content(request), src, sz); Genode::memcpy(tx_sink()->packet_content(request), src, sz);
} }
request.succeeded(reply.succeeded()); request.succeeded(reply.succeeded());
_ack_packet(request); _ack_packet(request);
if (_ack_queue_full) if (_ack_queue_full)
_packet_avail(0); _packet_avail();
} }
static List<Session_component>& wait_queue() static List<Session_component>& wait_queue()
@ -167,7 +170,7 @@ class Block::Session_component : public Block::Session_rpc_object,
wait_queue().remove(c); wait_queue().remove(c);
c->_req_queue_full = false; c->_req_queue_full = false;
c->_handle_packet(c->_p_to_handle); c->_handle_packet(c->_p_to_handle);
c->_packet_avail(0); c->_packet_avail();
} }
} }
@ -179,11 +182,11 @@ class Block::Session_component : public Block::Session_rpc_object,
Operations *ops) Operations *ops)
{ {
*blk_count = _partition->sectors; *blk_count = _partition->sectors;
*blk_size = Driver::driver().blk_size(); *blk_size = _driver.blk_size();
*ops = Driver::driver().ops(); *ops = _driver.ops();
} }
void sync() { Driver::driver().session().sync(); } void sync() { _driver.session().sync(); }
}; };
@ -195,8 +198,8 @@ class Block::Root :
{ {
private: private:
Rpc_entrypoint &_ep; Genode::Env &_env;
Signal_receiver &_receiver; Block::Driver &_driver;
Block::Partition_table &_table; Block::Partition_table &_table;
protected: protected:
@ -217,15 +220,17 @@ class Block::Root :
policy.attribute("partition").value(&num); policy.attribute("partition").value(&num);
} catch (Xml_node::Nonexistent_attribute) { } catch (Xml_node::Nonexistent_attribute) {
PERR("policy does not define partition number for for '%s'", label_str); error("policy does not define partition number for for '",
label_str, "'");
throw Root::Unavailable(); throw Root::Unavailable();
} catch (Session_policy::No_policy_defined) { } catch (Session_policy::No_policy_defined) {
PERR("rejecting session request, no matching policy for '%s'", label_str); error("rejecting session request, no matching policy for '",
label_str, "'");
throw Root::Unavailable(); throw Root::Unavailable();
} }
if (!_table.partition(num)) { if (!_table.partition(num)) {
PERR("Partition %ld unavailable for '%s'", num, label_str); error("Partition ", num, " unavailable for '", label_str, "'");
throw Root::Unavailable(); throw Root::Unavailable();
} }
@ -250,32 +255,27 @@ class Block::Root :
* to handle a possible overflow of the sum of both sizes. * to handle a possible overflow of the sum of both sizes.
*/ */
if (tx_buf_size > ram_quota - session_size) { if (tx_buf_size > ram_quota - session_size) {
PERR("insufficient 'ram_quota', got %zd, need %zd", error("insufficient 'ram_quota', got ", ram_quota, ", need ",
ram_quota, tx_buf_size + session_size); tx_buf_size + session_size);
throw Root::Quota_exceeded(); throw Root::Quota_exceeded();
} }
Ram_dataspace_capability ds_cap; Ram_dataspace_capability ds_cap;
ds_cap = Genode::env()->ram_session()->alloc(tx_buf_size); ds_cap = _env.ram().alloc(tx_buf_size);
Session_component *session = new (md_alloc()) Session_component *session = new (md_alloc())
Session_component(ds_cap, Session_component(ds_cap, _table.partition(num),
_table.partition(num), _env.ep(), _driver);
_ep, _receiver);
PLOG("session opened at partition %ld for '%s'", num, label_str); log("session opened at partition ", num, " for '", label_str, "'");
return session; return session;
} }
public: public:
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc, Root(Genode::Env &env, Genode::Heap &heap,
Signal_receiver &receiver, Block::Partition_table& table) Block::Driver &driver, Block::Partition_table &table)
: : Root_component(env.ep(), heap), _env(env),
Root_component(session_ep, md_alloc), _driver(driver), _table(table) { }
_ep(*session_ep),
_receiver(receiver),
_table(table)
{ }
}; };
#endif /* _PART_BLK__COMPONENT_H_ */ #endif /* _PART_BLK__COMPONENT_H_ */

View File

@ -75,19 +75,19 @@ class Block::Driver
enum { BLK_SZ = Session::TX_QUEUE_SIZE*sizeof(Request) }; enum { BLK_SZ = Session::TX_QUEUE_SIZE*sizeof(Request) };
Genode::Tslab<Request, BLK_SZ> _r_slab; Genode::Tslab<Request, BLK_SZ> _r_slab;
Genode::List<Request> _r_list; Genode::List<Request> _r_list;
Genode::Allocator_avl _block_alloc; Genode::Allocator_avl _block_alloc;
Block::Connection _session; Block::Connection _session;
Block::sector_t _blk_cnt; Block::sector_t _blk_cnt;
Genode::size_t _blk_size; Genode::size_t _blk_size;
Genode::Signal_dispatcher<Driver> _source_ack; Genode::Signal_handler<Driver> _source_ack;
Genode::Signal_dispatcher<Driver> _source_submit; Genode::Signal_handler<Driver> _source_submit;
Block::Session::Operations _ops; Block::Session::Operations _ops;
void _ready_to_submit(unsigned); void _ready_to_submit();
void _ack_avail(unsigned) void _ack_avail()
{ {
/* check for acknowledgements */ /* check for acknowledgements */
while (_session.tx()->ack_avail()) { while (_session.tx()->ack_avail()) {
@ -102,17 +102,17 @@ class Block::Driver
_session.tx()->release_packet(p); _session.tx()->release_packet(p);
} }
_ready_to_submit(0); _ready_to_submit();
} }
public: public:
Driver(Genode::Signal_receiver &receiver) Driver(Genode::Entrypoint &ep, Genode::Heap &heap)
: _r_slab(Genode::env()->heap()), : _r_slab(&heap),
_block_alloc(Genode::env()->heap()), _block_alloc(&heap),
_session(&_block_alloc, 4 * 1024 * 1024), _session(&_block_alloc, 4 * 1024 * 1024),
_source_ack(receiver, *this, &Driver::_ack_avail), _source_ack(ep, *this, &Driver::_ack_avail),
_source_submit(receiver, *this, &Driver::_ready_to_submit) _source_submit(ep, *this, &Driver::_ready_to_submit)
{ {
_session.info(&_blk_cnt, &_blk_size, &_ops); _session.info(&_blk_cnt, &_blk_size, &_ops);
} }

View File

@ -15,7 +15,7 @@
#define _PART_BLK__GPT_H_ #define _PART_BLK__GPT_H_
#include <base/env.h> #include <base/env.h>
#include <base/printf.h> #include <base/log.h>
#include <block_session/client.h> #include <block_session/client.h>
#include "driver.h" #include "driver.h"
@ -24,7 +24,6 @@
namespace { namespace {
static bool const verbose = false; static bool const verbose = false;
#define PLOGV(...) do { if (verbose) PLOG(__VA_ARGS__); } while (0)
/* simple bitwise CRC32 checking */ /* simple bitwise CRC32 checking */
static inline Genode::uint32_t crc32(void const * const buf, Genode::size_t size) static inline Genode::uint32_t crc32(void const * const buf, Genode::size_t size)
@ -110,23 +109,27 @@ class Gpt : public Block::Partition_table
void dump_hdr(bool check_primary) void dump_hdr(bool check_primary)
{ {
PLOGV("GPT %s header:", check_primary ? "primary" : "backup"); if (!verbose) return;
PLOGV(" rev: %u", _revision);
PLOGV(" size: %u", _hdr_size); using namespace Genode;
PLOGV(" crc: %x", _hdr_crc);
PLOGV(" reserved: %u", _reserved); log("GPT ", check_primary ? "primary" : "backup", " header:");
PLOGV(" hdr lba: %llu", _hdr_lba); log(" rev: ", (unsigned) _revision);
PLOGV(" bak lba: %llu", _backup_hdr_lba); log(" size: ", (unsigned) _hdr_size);
PLOGV(" part start lba: %llu", _part_lba_start); log(" crc: ", Hex(_hdr_crc, Hex::OMIT_PREFIX));
PLOGV(" part end lba: %llu", _part_lba_end); log(" reserved: ", (unsigned) _reserved);
PLOGV(" guid: %s", _guid.to_string()); log(" hdr lba: ", (unsigned long long) _hdr_lba);
PLOGV(" gpe lba: %llu", _gpe_lba); log(" bak lba: ", (unsigned long long) _backup_hdr_lba);
PLOGV(" entries: %u", _entries); log(" part start lba: ", (unsigned long long) _part_lba_start);
PLOGV(" entry size: %u", _entry_size); log(" part end lba: ", (unsigned long long) _part_lba_end);
PLOGV(" gpe crc: %x", _gpe_crc); log(" guid: ", _guid.to_string());
log(" gpe lba: ", (unsigned long long) _gpe_lba);
log(" entries: ", (unsigned) _entries);
log(" entry size: ", (unsigned) _entry_size);
log(" gpe crc: ", Hex(_gpe_crc, Hex::OMIT_PREFIX));
} }
bool valid(bool check_primary = true) bool valid(Block::Driver &driver, bool check_primary = true)
{ {
dump_hdr(check_primary); dump_hdr(check_primary);
@ -138,7 +141,7 @@ class Gpt : public Block::Partition_table
Genode::uint32_t crc = _hdr_crc; Genode::uint32_t crc = _hdr_crc;
_hdr_crc = 0; _hdr_crc = 0;
if (crc32(this, _hdr_size) != crc) { if (crc32(this, _hdr_size) != crc) {
PERR("Wrong GPT header checksum"); Genode::error("Wrong GPT header checksum");
return false; return false;
} }
@ -149,15 +152,15 @@ class Gpt : public Block::Partition_table
/* check GPT entry array */ /* check GPT entry array */
Genode::size_t length = _entries * _entry_size; Genode::size_t length = _entries * _entry_size;
Sector gpe(_gpe_lba, length / Block::Driver::driver().blk_size()); Sector gpe(driver, _gpe_lba, length / driver.blk_size());
if (crc32(gpe.addr<void *>(), length) != _gpe_crc) if (crc32(gpe.addr<void *>(), length) != _gpe_crc)
return false; return false;
if (check_primary) { if (check_primary) {
/* check backup gpt header */ /* check backup gpt header */
Sector backup_hdr(_backup_hdr_lba, 1); Sector backup_hdr(driver, _backup_hdr_lba, 1);
if (!backup_hdr.addr<Gpt_hdr*>()->valid(false)) { if (!backup_hdr.addr<Gpt_hdr*>()->valid(driver, false)) {
PWRN("Backup GPT header is corrupted"); Genode::warning("Backup GPT header is corrupted");
} }
} }
@ -226,11 +229,11 @@ class Gpt : public Block::Partition_table
*/ */
void _parse_gpt(Gpt_hdr *gpt) void _parse_gpt(Gpt_hdr *gpt)
{ {
if (!(gpt->valid())) if (!(gpt->valid(driver)))
throw Genode::Exception(); throw Genode::Exception();
Sector entry_array(gpt->_gpe_lba, Sector entry_array(driver, gpt->_gpe_lba,
gpt->_entries * gpt->_entry_size / Block::Driver::driver().blk_size()); gpt->_entries * gpt->_entry_size / driver.blk_size());
Gpt_entry *entries = entry_array.addr<Gpt_entry *>(); Gpt_entry *entries = entry_array.addr<Gpt_entry *>();
for (int i = 0; i < MAX_PARTITIONS; i++) { for (int i = 0; i < MAX_PARTITIONS; i++) {
@ -242,43 +245,31 @@ class Gpt : public Block::Partition_table
Genode::uint64_t start = e->_lba_start; Genode::uint64_t start = e->_lba_start;
Genode::uint64_t length = e->_lba_end - e->_lba_start + 1; /* [...) */ Genode::uint64_t length = e->_lba_end - e->_lba_start + 1; /* [...) */
_part_list[i] = new (Genode::env()->heap()) Block::Partition(start, length); _part_list[i] = new (&heap) Block::Partition(start, length);
PINF("Partition %d: LBA %llu (%llu blocks) type: '%s' name: '%s'", Genode::log("Partition ", i + 1, ": LBA ", start, " (", length,
i + 1, start, length, e->_type.to_string(), e->name()); " blocks) type: '", e->_type.to_string(),
"' name: '", e->name(), "'");
} }
} }
Gpt()
{
Sector s(Gpt_hdr::HEADER_LBA, 1);
_parse_gpt(s.addr<Gpt_hdr *>());
/*
* we read all partition information,
* now it's safe to turn in asynchronous mode
*/
Block::Driver::driver().work_asynchronously();
}
public: public:
using Partition_table::Partition_table;
Block::Partition *partition(int num) { Block::Partition *partition(int num) {
return (num <= MAX_PARTITIONS && num > 0) ? _part_list[num-1] : 0; } return (num <= MAX_PARTITIONS && num > 0) ? _part_list[num-1] : 0; }
bool avail() bool parse()
{ {
Sector s(driver, Gpt_hdr::HEADER_LBA, 1);
_parse_gpt(s.addr<Gpt_hdr *>());
for (unsigned num = 0; num < MAX_PARTITIONS; num++) for (unsigned num = 0; num < MAX_PARTITIONS; num++)
if (_part_list[num]) if (_part_list[num])
return true; return true;
return false; return false;
} }
static Gpt& table()
{
static Gpt table;
return table;
}
}; };
#endif /* _PART_BLK__GUID_PARTITION_TABLE_H_ */ #endif /* _PART_BLK__GUID_PARTITION_TABLE_H_ */

View File

@ -7,84 +7,92 @@
*/ */
/* /*
* Copyright (C) 2011-2014 Genode Labs GmbH * Copyright (C) 2011-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.
*/ */
#include <os/attached_rom_dataspace.h>
#include <block_session/rpc_object.h> #include <block_session/rpc_object.h>
#include <cap_session/connection.h>
#include <os/config.h>
#include "component.h" #include "component.h"
#include "driver.h" #include "driver.h"
#include "gpt.h" #include "gpt.h"
#include "mbr.h" #include "mbr.h"
static Genode::Signal_receiver receiver;
Block::Driver& Block::Driver::driver() void Block::Driver::_ready_to_submit() {
{
static Block::Driver driver(receiver);
return driver;
}
void Block::Driver::_ready_to_submit(unsigned) {
Block::Session_component::wake_up(); } Block::Session_component::wake_up(); }
static bool _use_gpt() class Main
{ {
return Genode::config()->xml_node().attribute_value("use_gpt", false); private:
}
Block::Partition_table & _table();
Genode::Env & _env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Block::Driver _driver { _env.ep(), _heap };
Mbr_partition_table _mbr { _heap, _driver };
Gpt _gpt { _heap, _driver };
Block::Root _root { _env, _heap, _driver, _table() };
public:
class No_partion_table : Genode::Exception {};
Main(Genode::Env &env) : _env(env)
{
/*
* we read all partition information,
* now it's safe to turn in asynchronous mode
*/
_driver.work_asynchronously();
/* announce at parent */
env.parent().announce(env.ep().manage(_root));
}
};
int main() Block::Partition_table & Main::_table()
{ {
using namespace Genode;
bool valid_mbr = false; bool valid_mbr = false;
bool valid_gpt = false; bool valid_gpt = false;
bool use_gpt = _use_gpt(); bool use_gpt = false;
try {
Genode::Attached_rom_dataspace config(_env, "config");
use_gpt = config.xml().attribute_value("use_gpt", false);
} catch(...) {}
if (use_gpt) if (use_gpt)
try { valid_gpt = Gpt::table().avail(); } catch (...) { } try { valid_gpt = _gpt.parse(); } catch (...) { }
/* fall back to MBR */ /* fall back to MBR */
if (!valid_gpt) { if (!valid_gpt) {
try { valid_mbr = Mbr_partition_table::table().avail(); } try { valid_mbr = _mbr.parse(); }
catch (Mbr_partition_table::Protective_mbr_found) { catch (Mbr_partition_table::Protective_mbr_found) {
if (!use_gpt) if (!use_gpt)
PERR("Aborting: found protective MBR but GPT usage was not requested."); Genode::error("Aborting: found protective MBR but ",
return 1; "GPT usage was not requested.");
throw;
} }
} }
Block::Partition_table *partition_table = 0; if (valid_gpt) return _gpt;
if (valid_gpt) if (valid_mbr) return _mbr;
partition_table = &Gpt::table();
if (valid_mbr)
partition_table = &Mbr_partition_table::table();
if (!partition_table) { Genode::error("Aborting: no partition table found.");
PERR("Aborting: no partition table found."); throw No_partion_table();
return 1;
}
enum { STACK_SIZE = 2048 * sizeof(Genode::size_t) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "part_ep");
static Block::Root block_root(&ep, env()->heap(), receiver,
*partition_table);
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
return 0;
} }
Genode::size_t Component::stack_size() {
return 2048*sizeof(Genode::addr_t); }
void Component::construct(Genode::Env &env) {
static Main main(env); }

View File

@ -17,10 +17,9 @@
#define _PART_BLK__MBR_H_ #define _PART_BLK__MBR_H_
#include <base/env.h> #include <base/env.h>
#include <base/printf.h> #include <base/log.h>
#include <block_session/client.h> #include <block_session/client.h>
#include "driver.h"
#include "partition_table.h" #include "partition_table.h"
@ -83,7 +82,7 @@ struct Mbr_partition_table : public Block::Partition_table
/* first logical partition number */ /* first logical partition number */
int nr = 5; int nr = 5;
do { do {
Sector s(lba, 1); Sector s(driver, lba, 1);
Mbr *ebr = s.addr<Mbr *>(); Mbr *ebr = s.addr<Mbr *>();
if (!(ebr->valid())) if (!(ebr->valid()))
@ -93,11 +92,12 @@ struct Mbr_partition_table : public Block::Partition_table
* partition is relative to the lba of the current EBR */ * partition is relative to the lba of the current EBR */
Partition_record *logical = &(ebr->_records[0]); Partition_record *logical = &(ebr->_records[0]);
if (logical->valid() && nr < MAX_PARTITIONS) { if (logical->valid() && nr < MAX_PARTITIONS) {
_part_list[nr++] = new (Genode::env()->heap()) _part_list[nr++] = new (&heap)
Block::Partition(logical->_lba + lba, logical->_sectors); Block::Partition(logical->_lba + lba, logical->_sectors);
PINF("Partition %d: LBA %u (%u blocks) type %x", nr - 1, Genode::log("Partition ", nr - 1, ": LBA ", logical->_lba + lba,
logical->_lba + lba, logical->_sectors, logical->_type); " (", (unsigned int)logical->_sectors, " blocks) type ",
Genode::Hex(logical->_type, Genode::Hex::OMIT_PREFIX));
} }
/* /*
@ -114,8 +114,8 @@ struct Mbr_partition_table : public Block::Partition_table
{ {
/* no partition table, use whole disc as partition 0 */ /* no partition table, use whole disc as partition 0 */
if (!(mbr->valid())) if (!(mbr->valid()))
_part_list[0] = new(Genode::env()->heap()) _part_list[0] = new (&heap)
Block::Partition(0, Block::Driver::driver().blk_cnt() - 1); Block::Partition(0, driver.blk_cnt() - 1);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
Partition_record *r = &(mbr->_records[i]); Partition_record *r = &(mbr->_records[i]);
@ -123,8 +123,10 @@ struct Mbr_partition_table : public Block::Partition_table
if (!r->valid()) if (!r->valid())
continue; continue;
PINF("Partition %d: LBA %u (%u blocks) type: %x", Genode::log("Partition ", i + 1, ": LBA ",
i + 1, r->_lba, r->_sectors, r->_type); (unsigned int) r->_lba, " (",
(unsigned int) r->_sectors, " blocks) type: ",
Genode::Hex(r->_type, Genode::Hex::OMIT_PREFIX));
if (r->protective()) if (r->protective())
throw Protective_mbr_found(); throw Protective_mbr_found();
@ -134,41 +136,27 @@ struct Mbr_partition_table : public Block::Partition_table
continue; continue;
} }
_part_list[i + 1] = new(Genode::env()->heap()) _part_list[i + 1] = new (&heap)
Block::Partition(r->_lba, r->_sectors); Block::Partition(r->_lba, r->_sectors);
} }
} }
Mbr_partition_table()
{
Sector s(0, 1);
_parse_mbr(s.addr<Mbr *>());
/*
* we read all partition information,
* now it's safe to turn in asynchronous mode
*/
Block::Driver::driver().work_asynchronously();
}
public: public:
using Partition_table::Partition_table;
Block::Partition *partition(int num) { Block::Partition *partition(int num) {
return (num < MAX_PARTITIONS) ? _part_list[num] : 0; } return (num < MAX_PARTITIONS) ? _part_list[num] : 0; }
bool avail() bool parse()
{ {
Sector s(driver, 0, 1);
_parse_mbr(s.addr<Mbr *>());
for (unsigned num = 0; num < MAX_PARTITIONS; num++) for (unsigned num = 0; num < MAX_PARTITIONS; num++)
if (_part_list[num]) if (_part_list[num])
return true; return true;
return false; return false;
} }
static Mbr_partition_table& table()
{
static Mbr_partition_table table;
return table;
}
}; };
#endif /* _PART_BLK__MBR_H_ */ #endif /* _PART_BLK__MBR_H_ */

View File

@ -16,7 +16,7 @@
#define _PART_BLK__PARTITION_TABLE_H_ #define _PART_BLK__PARTITION_TABLE_H_
#include <base/env.h> #include <base/env.h>
#include <base/printf.h> #include <base/log.h>
#include <block_session/client.h> #include <block_session/client.h>
#include "driver.h" #include "driver.h"
@ -43,23 +43,25 @@ struct Block::Partition_table
{ {
private: private:
Session_client &_session; Session_client &_session;
Packet_descriptor _p; Packet_descriptor _p;
public: public:
Sector(unsigned long blk_nr, Sector(Driver &driver,
unsigned long blk_nr,
unsigned long count, unsigned long count,
bool write = false) bool write = false)
: _session(Driver::driver().session()), : _session(driver.session()),
_p(_session.dma_alloc_packet(Driver::driver().blk_size() * count), _p(_session.dma_alloc_packet(driver.blk_size() * count),
write ? Packet_descriptor::WRITE : Packet_descriptor::READ, write ? Packet_descriptor::WRITE : Packet_descriptor::READ,
blk_nr, count) blk_nr, count)
{ {
_session.tx()->submit_packet(_p); _session.tx()->submit_packet(_p);
_p = _session.tx()->get_acked_packet(); _p = _session.tx()->get_acked_packet();
if (!_p.succeeded()) if (!_p.succeeded())
PERR("Could not access block %llu", _p.block_number()); Genode::error("Could not access block ",
(unsigned long long)_p.block_number());
} }
~Sector() { _session.tx()->release_packet(_p); } ~Sector() { _session.tx()->release_packet(_p); }
@ -68,9 +70,15 @@ struct Block::Partition_table
return reinterpret_cast<T>(_session.tx()->packet_content(_p)); } return reinterpret_cast<T>(_session.tx()->packet_content(_p)); }
}; };
Genode::Heap & heap;
Driver & driver;
Partition_table(Genode::Heap & h, Driver & d)
: heap(h), driver(d) {}
virtual Partition *partition(int num) = 0; virtual Partition *partition(int num) = 0;
virtual bool avail() = 0; virtual bool parse() = 0;
}; };
#endif /* _PART_BLK__PARTITION_TABLE_H_ */ #endif /* _PART_BLK__PARTITION_TABLE_H_ */