mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-17 02:10:05 +00:00
170 lines
3.8 KiB
C++
170 lines
3.8 KiB
C++
/*
|
|
* \brief GPT utils
|
|
* \author Josef Soentgen
|
|
* \date 2018-05-01
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2018 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _UTIL_H_
|
|
#define _UTIL_H_
|
|
|
|
/* Genode includes */
|
|
#include <base/fixed_stdint.h>
|
|
#include <block_session/connection.h>
|
|
#include <util/misc_math.h>
|
|
#include <util/string.h>
|
|
|
|
|
|
namespace Util {
|
|
|
|
using namespace Genode;
|
|
|
|
void init_random(Genode::Allocator &);
|
|
void get_random(uint8_t *dest, size_t len);
|
|
|
|
using Label = Genode::String<128>;
|
|
|
|
using Size_string = Genode::String<64>;
|
|
uint64_t convert(Size_string const &);
|
|
|
|
using sector_t = Block::sector_t;
|
|
|
|
sector_t align_start(size_t, size_t, sector_t);
|
|
sector_t size_to_lba(size_t, uint64_t);
|
|
|
|
struct Block_io;
|
|
|
|
uint32_t crc32(void const * const, size_t);
|
|
size_t extract_ascii(char *, size_t, uint16_t const *, size_t);
|
|
size_t convert_ascii(uint16_t *, size_t, uint8_t const *, size_t);
|
|
|
|
/*
|
|
* Wrapper to get suffixed uint64_t values
|
|
*/
|
|
class Number_of_bytes
|
|
{
|
|
uint64_t _n;
|
|
|
|
public:
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
Number_of_bytes() : _n(0) { }
|
|
|
|
/**
|
|
* Constructor, to be used implicitly via assignment operator
|
|
*/
|
|
Number_of_bytes(Genode::uint64_t n) : _n(n) { }
|
|
|
|
/**
|
|
* Convert number of bytes to 'size_t' value
|
|
*/
|
|
operator Genode::uint64_t() const { return _n; }
|
|
|
|
void print(Output &output) const
|
|
{
|
|
using Genode::print;
|
|
|
|
enum { KB = 1024UL, MB = KB*1024UL, GB = MB*1024UL };
|
|
|
|
if (_n == 0) print(output, 0);
|
|
else if (_n % GB == 0) print(output, _n/GB, "G");
|
|
else if (_n % MB == 0) print(output, _n/MB, "M");
|
|
else if (_n % KB == 0) print(output, _n/KB, "K");
|
|
else print(output, _n);
|
|
}
|
|
};
|
|
|
|
inline size_t ascii_to(const char *s, Number_of_bytes &result)
|
|
{
|
|
unsigned long res = 0;
|
|
|
|
/* convert numeric part of string */
|
|
int i = ascii_to_unsigned(s, res, 0);
|
|
|
|
/* handle suffixes */
|
|
if (i > 0)
|
|
switch (s[i]) {
|
|
case 'G': res *= 1024; [[fallthrough]];
|
|
case 'M': res *= 1024; [[fallthrough]];
|
|
case 'K': res *= 1024; i++;
|
|
default: break;
|
|
}
|
|
|
|
result = res;
|
|
return i;
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
* Block_io wraps a Block::Connection for synchronous operations
|
|
*/
|
|
struct Util::Block_io
|
|
{
|
|
struct Io_error : Genode::Exception { };
|
|
|
|
using Packet_descriptor = Block::Packet_descriptor;
|
|
|
|
Block::Connection<> &_block;
|
|
Packet_descriptor _p;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* \param block reference to underlying Block::Connection
|
|
* \param block_size logical block size of the Block::Connection
|
|
* \param lba LBA to start access from
|
|
* \param count number of LBAs to access
|
|
* \param write set type of operation, write if true, read
|
|
* if false
|
|
*
|
|
* \throw Io_error
|
|
*/
|
|
Block_io(Block::Connection<> &block, size_t block_size,
|
|
sector_t lba, size_t count,
|
|
bool write = false, void const *data = nullptr, size_t len = 0)
|
|
:
|
|
_block(block),
|
|
_p(_block.tx()->alloc_packet(block_size * count),
|
|
write ? Packet_descriptor::WRITE
|
|
: Packet_descriptor::READ, lba, count)
|
|
{
|
|
if (write) {
|
|
if (data && len) {
|
|
void *p = addr<void*>();
|
|
Genode::memcpy(p, data, len);
|
|
} else {
|
|
Genode::error("invalid data for write");
|
|
throw Io_error();
|
|
}
|
|
}
|
|
|
|
_block.tx()->submit_packet(_p);
|
|
_p = _block.tx()->get_acked_packet();
|
|
if (!_p.succeeded()) {
|
|
Genode::error("could not ", write ? "write" : "read",
|
|
" block-range [", _p.block_number(), ",",
|
|
_p.block_number() + count, ")");
|
|
_block.tx()->release_packet(_p);
|
|
throw Io_error();
|
|
}
|
|
}
|
|
|
|
~Block_io() { _block.tx()->release_packet(_p); }
|
|
|
|
template <typename T> T addr()
|
|
{
|
|
return reinterpret_cast<T>(_block.tx()->packet_content(_p));
|
|
}
|
|
};
|
|
|
|
#endif /* _UTIL_H_ */
|