The beginning of partitioning support:
* Added functionality to convert a PartitionMap to a string and vice versa. * get_partitioning_parameters() implemented, but not tested. * The code also needed by the GUI add-on now lives in separate files. * Some cleanup. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2591 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
59ec2bb9e7
commit
066d69dad4
@ -4,7 +4,7 @@
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file intel.cpp
|
||||
disk_scanner partition module for "intel" style partitions
|
||||
\brief disk_scanner partition module for "intel" style partitions.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@ -17,6 +17,9 @@
|
||||
#include <KernelExport.h>
|
||||
#include <disk_scanner/partition.h>
|
||||
|
||||
#include "intel_parameters.h"
|
||||
#include "intel_partition_map.h"
|
||||
|
||||
#define TRACE(x) ;
|
||||
//#define TRACE(x) dprintf x
|
||||
|
||||
@ -28,556 +31,6 @@ static const char *const kShortModuleName = "intel";
|
||||
// Maximal number of logical partitions per extended partition we allow.
|
||||
static const int32 kMaxLogicalPartitionCount = 128;
|
||||
|
||||
struct partition_type {
|
||||
uint8 type;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct partition_type gPartitionTypes[] = {
|
||||
// these entries must be sorted by type (currently not)
|
||||
{ 0x00, "empty" },
|
||||
{ 0x01, "FAT 12-bit" },
|
||||
{ 0x02, "Xenix root" },
|
||||
{ 0x03, "Xenix user" },
|
||||
{ 0x04, "FAT 16-bit (dos 3.0)" },
|
||||
{ 0x05, "Extended Partition" },
|
||||
{ 0x06, "FAT 16-bit (dos 3.31)" },
|
||||
{ 0x07, "OS/2 IFS, Windows NT, Advanced Unix" },
|
||||
{ 0x0b, "FAT 32-bit" },
|
||||
{ 0x0c, "FAT 32-bit, LBA-mapped" },
|
||||
{ 0x0d, "FAT 16-bit, LBA-mapped" },
|
||||
{ 0x0f, "Extended Partition, LBA-mapped" },
|
||||
{ 0x42, "Windows 2000 marker (switches to a proprietary partition table)" },
|
||||
{ 0x4d, "QNX 4" },
|
||||
{ 0x4e, "QNX 4 2nd part" },
|
||||
{ 0x4f, "QNX 4 3rd part" },
|
||||
{ 0x78, "XOSL boot loader" },
|
||||
{ 0x82, "Linux swapfile" },
|
||||
{ 0x83, "Linux native" },
|
||||
{ 0x85, "Linux extendend partition" },
|
||||
{ 0xa5, "FreeBSD" },
|
||||
{ 0xa6, "OpenBSD" },
|
||||
{ 0xa7, "NextSTEP" },
|
||||
{ 0xa8, "MacOS X" },
|
||||
{ 0xa9, "NetBSD" },
|
||||
{ 0xab, "MacOS X boot" },
|
||||
{ 0xbe, "Solaris 8 boot" },
|
||||
{ 0xeb, "BeOS" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
// is_empty_type
|
||||
static inline
|
||||
bool
|
||||
is_empty_type(uint8 type)
|
||||
{
|
||||
return (type == 0x00);
|
||||
}
|
||||
|
||||
// is_extended_type
|
||||
static inline
|
||||
bool
|
||||
is_extended_type(uint8 type)
|
||||
{
|
||||
return (type == 0x05 || type == 0x0f || type == 0x85);
|
||||
}
|
||||
|
||||
// chs
|
||||
struct chs {
|
||||
uint8 cylinder;
|
||||
uint16 head_sector; // head[15:10], sector[9:0]
|
||||
} _PACKED;
|
||||
|
||||
// partition_descriptor
|
||||
struct partition_descriptor {
|
||||
uint8 active;
|
||||
chs begin;
|
||||
uint8 type;
|
||||
chs end;
|
||||
uint32 start;
|
||||
uint32 size;
|
||||
|
||||
bool is_empty() const { return is_empty_type(type); }
|
||||
bool is_extended() const { return is_extended_type(type); }
|
||||
} _PACKED;
|
||||
|
||||
// partition_table_sector
|
||||
struct partition_table_sector {
|
||||
char pad1[446];
|
||||
partition_descriptor table[4];
|
||||
uint16 signature;
|
||||
} _PACKED;
|
||||
|
||||
static const uint16 kPartitionTableSectorSignature = 0xaa55;
|
||||
|
||||
// partition_type_string
|
||||
static
|
||||
const char *
|
||||
partition_type_string(uint8 type)
|
||||
{
|
||||
int32 i;
|
||||
for (i = 0; gPartitionTypes[i].name ; i++)
|
||||
{
|
||||
if (type == gPartitionTypes[i].type)
|
||||
return gPartitionTypes[i].name;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
// Partition
|
||||
class Partition {
|
||||
public:
|
||||
Partition();
|
||||
Partition(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize);
|
||||
|
||||
void SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize);
|
||||
void Unset();
|
||||
|
||||
bool IsEmpty() const { return is_empty_type(fType); }
|
||||
bool IsExtended() const { return is_extended_type(fType); }
|
||||
|
||||
off_t PTSOffset() const { return fPTSOffset; }
|
||||
off_t Offset() const { return fOffset; }
|
||||
off_t Size() const { return fSize; }
|
||||
uint8 Type() const { return fType; }
|
||||
const char *TypeString() const { return partition_type_string(fType); }
|
||||
|
||||
bool CheckLocation(off_t sessionSize) const;
|
||||
|
||||
private:
|
||||
off_t fPTSOffset;
|
||||
off_t fOffset; // relative to the start of the session
|
||||
off_t fSize;
|
||||
uint8 fType;
|
||||
};
|
||||
|
||||
// constructor
|
||||
Partition::Partition()
|
||||
: fPTSOffset(0),
|
||||
fOffset(0),
|
||||
fSize(0),
|
||||
fType(0)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
Partition::Partition(const partition_descriptor *descriptor,off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize)
|
||||
: fPTSOffset(0),
|
||||
fOffset(0),
|
||||
fSize(0),
|
||||
fType(0)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, baseOffset, blockSize);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
Partition::SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize)
|
||||
{
|
||||
fPTSOffset = ptsOffset;
|
||||
fOffset = baseOffset + (off_t)descriptor->start * blockSize;
|
||||
fSize = (off_t)descriptor->size * blockSize;
|
||||
fType = descriptor->type;
|
||||
if (fSize == 0)
|
||||
Unset();
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
Partition::Unset()
|
||||
{
|
||||
fPTSOffset = 0;
|
||||
fOffset = 0;
|
||||
fSize = 0;
|
||||
fType = 0;
|
||||
}
|
||||
|
||||
// CheckLocation
|
||||
bool
|
||||
Partition::CheckLocation(off_t sessionSize) const
|
||||
{
|
||||
return (fOffset >= 0 && fOffset + fSize <= sessionSize);
|
||||
}
|
||||
|
||||
|
||||
class LogicalPartition;
|
||||
|
||||
// PrimaryPartition
|
||||
|
||||
class PrimaryPartition : public Partition {
|
||||
public:
|
||||
PrimaryPartition();
|
||||
PrimaryPartition(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize);
|
||||
|
||||
void SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize);
|
||||
void Unset();
|
||||
|
||||
// only if extended
|
||||
int32 CountLogicalPartitions() const { return fLogicalPartitionCount; }
|
||||
LogicalPartition *LogicalPartitionAt(int32 index) const;
|
||||
void AddLogicalPartition(LogicalPartition *partition);
|
||||
|
||||
private:
|
||||
LogicalPartition *fHead;
|
||||
LogicalPartition *fTail;
|
||||
int32 fLogicalPartitionCount;
|
||||
};
|
||||
|
||||
|
||||
// LogicalPartition
|
||||
class LogicalPartition : public Partition {
|
||||
public:
|
||||
LogicalPartition();
|
||||
LogicalPartition(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize, PrimaryPartition *primary);
|
||||
|
||||
void SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize, PrimaryPartition *primary);
|
||||
void Unset();
|
||||
|
||||
PrimaryPartition *GetPrimaryPartition() const { return fPrimary; }
|
||||
|
||||
void SetNext(LogicalPartition *next) { fNext = next; }
|
||||
LogicalPartition *Next() const { return fNext; }
|
||||
|
||||
private:
|
||||
PrimaryPartition *fPrimary;
|
||||
LogicalPartition *fNext;
|
||||
};
|
||||
|
||||
|
||||
// PrimaryPartition
|
||||
|
||||
// constructor
|
||||
PrimaryPartition::PrimaryPartition()
|
||||
: Partition(),
|
||||
fHead(NULL),
|
||||
fTail(NULL),
|
||||
fLogicalPartitionCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
PrimaryPartition::PrimaryPartition(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize)
|
||||
: Partition(),
|
||||
fHead(NULL),
|
||||
fTail(NULL),
|
||||
fLogicalPartitionCount(0)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, blockSize);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
PrimaryPartition::SetTo(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize)
|
||||
{
|
||||
Unset();
|
||||
Partition::SetTo(descriptor, ptsOffset, 0, blockSize);
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
PrimaryPartition::Unset()
|
||||
{
|
||||
while (LogicalPartition *partition = fHead) {
|
||||
fHead = partition->Next();
|
||||
delete partition;
|
||||
}
|
||||
fHead = NULL;
|
||||
fTail = NULL;
|
||||
fLogicalPartitionCount = 0;
|
||||
Partition::Unset();
|
||||
}
|
||||
|
||||
// LogicalPartitionAt
|
||||
LogicalPartition *
|
||||
PrimaryPartition::LogicalPartitionAt(int32 index) const
|
||||
{
|
||||
LogicalPartition *partition = NULL;
|
||||
if (index >= 0 && index < fLogicalPartitionCount) {
|
||||
for (partition = fHead; index > 0; index--)
|
||||
partition = partition->Next();
|
||||
}
|
||||
return partition;
|
||||
}
|
||||
|
||||
// AddLogicalPartition
|
||||
void
|
||||
PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
||||
{
|
||||
if (partition) {
|
||||
if (fTail) {
|
||||
fTail->SetNext(partition);
|
||||
fTail = partition;
|
||||
} else
|
||||
fHead = fTail = partition;
|
||||
partition->SetNext(NULL);
|
||||
fLogicalPartitionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// LogicalPartition
|
||||
|
||||
// constructor
|
||||
LogicalPartition::LogicalPartition()
|
||||
: Partition(),
|
||||
fPrimary(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
LogicalPartition::LogicalPartition(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize,
|
||||
PrimaryPartition *primary)
|
||||
: Partition(),
|
||||
fPrimary(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, blockSize, primary);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
LogicalPartition::SetTo(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize,
|
||||
PrimaryPartition *primary)
|
||||
{
|
||||
Unset();
|
||||
if (descriptor && primary) {
|
||||
off_t baseOffset = (descriptor->is_extended() ? primary->Offset()
|
||||
: ptsOffset);
|
||||
Partition::SetTo(descriptor, ptsOffset, baseOffset, blockSize);
|
||||
fPrimary = primary;
|
||||
}
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
LogicalPartition::Unset()
|
||||
{
|
||||
fPrimary = NULL;
|
||||
fNext = NULL;
|
||||
Partition::Unset();
|
||||
}
|
||||
|
||||
|
||||
// PartitionMap
|
||||
|
||||
class PartitionMap {
|
||||
public:
|
||||
PartitionMap();
|
||||
~PartitionMap();
|
||||
|
||||
void Unset();
|
||||
|
||||
PrimaryPartition *PrimaryPartitionAt(int32 index);
|
||||
|
||||
int32 CountPartitions() const;
|
||||
Partition *PartitionAt(int32 index);
|
||||
const Partition *PartitionAt(int32 index) const;
|
||||
|
||||
bool Check() const;
|
||||
|
||||
private:
|
||||
PrimaryPartition fPrimaries[4];
|
||||
};
|
||||
|
||||
// constructor
|
||||
PartitionMap::PartitionMap()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
PartitionMap::~PartitionMap()
|
||||
{
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
PartitionMap::Unset()
|
||||
{
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
fPrimaries[i].Unset();
|
||||
}
|
||||
|
||||
// PrimaryPartitionAt
|
||||
PrimaryPartition *
|
||||
PartitionMap::PrimaryPartitionAt(int32 index)
|
||||
{
|
||||
PrimaryPartition *partition = NULL;
|
||||
if (index >= 0 && index < 4)
|
||||
partition = fPrimaries + index;
|
||||
return partition;
|
||||
}
|
||||
|
||||
// CountPartitions
|
||||
int32
|
||||
PartitionMap::CountPartitions() const
|
||||
{
|
||||
int32 count = 4;
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
count += fPrimaries[i].CountLogicalPartitions();
|
||||
return count;
|
||||
}
|
||||
|
||||
// PartitionAt
|
||||
Partition *
|
||||
PartitionMap::PartitionAt(int32 index)
|
||||
{
|
||||
Partition *partition = NULL;
|
||||
int32 count = CountPartitions();
|
||||
if (index >= 0 && index < count) {
|
||||
if (index < 4)
|
||||
partition = fPrimaries + index;
|
||||
else {
|
||||
index -= 4;
|
||||
int32 primary = 0;
|
||||
while (index >= fPrimaries[primary].CountLogicalPartitions()) {
|
||||
index -= fPrimaries[primary].CountLogicalPartitions();
|
||||
primary++;
|
||||
}
|
||||
partition = fPrimaries[primary].LogicalPartitionAt(index);
|
||||
}
|
||||
}
|
||||
return partition;
|
||||
}
|
||||
|
||||
// PartitionAt
|
||||
const Partition *
|
||||
PartitionMap::PartitionAt(int32 index) const
|
||||
{
|
||||
return const_cast<PartitionMap*>(this)->PartitionAt(index);
|
||||
}
|
||||
|
||||
// cmp_partition_offset
|
||||
static
|
||||
int
|
||||
cmp_partition_offset(const void *p1, const void *p2)
|
||||
{
|
||||
const Partition *partition1 = *static_cast<const Partition **>(p1);
|
||||
const Partition *partition2 = *static_cast<const Partition **>(p2);
|
||||
if (partition1->Offset() < partition2->Offset())
|
||||
return -1;
|
||||
else if (partition1->Offset() > partition2->Offset())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cmp_offset
|
||||
static
|
||||
int
|
||||
cmp_offset(const void *o1, const void *o2)
|
||||
{
|
||||
off_t offset1 = *static_cast<const off_t*>(o1);
|
||||
off_t offset2 = *static_cast<const off_t*>(o2);
|
||||
if (offset1 < offset2)
|
||||
return -1;
|
||||
else if (offset1 > offset2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// is_inside_partitions
|
||||
static
|
||||
bool
|
||||
is_inside_partitions(off_t location, const Partition **partitions, int32 count)
|
||||
{
|
||||
bool result = false;
|
||||
if (count > 0) {
|
||||
// binary search
|
||||
int32 lower = 0;
|
||||
int32 upper = count - 1;
|
||||
while (lower < upper) {
|
||||
int32 mid = (lower + upper) / 2;
|
||||
const Partition *midPartition = partitions[mid];
|
||||
if (location >= midPartition->Offset() + midPartition->Size())
|
||||
lower = mid + 1;
|
||||
else
|
||||
upper = mid;
|
||||
}
|
||||
const Partition *partition = partitions[lower];
|
||||
result = (location >= partition->Offset() &&
|
||||
location < partition->Offset() + partition->Size());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check
|
||||
bool
|
||||
PartitionMap::Check() const
|
||||
{
|
||||
bool result = true;
|
||||
int32 partitionCount = CountPartitions();
|
||||
const Partition **byOffset = new(nothrow) const Partition*[partitionCount];
|
||||
off_t *ptsOffsets = new(nothrow) off_t[partitionCount - 3];
|
||||
if (byOffset && ptsOffsets) {
|
||||
// fill the arrays
|
||||
int32 byOffsetCount = 0;
|
||||
int32 ptsOffsetCount = 1; // primary PTS
|
||||
ptsOffsets[0] = 0; //
|
||||
for (int32 i = 0; i < partitionCount; i++) {
|
||||
const Partition *partition = PartitionAt(i);
|
||||
if (!partition->IsExtended())
|
||||
byOffset[byOffsetCount++] = partition;
|
||||
// add only logical partition PTS locations
|
||||
if (i >= 4)
|
||||
ptsOffsets[ptsOffsetCount++] = partition->PTSOffset();
|
||||
}
|
||||
// sort the arrays
|
||||
qsort(byOffset, byOffsetCount, sizeof(const Partition*),
|
||||
cmp_partition_offset);
|
||||
qsort(ptsOffsets, ptsOffsetCount, sizeof(off_t), cmp_offset);
|
||||
// check for overlappings
|
||||
off_t nextOffset = 0;
|
||||
for (int32 i = 0; i < byOffsetCount; i++) {
|
||||
const Partition *partition = byOffset[i];
|
||||
if (partition->Offset() < nextOffset) {
|
||||
TRACE(("intel: PartitionMap::Check(): overlapping partitions!"
|
||||
"\n"));
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
nextOffset = partition->Offset() + partition->Size();
|
||||
}
|
||||
// check uniqueness of PTS offsets and whether they lie outside of the
|
||||
// non-extended partitions
|
||||
if (result) {
|
||||
for (int32 i = 0; i < ptsOffsetCount; i++) {
|
||||
if (i > 0 && ptsOffsets[i] == ptsOffsets[i - 1]) {
|
||||
TRACE(("intel: PartitionMap::Check(): same PTS for "
|
||||
"different extended partitions!\n"));
|
||||
result = false;
|
||||
break;
|
||||
} else if (is_inside_partitions(ptsOffsets[i], byOffset,
|
||||
byOffsetCount)) {
|
||||
TRACE(("intel: PartitionMap::Check(): a PTS lies "
|
||||
"inside a non-extended partition!\n"));
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
result = false; // no memory: assume failure
|
||||
// cleanup
|
||||
if (byOffset)
|
||||
delete[] byOffset;
|
||||
if (ptsOffsets)
|
||||
delete[] ptsOffsets;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// PartitionMapParser
|
||||
|
||||
@ -595,7 +48,7 @@ public:
|
||||
private:
|
||||
status_t _ParsePrimary(const partition_table_sector *pts);
|
||||
status_t _ParseExtended(PrimaryPartition *primary, off_t offset);
|
||||
status_t _ReadPTS(off_t offset);
|
||||
status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL);
|
||||
|
||||
private:
|
||||
int fDeviceFD;
|
||||
@ -631,10 +84,17 @@ PartitionMapParser::Parse(const uint8 *block, PartitionMap *map)
|
||||
if (error == B_OK) {
|
||||
fMap = map;
|
||||
fMap->Unset();
|
||||
const partition_table_sector *pts
|
||||
= (const partition_table_sector*)block;
|
||||
error = _ParsePrimary(pts);
|
||||
if (error == B_OK && !fMap->Check())
|
||||
if (block) {
|
||||
const partition_table_sector *pts
|
||||
= (const partition_table_sector*)block;
|
||||
error = _ParsePrimary(pts);
|
||||
} else {
|
||||
partition_table_sector pts;
|
||||
error = _ReadPTS(0, &pts);
|
||||
if (error == B_OK)
|
||||
error = _ParsePrimary(&pts);
|
||||
}
|
||||
if (error == B_OK && !fMap->Check(fSessionSize, fBlockSize))
|
||||
error = B_BAD_DATA;
|
||||
fMap = NULL;
|
||||
}
|
||||
@ -658,7 +118,7 @@ PartitionMapParser::_ParsePrimary(const partition_table_sector *pts)
|
||||
PrimaryPartition *partition = fMap->PrimaryPartitionAt(i);
|
||||
partition->SetTo(descriptor, 0, fBlockSize);
|
||||
// fail, if location is bad
|
||||
if (!partition->CheckLocation(fSessionSize)) {
|
||||
if (!partition->CheckLocation(fSessionSize, fBlockSize)) {
|
||||
error = B_BAD_DATA;
|
||||
break;
|
||||
}
|
||||
@ -738,8 +198,10 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
|
||||
}
|
||||
}
|
||||
// check the partition's location
|
||||
if (partition && !partition->CheckLocation(fSessionSize))
|
||||
if (partition && !partition->CheckLocation(fSessionSize,
|
||||
fBlockSize)) {
|
||||
error = B_BAD_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -763,16 +225,18 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
|
||||
|
||||
// _ReadPTS
|
||||
status_t
|
||||
PartitionMapParser::_ReadPTS(off_t offset)
|
||||
PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (!pts)
|
||||
pts = fPTS;
|
||||
int32 toRead = sizeof(partition_table_sector);
|
||||
// check the offset
|
||||
if (offset < 0 || offset + toRead > fSessionSize) {
|
||||
error = B_BAD_VALUE;
|
||||
TRACE(("intel: _ReadPTS(): bad offset: %Ld\n", offset));
|
||||
// read
|
||||
} else if (read_pos(fDeviceFD, fSessionOffset + offset, fPTS, toRead)
|
||||
} else if (read_pos(fDeviceFD, fSessionOffset + offset, pts, toRead)
|
||||
!= toRead) {
|
||||
error = errno;
|
||||
if (error == B_OK)
|
||||
@ -798,34 +262,43 @@ std_ops(int32 op, ...)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// read_partition_map
|
||||
static
|
||||
status_t
|
||||
read_partition_map(int deviceFD, const session_info *sessionInfo,
|
||||
const uchar *block, PartitionMap *map)
|
||||
{
|
||||
bool result = true;
|
||||
off_t sessionOffset = sessionInfo->offset;
|
||||
off_t sessionSize = sessionInfo->size;
|
||||
int32 blockSize = sessionInfo->logical_block_size;
|
||||
TRACE(("intel: read_partition_map(%d, %lld, %lld, %p, %ld)\n", deviceFD,
|
||||
sessionOffset, sessionSize, block, blockSize));
|
||||
// check block size
|
||||
if (result) {
|
||||
result = ((uint32)blockSize >= sizeof(partition_table_sector));
|
||||
if (!result) {
|
||||
TRACE(("intel: read_partition_map: bad block size: %ld, should be "
|
||||
">= %ld\n", blockSize, sizeof(partition_table_sector)));
|
||||
}
|
||||
}
|
||||
// read the partition structure
|
||||
if (result) {
|
||||
PartitionMapParser parser(deviceFD, sessionOffset, sessionSize,
|
||||
blockSize);
|
||||
result = (parser.Parse(block, map) == B_OK);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// intel_identify
|
||||
static
|
||||
bool
|
||||
intel_identify(int deviceFD, const session_info *sessionInfo,
|
||||
const uchar *block)
|
||||
{
|
||||
bool result = true;
|
||||
int32 blockSize = sessionInfo->logical_block_size;
|
||||
TRACE(("intel: identify(%d, %lld, %lld, %p, %ld)\n", deviceFD,
|
||||
sessionInfo->offset, sessionInfo->size, block, blockSize));
|
||||
// check block size
|
||||
if (result) {
|
||||
result = ((uint32)blockSize >= sizeof(partition_table_sector));
|
||||
if (!result) {
|
||||
TRACE(("intel: identify: bad block size: %ld, should be >= %ld\n",
|
||||
blockSize, sizeof(partition_table_sector)));
|
||||
}
|
||||
}
|
||||
// read the partition structure
|
||||
if (result) {
|
||||
PartitionMapParser parser(deviceFD, sessionInfo->offset,
|
||||
sessionInfo->size, blockSize);
|
||||
PartitionMap map;
|
||||
result = (parser.Parse(block, &map) == B_OK
|
||||
&& map.CountPartitions() > 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
PartitionMap map;
|
||||
return read_partition_map(deviceFD, sessionInfo, block, &map);
|
||||
}
|
||||
|
||||
// intel_get_nth_info
|
||||
@ -835,50 +308,38 @@ intel_get_nth_info(int deviceFD, const session_info *sessionInfo,
|
||||
const uchar *block, int32 index,
|
||||
extended_partition_info *partitionInfo)
|
||||
{
|
||||
status_t error = B_ENTRY_NOT_FOUND;
|
||||
status_t error = B_OK;
|
||||
off_t sessionOffset = sessionInfo->offset;
|
||||
off_t sessionSize = sessionInfo->size;
|
||||
int32 blockSize = sessionInfo->logical_block_size;
|
||||
TRACE(("intel: get_nth_info(%d, %lld, %lld, %p, %ld, %ld)\n", deviceFD,
|
||||
sessionOffset, sessionSize, block, blockSize, index));
|
||||
if (intel_identify(deviceFD, sessionInfo, block)) {
|
||||
if (index >= 0) {
|
||||
// parse the partition map
|
||||
PartitionMapParser parser(deviceFD, sessionOffset, sessionSize,
|
||||
blockSize);
|
||||
PartitionMap map;
|
||||
error = parser.Parse(block, &map);
|
||||
if (error == B_OK) {
|
||||
if (map.CountPartitions() == 0)
|
||||
error = B_BAD_DATA;
|
||||
sessionOffset, sessionInfo->size, block,
|
||||
sessionInfo->logical_block_size, index));
|
||||
PartitionMap map;
|
||||
if (read_partition_map(deviceFD, sessionInfo, block, &map)) {
|
||||
if (Partition *partition = map.PartitionAt(index)) {
|
||||
if (partition->IsEmpty()) {
|
||||
// empty partition
|
||||
partitionInfo->info.offset = sessionOffset;
|
||||
partitionInfo->info.size = 0;
|
||||
partitionInfo->flags
|
||||
= B_HIDDEN_PARTITION | B_EMPTY_PARTITION;
|
||||
} else {
|
||||
// non-empty partition
|
||||
partitionInfo->info.offset
|
||||
= partition->Offset() + sessionOffset;
|
||||
partitionInfo->info.size = partition->Size();
|
||||
if (partition->IsExtended())
|
||||
partitionInfo->flags = B_HIDDEN_PARTITION;
|
||||
else
|
||||
partitionInfo->flags = 0;
|
||||
}
|
||||
if (error == B_OK) {
|
||||
if (Partition *partition = map.PartitionAt(index)) {
|
||||
if (partition->IsEmpty()) {
|
||||
// empty partition
|
||||
partitionInfo->info.offset = sessionOffset;
|
||||
partitionInfo->info.size = 0;
|
||||
partitionInfo->flags
|
||||
= B_HIDDEN_PARTITION | B_EMPTY_PARTITION;
|
||||
} else {
|
||||
// non-empty partition
|
||||
partitionInfo->info.offset
|
||||
= partition->Offset() + sessionOffset;
|
||||
partitionInfo->info.size = partition->Size();
|
||||
if (partition->IsExtended())
|
||||
partitionInfo->flags = B_HIDDEN_PARTITION;
|
||||
else
|
||||
partitionInfo->flags = 0;
|
||||
}
|
||||
partitionInfo->partition_name[0] = '\0';
|
||||
strcpy(partitionInfo->partition_type,
|
||||
partition->TypeString());
|
||||
partitionInfo->partition_code = partition->Type();
|
||||
} else
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
partitionInfo->partition_name[0] = '\0';
|
||||
strcpy(partitionInfo->partition_type,
|
||||
partition->TypeString());
|
||||
partitionInfo->partition_code = partition->Type();
|
||||
} else
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
} else // couldn't read partition map -- we shouldn't be in get_nth_info()
|
||||
error = B_BAD_DATA;
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -890,8 +351,28 @@ intel_get_partitioning_params(int deviceFD,
|
||||
char *buffer, size_t bufferSize,
|
||||
size_t *actualSize)
|
||||
{
|
||||
// not yet supported
|
||||
return B_UNSUPPORTED;
|
||||
status_t error = B_OK;
|
||||
PartitionMap map;
|
||||
if (!read_partition_map(deviceFD, sessionInfo, NULL, &map)) {
|
||||
// couldn't read partition map, set up a default one:
|
||||
// four empty primary partitions
|
||||
map.Unset();
|
||||
}
|
||||
// get the parameter length
|
||||
size_t length = 0;
|
||||
if (error == B_OK) {
|
||||
ParameterUnparser unparser;
|
||||
error = unparser.GetParameterLength(&map, &length);
|
||||
}
|
||||
// write the parameters
|
||||
if (error == B_OK && length <= bufferSize) {
|
||||
ParameterUnparser unparser;
|
||||
error = unparser.Unparse(&map, buffer, bufferSize);
|
||||
}
|
||||
// set the results
|
||||
if (error == B_OK)
|
||||
*actualSize = length;
|
||||
return error;
|
||||
}
|
||||
|
||||
// intel_partition
|
||||
|
390
src/add-ons/kernel/disk_scanner/partition/intel_parameters.cpp
Normal file
390
src/add-ons/kernel/disk_scanner/partition/intel_parameters.cpp
Normal file
@ -0,0 +1,390 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file intel_parameters.cpp
|
||||
\brief Class implementations for "intel" style partitioning
|
||||
parameter support.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <new.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "intel_parameters.h"
|
||||
#include "intel_partition_map.h"
|
||||
|
||||
// Grammar for parameters:
|
||||
//
|
||||
// partition ::= "{" ptsoffset "," offset "," size "," type ","
|
||||
// active "}"
|
||||
// primary ::= "{" partition+ "}"
|
||||
// partition_map ::= primary primary primary primary
|
||||
|
||||
// longest token (including terminating null)
|
||||
const int32 kMaxTokenLen = 256;
|
||||
|
||||
|
||||
// Tokenizer
|
||||
|
||||
// constructor
|
||||
Tokenizer::Tokenizer()
|
||||
: fInput(NULL),
|
||||
fPosition(0),
|
||||
fLastPosition(0)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
Tokenizer::Tokenizer(const char *input)
|
||||
: fInput(input),
|
||||
fPosition(0),
|
||||
fLastPosition(0)
|
||||
{
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
Tokenizer::SetTo(const char *input)
|
||||
{
|
||||
fInput = input;
|
||||
fPosition = 0;
|
||||
fLastPosition = 0;
|
||||
}
|
||||
|
||||
// GetNextToken
|
||||
int32
|
||||
Tokenizer::GetNextToken(char *buffer)
|
||||
{
|
||||
int32 kind = TOKEN_ERROR;
|
||||
fLastPosition = fPosition;
|
||||
// skip WS
|
||||
_SkipWhiteSpace();
|
||||
switch (fInput[fPosition]) {
|
||||
case '{':
|
||||
case '}':
|
||||
case ',':
|
||||
kind = fInput[fPosition];
|
||||
fPosition++;
|
||||
break;
|
||||
case '\0':
|
||||
kind = TOKEN_EOF;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (isdigit(fInput[fPosition])) {
|
||||
int32 startPos = fPosition;
|
||||
while (isdigit(fInput[fPosition]))
|
||||
fPosition++;
|
||||
int32 len = fPosition - startPos;
|
||||
if (len < kMaxTokenLen) {
|
||||
if (buffer) {
|
||||
memcpy(buffer, fInput + startPos, len);
|
||||
buffer[len] = '\0';
|
||||
}
|
||||
kind = TOKEN_NUMBER;
|
||||
} else {
|
||||
printf("token too long at: %ld\n", startPos);
|
||||
kind = TOKEN_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return kind;
|
||||
}
|
||||
|
||||
// ExpectToken
|
||||
bool
|
||||
Tokenizer::ExpectToken(int32 kind, char *buffer)
|
||||
{
|
||||
bool result = (GetNextToken(buffer) == kind);
|
||||
if (!result)
|
||||
PutLastToken();
|
||||
return result;
|
||||
}
|
||||
|
||||
// ReadNumber
|
||||
bool
|
||||
Tokenizer::ReadNumber(int64 &number)
|
||||
{
|
||||
char buffer[kMaxTokenLen];
|
||||
bool result = ExpectToken(TOKEN_NUMBER, buffer);
|
||||
if (result)
|
||||
number = atoll(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
// _SkipWhiteSpace
|
||||
void
|
||||
Tokenizer::_SkipWhiteSpace()
|
||||
{
|
||||
while (fInput[fPosition] != '\0' && isspace(fInput[fPosition]))
|
||||
fPosition++;
|
||||
}
|
||||
|
||||
|
||||
// ParameterParser
|
||||
|
||||
// constructor
|
||||
ParameterParser::ParameterParser()
|
||||
: fTokenizer(),
|
||||
fParseError(B_OK),
|
||||
fMap(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// Parse
|
||||
status_t
|
||||
ParameterParser::Parse(const char *parameters, PartitionMap *map)
|
||||
{
|
||||
status_t error = (parameters && map ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
// init parser
|
||||
fParseError = B_OK;
|
||||
fTokenizer.SetTo(parameters);
|
||||
fMap = map;
|
||||
// partition_map ::= primary primary primary primary
|
||||
if (_ParsePrimaryPartition(fMap->PrimaryPartitionAt(0))
|
||||
&& _ParsePrimaryPartition(fMap->PrimaryPartitionAt(1))
|
||||
&& _ParsePrimaryPartition(fMap->PrimaryPartitionAt(2))
|
||||
&& _ParsePrimaryPartition(fMap->PrimaryPartitionAt(3))
|
||||
&& fTokenizer.ReadEOF()) {
|
||||
// successfully parsed
|
||||
} else
|
||||
_ErrorOccurred();
|
||||
// cleanup / set results
|
||||
fMap = NULL;
|
||||
error = fParseError;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _ParsePrimaryPartition
|
||||
bool
|
||||
ParameterParser::_ParsePrimaryPartition(PrimaryPartition *primary)
|
||||
{
|
||||
// primary ::= "{" partition+ "}"
|
||||
if (fTokenizer.ReadOpen()
|
||||
&& _ParsePartition(primary)) {
|
||||
while (_NoError() && !fTokenizer.ReadClose()) {
|
||||
LogicalPartition *partition = new(nothrow) LogicalPartition;
|
||||
if (partition) {
|
||||
if (_ParsePartition(partition))
|
||||
primary->AddLogicalPartition(partition);
|
||||
else
|
||||
delete partition;
|
||||
} else
|
||||
_ErrorOccurred(B_NO_MEMORY);
|
||||
}
|
||||
} else
|
||||
_ErrorOccurred();
|
||||
return _NoError();
|
||||
}
|
||||
|
||||
// _ParsePartition
|
||||
bool
|
||||
ParameterParser::_ParsePartition(Partition *partition)
|
||||
{
|
||||
// partition ::= "{" ptsoffset "," offset "," size "," type ","
|
||||
// active "}"
|
||||
int64 ptsOffset, offset, size, type, active;
|
||||
if (fTokenizer.ReadOpen()
|
||||
&& fTokenizer.ReadNumber(ptsOffset)
|
||||
&& fTokenizer.ReadComma()
|
||||
&& fTokenizer.ReadNumber(offset)
|
||||
&& fTokenizer.ReadComma()
|
||||
&& fTokenizer.ReadNumber(size)
|
||||
&& fTokenizer.ReadComma()
|
||||
&& fTokenizer.ReadNumber(type)
|
||||
&& fTokenizer.ReadComma()
|
||||
&& fTokenizer.ReadNumber(active)
|
||||
&& fTokenizer.ReadClose()) {
|
||||
if (ptsOffset >= 0 && offset >= 0 && size >= 0
|
||||
&& type >= 0 && type < 256) {
|
||||
partition->SetPTSOffset(ptsOffset);
|
||||
partition->SetOffset(offset);
|
||||
partition->SetSize(size);
|
||||
partition->SetType((uint8)type);
|
||||
partition->SetActive(active);
|
||||
} else
|
||||
_ErrorOccurred(B_BAD_VALUE);
|
||||
} else
|
||||
_ErrorOccurred();
|
||||
return _NoError();
|
||||
}
|
||||
|
||||
// _ErrorOccurred
|
||||
void
|
||||
ParameterParser::_ErrorOccurred(status_t error)
|
||||
{
|
||||
if (fParseError == B_OK)
|
||||
fParseError = error;
|
||||
}
|
||||
|
||||
|
||||
// ParameterUnparser
|
||||
|
||||
// constructor
|
||||
ParameterUnparser::ParameterUnparser()
|
||||
: fMap(NULL),
|
||||
fParameters(NULL),
|
||||
fPosition(0),
|
||||
fSize(0),
|
||||
fDryRun(false),
|
||||
fUnparseError(B_OK)
|
||||
{
|
||||
}
|
||||
|
||||
// GetParameterLength
|
||||
status_t
|
||||
ParameterUnparser::GetParameterLength(const PartitionMap *map, size_t *length)
|
||||
{
|
||||
status_t error = (map && length ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
// init unparser for a dry run
|
||||
fUnparseError = B_OK;
|
||||
fMap = map;
|
||||
char buffer[kMaxTokenLen];
|
||||
fParameters = buffer;
|
||||
fPosition = 0;
|
||||
fSize = 0;
|
||||
fDryRun = true;
|
||||
// dry run -- get the parameter size
|
||||
if (_UnparsePartitionMap())
|
||||
*length = fPosition + 1;
|
||||
// cleanup / set results
|
||||
fMap = NULL;
|
||||
error = fUnparseError;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Unparse
|
||||
status_t
|
||||
ParameterUnparser::Unparse(const PartitionMap *map, char *parameters,
|
||||
size_t size)
|
||||
{
|
||||
status_t error = (map && parameters ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
// init unparser
|
||||
fUnparseError = B_OK;
|
||||
fMap = map;
|
||||
fParameters = parameters;
|
||||
fPosition = 0;
|
||||
fSize = size;
|
||||
fDryRun = false;
|
||||
// unparse the partition map
|
||||
_UnparsePartitionMap();
|
||||
// cleanup / set results
|
||||
fMap = NULL;
|
||||
error = fUnparseError;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _UnparsePartitionMap
|
||||
bool
|
||||
ParameterUnparser::_UnparsePartitionMap()
|
||||
{
|
||||
if (_UnparsePrimaryPartition(fMap->PrimaryPartitionAt(0))
|
||||
&& _UnparsePrimaryPartition(fMap->PrimaryPartitionAt(1))
|
||||
&& _UnparsePrimaryPartition(fMap->PrimaryPartitionAt(2))
|
||||
&& _UnparsePrimaryPartition(fMap->PrimaryPartitionAt(3))) {
|
||||
// successfully unparsed
|
||||
}
|
||||
return _NoError();
|
||||
}
|
||||
|
||||
// _UnparsePrimaryPartition
|
||||
bool
|
||||
ParameterUnparser::_UnparsePrimaryPartition(const PrimaryPartition *primary)
|
||||
{
|
||||
// primary ::= "{" partition+ "}"
|
||||
if (_WriteOpen() && _UnparsePartition(primary)) {
|
||||
for (int32 i = 0; i < primary->CountLogicalPartitions(); i++) {
|
||||
const LogicalPartition *partition = primary->LogicalPartitionAt(i);
|
||||
if (!_UnparsePartition(partition))
|
||||
break;
|
||||
}
|
||||
if (_NoError())
|
||||
_WriteClose();
|
||||
}
|
||||
return _NoError();
|
||||
}
|
||||
|
||||
// _UnparsePartition
|
||||
bool
|
||||
ParameterUnparser::_UnparsePartition(const Partition *partition)
|
||||
{
|
||||
// partition ::= "{" ptsoffset "," offset "," size "," type ","
|
||||
// active "}"
|
||||
if (_WriteOpen()
|
||||
&& _WriteNumber(partition->PTSOffset())
|
||||
&& _WriteComma()
|
||||
&& _WriteNumber(partition->Offset())
|
||||
&& _WriteComma()
|
||||
&& _WriteNumber(partition->Size())
|
||||
&& _WriteComma()
|
||||
&& _WriteNumber(partition->Type())
|
||||
&& _WriteComma()
|
||||
&& _WriteNumber(partition->Active() ? 1 : 0)
|
||||
&& _WriteClose()) {
|
||||
// success
|
||||
}
|
||||
return _NoError();
|
||||
}
|
||||
|
||||
// _Write
|
||||
bool
|
||||
ParameterUnparser::_Write(const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
if (!fDryRun) {
|
||||
if (fSize > fPosition + len)
|
||||
strcpy(fParameters + fPosition, str);
|
||||
else
|
||||
_ErrorOccurred(B_BAD_VALUE);
|
||||
}
|
||||
fPosition += len;
|
||||
return _NoError();
|
||||
}
|
||||
|
||||
// _WriteNumber
|
||||
bool
|
||||
ParameterUnparser::_WriteNumber(int64 number)
|
||||
{
|
||||
char buffer[kMaxTokenLen];
|
||||
sprintf(buffer, "%lld", number);
|
||||
return _Write(buffer);
|
||||
}
|
||||
|
||||
// _ErrorOccurred
|
||||
void
|
||||
ParameterUnparser::_ErrorOccurred(status_t error)
|
||||
{
|
||||
if (fUnparseError == B_OK)
|
||||
fUnparseError = error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// main
|
||||
int
|
||||
main()
|
||||
{
|
||||
const char *parameters = "{{ 0, 10, 1, 0}{ 0, 3, 1, 0}}"
|
||||
"{{10, 13, 1, 1}}"
|
||||
"{{23, 7, 1, 0}}"
|
||||
"{{30, 9, 1, 0}}";
|
||||
ParameterParser parser;
|
||||
status_t error = parser.Parse(parameters);
|
||||
if (error != B_OK)
|
||||
printf("error while parsing: %s\n", strerror(error));
|
||||
return 0;
|
||||
}
|
||||
*/
|
110
src/add-ons/kernel/disk_scanner/partition/intel_parameters.h
Normal file
110
src/add-ons/kernel/disk_scanner/partition/intel_parameters.h
Normal file
@ -0,0 +1,110 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file intel_parameters.h
|
||||
\brief Class interface definitions for "intel" style partitioning
|
||||
parameter support.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_PARAMETERS_H
|
||||
#define _INTEL_PARAMETERS_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class Partition;
|
||||
class PartitionMap;
|
||||
class PrimaryPartition;
|
||||
|
||||
// tokens
|
||||
enum {
|
||||
TOKEN_ERROR = -1,
|
||||
TOKEN_EOF = '\0',
|
||||
TOKEN_OPEN = '{',
|
||||
TOKEN_CLOSE = '}',
|
||||
TOKEN_COMMA = ',',
|
||||
TOKEN_NUMBER = '0',
|
||||
};
|
||||
|
||||
// Tokenizer
|
||||
class Tokenizer {
|
||||
public:
|
||||
Tokenizer();
|
||||
Tokenizer(const char *input);
|
||||
|
||||
void SetTo(const char *input);
|
||||
|
||||
int32 GetNextToken(char *buffer = NULL);
|
||||
void PutLastToken() { fPosition = fLastPosition; }
|
||||
|
||||
bool ExpectToken(int32 kind, char *buffer = NULL);
|
||||
|
||||
bool ReadOpen() { return (ExpectToken(TOKEN_OPEN)); }
|
||||
bool ReadClose() { return (ExpectToken(TOKEN_CLOSE)); }
|
||||
bool ReadComma() { return (ExpectToken(TOKEN_COMMA)); }
|
||||
bool ReadEOF() { return (ExpectToken(TOKEN_EOF)); }
|
||||
bool ReadNumber(int64 &number);
|
||||
|
||||
private:
|
||||
void _SkipWhiteSpace();
|
||||
|
||||
private:
|
||||
const char *fInput;
|
||||
int32 fPosition;
|
||||
int32 fLastPosition;
|
||||
};
|
||||
|
||||
// ParameterParser
|
||||
class ParameterParser {
|
||||
public:
|
||||
ParameterParser();
|
||||
~ParameterParser() {}
|
||||
|
||||
status_t Parse(const char *parameters, PartitionMap *map);
|
||||
|
||||
private:
|
||||
bool _ParsePrimaryPartition(PrimaryPartition *primary);
|
||||
bool _ParsePartition(Partition *partition);
|
||||
void _ErrorOccurred(status_t error = B_ERROR);
|
||||
bool _NoError() const { return (fParseError == B_OK); }
|
||||
|
||||
private:
|
||||
Tokenizer fTokenizer;
|
||||
status_t fParseError;
|
||||
PartitionMap *fMap;
|
||||
};
|
||||
|
||||
// ParameterUnparser
|
||||
class ParameterUnparser {
|
||||
public:
|
||||
ParameterUnparser();
|
||||
~ParameterUnparser() {}
|
||||
|
||||
status_t GetParameterLength(const PartitionMap *map, size_t *length);
|
||||
status_t Unparse(const PartitionMap *map, char *parameters, size_t length);
|
||||
|
||||
private:
|
||||
bool _UnparsePartitionMap();
|
||||
bool _UnparsePrimaryPartition(const PrimaryPartition *primary);
|
||||
bool _UnparsePartition(const Partition *partition);
|
||||
|
||||
bool _Write(const char *str);
|
||||
bool _WriteOpen() { return _Write("{"); }
|
||||
bool _WriteClose() { return _Write("}"); }
|
||||
bool _WriteComma() { return _Write(","); }
|
||||
bool _WriteNumber(int64 number);
|
||||
|
||||
void _ErrorOccurred(status_t error = B_ERROR);
|
||||
bool _NoError() const { return (fUnparseError == B_OK); }
|
||||
|
||||
private:
|
||||
const PartitionMap *fMap;
|
||||
char *fParameters;
|
||||
size_t fPosition;
|
||||
size_t fSize;
|
||||
bool fDryRun;
|
||||
status_t fUnparseError;
|
||||
};
|
||||
|
||||
#endif // _INTEL_PARAMETERS_H
|
@ -0,0 +1,459 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file intel_partition_map.cpp
|
||||
\brief Definitions for "intel" style partitions and implementation
|
||||
of related classes.
|
||||
*/
|
||||
|
||||
#include <new.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "intel_partition_map.h"
|
||||
|
||||
#define TRACE(x) ;
|
||||
//#define TRACE(x) dprintf x
|
||||
|
||||
|
||||
// partition_type
|
||||
struct partition_type {
|
||||
uint8 type;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct partition_type kPartitionTypes[] = {
|
||||
// these entries must be sorted by type (currently not)
|
||||
{ 0x00, "empty" },
|
||||
{ 0x01, "FAT 12-bit" },
|
||||
{ 0x02, "Xenix root" },
|
||||
{ 0x03, "Xenix user" },
|
||||
{ 0x04, "FAT 16-bit (dos 3.0)" },
|
||||
{ 0x05, "Extended Partition" },
|
||||
{ 0x06, "FAT 16-bit (dos 3.31)" },
|
||||
{ 0x07, "OS/2 IFS, Windows NT, Advanced Unix" },
|
||||
{ 0x0b, "FAT 32-bit" },
|
||||
{ 0x0c, "FAT 32-bit, LBA-mapped" },
|
||||
{ 0x0d, "FAT 16-bit, LBA-mapped" },
|
||||
{ 0x0f, "Extended Partition, LBA-mapped" },
|
||||
{ 0x42, "Windows 2000 marker (switches to a proprietary partition table)" },
|
||||
{ 0x4d, "QNX 4" },
|
||||
{ 0x4e, "QNX 4 2nd part" },
|
||||
{ 0x4f, "QNX 4 3rd part" },
|
||||
{ 0x78, "XOSL boot loader" },
|
||||
{ 0x82, "Linux swapfile" },
|
||||
{ 0x83, "Linux native" },
|
||||
{ 0x85, "Linux extendend partition" },
|
||||
{ 0xa5, "FreeBSD" },
|
||||
{ 0xa6, "OpenBSD" },
|
||||
{ 0xa7, "NextSTEP" },
|
||||
{ 0xa8, "MacOS X" },
|
||||
{ 0xa9, "NetBSD" },
|
||||
{ 0xab, "MacOS X boot" },
|
||||
{ 0xbe, "Solaris 8 boot" },
|
||||
{ 0xeb, "BeOS" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
// partition_type_string
|
||||
const char *
|
||||
partition_type_string(uint8 type)
|
||||
{
|
||||
int32 i;
|
||||
for (i = 0; kPartitionTypes[i].name ; i++)
|
||||
{
|
||||
if (type == kPartitionTypes[i].type)
|
||||
return kPartitionTypes[i].name;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
// Partition
|
||||
|
||||
// constructor
|
||||
Partition::Partition()
|
||||
: fPTSOffset(0),
|
||||
fOffset(0),
|
||||
fSize(0),
|
||||
fType(0),
|
||||
fActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
Partition::Partition(const partition_descriptor *descriptor,off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize)
|
||||
: fPTSOffset(0),
|
||||
fOffset(0),
|
||||
fSize(0),
|
||||
fType(0),
|
||||
fActive(false)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, baseOffset, blockSize);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
Partition::SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize)
|
||||
{
|
||||
fPTSOffset = ptsOffset;
|
||||
fOffset = baseOffset + (off_t)descriptor->start * blockSize;
|
||||
fSize = (off_t)descriptor->size * blockSize;
|
||||
fType = descriptor->type;
|
||||
fActive = descriptor->active;
|
||||
if (fSize == 0)
|
||||
Unset();
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
Partition::Unset()
|
||||
{
|
||||
fPTSOffset = 0;
|
||||
fOffset = 0;
|
||||
fSize = 0;
|
||||
fType = 0;
|
||||
fActive = false;
|
||||
}
|
||||
|
||||
// CheckLocation
|
||||
bool
|
||||
Partition::CheckLocation(off_t sessionSize, int32 blockSize) const
|
||||
{
|
||||
// offsets and size must be block aligned, PTS and partition must lie
|
||||
// within the session
|
||||
return (fPTSOffset % blockSize == 0
|
||||
&& fOffset % blockSize == 0
|
||||
&& fSize % blockSize == 0
|
||||
&& fPTSOffset >= 0 && fPTSOffset < sessionSize
|
||||
&& fOffset >= 0 && fOffset + fSize <= sessionSize);
|
||||
}
|
||||
|
||||
|
||||
// PrimaryPartition
|
||||
|
||||
// constructor
|
||||
PrimaryPartition::PrimaryPartition()
|
||||
: Partition(),
|
||||
fHead(NULL),
|
||||
fTail(NULL),
|
||||
fLogicalPartitionCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
PrimaryPartition::PrimaryPartition(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize)
|
||||
: Partition(),
|
||||
fHead(NULL),
|
||||
fTail(NULL),
|
||||
fLogicalPartitionCount(0)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, blockSize);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
PrimaryPartition::SetTo(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize)
|
||||
{
|
||||
Unset();
|
||||
Partition::SetTo(descriptor, ptsOffset, 0, blockSize);
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
PrimaryPartition::Unset()
|
||||
{
|
||||
while (LogicalPartition *partition = fHead) {
|
||||
fHead = partition->Next();
|
||||
delete partition;
|
||||
}
|
||||
fHead = NULL;
|
||||
fTail = NULL;
|
||||
fLogicalPartitionCount = 0;
|
||||
Partition::Unset();
|
||||
}
|
||||
|
||||
// LogicalPartitionAt
|
||||
LogicalPartition *
|
||||
PrimaryPartition::LogicalPartitionAt(int32 index) const
|
||||
{
|
||||
LogicalPartition *partition = NULL;
|
||||
if (index >= 0 && index < fLogicalPartitionCount) {
|
||||
for (partition = fHead; index > 0; index--)
|
||||
partition = partition->Next();
|
||||
}
|
||||
return partition;
|
||||
}
|
||||
|
||||
// AddLogicalPartition
|
||||
void
|
||||
PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
||||
{
|
||||
if (partition) {
|
||||
partition->SetPrimaryPartition(this);
|
||||
if (fTail) {
|
||||
fTail->SetNext(partition);
|
||||
fTail = partition;
|
||||
} else
|
||||
fHead = fTail = partition;
|
||||
partition->SetNext(NULL);
|
||||
fLogicalPartitionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// LogicalPartition
|
||||
|
||||
// constructor
|
||||
LogicalPartition::LogicalPartition()
|
||||
: Partition(),
|
||||
fPrimary(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
LogicalPartition::LogicalPartition(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize,
|
||||
PrimaryPartition *primary)
|
||||
: Partition(),
|
||||
fPrimary(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, blockSize, primary);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
LogicalPartition::SetTo(const partition_descriptor *descriptor,
|
||||
off_t ptsOffset, int32 blockSize,
|
||||
PrimaryPartition *primary)
|
||||
{
|
||||
Unset();
|
||||
if (descriptor && primary) {
|
||||
off_t baseOffset = (descriptor->is_extended() ? primary->Offset()
|
||||
: ptsOffset);
|
||||
Partition::SetTo(descriptor, ptsOffset, baseOffset, blockSize);
|
||||
fPrimary = primary;
|
||||
}
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
LogicalPartition::Unset()
|
||||
{
|
||||
fPrimary = NULL;
|
||||
fNext = NULL;
|
||||
Partition::Unset();
|
||||
}
|
||||
|
||||
|
||||
// PartitionMap
|
||||
|
||||
// constructor
|
||||
PartitionMap::PartitionMap()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
PartitionMap::~PartitionMap()
|
||||
{
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
PartitionMap::Unset()
|
||||
{
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
fPrimaries[i].Unset();
|
||||
}
|
||||
|
||||
// PrimaryPartitionAt
|
||||
PrimaryPartition *
|
||||
PartitionMap::PrimaryPartitionAt(int32 index)
|
||||
{
|
||||
PrimaryPartition *partition = NULL;
|
||||
if (index >= 0 && index < 4)
|
||||
partition = fPrimaries + index;
|
||||
return partition;
|
||||
}
|
||||
|
||||
// PrimaryPartitionAt
|
||||
const PrimaryPartition *
|
||||
PartitionMap::PrimaryPartitionAt(int32 index) const
|
||||
{
|
||||
const PrimaryPartition *partition = NULL;
|
||||
if (index >= 0 && index < 4)
|
||||
partition = fPrimaries + index;
|
||||
return partition;
|
||||
}
|
||||
|
||||
// CountPartitions
|
||||
int32
|
||||
PartitionMap::CountPartitions() const
|
||||
{
|
||||
int32 count = 4;
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
count += fPrimaries[i].CountLogicalPartitions();
|
||||
return count;
|
||||
}
|
||||
|
||||
// PartitionAt
|
||||
Partition *
|
||||
PartitionMap::PartitionAt(int32 index)
|
||||
{
|
||||
Partition *partition = NULL;
|
||||
int32 count = CountPartitions();
|
||||
if (index >= 0 && index < count) {
|
||||
if (index < 4)
|
||||
partition = fPrimaries + index;
|
||||
else {
|
||||
index -= 4;
|
||||
int32 primary = 0;
|
||||
while (index >= fPrimaries[primary].CountLogicalPartitions()) {
|
||||
index -= fPrimaries[primary].CountLogicalPartitions();
|
||||
primary++;
|
||||
}
|
||||
partition = fPrimaries[primary].LogicalPartitionAt(index);
|
||||
}
|
||||
}
|
||||
return partition;
|
||||
}
|
||||
|
||||
// PartitionAt
|
||||
const Partition *
|
||||
PartitionMap::PartitionAt(int32 index) const
|
||||
{
|
||||
return const_cast<PartitionMap*>(this)->PartitionAt(index);
|
||||
}
|
||||
|
||||
// cmp_partition_offset
|
||||
static
|
||||
int
|
||||
cmp_partition_offset(const void *p1, const void *p2)
|
||||
{
|
||||
const Partition *partition1 = *static_cast<const Partition **>(p1);
|
||||
const Partition *partition2 = *static_cast<const Partition **>(p2);
|
||||
if (partition1->Offset() < partition2->Offset())
|
||||
return -1;
|
||||
else if (partition1->Offset() > partition2->Offset())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cmp_offset
|
||||
static
|
||||
int
|
||||
cmp_offset(const void *o1, const void *o2)
|
||||
{
|
||||
off_t offset1 = *static_cast<const off_t*>(o1);
|
||||
off_t offset2 = *static_cast<const off_t*>(o2);
|
||||
if (offset1 < offset2)
|
||||
return -1;
|
||||
else if (offset1 > offset2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// is_inside_partitions
|
||||
static
|
||||
bool
|
||||
is_inside_partitions(off_t location, const Partition **partitions, int32 count)
|
||||
{
|
||||
bool result = false;
|
||||
if (count > 0) {
|
||||
// binary search
|
||||
int32 lower = 0;
|
||||
int32 upper = count - 1;
|
||||
while (lower < upper) {
|
||||
int32 mid = (lower + upper) / 2;
|
||||
const Partition *midPartition = partitions[mid];
|
||||
if (location >= midPartition->Offset() + midPartition->Size())
|
||||
lower = mid + 1;
|
||||
else
|
||||
upper = mid;
|
||||
}
|
||||
const Partition *partition = partitions[lower];
|
||||
result = (location >= partition->Offset() &&
|
||||
location < partition->Offset() + partition->Size());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check
|
||||
bool
|
||||
PartitionMap::Check(off_t sessionSize, int32 blockSize) const
|
||||
{
|
||||
int32 partitionCount = CountPartitions();
|
||||
// 1. check partition locations
|
||||
for (int32 i = 0; i < partitionCount; i++) {
|
||||
if (!PartitionAt(i)->CheckLocation(sessionSize, blockSize))
|
||||
return false;
|
||||
}
|
||||
// 2. check overlapping of partitions and location of PTSs
|
||||
bool result = true;
|
||||
const Partition **byOffset = new(nothrow) const Partition*[partitionCount];
|
||||
off_t *ptsOffsets = new(nothrow) off_t[partitionCount - 3];
|
||||
if (byOffset && ptsOffsets) {
|
||||
// fill the arrays
|
||||
int32 byOffsetCount = 0;
|
||||
int32 ptsOffsetCount = 1; // primary PTS
|
||||
ptsOffsets[0] = 0; //
|
||||
for (int32 i = 0; i < partitionCount; i++) {
|
||||
const Partition *partition = PartitionAt(i);
|
||||
if (!partition->IsExtended())
|
||||
byOffset[byOffsetCount++] = partition;
|
||||
// add only logical partition PTS locations
|
||||
if (i >= 4)
|
||||
ptsOffsets[ptsOffsetCount++] = partition->PTSOffset();
|
||||
}
|
||||
// sort the arrays
|
||||
qsort(byOffset, byOffsetCount, sizeof(const Partition*),
|
||||
cmp_partition_offset);
|
||||
qsort(ptsOffsets, ptsOffsetCount, sizeof(off_t), cmp_offset);
|
||||
// check for overlappings
|
||||
off_t nextOffset = 0;
|
||||
for (int32 i = 0; i < byOffsetCount; i++) {
|
||||
const Partition *partition = byOffset[i];
|
||||
if (partition->Offset() < nextOffset) {
|
||||
TRACE(("intel: PartitionMap::Check(): overlapping partitions!"
|
||||
"\n"));
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
nextOffset = partition->Offset() + partition->Size();
|
||||
}
|
||||
// check uniqueness of PTS offsets and whether they lie outside of the
|
||||
// non-extended partitions
|
||||
if (result) {
|
||||
for (int32 i = 0; i < ptsOffsetCount; i++) {
|
||||
if (i > 0 && ptsOffsets[i] == ptsOffsets[i - 1]) {
|
||||
TRACE(("intel: PartitionMap::Check(): same PTS for "
|
||||
"different extended partitions!\n"));
|
||||
result = false;
|
||||
break;
|
||||
} else if (is_inside_partitions(ptsOffsets[i], byOffset,
|
||||
byOffsetCount)) {
|
||||
TRACE(("intel: PartitionMap::Check(): a PTS lies "
|
||||
"inside a non-extended partition!\n"));
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
result = false; // no memory: assume failure
|
||||
// cleanup
|
||||
if (byOffset)
|
||||
delete[] byOffset;
|
||||
if (ptsOffsets)
|
||||
delete[] ptsOffsets;
|
||||
return result;
|
||||
}
|
||||
|
168
src/add-ons/kernel/disk_scanner/partition/intel_partition_map.h
Normal file
168
src/add-ons/kernel/disk_scanner/partition/intel_partition_map.h
Normal file
@ -0,0 +1,168 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file intel_partition_map.h
|
||||
\brief Definitions for "intel" style partitions and interface definitions
|
||||
for related classes.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_PARTITION_MAP_H
|
||||
#define _INTEL_PARTITION_MAP_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
// is_empty_type
|
||||
static inline
|
||||
bool
|
||||
is_empty_type(uint8 type)
|
||||
{
|
||||
return (type == 0x00);
|
||||
}
|
||||
|
||||
// is_extended_type
|
||||
static inline
|
||||
bool
|
||||
is_extended_type(uint8 type)
|
||||
{
|
||||
return (type == 0x05 || type == 0x0f || type == 0x85);
|
||||
}
|
||||
|
||||
const char *partition_type_string(uint8 type);
|
||||
|
||||
// chs
|
||||
struct chs {
|
||||
uint8 cylinder;
|
||||
uint16 head_sector; // head[15:10], sector[9:0]
|
||||
} _PACKED;
|
||||
|
||||
// partition_descriptor
|
||||
struct partition_descriptor {
|
||||
uint8 active;
|
||||
chs begin;
|
||||
uint8 type;
|
||||
chs end;
|
||||
uint32 start;
|
||||
uint32 size;
|
||||
|
||||
bool is_empty() const { return is_empty_type(type); }
|
||||
bool is_extended() const { return is_extended_type(type); }
|
||||
} _PACKED;
|
||||
|
||||
// partition_table_sector
|
||||
struct partition_table_sector {
|
||||
char pad1[446];
|
||||
partition_descriptor table[4];
|
||||
uint16 signature;
|
||||
} _PACKED;
|
||||
|
||||
static const uint16 kPartitionTableSectorSignature = 0xaa55;
|
||||
|
||||
class Partition;
|
||||
class PrimaryPartition;
|
||||
class LogicalPartition;
|
||||
|
||||
// Partition
|
||||
class Partition {
|
||||
public:
|
||||
Partition();
|
||||
Partition(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize);
|
||||
|
||||
void SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
off_t baseOffset, int32 blockSize);
|
||||
void Unset();
|
||||
|
||||
bool IsEmpty() const { return is_empty_type(fType); }
|
||||
bool IsExtended() const { return is_extended_type(fType); }
|
||||
|
||||
off_t PTSOffset() const { return fPTSOffset; }
|
||||
off_t Offset() const { return fOffset; }
|
||||
off_t Size() const { return fSize; }
|
||||
uint8 Type() const { return fType; }
|
||||
bool Active() const { return fActive; }
|
||||
const char *TypeString() const { return partition_type_string(fType); }
|
||||
|
||||
void SetPTSOffset(off_t offset) { fPTSOffset = offset; }
|
||||
void SetOffset(off_t offset) { fOffset = offset; }
|
||||
void SetSize(off_t size) { fSize = size; }
|
||||
void SetType(uint8 type) { fType = type; }
|
||||
void SetActive(bool active) { fActive = active; }
|
||||
|
||||
bool CheckLocation(off_t sessionSize, int32 blockSize) const;
|
||||
|
||||
private:
|
||||
off_t fPTSOffset;
|
||||
off_t fOffset; // relative to the start of the session
|
||||
off_t fSize;
|
||||
uint8 fType;
|
||||
bool fActive;
|
||||
};
|
||||
|
||||
// PrimaryPartition
|
||||
class PrimaryPartition : public Partition {
|
||||
public:
|
||||
PrimaryPartition();
|
||||
PrimaryPartition(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize);
|
||||
|
||||
void SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize);
|
||||
void Unset();
|
||||
|
||||
// only if extended
|
||||
int32 CountLogicalPartitions() const { return fLogicalPartitionCount; }
|
||||
LogicalPartition *LogicalPartitionAt(int32 index) const;
|
||||
void AddLogicalPartition(LogicalPartition *partition);
|
||||
|
||||
private:
|
||||
LogicalPartition *fHead;
|
||||
LogicalPartition *fTail;
|
||||
int32 fLogicalPartitionCount;
|
||||
};
|
||||
|
||||
// LogicalPartition
|
||||
class LogicalPartition : public Partition {
|
||||
public:
|
||||
LogicalPartition();
|
||||
LogicalPartition(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize, PrimaryPartition *primary);
|
||||
|
||||
void SetTo(const partition_descriptor *descriptor, off_t ptsOffset,
|
||||
int32 blockSize, PrimaryPartition *primary);
|
||||
void Unset();
|
||||
|
||||
void SetPrimaryPartition(PrimaryPartition *primary) { fPrimary = primary; }
|
||||
PrimaryPartition *GetPrimaryPartition() const { return fPrimary; }
|
||||
|
||||
void SetNext(LogicalPartition *next) { fNext = next; }
|
||||
LogicalPartition *Next() const { return fNext; }
|
||||
|
||||
private:
|
||||
PrimaryPartition *fPrimary;
|
||||
LogicalPartition *fNext;
|
||||
};
|
||||
|
||||
// PartitionMap
|
||||
class PartitionMap {
|
||||
public:
|
||||
PartitionMap();
|
||||
~PartitionMap();
|
||||
|
||||
void Unset();
|
||||
|
||||
PrimaryPartition *PrimaryPartitionAt(int32 index);
|
||||
const PrimaryPartition *PrimaryPartitionAt(int32 index) const;
|
||||
|
||||
int32 CountPartitions() const;
|
||||
Partition *PartitionAt(int32 index);
|
||||
const Partition *PartitionAt(int32 index) const;
|
||||
|
||||
bool Check(off_t sessionSize, int32 blockSize) const;
|
||||
|
||||
private:
|
||||
PrimaryPartition fPrimaries[4];
|
||||
};
|
||||
|
||||
#endif // _INTEL_PARTITION_MAP_H
|
Loading…
Reference in New Issue
Block a user