2014-09-20 22:12:26 +02:00
|
|
|
/*
|
|
|
|
* \brief MBR partition table definitions
|
|
|
|
* \author Sebastian Sumpf
|
|
|
|
* \author Stefan Kalkowski
|
|
|
|
* \author Josef Soentgen
|
|
|
|
* \date 2013-12-04
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2014-09-20 22:12:26 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2014-09-20 22:12:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _PART_BLK__MBR_H_
|
|
|
|
#define _PART_BLK__MBR_H_
|
|
|
|
|
|
|
|
#include <base/env.h>
|
2016-08-03 10:35:32 +02:00
|
|
|
#include <base/log.h>
|
2014-09-20 22:12:26 +02:00
|
|
|
#include <block_session/client.h>
|
|
|
|
|
|
|
|
#include "partition_table.h"
|
|
|
|
|
|
|
|
|
|
|
|
struct Mbr_partition_table : public Block::Partition_table
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
class Protective_mbr_found { };
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
typedef Block::Partition_table::Sector Sector;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Partition table entry format
|
|
|
|
*/
|
|
|
|
struct Partition_record
|
|
|
|
{
|
2017-05-13 23:16:12 +02:00
|
|
|
enum {
|
|
|
|
INVALID = 0,
|
|
|
|
EXTENTED_CHS = 0x5, EXTENTED_LBA = 0xf, PROTECTIVE = 0xee
|
|
|
|
};
|
2014-09-20 22:12:26 +02:00
|
|
|
Genode::uint8_t _unused[4];
|
|
|
|
Genode::uint8_t _type; /* partition type */
|
|
|
|
Genode::uint8_t _unused2[3];
|
|
|
|
Genode::uint32_t _lba; /* logical block address */
|
|
|
|
Genode::uint32_t _sectors; /* number of sectors */
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
bool valid() { return _type != INVALID; }
|
2017-05-18 11:12:11 +02:00
|
|
|
bool extended() { return _type == EXTENTED_CHS
|
2017-05-13 23:16:12 +02:00
|
|
|
|| _type == EXTENTED_LBA; }
|
2016-05-11 18:21:47 +02:00
|
|
|
bool protective() { return _type == PROTECTIVE; }
|
2014-09-20 22:12:26 +02:00
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Master/Extented boot record format
|
|
|
|
*/
|
|
|
|
struct Mbr
|
|
|
|
{
|
|
|
|
Genode::uint8_t _unused[446];
|
|
|
|
Partition_record _records[4];
|
|
|
|
Genode::uint16_t _magic;
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
bool valid()
|
2014-09-20 22:12:26 +02:00
|
|
|
{
|
|
|
|
/* magic number of partition table */
|
|
|
|
enum { MAGIC = 0xaa55 };
|
|
|
|
return _magic == MAGIC;
|
|
|
|
}
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
|
|
enum { MAX_PARTITIONS = 32 };
|
|
|
|
|
|
|
|
Block::Partition *_part_list[MAX_PARTITIONS]; /* contains pointers to valid
|
|
|
|
partitions or 0 */
|
|
|
|
|
2017-05-18 11:12:11 +02:00
|
|
|
template <typename FUNC>
|
|
|
|
void _parse_extended(Partition_record *record, FUNC const &f)
|
2014-09-20 22:12:26 +02:00
|
|
|
{
|
|
|
|
Partition_record *r = record;
|
|
|
|
unsigned lba = r->_lba;
|
|
|
|
|
|
|
|
/* first logical partition number */
|
|
|
|
int nr = 5;
|
|
|
|
do {
|
2016-08-03 10:35:32 +02:00
|
|
|
Sector s(driver, lba, 1);
|
2014-09-20 22:12:26 +02:00
|
|
|
Mbr *ebr = s.addr<Mbr *>();
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
if (!(ebr->valid()))
|
2014-09-20 22:12:26 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* The first record is the actual logical partition. The lba of this
|
|
|
|
* partition is relative to the lba of the current EBR */
|
|
|
|
Partition_record *logical = &(ebr->_records[0]);
|
2016-05-11 18:21:47 +02:00
|
|
|
if (logical->valid() && nr < MAX_PARTITIONS) {
|
2017-05-18 11:12:11 +02:00
|
|
|
f(nr++, logical, lba);
|
2014-09-20 22:12:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* the second record points to the next EBR
|
|
|
|
* (relative form this EBR)
|
|
|
|
*/
|
|
|
|
r = &(ebr->_records[1]);
|
|
|
|
lba += ebr->_records[1]._lba;
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
} while (r->valid());
|
2014-09-20 22:12:26 +02:00
|
|
|
}
|
|
|
|
|
2017-05-18 11:12:11 +02:00
|
|
|
template <typename FUNC>
|
|
|
|
void _parse_mbr(Mbr *mbr, FUNC const &f)
|
2014-09-20 22:12:26 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
Partition_record *r = &(mbr->_records[i]);
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
if (!r->valid())
|
2014-09-20 22:12:26 +02:00
|
|
|
continue;
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
if (r->protective())
|
2014-09-20 22:12:26 +02:00
|
|
|
throw Protective_mbr_found();
|
|
|
|
|
2017-05-18 11:12:11 +02:00
|
|
|
f(i + 1, r, 0);
|
2014-09-20 22:12:26 +02:00
|
|
|
|
2017-05-18 11:12:11 +02:00
|
|
|
if (r->extended()) {
|
|
|
|
_parse_extended(r, f);
|
|
|
|
}
|
2014-09-20 22:12:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2016-08-03 10:35:32 +02:00
|
|
|
using Partition_table::Partition_table;
|
|
|
|
|
2014-09-20 22:12:26 +02:00
|
|
|
Block::Partition *partition(int num) {
|
|
|
|
return (num < MAX_PARTITIONS) ? _part_list[num] : 0; }
|
|
|
|
|
2016-08-03 10:35:32 +02:00
|
|
|
bool parse()
|
2014-09-20 22:12:26 +02:00
|
|
|
{
|
2016-08-03 10:35:32 +02:00
|
|
|
Sector s(driver, 0, 1);
|
2017-05-18 11:12:11 +02:00
|
|
|
Mbr *mbr = s.addr<Mbr *>();
|
|
|
|
|
|
|
|
/* no partition table, use whole disc as partition 0 */
|
|
|
|
if (!(mbr->valid()))
|
|
|
|
_part_list[0] = new (&heap)
|
|
|
|
Block::Partition(0, driver.blk_cnt() - 1);
|
|
|
|
|
|
|
|
_parse_mbr(mbr, [&] (int i, Partition_record *r, unsigned offset) {
|
|
|
|
Genode::log("Partition ", i, ": LBA ",
|
|
|
|
(unsigned int) r->_lba + offset, " (",
|
|
|
|
(unsigned int) r->_sectors, " blocks) type: ",
|
|
|
|
Genode::Hex(r->_type, Genode::Hex::OMIT_PREFIX));
|
|
|
|
if (!r->extended())
|
|
|
|
_part_list[i] = new (&heap)
|
|
|
|
Block::Partition(r->_lba + offset, r->_sectors);
|
|
|
|
});
|
|
|
|
|
|
|
|
/* Report the partitions */
|
|
|
|
if (reporter.enabled())
|
|
|
|
{
|
|
|
|
Genode::Reporter::Xml_generator xml(reporter, [&] () {
|
|
|
|
xml.attribute("type", "mbr");
|
|
|
|
|
|
|
|
_parse_mbr(mbr, [&] (int i, Partition_record *r, unsigned offset) {
|
|
|
|
xml.node("partition", [&] {
|
|
|
|
xml.attribute("number", i);
|
|
|
|
xml.attribute("type", r->_type);
|
|
|
|
xml.attribute("start", r->_lba + offset);
|
|
|
|
xml.attribute("length", r->_sectors);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-09-20 22:12:26 +02:00
|
|
|
for (unsigned num = 0; num < MAX_PARTITIONS; num++)
|
|
|
|
if (_part_list[num])
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _PART_BLK__MBR_H_ */
|