mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
parent
d4879f04a6
commit
ef7c51548d
@ -14,8 +14,9 @@
|
||||
#ifndef _PART_BLK__COMPONENT_H_
|
||||
#define _PART_BLK__COMPONENT_H_
|
||||
|
||||
#include <os/session_policy.h>
|
||||
#include <base/exception.h>
|
||||
#include <base/component.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <root/component.h>
|
||||
#include <block_session/rpc_object.h>
|
||||
|
||||
@ -39,12 +40,13 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
Ram_dataspace_capability _rq_ds;
|
||||
addr_t _rq_phys;
|
||||
Partition *_partition;
|
||||
Signal_dispatcher<Session_component> _sink_ack;
|
||||
Signal_dispatcher<Session_component> _sink_submit;
|
||||
Signal_handler<Session_component> _sink_ack;
|
||||
Signal_handler<Session_component> _sink_submit;
|
||||
bool _req_queue_full;
|
||||
bool _ack_queue_full;
|
||||
Packet_descriptor _p_to_handle;
|
||||
unsigned _p_in_fly;
|
||||
Block::Driver &_driver;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (!tx_sink()->ready_to_ack())
|
||||
PERR("Not ready to ack!");
|
||||
error("Not ready to ack!");
|
||||
|
||||
tx_sink()->acknowledge_packet(packet);
|
||||
_p_in_fly--;
|
||||
@ -83,7 +85,7 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
size_t cnt = _p_to_handle.block_count();
|
||||
void* addr = tx_sink()->packet_content(_p_to_handle);
|
||||
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) {
|
||||
_req_queue_full = true;
|
||||
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
|
||||
*/
|
||||
void _packet_avail(unsigned)
|
||||
void _packet_avail()
|
||||
{
|
||||
_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
|
||||
*/
|
||||
void _ready_to_ack(unsigned) { _packet_avail(0); }
|
||||
void _ready_to_ack() { _packet_avail(); }
|
||||
|
||||
public:
|
||||
|
||||
@ -120,17 +122,18 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
*/
|
||||
Session_component(Ram_dataspace_capability rq_ds,
|
||||
Partition *partition,
|
||||
Rpc_entrypoint &ep,
|
||||
Signal_receiver &receiver)
|
||||
: Session_rpc_object(rq_ds, ep),
|
||||
Genode::Entrypoint &ep,
|
||||
Block::Driver &driver)
|
||||
: Session_rpc_object(rq_ds, ep.rpc_ep()),
|
||||
_rq_ds(rq_ds),
|
||||
_rq_phys(Dataspace_client(_rq_ds).phys_addr()),
|
||||
_partition(partition),
|
||||
_sink_ack(receiver, *this, &Session_component::_ready_to_ack),
|
||||
_sink_submit(receiver, *this, &Session_component::_packet_avail),
|
||||
_sink_ack(ep, *this, &Session_component::_ready_to_ack),
|
||||
_sink_submit(ep, *this, &Session_component::_packet_avail),
|
||||
_req_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_packet_avail(_sink_submit);
|
||||
@ -142,16 +145,16 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
{
|
||||
if (request.operation() == Block::Packet_descriptor::READ) {
|
||||
void *src =
|
||||
Driver::driver().session().tx()->packet_content(reply);
|
||||
_driver.session().tx()->packet_content(reply);
|
||||
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);
|
||||
}
|
||||
request.succeeded(reply.succeeded());
|
||||
_ack_packet(request);
|
||||
|
||||
if (_ack_queue_full)
|
||||
_packet_avail(0);
|
||||
_packet_avail();
|
||||
}
|
||||
|
||||
static List<Session_component>& wait_queue()
|
||||
@ -167,7 +170,7 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
wait_queue().remove(c);
|
||||
c->_req_queue_full = false;
|
||||
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)
|
||||
{
|
||||
*blk_count = _partition->sectors;
|
||||
*blk_size = Driver::driver().blk_size();
|
||||
*ops = Driver::driver().ops();
|
||||
*blk_size = _driver.blk_size();
|
||||
*ops = _driver.ops();
|
||||
}
|
||||
|
||||
void sync() { Driver::driver().session().sync(); }
|
||||
void sync() { _driver.session().sync(); }
|
||||
};
|
||||
|
||||
|
||||
@ -195,8 +198,8 @@ class Block::Root :
|
||||
{
|
||||
private:
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
Signal_receiver &_receiver;
|
||||
Genode::Env &_env;
|
||||
Block::Driver &_driver;
|
||||
Block::Partition_table &_table;
|
||||
|
||||
protected:
|
||||
@ -217,15 +220,17 @@ class Block::Root :
|
||||
policy.attribute("partition").value(&num);
|
||||
|
||||
} 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();
|
||||
} 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();
|
||||
}
|
||||
|
||||
if (!_table.partition(num)) {
|
||||
PERR("Partition %ld unavailable for '%s'", num, label_str);
|
||||
error("Partition ", num, " unavailable for '", label_str, "'");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
@ -250,32 +255,27 @@ class Block::Root :
|
||||
* to handle a possible overflow of the sum of both sizes.
|
||||
*/
|
||||
if (tx_buf_size > ram_quota - session_size) {
|
||||
PERR("insufficient 'ram_quota', got %zd, need %zd",
|
||||
ram_quota, tx_buf_size + session_size);
|
||||
error("insufficient 'ram_quota', got ", ram_quota, ", need ",
|
||||
tx_buf_size + session_size);
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
|
||||
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(ds_cap,
|
||||
_table.partition(num),
|
||||
_ep, _receiver);
|
||||
Session_component(ds_cap, _table.partition(num),
|
||||
_env.ep(), _driver);
|
||||
|
||||
PLOG("session opened at partition %ld for '%s'", num, label_str);
|
||||
log("session opened at partition ", num, " for '", label_str, "'");
|
||||
return session;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
|
||||
Signal_receiver &receiver, Block::Partition_table& table)
|
||||
:
|
||||
Root_component(session_ep, md_alloc),
|
||||
_ep(*session_ep),
|
||||
_receiver(receiver),
|
||||
_table(table)
|
||||
{ }
|
||||
Root(Genode::Env &env, Genode::Heap &heap,
|
||||
Block::Driver &driver, Block::Partition_table &table)
|
||||
: Root_component(env.ep(), heap), _env(env),
|
||||
_driver(driver), _table(table) { }
|
||||
};
|
||||
|
||||
#endif /* _PART_BLK__COMPONENT_H_ */
|
||||
|
@ -81,13 +81,13 @@ class Block::Driver
|
||||
Block::Connection _session;
|
||||
Block::sector_t _blk_cnt;
|
||||
Genode::size_t _blk_size;
|
||||
Genode::Signal_dispatcher<Driver> _source_ack;
|
||||
Genode::Signal_dispatcher<Driver> _source_submit;
|
||||
Genode::Signal_handler<Driver> _source_ack;
|
||||
Genode::Signal_handler<Driver> _source_submit;
|
||||
Block::Session::Operations _ops;
|
||||
|
||||
void _ready_to_submit(unsigned);
|
||||
void _ready_to_submit();
|
||||
|
||||
void _ack_avail(unsigned)
|
||||
void _ack_avail()
|
||||
{
|
||||
/* check for acknowledgements */
|
||||
while (_session.tx()->ack_avail()) {
|
||||
@ -102,17 +102,17 @@ class Block::Driver
|
||||
_session.tx()->release_packet(p);
|
||||
}
|
||||
|
||||
_ready_to_submit(0);
|
||||
_ready_to_submit();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Driver(Genode::Signal_receiver &receiver)
|
||||
: _r_slab(Genode::env()->heap()),
|
||||
_block_alloc(Genode::env()->heap()),
|
||||
Driver(Genode::Entrypoint &ep, Genode::Heap &heap)
|
||||
: _r_slab(&heap),
|
||||
_block_alloc(&heap),
|
||||
_session(&_block_alloc, 4 * 1024 * 1024),
|
||||
_source_ack(receiver, *this, &Driver::_ack_avail),
|
||||
_source_submit(receiver, *this, &Driver::_ready_to_submit)
|
||||
_source_ack(ep, *this, &Driver::_ack_avail),
|
||||
_source_submit(ep, *this, &Driver::_ready_to_submit)
|
||||
{
|
||||
_session.info(&_blk_cnt, &_blk_size, &_ops);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#define _PART_BLK__GPT_H_
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/log.h>
|
||||
#include <block_session/client.h>
|
||||
|
||||
#include "driver.h"
|
||||
@ -24,7 +24,6 @@
|
||||
namespace {
|
||||
|
||||
static bool const verbose = false;
|
||||
#define PLOGV(...) do { if (verbose) PLOG(__VA_ARGS__); } while (0)
|
||||
|
||||
/* simple bitwise CRC32 checking */
|
||||
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)
|
||||
{
|
||||
PLOGV("GPT %s header:", check_primary ? "primary" : "backup");
|
||||
PLOGV(" rev: %u", _revision);
|
||||
PLOGV(" size: %u", _hdr_size);
|
||||
PLOGV(" crc: %x", _hdr_crc);
|
||||
PLOGV(" reserved: %u", _reserved);
|
||||
PLOGV(" hdr lba: %llu", _hdr_lba);
|
||||
PLOGV(" bak lba: %llu", _backup_hdr_lba);
|
||||
PLOGV(" part start lba: %llu", _part_lba_start);
|
||||
PLOGV(" part end lba: %llu", _part_lba_end);
|
||||
PLOGV(" guid: %s", _guid.to_string());
|
||||
PLOGV(" gpe lba: %llu", _gpe_lba);
|
||||
PLOGV(" entries: %u", _entries);
|
||||
PLOGV(" entry size: %u", _entry_size);
|
||||
PLOGV(" gpe crc: %x", _gpe_crc);
|
||||
if (!verbose) return;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
log("GPT ", check_primary ? "primary" : "backup", " header:");
|
||||
log(" rev: ", (unsigned) _revision);
|
||||
log(" size: ", (unsigned) _hdr_size);
|
||||
log(" crc: ", Hex(_hdr_crc, Hex::OMIT_PREFIX));
|
||||
log(" reserved: ", (unsigned) _reserved);
|
||||
log(" hdr lba: ", (unsigned long long) _hdr_lba);
|
||||
log(" bak lba: ", (unsigned long long) _backup_hdr_lba);
|
||||
log(" part start lba: ", (unsigned long long) _part_lba_start);
|
||||
log(" part end lba: ", (unsigned long long) _part_lba_end);
|
||||
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);
|
||||
|
||||
@ -138,7 +141,7 @@ class Gpt : public Block::Partition_table
|
||||
Genode::uint32_t crc = _hdr_crc;
|
||||
_hdr_crc = 0;
|
||||
if (crc32(this, _hdr_size) != crc) {
|
||||
PERR("Wrong GPT header checksum");
|
||||
Genode::error("Wrong GPT header checksum");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -149,15 +152,15 @@ class Gpt : public Block::Partition_table
|
||||
|
||||
/* check GPT entry array */
|
||||
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)
|
||||
return false;
|
||||
|
||||
if (check_primary) {
|
||||
/* check backup gpt header */
|
||||
Sector backup_hdr(_backup_hdr_lba, 1);
|
||||
if (!backup_hdr.addr<Gpt_hdr*>()->valid(false)) {
|
||||
PWRN("Backup GPT header is corrupted");
|
||||
Sector backup_hdr(driver, _backup_hdr_lba, 1);
|
||||
if (!backup_hdr.addr<Gpt_hdr*>()->valid(driver, false)) {
|
||||
Genode::warning("Backup GPT header is corrupted");
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,11 +229,11 @@ class Gpt : public Block::Partition_table
|
||||
*/
|
||||
void _parse_gpt(Gpt_hdr *gpt)
|
||||
{
|
||||
if (!(gpt->valid()))
|
||||
if (!(gpt->valid(driver)))
|
||||
throw Genode::Exception();
|
||||
|
||||
Sector entry_array(gpt->_gpe_lba,
|
||||
gpt->_entries * gpt->_entry_size / Block::Driver::driver().blk_size());
|
||||
Sector entry_array(driver, gpt->_gpe_lba,
|
||||
gpt->_entries * gpt->_entry_size / driver.blk_size());
|
||||
Gpt_entry *entries = entry_array.addr<Gpt_entry *>();
|
||||
|
||||
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 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'",
|
||||
i + 1, start, length, e->_type.to_string(), e->name());
|
||||
Genode::log("Partition ", i + 1, ": LBA ", start, " (", length,
|
||||
" 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:
|
||||
|
||||
using Partition_table::Partition_table;
|
||||
|
||||
Block::Partition *partition(int num) {
|
||||
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++)
|
||||
if (_part_list[num])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static Gpt& table()
|
||||
{
|
||||
static Gpt table;
|
||||
return table;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _PART_BLK__GUID_PARTITION_TABLE_H_ */
|
||||
|
@ -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
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
#include <block_session/rpc_object.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <os/config.h>
|
||||
|
||||
#include "component.h"
|
||||
#include "driver.h"
|
||||
#include "gpt.h"
|
||||
#include "mbr.h"
|
||||
|
||||
static Genode::Signal_receiver receiver;
|
||||
|
||||
Block::Driver& Block::Driver::driver()
|
||||
{
|
||||
static Block::Driver driver(receiver);
|
||||
return driver;
|
||||
}
|
||||
|
||||
|
||||
void Block::Driver::_ready_to_submit(unsigned) {
|
||||
void Block::Driver::_ready_to_submit() {
|
||||
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_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)
|
||||
try { valid_gpt = Gpt::table().avail(); } catch (...) { }
|
||||
try { valid_gpt = _gpt.parse(); } catch (...) { }
|
||||
|
||||
/* fall back to MBR */
|
||||
if (!valid_gpt) {
|
||||
try { valid_mbr = Mbr_partition_table::table().avail(); }
|
||||
try { valid_mbr = _mbr.parse(); }
|
||||
catch (Mbr_partition_table::Protective_mbr_found) {
|
||||
if (!use_gpt)
|
||||
PERR("Aborting: found protective MBR but GPT usage was not requested.");
|
||||
return 1;
|
||||
Genode::error("Aborting: found protective MBR but ",
|
||||
"GPT usage was not requested.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Block::Partition_table *partition_table = 0;
|
||||
if (valid_gpt)
|
||||
partition_table = &Gpt::table();
|
||||
if (valid_mbr)
|
||||
partition_table = &Mbr_partition_table::table();
|
||||
if (valid_gpt) return _gpt;
|
||||
if (valid_mbr) return _mbr;
|
||||
|
||||
if (!partition_table) {
|
||||
PERR("Aborting: no partition table found.");
|
||||
return 1;
|
||||
Genode::error("Aborting: no partition table found.");
|
||||
throw No_partion_table();
|
||||
}
|
||||
|
||||
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));
|
||||
Genode::size_t Component::stack_size() {
|
||||
return 2048*sizeof(Genode::addr_t); }
|
||||
|
||||
while (true) {
|
||||
Signal s = receiver.wait_for_signal();
|
||||
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Component::construct(Genode::Env &env) {
|
||||
static Main main(env); }
|
||||
|
@ -17,10 +17,9 @@
|
||||
#define _PART_BLK__MBR_H_
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/log.h>
|
||||
#include <block_session/client.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "partition_table.h"
|
||||
|
||||
|
||||
@ -83,7 +82,7 @@ struct Mbr_partition_table : public Block::Partition_table
|
||||
/* first logical partition number */
|
||||
int nr = 5;
|
||||
do {
|
||||
Sector s(lba, 1);
|
||||
Sector s(driver, lba, 1);
|
||||
Mbr *ebr = s.addr<Mbr *>();
|
||||
|
||||
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_record *logical = &(ebr->_records[0]);
|
||||
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);
|
||||
|
||||
PINF("Partition %d: LBA %u (%u blocks) type %x", nr - 1,
|
||||
logical->_lba + lba, logical->_sectors, logical->_type);
|
||||
Genode::log("Partition ", nr - 1, ": LBA ", logical->_lba + lba,
|
||||
" (", (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 */
|
||||
if (!(mbr->valid()))
|
||||
_part_list[0] = new(Genode::env()->heap())
|
||||
Block::Partition(0, Block::Driver::driver().blk_cnt() - 1);
|
||||
_part_list[0] = new (&heap)
|
||||
Block::Partition(0, driver.blk_cnt() - 1);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Partition_record *r = &(mbr->_records[i]);
|
||||
@ -123,8 +123,10 @@ struct Mbr_partition_table : public Block::Partition_table
|
||||
if (!r->valid())
|
||||
continue;
|
||||
|
||||
PINF("Partition %d: LBA %u (%u blocks) type: %x",
|
||||
i + 1, r->_lba, r->_sectors, r->_type);
|
||||
Genode::log("Partition ", i + 1, ": LBA ",
|
||||
(unsigned int) r->_lba, " (",
|
||||
(unsigned int) r->_sectors, " blocks) type: ",
|
||||
Genode::Hex(r->_type, Genode::Hex::OMIT_PREFIX));
|
||||
|
||||
if (r->protective())
|
||||
throw Protective_mbr_found();
|
||||
@ -134,41 +136,27 @@ struct Mbr_partition_table : public Block::Partition_table
|
||||
continue;
|
||||
}
|
||||
|
||||
_part_list[i + 1] = new(Genode::env()->heap())
|
||||
_part_list[i + 1] = new (&heap)
|
||||
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:
|
||||
|
||||
using Partition_table::Partition_table;
|
||||
|
||||
Block::Partition *partition(int num) {
|
||||
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++)
|
||||
if (_part_list[num])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static Mbr_partition_table& table()
|
||||
{
|
||||
static Mbr_partition_table table;
|
||||
return table;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _PART_BLK__MBR_H_ */
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define _PART_BLK__PARTITION_TABLE_H_
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/log.h>
|
||||
#include <block_session/client.h>
|
||||
|
||||
#include "driver.h"
|
||||
@ -48,18 +48,20 @@ struct Block::Partition_table
|
||||
|
||||
public:
|
||||
|
||||
Sector(unsigned long blk_nr,
|
||||
Sector(Driver &driver,
|
||||
unsigned long blk_nr,
|
||||
unsigned long count,
|
||||
bool write = false)
|
||||
: _session(Driver::driver().session()),
|
||||
_p(_session.dma_alloc_packet(Driver::driver().blk_size() * count),
|
||||
: _session(driver.session()),
|
||||
_p(_session.dma_alloc_packet(driver.blk_size() * count),
|
||||
write ? Packet_descriptor::WRITE : Packet_descriptor::READ,
|
||||
blk_nr, count)
|
||||
{
|
||||
_session.tx()->submit_packet(_p);
|
||||
_p = _session.tx()->get_acked_packet();
|
||||
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); }
|
||||
@ -68,9 +70,15 @@ struct Block::Partition_table
|
||||
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 bool avail() = 0;
|
||||
virtual bool parse() = 0;
|
||||
};
|
||||
|
||||
#endif /* _PART_BLK__PARTITION_TABLE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user