Ported the intel partitioning system module to the new interface
(disk device manager) and moved it to a nicer place. First tests look good, though my hard disk structure doesn't even have extended partitions. Going to install Linux now... git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3504 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
be4ab5d842
commit
852d12ef4c
@ -6,4 +6,4 @@ SubInclude OBOS_TOP src add-ons kernel drivers ;
|
|||||||
SubInclude OBOS_TOP src add-ons kernel file_systems ;
|
SubInclude OBOS_TOP src add-ons kernel file_systems ;
|
||||||
SubInclude OBOS_TOP src add-ons kernel network ;
|
SubInclude OBOS_TOP src add-ons kernel network ;
|
||||||
SubInclude OBOS_TOP src add-ons kernel media ;
|
SubInclude OBOS_TOP src add-ons kernel media ;
|
||||||
|
SubInclude OBOS_TOP src add-ons kernel partitioning_systems ;
|
||||||
|
3
src/add-ons/kernel/partitioning_systems/Jamfile
Normal file
3
src/add-ons/kernel/partitioning_systems/Jamfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SubDir OBOS_TOP src add-ons kernel partitioning_systems ;
|
||||||
|
|
||||||
|
SubInclude OBOS_TOP src add-ons kernel partitioning_systems intel ;
|
15
src/add-ons/kernel/partitioning_systems/intel/Jamfile
Normal file
15
src/add-ons/kernel/partitioning_systems/intel/Jamfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
SubDir OBOS_TOP src add-ons kernel partitioning_systems intel ;
|
||||||
|
|
||||||
|
#UsePrivateHeaders $(DOT) ;
|
||||||
|
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||||
|
|
||||||
|
# For now build a userland version only.
|
||||||
|
Addon <partitioning_system>intel : userland partitioning_systems :
|
||||||
|
intel.cpp
|
||||||
|
PartitionMap.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
LinkSharedOSLibs <partitioning_system>intel :
|
||||||
|
libkernelland_emu.so
|
||||||
|
libdisk_device_manager.so
|
||||||
|
;
|
476
src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp
Normal file
476
src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp
Normal file
@ -0,0 +1,476 @@
|
|||||||
|
//----------------------------------------------------------------------
|
||||||
|
// This software is part of the OpenBeOS distribution and is covered
|
||||||
|
// by the OpenBeOS license.
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
\file PartitionMap.cpp
|
||||||
|
\brief Definitions for "intel" style partitions and implementation
|
||||||
|
of related classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <new.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include "PartitionMap.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
|
||||||
|
static
|
||||||
|
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 NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_partition_type_string
|
||||||
|
void
|
||||||
|
get_partition_type_string(uint8 type, char *buffer)
|
||||||
|
{
|
||||||
|
if (buffer) {
|
||||||
|
if (const char *str = partition_type_string(type))
|
||||||
|
strcpy(buffer, str);
|
||||||
|
else
|
||||||
|
sprintf(buffer, "Unrecognized Type 0x%x", type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
TRACE(("Partition::SetTo(): active: %x\n", descriptor->active));
|
||||||
|
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 = *(const Partition**)p1;
|
||||||
|
const Partition *partition2 = *(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;
|
||||||
|
}
|
||||||
|
|
169
src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h
Normal file
169
src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
//----------------------------------------------------------------------
|
||||||
|
// This software is part of the OpenBeOS distribution and is covered
|
||||||
|
// by the OpenBeOS license.
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
\file PartitionMap.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_partition_type_string(uint8 type, char *buffer);
|
||||||
|
|
||||||
|
// 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; }
|
||||||
|
void GetTypeString(char *buffer) const
|
||||||
|
{ get_partition_type_string(fType, buffer); }
|
||||||
|
|
||||||
|
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
|
836
src/add-ons/kernel/partitioning_systems/intel/intel.cpp
Normal file
836
src/add-ons/kernel/partitioning_systems/intel/intel.cpp
Normal file
@ -0,0 +1,836 @@
|
|||||||
|
//----------------------------------------------------------------------
|
||||||
|
// This software is part of the OpenBeOS distribution and is covered
|
||||||
|
// by the OpenBeOS license.
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
\file intel.cpp
|
||||||
|
\brief disk_scanner partition module for "intel" style partitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: The implementation is very strict right now. It rejects a partition
|
||||||
|
// completely, if it finds an error in its partition tables. We should see,
|
||||||
|
// what error can be handled gracefully, e.g. by ignoring the partition
|
||||||
|
// descriptor or the whole partition table sector.
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <ddm_modules.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include "PartitionMap.h"
|
||||||
|
|
||||||
|
//#define TRACE(x) ;
|
||||||
|
#define TRACE(x) dprintf x
|
||||||
|
|
||||||
|
// module names
|
||||||
|
#define INTEL_PARTITION_MAP_MODULE_NAME "partitioning_systems/intel/map/v1"
|
||||||
|
#define INTEL_EXTENDED_PARTITION_MODULE_NAME \
|
||||||
|
"partitioning_systems/intel/extended/v1"
|
||||||
|
|
||||||
|
// partition module identifier
|
||||||
|
static const char *const kPartitionMapPrettyName = "Intel Partition Map";
|
||||||
|
static const char *const kPrimaryPartitionPrettyName
|
||||||
|
= "Intel Primary Partition";
|
||||||
|
static const char *const kExtendedPartitionPrettyName
|
||||||
|
= "Intel Extended Partition";
|
||||||
|
static const char *const kLogicalPartitionPrettyName
|
||||||
|
= "Intel Logical Partition";
|
||||||
|
|
||||||
|
// Maximal number of logical partitions per extended partition we allow.
|
||||||
|
static const int32 kMaxLogicalPartitionCount = 128;
|
||||||
|
|
||||||
|
|
||||||
|
// AutoDeleter
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
class AutoDeleter {
|
||||||
|
public:
|
||||||
|
AutoDeleter(C *object) : fObject(object) {}
|
||||||
|
~AutoDeleter() { delete fObject; }
|
||||||
|
void SetObject(C *object) { fObject = object; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
C *fObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// PartitionMapParser
|
||||||
|
|
||||||
|
class PartitionMapParser {
|
||||||
|
public:
|
||||||
|
PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize,
|
||||||
|
int32 blockSize);
|
||||||
|
~PartitionMapParser();
|
||||||
|
|
||||||
|
status_t Parse(const uint8 *block, PartitionMap *map);
|
||||||
|
|
||||||
|
int32 CountPartitions() const;
|
||||||
|
const Partition *PartitionAt(int32 index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _ParsePrimary(const partition_table_sector *pts);
|
||||||
|
status_t _ParseExtended(PrimaryPartition *primary, off_t offset);
|
||||||
|
status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fDeviceFD;
|
||||||
|
off_t fSessionOffset;
|
||||||
|
off_t fSessionSize;
|
||||||
|
int32 fBlockSize;
|
||||||
|
partition_table_sector *fPTS; // while parsing
|
||||||
|
PartitionMap *fMap; //
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PartitionMapParser::PartitionMapParser(int deviceFD, off_t sessionOffset,
|
||||||
|
off_t sessionSize, int32 blockSize)
|
||||||
|
: fDeviceFD(deviceFD),
|
||||||
|
fSessionOffset(sessionOffset),
|
||||||
|
fSessionSize(sessionSize),
|
||||||
|
fBlockSize(blockSize),
|
||||||
|
fPTS(NULL),
|
||||||
|
fMap(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PartitionMapParser::~PartitionMapParser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse
|
||||||
|
status_t
|
||||||
|
PartitionMapParser::Parse(const uint8 *block, PartitionMap *map)
|
||||||
|
{
|
||||||
|
status_t error = (map ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK) {
|
||||||
|
fMap = map;
|
||||||
|
fMap->Unset();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ParsePrimary
|
||||||
|
status_t
|
||||||
|
PartitionMapParser::_ParsePrimary(const partition_table_sector *pts)
|
||||||
|
{
|
||||||
|
status_t error = (pts ? B_OK : B_BAD_VALUE);
|
||||||
|
// check the signature
|
||||||
|
if (error == B_OK && pts->signature != kPartitionTableSectorSignature) {
|
||||||
|
TRACE(("intel: _ParsePrimary(): invalid PTS signature\n"));
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
}
|
||||||
|
// examine the table
|
||||||
|
if (error == B_OK) {
|
||||||
|
for (int32 i = 0; i < 4; i++) {
|
||||||
|
const partition_descriptor *descriptor = &pts->table[i];
|
||||||
|
PrimaryPartition *partition = fMap->PrimaryPartitionAt(i);
|
||||||
|
partition->SetTo(descriptor, 0, fBlockSize);
|
||||||
|
// fail, if location is bad
|
||||||
|
if (!partition->CheckLocation(fSessionSize, fBlockSize)) {
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// allocate a PTS buffer
|
||||||
|
if (error == B_OK) {
|
||||||
|
fPTS = new(nothrow) partition_table_sector;
|
||||||
|
if (!fPTS)
|
||||||
|
error = B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
// parse extended partitions
|
||||||
|
if (error == B_OK) {
|
||||||
|
for (int32 i = 0; error == B_OK && i < 4; i++) {
|
||||||
|
PrimaryPartition *primary = fMap->PrimaryPartitionAt(i);
|
||||||
|
if (primary->IsExtended())
|
||||||
|
error = _ParseExtended(primary, primary->Offset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// cleanup
|
||||||
|
if (fPTS) {
|
||||||
|
delete fPTS;
|
||||||
|
fPTS = NULL;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ParseExtended
|
||||||
|
status_t
|
||||||
|
PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
int32 partitionCount = 0;
|
||||||
|
while (error == B_OK) {
|
||||||
|
// check for cycles
|
||||||
|
if (++partitionCount > kMaxLogicalPartitionCount) {
|
||||||
|
TRACE(("intel: _ParseExtended(): Maximal number of logical "
|
||||||
|
"partitions for extended partition reached. Cycle?\n"));
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
}
|
||||||
|
// read the PTS
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _ReadPTS(offset);
|
||||||
|
// check the signature
|
||||||
|
if (error == B_OK
|
||||||
|
&& fPTS->signature != kPartitionTableSectorSignature) {
|
||||||
|
TRACE(("intel: _ParseExtended(): invalid PTS signature\n"));
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
}
|
||||||
|
// ignore the PTS, if any error occured till now
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE(("intel: _ParseExtended(): ignoring this PTS\n"));
|
||||||
|
error = B_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// examine the table
|
||||||
|
LogicalPartition extended;
|
||||||
|
LogicalPartition nonExtended;
|
||||||
|
if (error == B_OK) {
|
||||||
|
for (int32 i = 0; error == B_OK && i < 4; i++) {
|
||||||
|
const partition_descriptor *descriptor = &fPTS->table[i];
|
||||||
|
LogicalPartition *partition = NULL;
|
||||||
|
if (!descriptor->is_empty()) {
|
||||||
|
if (descriptor->is_extended()) {
|
||||||
|
if (extended.IsEmpty()) {
|
||||||
|
extended.SetTo(descriptor, offset, fBlockSize,
|
||||||
|
primary);
|
||||||
|
partition = &extended;
|
||||||
|
} else {
|
||||||
|
// only one extended partition allowed
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
TRACE(("intel: _ParseExtended(): "
|
||||||
|
"only one extended partition allowed\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nonExtended.IsEmpty()) {
|
||||||
|
nonExtended.SetTo(descriptor, offset, fBlockSize,
|
||||||
|
primary);
|
||||||
|
partition = &nonExtended;
|
||||||
|
} else {
|
||||||
|
// only one non-extended partition allowed
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
TRACE(("intel: _ParseExtended(): only one "
|
||||||
|
"non-extended partition allowed\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check the partition's location
|
||||||
|
if (partition && !partition->CheckLocation(fSessionSize,
|
||||||
|
fBlockSize)) {
|
||||||
|
error = B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add non-extended partition to list
|
||||||
|
if (error == B_OK && !nonExtended.IsEmpty()) {
|
||||||
|
LogicalPartition *partition
|
||||||
|
= new(nothrow) LogicalPartition(nonExtended);
|
||||||
|
if (partition)
|
||||||
|
primary->AddLogicalPartition(partition);
|
||||||
|
else
|
||||||
|
error = B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
// prepare to parse next extended partition
|
||||||
|
if (error == B_OK && !extended.IsEmpty())
|
||||||
|
offset = extended.Offset();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadPTS
|
||||||
|
status_t
|
||||||
|
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, pts, toRead)
|
||||||
|
!= toRead) {
|
||||||
|
error = errno;
|
||||||
|
if (error == B_OK)
|
||||||
|
error = B_IO_ERROR;
|
||||||
|
TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n",
|
||||||
|
strerror(error)));
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// std_ops
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
TRACE(("intel: std_ops(0x%lx)\n", op));
|
||||||
|
switch(op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read_partition_map
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
TRACE(("intel: identify(%d, %lld, %lld, %p, %ld)\n", deviceFD,
|
||||||
|
sessionInfo->offset, sessionInfo->size, block,
|
||||||
|
sessionInfo->logical_block_size));
|
||||||
|
PartitionMap map;
|
||||||
|
return read_partition_map(deviceFD, sessionInfo, block, &map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// intel_get_nth_info
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
intel_get_nth_info(int deviceFD, const session_info *sessionInfo,
|
||||||
|
const uchar *block, int32 index,
|
||||||
|
extended_partition_info *partitionInfo)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
off_t sessionOffset = sessionInfo->offset;
|
||||||
|
TRACE(("intel: get_nth_info(%d, %lld, %lld, %p, %ld, %ld)\n", deviceFD,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
partitionInfo->partition_name[0] = '\0';
|
||||||
|
partition->GetTypeString(partitionInfo->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// intel_get_partitioning_params
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
intel_get_partitioning_params(int deviceFD,
|
||||||
|
const struct session_info *sessionInfo,
|
||||||
|
char *buffer, size_t bufferSize,
|
||||||
|
size_t *actualSize)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
intel_partition(int deviceFD, const struct session_info *sessionInfo,
|
||||||
|
const char *parameters)
|
||||||
|
{
|
||||||
|
// not yet supported
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// intel partition map module
|
||||||
|
|
||||||
|
// module
|
||||||
|
static status_t pm_std_ops(int32 op, ...);
|
||||||
|
|
||||||
|
// scanning
|
||||||
|
static float pm_identify_partition(int fd, partition_data *partition,
|
||||||
|
void **cookie);
|
||||||
|
static status_t pm_scan_partition(int fd, partition_data *partition,
|
||||||
|
void *cookie);
|
||||||
|
static void pm_free_identify_partition_cookie(partition_data *partition,
|
||||||
|
void *cookie);
|
||||||
|
static void pm_free_partition_cookie(partition_data *partition);
|
||||||
|
static void pm_free_partition_content_cookie(partition_data *partition);
|
||||||
|
|
||||||
|
static partition_module_info intel_partition_map_module = {
|
||||||
|
{
|
||||||
|
INTEL_PARTITION_MAP_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
pm_std_ops
|
||||||
|
},
|
||||||
|
kPartitionMapPrettyName, // pretty_name
|
||||||
|
|
||||||
|
// scanning
|
||||||
|
pm_identify_partition, // identify_partition
|
||||||
|
pm_scan_partition, // scan_partition
|
||||||
|
pm_free_identify_partition_cookie, // free_identify_partition_cookie
|
||||||
|
pm_free_partition_cookie, // free_partition_cookie
|
||||||
|
pm_free_partition_content_cookie, // free_partition_content_cookie
|
||||||
|
|
||||||
|
// querying
|
||||||
|
NULL, // supports_reparing_partition
|
||||||
|
NULL, // supports_resizing_partition
|
||||||
|
NULL, // supports_resizing_child_partition
|
||||||
|
NULL, // supports_moving_partition
|
||||||
|
NULL, // supports_moving_child_partition
|
||||||
|
NULL, // supports_parent_system
|
||||||
|
NULL, // supports_child_system
|
||||||
|
NULL, // validate_resize_partition
|
||||||
|
NULL, // validate_move_partition
|
||||||
|
NULL, // validate_resize_child_partition
|
||||||
|
NULL, // validate_move_child_partition
|
||||||
|
NULL, // validate_create_child_partition
|
||||||
|
NULL, // validate_initialize_partition
|
||||||
|
NULL, // validate_set_partition_parameters
|
||||||
|
NULL,
|
||||||
|
// validate_set_partition_content_parameters
|
||||||
|
NULL, // get_partitionable_spaces;
|
||||||
|
|
||||||
|
// writing
|
||||||
|
NULL, // repair_partition
|
||||||
|
NULL, // resize_partition
|
||||||
|
NULL, // resize_child_partition
|
||||||
|
NULL, // move_partition
|
||||||
|
NULL, // move_child_partition
|
||||||
|
NULL, // create_child_partition
|
||||||
|
NULL, // delete_child_partition
|
||||||
|
NULL, // initialize_partition
|
||||||
|
NULL, // set_parameters_partition
|
||||||
|
NULL, // set_partition_content_parameters
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// intel extended partition module
|
||||||
|
|
||||||
|
// module
|
||||||
|
static status_t ep_std_ops(int32 op, ...);
|
||||||
|
|
||||||
|
// scanning
|
||||||
|
static float ep_identify_partition(int fd, partition_data *partition,
|
||||||
|
void **cookie);
|
||||||
|
static status_t ep_scan_partition(int fd, partition_data *partition,
|
||||||
|
void *cookie);
|
||||||
|
static void ep_free_identify_partition_cookie(partition_data *partition,
|
||||||
|
void *cookie);
|
||||||
|
static void ep_free_partition_cookie(partition_data *partition);
|
||||||
|
static void ep_free_partition_content_cookie(partition_data *partition);
|
||||||
|
|
||||||
|
static partition_module_info intel_extended_partition_module = {
|
||||||
|
{
|
||||||
|
INTEL_EXTENDED_PARTITION_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
ep_std_ops
|
||||||
|
},
|
||||||
|
kExtendedPartitionPrettyName, // pretty_name
|
||||||
|
|
||||||
|
// scanning
|
||||||
|
ep_identify_partition, // identify_partition
|
||||||
|
ep_scan_partition, // scan_partition
|
||||||
|
ep_free_identify_partition_cookie, // free_identify_partition_cookie
|
||||||
|
ep_free_partition_cookie, // free_partition_cookie
|
||||||
|
ep_free_partition_content_cookie, // free_partition_content_cookie
|
||||||
|
|
||||||
|
// querying
|
||||||
|
NULL, // supports_reparing_partition
|
||||||
|
NULL, // supports_resizing_partition
|
||||||
|
NULL, // supports_resizing_child_partition
|
||||||
|
NULL, // supports_moving_partition
|
||||||
|
NULL, // supports_moving_child_partition
|
||||||
|
NULL, // supports_parent_system
|
||||||
|
NULL, // supports_child_system
|
||||||
|
NULL, // validate_resize_partition
|
||||||
|
NULL, // validate_move_partition
|
||||||
|
NULL, // validate_resize_child_partition
|
||||||
|
NULL, // validate_move_child_partition
|
||||||
|
NULL, // validate_create_child_partition
|
||||||
|
NULL, // validate_initialize_partition
|
||||||
|
NULL, // validate_set_partition_parameters
|
||||||
|
NULL,
|
||||||
|
// validate_set_partition_content_parameters
|
||||||
|
NULL, // get_partitionable_spaces;
|
||||||
|
|
||||||
|
// writing
|
||||||
|
NULL, // repair_partition
|
||||||
|
NULL, // resize_partition
|
||||||
|
NULL, // resize_child_partition
|
||||||
|
NULL, // move_partition
|
||||||
|
NULL, // move_child_partition
|
||||||
|
NULL, // create_child_partition
|
||||||
|
NULL, // delete_child_partition
|
||||||
|
NULL, // initialize_partition
|
||||||
|
NULL, // set_parameters_partition
|
||||||
|
NULL, // set_partition_content_parameters
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" partition_module_info *modules[];
|
||||||
|
_EXPORT partition_module_info *modules[] =
|
||||||
|
{
|
||||||
|
&intel_partition_map_module,
|
||||||
|
&intel_extended_partition_module,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// intel partition map module
|
||||||
|
|
||||||
|
// pm_std_ops
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
pm_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
TRACE(("intel: pm_std_ops(0x%lx)\n", op));
|
||||||
|
switch(op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pm_identify_partition
|
||||||
|
static
|
||||||
|
float
|
||||||
|
pm_identify_partition(int fd, partition_data *partition, void **cookie)
|
||||||
|
{
|
||||||
|
// check parameters
|
||||||
|
if (fd < 0 || !partition || !cookie)
|
||||||
|
return -1;
|
||||||
|
TRACE(("intel: pm_identify_partition(%d, %ld: %lld, %lld, %ld)\n", fd,
|
||||||
|
partition->id, partition->offset, partition->size,
|
||||||
|
partition->block_size));
|
||||||
|
// check block size
|
||||||
|
uint32 blockSize = partition->block_size;
|
||||||
|
if (blockSize < sizeof(partition_table_sector)) {
|
||||||
|
TRACE(("intel: read_partition_map: bad block size: %ld, should be "
|
||||||
|
">= %ld\n", blockSize, sizeof(partition_table_sector)));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// allocate a PartitionMap
|
||||||
|
PartitionMap *map = new(nothrow) PartitionMap;
|
||||||
|
if (!map)
|
||||||
|
return -1;
|
||||||
|
// read the partition structure
|
||||||
|
PartitionMapParser parser(fd, 0, partition->size, blockSize);
|
||||||
|
status_t error = parser.Parse(NULL, map);
|
||||||
|
if (error == B_OK) {
|
||||||
|
*cookie = map;
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
// cleanup, if not detected
|
||||||
|
delete map;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pm_scan_partition
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
pm_scan_partition(int fd, partition_data *partition, void *cookie)
|
||||||
|
{
|
||||||
|
AutoDeleter<PartitionMap> deleter((PartitionMap*)cookie);
|
||||||
|
// check parameters
|
||||||
|
if (fd < 0 || !partition || !cookie)
|
||||||
|
return B_ERROR;
|
||||||
|
TRACE(("intel: pm_scan_partition(%d, %ld: %lld, %lld, %ld)\n", fd,
|
||||||
|
partition->id, partition->offset, partition->size,
|
||||||
|
partition->block_size));
|
||||||
|
PartitionMap *map = (PartitionMap*)cookie;
|
||||||
|
// fill in the partition_data structure
|
||||||
|
// (no content_name and content_parameters)
|
||||||
|
partition->content_type = strdup(kPartitionMapPrettyName);
|
||||||
|
if (!partition->content_type)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
partition->content_cookie = map;
|
||||||
|
// children
|
||||||
|
status_t error = B_OK;
|
||||||
|
int32 index = 0;
|
||||||
|
for (int32 i = 0; i < 4; i++) {
|
||||||
|
PrimaryPartition *primary = map->PrimaryPartitionAt(i);
|
||||||
|
if (!primary->IsEmpty()) {
|
||||||
|
partition_data *child = create_child_partition(partition->id,
|
||||||
|
index, -1);
|
||||||
|
index++;
|
||||||
|
if (!child) {
|
||||||
|
TRACE(("Creating child at index %ld failed\n", index - 1));
|
||||||
|
// something went wrong
|
||||||
|
error = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
child->offset = partition->offset + primary->Offset();
|
||||||
|
child->size = primary->Size();
|
||||||
|
child->block_size = partition->block_size;
|
||||||
|
// (no name)
|
||||||
|
child->type = strdup(primary->IsExtended()
|
||||||
|
? kExtendedPartitionPrettyName : kPrimaryPartitionPrettyName);
|
||||||
|
// parameters
|
||||||
|
char buffer[128];
|
||||||
|
sprintf(buffer, "type = %u ; active = %d\n", primary->Type(),
|
||||||
|
primary->Active());
|
||||||
|
child->parameters = strdup(buffer);
|
||||||
|
child->cookie = primary;
|
||||||
|
// check for allocation problems
|
||||||
|
if (!child->type || !child->parameters) {
|
||||||
|
error = B_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// keep map on success or cleanup on error
|
||||||
|
if (error == B_OK) {
|
||||||
|
deleter.SetObject(NULL);
|
||||||
|
} else {
|
||||||
|
partition->content_cookie = NULL;
|
||||||
|
for (int32 i = 0; i < partition->child_count; i++) {
|
||||||
|
if (partition_data *child = get_child_partition(partition->id, i))
|
||||||
|
child->cookie = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pm_free_identify_partition_cookie
|
||||||
|
static
|
||||||
|
void
|
||||||
|
pm_free_identify_partition_cookie(partition_data */*partition*/, void *cookie)
|
||||||
|
{
|
||||||
|
if (cookie)
|
||||||
|
delete (PartitionMap*)cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pm_free_partition_cookie
|
||||||
|
static
|
||||||
|
void
|
||||||
|
pm_free_partition_cookie(partition_data *partition)
|
||||||
|
{
|
||||||
|
// called for the primary partitions: the PrimaryPartition is allocated
|
||||||
|
// by the partition containing the partition map
|
||||||
|
if (partition)
|
||||||
|
partition->cookie = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pm_free_partition_content_cookie
|
||||||
|
static
|
||||||
|
void
|
||||||
|
pm_free_partition_content_cookie(partition_data *partition)
|
||||||
|
{
|
||||||
|
if (partition && partition->content_cookie) {
|
||||||
|
delete (PartitionMap*)partition->content_cookie;
|
||||||
|
partition->content_cookie = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// intel extended partition module
|
||||||
|
|
||||||
|
// ep_std_ops
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
ep_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
TRACE(("intel: ep_std_ops(0x%lx)\n", op));
|
||||||
|
switch(op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ep_identify_partition
|
||||||
|
static
|
||||||
|
float
|
||||||
|
ep_identify_partition(int fd, partition_data *partition, void **cookie)
|
||||||
|
{
|
||||||
|
// check parameters
|
||||||
|
if (fd < 0 || !partition || !cookie || !partition->cookie)
|
||||||
|
return -1;
|
||||||
|
TRACE(("intel: ep_identify_partition(%d, %lld, %lld, %ld)\n", fd,
|
||||||
|
partition->offset, partition->size, partition->block_size));
|
||||||
|
// our parent must be a intel partition map partition and we must have
|
||||||
|
// extended partition type
|
||||||
|
if (!partition->type
|
||||||
|
|| strcmp(partition->type, kExtendedPartitionPrettyName)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
partition_data *parent = get_parent_partition(partition->id);
|
||||||
|
if (!parent || !parent->content_type
|
||||||
|
|| strcmp(parent->content_type, kPartitionMapPrettyName)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// things seem to be in order
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ep_scan_partition
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
ep_scan_partition(int fd, partition_data *partition, void *cookie)
|
||||||
|
{
|
||||||
|
// check parameters
|
||||||
|
if (fd < 0 || !partition || !cookie || !partition->cookie)
|
||||||
|
return B_ERROR;
|
||||||
|
partition_data *parent = get_parent_partition(partition->id);
|
||||||
|
if (!parent)
|
||||||
|
return B_ERROR;
|
||||||
|
PrimaryPartition *primary = (PrimaryPartition*)partition->cookie;
|
||||||
|
// fill in the partition_data structure
|
||||||
|
// (no content_name and content_parameters)
|
||||||
|
partition->content_type = strdup(kExtendedPartitionPrettyName);
|
||||||
|
if (!partition->content_type)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
partition->content_cookie = primary;
|
||||||
|
// children
|
||||||
|
status_t error = B_OK;
|
||||||
|
int32 index = 0;
|
||||||
|
for (int32 i = 0; i < primary->CountLogicalPartitions(); i++) {
|
||||||
|
LogicalPartition *logical = primary->LogicalPartitionAt(i);
|
||||||
|
partition_data *child = create_child_partition(partition->id,
|
||||||
|
index, -1);
|
||||||
|
if (!child) {
|
||||||
|
// something went wrong
|
||||||
|
error = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
child->offset = parent->offset + logical->Offset();
|
||||||
|
child->size = logical->Size();
|
||||||
|
child->block_size = partition->block_size;
|
||||||
|
// (no name)
|
||||||
|
child->type = strdup(kLogicalPartitionPrettyName);
|
||||||
|
// parameters
|
||||||
|
char buffer[128];
|
||||||
|
sprintf(buffer, "type = %u ; active = %d\n", primary->Type(),
|
||||||
|
primary->Active());
|
||||||
|
child->parameters = strdup(buffer);
|
||||||
|
child->cookie = logical;
|
||||||
|
// check for allocation problems
|
||||||
|
if (!child->type || !child->parameters) {
|
||||||
|
error = B_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// cleanup on error
|
||||||
|
if (error != B_OK) {
|
||||||
|
partition->content_cookie = NULL;
|
||||||
|
for (int32 i = 0; i < partition->child_count; i++) {
|
||||||
|
if (partition_data *child = get_child_partition(partition->id, i))
|
||||||
|
child->cookie = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ep_free_identify_partition_cookie
|
||||||
|
static
|
||||||
|
void
|
||||||
|
ep_free_identify_partition_cookie(partition_data *partition, void *cookie)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
// ep_free_partition_cookie
|
||||||
|
static
|
||||||
|
void
|
||||||
|
ep_free_partition_cookie(partition_data *partition)
|
||||||
|
{
|
||||||
|
// the logical partition's cookie belongs to the partition map partition
|
||||||
|
if (partition)
|
||||||
|
partition->cookie = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ep_free_partition_content_cookie
|
||||||
|
static
|
||||||
|
void
|
||||||
|
ep_free_partition_content_cookie(partition_data *partition)
|
||||||
|
{
|
||||||
|
// the extended partition's cookie belongs to the partition map partition
|
||||||
|
if (partition)
|
||||||
|
partition->content_cookie = NULL;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user