Write support for the Intel partitioning system module. Courtesy of
Tomas Kucera. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21697 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -7,16 +7,20 @@ UsePrivateHeaders storage ;
|
|||||||
|
|
||||||
KernelAddon intel :
|
KernelAddon intel :
|
||||||
intel.cpp
|
intel.cpp
|
||||||
|
PartitionLocker.cpp
|
||||||
PartitionMap.cpp
|
PartitionMap.cpp
|
||||||
PartitionMapParser.cpp
|
PartitionMapParser.cpp
|
||||||
|
PartitionMapWriter.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
# Also build a userland version
|
# Also build a userland version
|
||||||
# ToDo: it's probably not a good idea to build them into the same directory
|
# ToDo: it's probably not a good idea to build them into the same directory
|
||||||
#Addon <partitioning_system>intel :
|
#Addon <partitioning_system>intel :
|
||||||
# intel.cpp
|
# intel.cpp
|
||||||
|
# PartitionLocker.cpp
|
||||||
# PartitionMap.cpp
|
# PartitionMap.cpp
|
||||||
# PartitionMapParser.cpp
|
# PartitionMapParser.cpp
|
||||||
|
# PartitionMapWriter.cpp
|
||||||
#;
|
#;
|
||||||
|
|
||||||
#LinkAgainst <partitioning_system>intel :
|
#LinkAgainst <partitioning_system>intel :
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Tomas Kucera, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PartitionLocker.h"
|
||||||
|
|
||||||
|
// #pragma mark - PartitionLocker
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PartitionLocker::PartitionLocker(partition_id partitionID)
|
||||||
|
: device_(NULL),
|
||||||
|
partitionID_(partitionID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PartitionLocker::~PartitionLocker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLocked
|
||||||
|
bool
|
||||||
|
PartitionLocker::IsLocked() const
|
||||||
|
{
|
||||||
|
return device_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionId
|
||||||
|
partition_id
|
||||||
|
PartitionLocker::PartitionId() const
|
||||||
|
{
|
||||||
|
return partitionID_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PartitionReadLocker
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PartitionReadLocker::PartitionReadLocker(partition_id partitionID)
|
||||||
|
: PartitionLocker(partitionID)
|
||||||
|
{
|
||||||
|
device_ = read_lock_disk_device(partitionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PartitionReadLocker::~PartitionReadLocker()
|
||||||
|
{
|
||||||
|
if (IsLocked())
|
||||||
|
read_unlock_disk_device(PartitionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PartitionWriteLocker
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PartitionWriteLocker::PartitionWriteLocker(partition_id partitionID)
|
||||||
|
: PartitionLocker(partitionID)
|
||||||
|
{
|
||||||
|
device_ = write_lock_disk_device(partitionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PartitionWriteLocker::~PartitionWriteLocker()
|
||||||
|
{
|
||||||
|
if (IsLocked())
|
||||||
|
write_unlock_disk_device(PartitionId());
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Tomas Kucera, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file PartitionLocker.h
|
||||||
|
\ingroup intel_module
|
||||||
|
\brief Structures for easy locking and automatic unlocking partitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PARTITION_LOCKER_H
|
||||||
|
#define _PARTITION_LOCKER_H
|
||||||
|
|
||||||
|
#include <disk_device_manager.h>
|
||||||
|
|
||||||
|
class PartitionLocker {
|
||||||
|
public:
|
||||||
|
PartitionLocker(partition_id partitionID);
|
||||||
|
virtual ~PartitionLocker();
|
||||||
|
bool IsLocked() const;
|
||||||
|
partition_id PartitionId() const;
|
||||||
|
protected:
|
||||||
|
const disk_device_data *device_;
|
||||||
|
private:
|
||||||
|
partition_id partitionID_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Structure which locks given partition for reading.
|
||||||
|
|
||||||
|
When this structure is going to be destroyed, it automatically unlocks
|
||||||
|
that partition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PartitionReadLocker : public PartitionLocker {
|
||||||
|
public:
|
||||||
|
PartitionReadLocker(partition_id partitionID);
|
||||||
|
virtual ~PartitionReadLocker();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Structure which locks given partition for writing.
|
||||||
|
|
||||||
|
When this structure is going to be destroyed, it automatically unlocks
|
||||||
|
that partition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PartitionWriteLocker : public PartitionLocker {
|
||||||
|
public:
|
||||||
|
PartitionWriteLocker(partition_id partitionID);
|
||||||
|
virtual ~PartitionWriteLocker();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _PARTITION_LOCKER_H
|
||||||
@@ -79,11 +79,27 @@ static const struct partition_type kPartitionTypes[] = {
|
|||||||
{ 0xa8, "MacOS X" },
|
{ 0xa8, "MacOS X" },
|
||||||
{ 0xa9, "NetBSD" },
|
{ 0xa9, "NetBSD" },
|
||||||
{ 0xab, "MacOS X boot" },
|
{ 0xab, "MacOS X boot" },
|
||||||
|
{ 0xaf, "MacOS X HFS" },
|
||||||
{ 0xbe, "Solaris 8 boot" },
|
{ 0xbe, "Solaris 8 boot" },
|
||||||
{ 0xeb, /*"BeOS"*/ BFS_NAME },
|
{ 0xeb, /*"BeOS"*/ BFS_NAME },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct partition_type kPartitionContentTypes[] = {
|
||||||
|
#ifndef _USER_MODE
|
||||||
|
{ 0x01, kPartitionTypeFAT12 },
|
||||||
|
{ 0x0c, kPartitionTypeFAT32 },
|
||||||
|
{ 0x0f, kPartitionTypeIntelExtended },
|
||||||
|
{ 0x83, kPartitionTypeEXT2 },
|
||||||
|
{ 0x83, kPartitionTypeEXT3 },
|
||||||
|
{ 0x83, kPartitionTypeReiser },
|
||||||
|
{ 0xaf, kPartitionTypeHFS },
|
||||||
|
{ 0xaf, kPartitionTypeHFSPlus },
|
||||||
|
{ 0xeb, kPartitionTypeBFS },
|
||||||
|
#endif
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// partition_type_string
|
// partition_type_string
|
||||||
static const char *
|
static const char *
|
||||||
@@ -111,6 +127,7 @@ get_partition_type_string(uint8 type, char *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_partition_offset(const void *p1, const void *p2)
|
cmp_partition_offset(const void *p1, const void *p2)
|
||||||
{
|
{
|
||||||
@@ -161,6 +178,67 @@ is_inside_partitions(off_t location, const Partition **partitions, int32 count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PartitionType
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PartitionType::PartitionType()
|
||||||
|
: type_(0),
|
||||||
|
valid_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetType
|
||||||
|
void
|
||||||
|
PartitionType::SetType(uint8 type)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
valid_ = partition_type_string(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetType
|
||||||
|
void
|
||||||
|
PartitionType::SetType(const char *type_name)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; kPartitionTypes[i].name ; i++) {
|
||||||
|
if (!strcmp(type_name, kPartitionTypes[i].name)) {
|
||||||
|
type_ = kPartitionTypes[i].type;
|
||||||
|
valid_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContentType
|
||||||
|
void
|
||||||
|
PartitionType::SetContentType(const char *content_type)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; kPartitionContentTypes[i].name ; i++) {
|
||||||
|
if (!strcmp(content_type, kPartitionContentTypes[i].name)) {
|
||||||
|
type_ = kPartitionContentTypes[i].type;
|
||||||
|
valid_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindNext
|
||||||
|
void
|
||||||
|
PartitionType::FindNext()
|
||||||
|
{
|
||||||
|
for (int32 i = 0; kPartitionTypes[i].name; i++) {
|
||||||
|
if (type_ < kPartitionTypes[i].type) {
|
||||||
|
type_ = kPartitionTypes[i].type;
|
||||||
|
valid_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Partition
|
// #pragma mark - Partition
|
||||||
|
|
||||||
|
|
||||||
@@ -212,6 +290,19 @@ Partition::Unset()
|
|||||||
fActive = false;
|
fActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPartitionDescriptor
|
||||||
|
void
|
||||||
|
Partition::GetPartitionDescriptor(partition_descriptor *descriptor,
|
||||||
|
off_t baseOffset, int32 blockSize) const
|
||||||
|
{
|
||||||
|
descriptor->start = (fOffset - baseOffset) / blockSize;
|
||||||
|
descriptor->size = fSize / blockSize;
|
||||||
|
descriptor->type = fType;
|
||||||
|
descriptor->active = fActive ? 0x80 : 0x00;
|
||||||
|
descriptor->begin.Unset();
|
||||||
|
descriptor->end.Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _BOOT_MODE
|
#ifdef _BOOT_MODE
|
||||||
void
|
void
|
||||||
@@ -303,6 +394,7 @@ PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
|||||||
{
|
{
|
||||||
if (partition) {
|
if (partition) {
|
||||||
partition->SetPrimaryPartition(this);
|
partition->SetPrimaryPartition(this);
|
||||||
|
partition->SetPrevious(fTail);
|
||||||
if (fTail) {
|
if (fTail) {
|
||||||
fTail->SetNext(partition);
|
fTail->SetNext(partition);
|
||||||
fTail = partition;
|
fTail = partition;
|
||||||
@@ -313,6 +405,30 @@ PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveLogicalPartition
|
||||||
|
void
|
||||||
|
PrimaryPartition::RemoveLogicalPartition(LogicalPartition *partition)
|
||||||
|
{
|
||||||
|
if (!partition || partition->GetPrimaryPartition() != this)
|
||||||
|
return;
|
||||||
|
LogicalPartition *prev = partition->Previous();
|
||||||
|
LogicalPartition *next = partition->Next();
|
||||||
|
|
||||||
|
if (prev)
|
||||||
|
prev->SetNext(next);
|
||||||
|
else
|
||||||
|
fHead = next;
|
||||||
|
if (next)
|
||||||
|
next->SetPrevious(prev);
|
||||||
|
else
|
||||||
|
fTail = prev;
|
||||||
|
fLogicalPartitionCount--;
|
||||||
|
|
||||||
|
partition->SetNext(NULL);
|
||||||
|
partition->SetPrevious(NULL);
|
||||||
|
partition->SetPrimaryPartition(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - LogicalPartition
|
// #pragma mark - LogicalPartition
|
||||||
|
|
||||||
@@ -321,7 +437,8 @@ PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
|||||||
LogicalPartition::LogicalPartition()
|
LogicalPartition::LogicalPartition()
|
||||||
: Partition(),
|
: Partition(),
|
||||||
fPrimary(NULL),
|
fPrimary(NULL),
|
||||||
fNext(NULL)
|
fNext(NULL),
|
||||||
|
fPrevious(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +448,8 @@ LogicalPartition::LogicalPartition(const partition_descriptor *descriptor,
|
|||||||
PrimaryPartition *primary)
|
PrimaryPartition *primary)
|
||||||
: Partition(),
|
: Partition(),
|
||||||
fPrimary(NULL),
|
fPrimary(NULL),
|
||||||
fNext(NULL)
|
fNext(NULL),
|
||||||
|
fPrevious(NULL)
|
||||||
{
|
{
|
||||||
SetTo(descriptor, ptsOffset, blockSize, primary);
|
SetTo(descriptor, ptsOffset, blockSize, primary);
|
||||||
}
|
}
|
||||||
@@ -357,6 +475,7 @@ LogicalPartition::Unset()
|
|||||||
{
|
{
|
||||||
fPrimary = NULL;
|
fPrimary = NULL;
|
||||||
fNext = NULL;
|
fNext = NULL;
|
||||||
|
fPrevious = NULL;
|
||||||
Partition::Unset();
|
Partition::Unset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\file PartitionMap.h
|
\file PartitionMap.h
|
||||||
|
\ingroup intel_module
|
||||||
\brief Definitions for "intel" style partitions and interface definitions
|
\brief Definitions for "intel" style partitions and interface definitions
|
||||||
for related classes.
|
for related classes.
|
||||||
*/
|
*/
|
||||||
@@ -45,12 +46,22 @@ is_extended_type(uint8 type)
|
|||||||
return (type == 0x05 || type == 0x0f || type == 0x85);
|
return (type == 0x05 || type == 0x0f || type == 0x85);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill_buffer
|
||||||
|
static inline
|
||||||
|
void
|
||||||
|
fill_buffer(char *buffer, uint32 length, char ch)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < length; i++)
|
||||||
|
buffer[i] = ch;
|
||||||
|
}
|
||||||
|
|
||||||
void get_partition_type_string(uint8 type, char *buffer);
|
void get_partition_type_string(uint8 type, char *buffer);
|
||||||
|
|
||||||
// chs
|
// chs
|
||||||
struct chs {
|
struct chs {
|
||||||
uint8 cylinder;
|
uint8 cylinder;
|
||||||
uint16 head_sector; // head[15:10], sector[9:0]
|
uint16 head_sector; // head[15:10], sector[9:0]
|
||||||
|
void Unset() { cylinder = 0; head_sector = 0; }
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
// partition_descriptor
|
// partition_descriptor
|
||||||
@@ -71,6 +82,7 @@ struct partition_table_sector {
|
|||||||
char pad1[446];
|
char pad1[446];
|
||||||
partition_descriptor table[4];
|
partition_descriptor table[4];
|
||||||
uint16 signature;
|
uint16 signature;
|
||||||
|
void clear_code_area() { fill_buffer(pad1, 446, '\0'); }
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
static const uint16 kPartitionTableSectorSignature = 0xaa55;
|
static const uint16 kPartitionTableSectorSignature = 0xaa55;
|
||||||
@@ -79,6 +91,68 @@ class Partition;
|
|||||||
class PrimaryPartition;
|
class PrimaryPartition;
|
||||||
class LogicalPartition;
|
class LogicalPartition;
|
||||||
|
|
||||||
|
// PartitionType
|
||||||
|
/*!
|
||||||
|
\brief Class for validating partition types.
|
||||||
|
|
||||||
|
To this class we can set partition type and then we can check whether
|
||||||
|
this type is valid, empty or if it represents extended partition.
|
||||||
|
We can also retrieve the name of that partition type or find next
|
||||||
|
supported type.
|
||||||
|
*/
|
||||||
|
class PartitionType {
|
||||||
|
public:
|
||||||
|
PartitionType();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Sets the \a type via its ID.
|
||||||
|
\param type ID of the partition type, it is in the range [0..255].
|
||||||
|
*/
|
||||||
|
void SetType(uint8 type);
|
||||||
|
/*!
|
||||||
|
\brief Sets the type via its string name.
|
||||||
|
\param type_name Name of the partition type.
|
||||||
|
*/
|
||||||
|
void SetType(const char *type_name);
|
||||||
|
/*!
|
||||||
|
\brief Converts content type to the partition type that fits best.
|
||||||
|
\param content_type Name of the content type, it is standardized by system.
|
||||||
|
*/
|
||||||
|
void SetContentType(const char *content_type);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Check whether the current type is valid.
|
||||||
|
*/
|
||||||
|
bool IsValid() const { return valid_; }
|
||||||
|
/*!
|
||||||
|
\brief Check whether the current type describes empty type.
|
||||||
|
*/
|
||||||
|
bool IsEmpty() const { return is_empty_type(type_); }
|
||||||
|
/*!
|
||||||
|
\brief Check whether the current type describes extended partition type.
|
||||||
|
*/
|
||||||
|
bool IsExtended() const { return is_extended_type(type_); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Returns ID of the current type.
|
||||||
|
*/
|
||||||
|
uint8 Type() const { return type_; }
|
||||||
|
/*!
|
||||||
|
\brief Finds next supported partition.
|
||||||
|
*/
|
||||||
|
void FindNext();
|
||||||
|
/*!
|
||||||
|
\brief Returns string name of the current type.
|
||||||
|
\param buffer Buffer where the name is stored, has to be allocated with
|
||||||
|
sufficient length.
|
||||||
|
*/
|
||||||
|
void GetTypeString(char *buffer) const
|
||||||
|
{ get_partition_type_string(type_, buffer); }
|
||||||
|
private:
|
||||||
|
uint8 type_;
|
||||||
|
bool valid_;
|
||||||
|
};
|
||||||
|
|
||||||
// Partition
|
// Partition
|
||||||
class Partition {
|
class Partition {
|
||||||
public:
|
public:
|
||||||
@@ -100,6 +174,8 @@ public:
|
|||||||
bool Active() const { return fActive; }
|
bool Active() const { return fActive; }
|
||||||
void GetTypeString(char *buffer) const
|
void GetTypeString(char *buffer) const
|
||||||
{ get_partition_type_string(fType, buffer); }
|
{ get_partition_type_string(fType, buffer); }
|
||||||
|
void GetPartitionDescriptor(partition_descriptor *descriptor,
|
||||||
|
off_t baseOffset, int32 blockSize) const;
|
||||||
|
|
||||||
void SetPTSOffset(off_t offset) { fPTSOffset = offset; }
|
void SetPTSOffset(off_t offset) { fPTSOffset = offset; }
|
||||||
void SetOffset(off_t offset) { fOffset = offset; }
|
void SetOffset(off_t offset) { fOffset = offset; }
|
||||||
@@ -135,6 +211,7 @@ public:
|
|||||||
int32 CountLogicalPartitions() const { return fLogicalPartitionCount; }
|
int32 CountLogicalPartitions() const { return fLogicalPartitionCount; }
|
||||||
LogicalPartition *LogicalPartitionAt(int32 index) const;
|
LogicalPartition *LogicalPartitionAt(int32 index) const;
|
||||||
void AddLogicalPartition(LogicalPartition *partition);
|
void AddLogicalPartition(LogicalPartition *partition);
|
||||||
|
void RemoveLogicalPartition(LogicalPartition *partition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LogicalPartition *fHead;
|
LogicalPartition *fHead;
|
||||||
@@ -159,9 +236,13 @@ public:
|
|||||||
void SetNext(LogicalPartition *next) { fNext = next; }
|
void SetNext(LogicalPartition *next) { fNext = next; }
|
||||||
LogicalPartition *Next() const { return fNext; }
|
LogicalPartition *Next() const { return fNext; }
|
||||||
|
|
||||||
|
void SetPrevious(LogicalPartition *previous) { fPrevious = previous; }
|
||||||
|
LogicalPartition *Previous() const { return fPrevious; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PrimaryPartition *fPrimary;
|
PrimaryPartition *fPrimary;
|
||||||
LogicalPartition *fNext;
|
LogicalPartition *fNext;
|
||||||
|
LogicalPartition *fPrevious;
|
||||||
};
|
};
|
||||||
|
|
||||||
// PartitionMap
|
// PartitionMap
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
* Authors:
|
* Authors:
|
||||||
* Ingo Weinhold, [email protected]
|
* Ingo Weinhold, [email protected]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file PartitionMapParser.h
|
||||||
|
\brief Implementation of disk parser for "intel" style partitions.
|
||||||
|
|
||||||
|
Parser reads primary and logical partitions from the disk (according to
|
||||||
|
Master Boot and Extended Boot Records) and fills \c PartitionMap structure
|
||||||
|
with partition representation.
|
||||||
|
*/
|
||||||
#ifndef PARTITION_MAP_PARSER_H
|
#ifndef PARTITION_MAP_PARSER_H
|
||||||
#define PARTITION_MAP_PARSER_H
|
#define PARTITION_MAP_PARSER_H
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Tomas Kucera, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _USER_MODE
|
||||||
|
# include <KernelExport.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "PartitionMap.h"
|
||||||
|
#include "PartitionMapWriter.h"
|
||||||
|
|
||||||
|
#define TRACE_ENABLED
|
||||||
|
|
||||||
|
#ifdef TRACE_ENABLED
|
||||||
|
# ifdef _USER_MODE
|
||||||
|
# define TRACE(x) printf x
|
||||||
|
# else
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
PartitionMapWriter::PartitionMapWriter(int deviceFD, off_t sessionOffset,
|
||||||
|
off_t sessionSize, int32 blockSize)
|
||||||
|
: fDeviceFD(deviceFD),
|
||||||
|
fSessionOffset(sessionOffset),
|
||||||
|
fSessionSize(sessionSize),
|
||||||
|
fBlockSize(blockSize),
|
||||||
|
fPTS(NULL),
|
||||||
|
fMap(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
PartitionMapWriter::~PartitionMapWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteMBR
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::WriteMBR(uint8 *block, const PartitionMap *map)
|
||||||
|
{
|
||||||
|
status_t error = (map ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK) {
|
||||||
|
fMap = map;
|
||||||
|
if (block) {
|
||||||
|
partition_table_sector *pts
|
||||||
|
= (partition_table_sector*)block;
|
||||||
|
error = _WritePrimary(pts);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _WritePTS(0, pts);
|
||||||
|
} else {
|
||||||
|
partition_table_sector pts;
|
||||||
|
error = _ReadPTS(0, &pts);
|
||||||
|
if (error == B_OK) {
|
||||||
|
error = _WritePrimary(&pts);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _WritePTS(0, &pts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fMap = NULL;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteLogical
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::WriteLogical(uint8 *block, const LogicalPartition *partition)
|
||||||
|
{
|
||||||
|
status_t error = (partition ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK) {
|
||||||
|
if (block) {
|
||||||
|
partition_table_sector *pts
|
||||||
|
= (partition_table_sector*)block;
|
||||||
|
error = _WriteExtended(pts, partition, partition->Next());
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _WritePTS(partition->PTSOffset(), pts);
|
||||||
|
} else {
|
||||||
|
partition_table_sector pts;
|
||||||
|
error = _ReadPTS(partition->PTSOffset(), &pts);
|
||||||
|
if (error == B_OK) {
|
||||||
|
error = _WriteExtended(&pts, partition, partition->Next());
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _WritePTS(partition->PTSOffset(), &pts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteExtendedHead
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::WriteExtendedHead(uint8 *block,
|
||||||
|
const LogicalPartition *first_partition)
|
||||||
|
{
|
||||||
|
LogicalPartition partition;
|
||||||
|
if (first_partition)
|
||||||
|
partition.SetPrimaryPartition(first_partition->GetPrimaryPartition());
|
||||||
|
status_t error = B_OK;
|
||||||
|
if (block) {
|
||||||
|
partition_table_sector *pts
|
||||||
|
= (partition_table_sector*)block;
|
||||||
|
error = _WriteExtended(pts, &partition, first_partition);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _WritePTS(0, pts);
|
||||||
|
} else {
|
||||||
|
partition_table_sector pts;
|
||||||
|
error = _ReadPTS(0, &pts);
|
||||||
|
if (error == B_OK) {
|
||||||
|
error = _WriteExtended(&pts, &partition, first_partition);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _WritePTS(0, &pts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WritePrimary
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::_WritePrimary(partition_table_sector *pts)
|
||||||
|
{
|
||||||
|
if (pts == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// write the signature
|
||||||
|
pts->signature = kPartitionTableSectorSignature;
|
||||||
|
|
||||||
|
// write the table
|
||||||
|
for (int32 i = 0; i < 4; i++) {
|
||||||
|
partition_descriptor *descriptor = &pts->table[i];
|
||||||
|
const PrimaryPartition *partition = fMap->PrimaryPartitionAt(i);
|
||||||
|
|
||||||
|
// ignore, if location is bad
|
||||||
|
if (!partition->CheckLocation(fSessionSize, fBlockSize)) {
|
||||||
|
TRACE(("intel: _WritePrimary(): partition %ld: bad location, "
|
||||||
|
"ignoring\n", i));
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
partition->GetPartitionDescriptor(descriptor, 0, fBlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WriteExtended
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::_WriteExtended(partition_table_sector *pts,
|
||||||
|
const LogicalPartition *partition,
|
||||||
|
const LogicalPartition *next)
|
||||||
|
{
|
||||||
|
if (!pts || !partition)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// write the signature
|
||||||
|
pts->signature = kPartitionTableSectorSignature;
|
||||||
|
|
||||||
|
// check the partition's location
|
||||||
|
if (!partition->CheckLocation(fSessionSize, fBlockSize)) {
|
||||||
|
TRACE(("intel: _WriteExtended(): Invalid partition "
|
||||||
|
"location: pts: %lld, offset: %lld, size: %lld, fSessionSize: %lld\n",
|
||||||
|
partition->PTSOffset(), partition->Offset(),
|
||||||
|
partition->Size(), fSessionSize));
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the table
|
||||||
|
partition_descriptor *descriptor = &(pts->table[0]);
|
||||||
|
partition->GetPartitionDescriptor(descriptor, partition->PTSOffset(), fBlockSize);
|
||||||
|
|
||||||
|
// setting offset and size of the next partition in the linked list
|
||||||
|
descriptor = &(pts->table[1]);
|
||||||
|
LogicalPartition extended;
|
||||||
|
if (next) {
|
||||||
|
extended.SetPTSOffset(partition->PTSOffset());
|
||||||
|
extended.SetOffset(next->PTSOffset());
|
||||||
|
extended.SetSize(next->Size() + next->Offset() - next->PTSOffset());
|
||||||
|
extended.SetType(partition->GetPrimaryPartition()->Type());
|
||||||
|
extended.GetPartitionDescriptor(descriptor, 0, fBlockSize);
|
||||||
|
extended.Unset();
|
||||||
|
} else
|
||||||
|
extended.GetPartitionDescriptor(descriptor, 0, fBlockSize);
|
||||||
|
|
||||||
|
// last two descriptors are empty
|
||||||
|
for (int32 i = 2; i < 4; i++) {
|
||||||
|
descriptor = &(pts->table[i]);
|
||||||
|
extended.GetPartitionDescriptor(descriptor, 0, fBlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ReadPTS
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::_ReadPTS(off_t offset, partition_table_sector *pts)
|
||||||
|
// reads the sector from the disk
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
#ifndef _BOOT_MODE
|
||||||
|
error = errno;
|
||||||
|
if (error == B_OK)
|
||||||
|
error = B_IO_ERROR;
|
||||||
|
#else
|
||||||
|
error = B_IO_ERROR;
|
||||||
|
#endif
|
||||||
|
TRACE(("intel: _ReadPTS(): reading the PTS failed: %lx\n", error));
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WritePTS
|
||||||
|
status_t
|
||||||
|
PartitionMapWriter::_WritePTS(off_t offset, const partition_table_sector *pts)
|
||||||
|
// writes the sector to the disk
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
if (!pts)
|
||||||
|
pts = fPTS;
|
||||||
|
int32 toWrite = sizeof(partition_table_sector);
|
||||||
|
// check the offset
|
||||||
|
if (offset < 0 || offset + toWrite > fSessionSize) {
|
||||||
|
error = B_BAD_VALUE;
|
||||||
|
TRACE(("intel: _WritePTS(): bad offset: %Ld\n", offset));
|
||||||
|
// write
|
||||||
|
} else if (write_pos(fDeviceFD, fSessionOffset + offset, pts, toWrite)
|
||||||
|
!= toWrite) {
|
||||||
|
#ifndef _BOOT_MODE
|
||||||
|
error = errno;
|
||||||
|
if (error == B_OK)
|
||||||
|
error = B_IO_ERROR;
|
||||||
|
#else
|
||||||
|
error = B_IO_ERROR;
|
||||||
|
#endif
|
||||||
|
TRACE(("intel: _WritePTS(): writing the PTS failed: %lx\n", error));
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Tomas Kucera, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file PartitionMapWriter.h
|
||||||
|
\ingroup intel_module
|
||||||
|
\brief Implementation of disk writer for "intel" style partitions.
|
||||||
|
|
||||||
|
Writer can write \b Master \b Boot \b Record or \b Extended \b Boot \b Records
|
||||||
|
to the disk according to partitions defined in \c PartitionMap structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PARTITION_MAP_WRITER_H
|
||||||
|
#define PARTITION_MAP_WRITER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class PartitionMap;
|
||||||
|
class LogicalPartition;
|
||||||
|
struct partition_table_sector;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Writer for "Intel" style partitions.
|
||||||
|
|
||||||
|
This class serves for writing \a primary and \a logical \a partitions to disk.
|
||||||
|
*/
|
||||||
|
class PartitionMapWriter {
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
\brief Creates the writer.
|
||||||
|
|
||||||
|
\param deviceFD File descriptor.
|
||||||
|
\param sessionOffset Disk offset of the partition with partitioning system.
|
||||||
|
\param sessionSize Size of the partition with partitioning system.
|
||||||
|
\param blockSize Size of the sector on given disk.
|
||||||
|
*/
|
||||||
|
PartitionMapWriter(int deviceFD, off_t sessionOffset, off_t sessionSize,
|
||||||
|
int32 blockSize);
|
||||||
|
~PartitionMapWriter();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Writes Master Boot Record to the first sector of the disk.
|
||||||
|
|
||||||
|
If a \a block is not specified, the sector is firstly read from the disk
|
||||||
|
and after changing relevant items it is written back to the disk.
|
||||||
|
This allows to keep code area in MBR intact.
|
||||||
|
\param block Pointer to \c partition_table_sector.
|
||||||
|
\param map Pointer to the PartitionMap structure describing disk partitions.
|
||||||
|
*/
|
||||||
|
status_t WriteMBR(uint8 *block, const PartitionMap *map);
|
||||||
|
/*!
|
||||||
|
\brief Writes Partition Table Sector of the logical \a partition to the disk.
|
||||||
|
|
||||||
|
This function ensures that the connection of the following linked list of logical
|
||||||
|
partitions will be correct. It do nothing with the connection of previous logical
|
||||||
|
partitions (call this function on previous logical partition to ensure it).
|
||||||
|
\param block Pointer to \c partition_table_sector.
|
||||||
|
\param partition Pointer to the logical partition.
|
||||||
|
*/
|
||||||
|
status_t WriteLogical(uint8 *block, const LogicalPartition *partition);
|
||||||
|
/*!
|
||||||
|
\brief Writes Extended Boot Record to the first sector of Extended Partition.
|
||||||
|
|
||||||
|
Writes the head of linked list describing logical partitions.
|
||||||
|
|
||||||
|
If the \a first_partition is not specified, it only initializes EBR and the linked
|
||||||
|
list contains no logical partitions.
|
||||||
|
\param block Pointer to \c partition_table_sector.
|
||||||
|
\param first_partition Pointer to the first logical partition.
|
||||||
|
*/
|
||||||
|
status_t WriteExtendedHead(uint8 *block, const LogicalPartition *first_partition);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _WritePrimary(partition_table_sector *pts);
|
||||||
|
status_t _WriteExtended(partition_table_sector *pts,
|
||||||
|
const LogicalPartition *partition,
|
||||||
|
const LogicalPartition *next);
|
||||||
|
status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL);
|
||||||
|
status_t _WritePTS(off_t offset, const partition_table_sector *pts = NULL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fDeviceFD;
|
||||||
|
off_t fSessionOffset;
|
||||||
|
off_t fSessionSize;
|
||||||
|
int32 fBlockSize;
|
||||||
|
partition_table_sector *fPTS; // while writing
|
||||||
|
const PartitionMap *fMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PARTITION_MAP_WRITER_H
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user