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 :
|
||||
intel.cpp
|
||||
PartitionLocker.cpp
|
||||
PartitionMap.cpp
|
||||
PartitionMapParser.cpp
|
||||
PartitionMapWriter.cpp
|
||||
;
|
||||
|
||||
# Also build a userland version
|
||||
# ToDo: it's probably not a good idea to build them into the same directory
|
||||
#Addon <partitioning_system>intel :
|
||||
# intel.cpp
|
||||
# PartitionLocker.cpp
|
||||
# PartitionMap.cpp
|
||||
# PartitionMapParser.cpp
|
||||
# PartitionMapWriter.cpp
|
||||
#;
|
||||
|
||||
#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" },
|
||||
{ 0xa9, "NetBSD" },
|
||||
{ 0xab, "MacOS X boot" },
|
||||
{ 0xaf, "MacOS X HFS" },
|
||||
{ 0xbe, "Solaris 8 boot" },
|
||||
{ 0xeb, /*"BeOS"*/ BFS_NAME },
|
||||
{ 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
|
||||
static const char *
|
||||
@@ -111,6 +127,7 @@ get_partition_type_string(uint8 type, char *buffer)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
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
|
||||
|
||||
|
||||
@@ -212,6 +290,19 @@ Partition::Unset()
|
||||
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
|
||||
void
|
||||
@@ -303,6 +394,7 @@ PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
||||
{
|
||||
if (partition) {
|
||||
partition->SetPrimaryPartition(this);
|
||||
partition->SetPrevious(fTail);
|
||||
if (fTail) {
|
||||
fTail->SetNext(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
|
||||
|
||||
@@ -321,7 +437,8 @@ PrimaryPartition::AddLogicalPartition(LogicalPartition *partition)
|
||||
LogicalPartition::LogicalPartition()
|
||||
: Partition(),
|
||||
fPrimary(NULL),
|
||||
fNext(NULL)
|
||||
fNext(NULL),
|
||||
fPrevious(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -331,7 +448,8 @@ LogicalPartition::LogicalPartition(const partition_descriptor *descriptor,
|
||||
PrimaryPartition *primary)
|
||||
: Partition(),
|
||||
fPrimary(NULL),
|
||||
fNext(NULL)
|
||||
fNext(NULL),
|
||||
fPrevious(NULL)
|
||||
{
|
||||
SetTo(descriptor, ptsOffset, blockSize, primary);
|
||||
}
|
||||
@@ -357,6 +475,7 @@ LogicalPartition::Unset()
|
||||
{
|
||||
fPrimary = NULL;
|
||||
fNext = NULL;
|
||||
fPrevious = NULL;
|
||||
Partition::Unset();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
/*!
|
||||
\file PartitionMap.h
|
||||
\ingroup intel_module
|
||||
\brief Definitions for "intel" style partitions and interface definitions
|
||||
for related classes.
|
||||
*/
|
||||
@@ -45,12 +46,22 @@ is_extended_type(uint8 type)
|
||||
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);
|
||||
|
||||
// chs
|
||||
struct chs {
|
||||
uint8 cylinder;
|
||||
uint16 head_sector; // head[15:10], sector[9:0]
|
||||
void Unset() { cylinder = 0; head_sector = 0; }
|
||||
} _PACKED;
|
||||
|
||||
// partition_descriptor
|
||||
@@ -71,6 +82,7 @@ struct partition_table_sector {
|
||||
char pad1[446];
|
||||
partition_descriptor table[4];
|
||||
uint16 signature;
|
||||
void clear_code_area() { fill_buffer(pad1, 446, '\0'); }
|
||||
} _PACKED;
|
||||
|
||||
static const uint16 kPartitionTableSectorSignature = 0xaa55;
|
||||
@@ -79,6 +91,68 @@ class Partition;
|
||||
class PrimaryPartition;
|
||||
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
|
||||
class Partition {
|
||||
public:
|
||||
@@ -100,6 +174,8 @@ public:
|
||||
bool Active() const { return fActive; }
|
||||
void GetTypeString(char *buffer) const
|
||||
{ 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 SetOffset(off_t offset) { fOffset = offset; }
|
||||
@@ -135,6 +211,7 @@ public:
|
||||
int32 CountLogicalPartitions() const { return fLogicalPartitionCount; }
|
||||
LogicalPartition *LogicalPartitionAt(int32 index) const;
|
||||
void AddLogicalPartition(LogicalPartition *partition);
|
||||
void RemoveLogicalPartition(LogicalPartition *partition);
|
||||
|
||||
private:
|
||||
LogicalPartition *fHead;
|
||||
@@ -159,9 +236,13 @@ public:
|
||||
void SetNext(LogicalPartition *next) { fNext = next; }
|
||||
LogicalPartition *Next() const { return fNext; }
|
||||
|
||||
void SetPrevious(LogicalPartition *previous) { fPrevious = previous; }
|
||||
LogicalPartition *Previous() const { return fPrevious; }
|
||||
|
||||
private:
|
||||
PrimaryPartition *fPrimary;
|
||||
LogicalPartition *fNext;
|
||||
LogicalPartition *fPrevious;
|
||||
};
|
||||
|
||||
// PartitionMap
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
* Authors:
|
||||
* 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
|
||||
#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