* Added open_partition to disk_device_manager

* Rewrote PartitionMapWriter
* Updated style to match current style guide for the intel partitioning system.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32235 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Bryce Groff
2009-08-10 22:28:47 +00:00
parent 99452e33a8
commit 1987b05aa0
10 changed files with 744 additions and 747 deletions
+2
View File
@@ -101,6 +101,8 @@ partition_data *get_partition(partition_id partitionID);
partition_data *get_parent_partition(partition_id partitionID);
partition_data *get_child_partition(partition_id partitionID, int32 index);
int open_partition(partition_id partitionID, int openMode);
// partition write access
// (write lock required)
partition_data *create_child_partition(partition_id partitionID, int32 index,
@@ -36,7 +36,7 @@ static const uint32 kDiskSystemFlags =
// | B_DISK_SYSTEM_SUPPORTS_MOVING
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_INITIALIZING
// | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
// | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
// | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
@@ -92,7 +92,7 @@ bool
ExtendedPartitionAddOn::CanInitialize(const BMutablePartition* partition)
{
// If it's big enough, we can initialize it.
return partition->Size() >= 2 * partition->BlockSize();
return false;
}
@@ -222,7 +222,7 @@ ExtendedPartitionHandle::Init()
uint32
ExtendedPartitionHandle::SupportedOperations(uint32 mask)
{
uint32 flags = B_DISK_SYSTEM_SUPPORTS_INITIALIZING;
uint32 flags = 0;//B_DISK_SYSTEM_SUPPORTS_INITIALIZING;
// creating child
if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) {
@@ -254,10 +254,25 @@ ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
TRACE("%p->ExtendedPartitionHandle::GetNextSupportedType(child: %p, "
"cookie: %ld)\n", this, child, *cookie);
if (*cookie != 0)
int32 index = *cookie;
const partition_type* nextType;
PartitionMap partitionMap;
while (true) {
nextType = partitionMap.GetNextSupportedPartitionType(index);
if (nextType == NULL)
return B_ENTRY_NOT_FOUND;
index++;
if (nextType->used
&& strcmp(nextType->name, kPartitionTypeIntelExtended) != 0)
break;
}
if (!nextType)
return B_ENTRY_NOT_FOUND;
*cookie = *cookie + 1;
*type = kPartitionTypeIntelLogical;
type->SetTo(nextType->name);
*cookie = index;
return B_OK;
}
@@ -266,39 +281,22 @@ ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
status_t
ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info)
{
// NOTE stippi: At first I tried to use the fPrimaryPartition
// here but it does not return any LogicalPartitions. What
// happens now is probably what used to happen before, though
// I don't understand *where*, since this handle type never
// implemented this virtual function.
// init to the full size (minus the first sector)
BMutablePartition* partition = Partition();
off_t offset = partition->Offset();// + SECTOR_SIZE;
off_t size = partition->Size();//- SECTOR_SIZE;
off_t offset = partition->Offset();
off_t size = partition->Size();
status_t error = info->SetTo(offset, size);
if (error != B_OK)
return error;
// exclude the space of the existing logical partitions
int32 count = partition->CountChildren();
printf("%ld logical partitions\n", count);
for (int32 i = 0; i < count; i++) {
BMutablePartition* child = partition->ChildAt(i);
// TODO: Does this correctly account for the partition table
// sectors? Preceeding each logical partition should be a
// sector for the partition table entry. Those entries form
// the linked list of "inner extended partition" + "real partition"
// Following the logic above (copied from PartitionMapAddOn),
// the outer size includes the first sector and is therefor
// what we need here.
error = info->ExcludeOccupiedSpace(child->Offset(), child->Size());
printf(" %ld: offset = %lld (relative: %lld), size = %lld\n", i,
child->Offset(), child->Offset() - offset, child->Size());
if (error != B_OK)
return error;
}
info->PrintToStream();
return B_OK;
}
@@ -309,7 +307,6 @@ status_t
ExtendedPartitionHandle::GetChildCreationParameterEditor(const char* type,
BPartitionParameterEditor** editor)
{
// TODO: We actually need an editor here.
*editor = NULL;
return B_OK;
}
@@ -321,102 +318,98 @@ ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
const char* typeString, BString* name, const char* parameters)
{
// check type
if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0)
if (!typeString)
return B_BAD_VALUE;
// check name
if (name)
name->Truncate(0);
// check parameters
// TODO:...
// check the free space situation
BPartitioningInfo info;
status_t error = GetPartitioningInfo(&info);
if (error != B_OK)
return error;
return B_NOT_SUPPORTED;
// // check the free space situation
// BPartitioningInfo info;
// status_t error = GetPartitioningInfo(&info);
// if (error != B_OK)
// return error;
//
// // any space in the partition at all?
// int32 spacesCount = info.CountPartitionableSpaces();
// if (spacesCount == 0)
// return B_BAD_VALUE;
//
// // check offset and size
// off_t offset = sector_align(*_offset);
// off_t size = sector_align(*_size);
// // TODO: Rather round size up?
// off_t end = offset + size;
//
// // get the first partitionable space the requested interval intersects with
// int32 spaceIndex = -1;
// int32 closestSpaceIndex = -1;
// off_t closestSpaceDistance = 0;
// for (int32 i = 0; i < spacesCount; i++) {
// off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
// off_t spaceEnd = spaceOffset + spaceSize;
//
// if (spaceOffset >= offset && spaceOffset < end
// || offset >= spaceOffset && offset < spaceEnd) {
// spaceIndex = i;
// break;
// }
//
// off_t distance;
// if (offset < spaceOffset)
// distance = spaceOffset - end;
// else
// distance = spaceEnd - offset;
//
// if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
// closestSpaceIndex = i;
// closestSpaceDistance = distance;
// }
// }
//
// // get the space we found
// off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(
// spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
// &spaceSize);
// off_t spaceEnd = spaceOffset + spaceSize;
//
// // If the requested intervald doesn't intersect with any space yet, move
// // it, so that it does.
// if (spaceIndex < 0) {
// spaceIndex = closestSpaceIndex;
// if (offset < spaceOffset) {
// offset = spaceOffset;
// end = offset + size;
// } else {
// end = spaceEnd;
// offset = end - size;
// }
// }
//
// // move/shrink the interval, so that it fully lies within the space
// if (offset < spaceOffset) {
// offset = spaceOffset;
// end = offset + size;
// if (end > spaceEnd) {
// end = spaceEnd;
// size = end - offset;
// }
// } else if (end > spaceEnd) {
// end = spaceEnd;
// offset = end - size;
// if (offset < spaceOffset) {
// offset = spaceOffset;
// size = end - offset;
// }
// }
//
// *_offset = offset;
// *_size = size;
//
// return B_OK;
// any space in the partition at all?
int32 spacesCount = info.CountPartitionableSpaces();
if (spacesCount == 0)
return B_BAD_VALUE;
// check offset and size
off_t offset = sector_align(*_offset, Partition()->BlockSize());
off_t size = sector_align(*_size, Partition()->BlockSize());
// TODO: Rather round size up?
off_t end = offset + size;
// get the first partitionable space the requested interval intersects with
int32 spaceIndex = -1;
int32 closestSpaceIndex = -1;
off_t closestSpaceDistance = 0;
for (int32 i = 0; i < spacesCount; i++) {
off_t spaceOffset, spaceSize;
info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
off_t spaceEnd = spaceOffset + spaceSize;
if (spaceOffset >= offset && spaceOffset < end
|| offset >= spaceOffset && offset < spaceEnd) {
spaceIndex = i;
break;
}
off_t distance;
if (offset < spaceOffset)
distance = spaceOffset - end;
else
distance = spaceEnd - offset;
if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
closestSpaceIndex = i;
closestSpaceDistance = distance;
}
}
// get the space we found
off_t spaceOffset, spaceSize;
info.GetPartitionableSpaceAt(
spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
&spaceSize);
off_t spaceEnd = spaceOffset + spaceSize;
// If the requested intervald doesn't intersect with any space yet, move
// it, so that it does.
if (spaceIndex < 0) {
spaceIndex = closestSpaceIndex;
if (offset < spaceOffset) {
offset = spaceOffset;
end = offset + size;
} else {
end = spaceEnd;
offset = end - size;
}
}
// move/shrink the interval, so that it fully lies within the space
if (offset < spaceOffset) {
offset = spaceOffset;
end = offset + size;
if (end > spaceEnd) {
end = spaceEnd;
size = end - offset;
}
} else if (end > spaceEnd) {
end = spaceEnd;
offset = end - size;
if (offset < spaceOffset) {
offset = spaceOffset;
size = end - offset;
}
}
*_offset = offset;
*_size = size;
return B_OK;
}
@@ -427,73 +420,69 @@ ExtendedPartitionHandle::CreateChild(off_t offset, off_t size,
BMutablePartition** _child)
{
// check type
if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0)
PartitionType type;
if (!type.SetType(typeString) || type.IsEmpty())
return B_BAD_VALUE;
// check name
if (name && strlen(name) > 0)
return B_BAD_VALUE;
// check parameters
// TODO:...
// offset properly aligned?
if (offset != sector_align(offset, Partition()->BlockSize())
|| size != sector_align(size, Partition()->BlockSize()))
return B_BAD_VALUE;
return B_NOT_SUPPORTED;
// // offset properly aligned?
// if (offset != sector_align(offset) || size != sector_align(size))
// return B_BAD_VALUE;
//
// // check the free space situation
// BPartitioningInfo info;
// status_t error = GetPartitioningInfo(&info);
// if (error != B_OK)
// return error;
//
// bool foundSpace = false;
// off_t end = offset + size;
// int32 spacesCount = info.CountPartitionableSpaces();
// for (int32 i = 0; i < spacesCount; i++) {
// off_t spaceOffset, spaceSize;
// info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
// off_t spaceEnd = spaceOffset + spaceSize;
//
// if (offset >= spaceOffset && end <= spaceEnd) {
// foundSpace = true;
// break;
// }
// }
//
// if (!foundSpace)
// return B_BAD_VALUE;
//
// // everything looks good, do it
//
// // create the child
// // (Note: the primary partition index is indeed the child index, since
// // we picked the first empty primary partition.)
// BMutablePartition* partition = Partition();
// BMutablePartition* child;
// error = partition->CreateChild(primary->Index(), typeString, NULL,
// parameters, &child);
// if (error != B_OK)
// return error;
//
// // init the child
// child->SetOffset(offset);
// child->SetSize(size);
// child->SetBlockSize(SECTOR_SIZE);
// //child->SetFlags(0);
// child->SetChildCookie(primary);
//
// // init the primary partition
// bool active = false;
// // TODO: Get from parameters!
// primary->SetTo(offset, size, type.Type(), active);
//
//// TODO: If the child is an extended partition, we should trigger its
//// initialization.
//
// *_child = child;
// return B_OK;
// check the free space situation
BPartitioningInfo info;
status_t error = GetPartitioningInfo(&info);
if (error != B_OK)
return error;
bool foundSpace = false;
off_t end = offset + size;
int32 spacesCount = info.CountPartitionableSpaces();
for (int32 i = 0; i < spacesCount; i++) {
off_t spaceOffset, spaceSize;
info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
off_t spaceEnd = spaceOffset + spaceSize;
if (offset >= spaceOffset && end <= spaceEnd) {
foundSpace = true;
break;
}
}
if (!foundSpace)
return B_BAD_VALUE;
// everything looks good, do it
// create the child
BMutablePartition* child;
error = Partition()->CreateChild(-1, typeString,
NULL, parameters, &child);
if (error != B_OK)
return error;
// init the child
child->SetOffset(offset);
child->SetSize(size);
child->SetBlockSize(Partition()->BlockSize());
//child->SetFlags(0);
child->SetChildCookie(Partition());
*_child = child;
return B_OK;
}
// DeleteChild
status_t
ExtendedPartitionHandle::DeleteChild(BMutablePartition* child)
{
BMutablePartition* parent = child->Parent();
status_t error = parent->DeleteChild(child);
return error;
}
@@ -62,6 +62,8 @@ public:
const char* type, const char* name,
const char* parameters,
BMutablePartition** child);
virtual status_t DeleteChild(BMutablePartition* child);
private:
PrimaryPartition* fPrimaryPartition;
};
@@ -166,13 +166,13 @@ is_inside_partitions(off_t location, const Partition** partitions, int32 count)
int32 upper = count - 1;
while (lower < upper) {
int32 mid = (lower + upper) / 2;
const Partition *midPartition = partitions[mid];
const Partition* midPartition = partitions[mid];
if (location >= midPartition->Offset() + midPartition->Size())
lower = mid + 1;
else
upper = mid;
}
const Partition *partition = partitions[lower];
const Partition* partition = partitions[lower];
result = (location >= partition->Offset() &&
location < partition->Offset() + partition->Size());
}
@@ -207,7 +207,7 @@ PartitionType::SetType(uint8 type)
\param typeName Name of the partition type.
*/
bool
PartitionType::SetType(const char *typeName)
PartitionType::SetType(const char* typeName)
{
for (int32 i = 0; kPartitionTypes[i].name ; i++) {
if (!strcmp(typeName, kPartitionTypes[i].name)) {
@@ -237,7 +237,7 @@ PartitionType::SetType(const char *typeName)
\param content_type Name of the content type, it is standardized by system.
*/
bool
PartitionType::SetContentType(const char *contentType)
PartitionType::SetContentType(const char* contentType)
{
for (int32 i = 0; kPartitionContentTypes[i].name ; i++) {
if (!strcmp(contentType, kPartitionContentTypes[i].name)) {
@@ -319,7 +319,7 @@ Partition::Partition(const partition_descriptor* descriptor, off_t tableOffset,
void
Partition::SetTo(const partition_descriptor *descriptor, off_t tableOffset,
Partition::SetTo(const partition_descriptor* descriptor, off_t tableOffset,
off_t baseOffset, uint32 blockSize)
{
TRACE(("Partition::SetTo(): active: %x\n", descriptor->active));
@@ -356,19 +356,6 @@ Partition::Unset()
}
void
Partition::GetPartitionDescriptor(partition_descriptor *descriptor,
off_t baseOffset) const
{
descriptor->start = (fOffset - baseOffset) / fBlockSize;
descriptor->size = fSize / fBlockSize;
descriptor->type = fType;
descriptor->active = fActive ? 0x80 : 0x00;
descriptor->begin.Unset();
descriptor->end.Unset();
}
#ifdef _BOOT_MODE
void
Partition::AdjustSize(off_t sessionSize)
@@ -389,7 +376,8 @@ Partition::CheckLocation(off_t sessionSize) const
// lie within the session
if (fPartitionTableOffset % fBlockSize != 0) {
TRACE(("Partition::CheckLocation() - bad partition table offset: %lld "
"(session: %lld)\n", fPartitionTableOffset, sessionSize));
"(session: %lld), (fBlockSize: %ld)\n", fPartitionTableOffset,
sessionSize, fBlockSize));
return false;
}
if (fOffset % fBlockSize != 0) {
@@ -426,7 +414,8 @@ Partition::CheckLocation(off_t sessionSize) const
PrimaryPartition::PrimaryPartition()
: Partition(),
:
Partition(),
fHead(NULL),
fTail(NULL),
fLogicalPartitionCount(0)
@@ -455,7 +444,7 @@ PrimaryPartition::SetTo(off_t offset, off_t size, uint8 type, bool active,
void
PrimaryPartition::Unset()
{
while (LogicalPartition *partition = fHead) {
while (LogicalPartition* partition = fHead) {
fHead = partition->Next();
delete partition;
}
@@ -470,13 +459,13 @@ status_t
PrimaryPartition::Assign(const PrimaryPartition& other)
{
partition_descriptor descriptor;
other.GetPartitionDescriptor(&descriptor, 0);
other.GetPartitionDescriptor(&descriptor);
SetTo(&descriptor, 0, other.BlockSize());
const LogicalPartition* otherLogical = other.fHead;
while (otherLogical) {
off_t tableOffset = otherLogical->PartitionTableOffset();
otherLogical->GetPartitionDescriptor(&descriptor, tableOffset);
otherLogical->GetPartitionDescriptor(&descriptor);
LogicalPartition* logical = new(nothrow) LogicalPartition(
&descriptor, tableOffset, this);
@@ -492,10 +481,26 @@ PrimaryPartition::Assign(const PrimaryPartition& other)
}
void
PrimaryPartition::GetPartitionDescriptor(partition_descriptor* descriptor) const
{
if (IsEmpty()) {
memset(descriptor, 0, sizeof(partition_descriptor));
} else {
descriptor->start = Offset() / BlockSize();
descriptor->size = Size() / BlockSize();
descriptor->type = Type();
descriptor->active = Active() ? 0x80 : 0x00;
descriptor->begin.Unset();
descriptor->end.Unset();
}
}
LogicalPartition*
PrimaryPartition::LogicalPartitionAt(int32 index) const
{
LogicalPartition *partition = NULL;
LogicalPartition* partition = NULL;
if (index >= 0 && index < fLogicalPartitionCount) {
for (partition = fHead; index > 0; index--)
partition = partition->Next();
@@ -530,8 +535,8 @@ PrimaryPartition::RemoveLogicalPartition(LogicalPartition* partition)
if (!partition || partition->GetPrimaryPartition() != this)
return;
LogicalPartition *prev = partition->Previous();
LogicalPartition *next = partition->Next();
LogicalPartition* prev = partition->Previous();
LogicalPartition* next = partition->Next();
if (prev)
prev->SetNext(next);
@@ -554,7 +559,8 @@ PrimaryPartition::RemoveLogicalPartition(LogicalPartition* partition)
LogicalPartition::LogicalPartition()
: Partition(),
:
Partition(),
fPrimary(NULL),
fNext(NULL),
fPrevious(NULL)
@@ -564,7 +570,8 @@ LogicalPartition::LogicalPartition()
LogicalPartition::LogicalPartition(const partition_descriptor* descriptor,
off_t tableOffset, PrimaryPartition* primary)
: Partition(),
:
Partition(),
fPrimary(NULL),
fNext(NULL),
fPrevious(NULL)
@@ -601,7 +608,7 @@ LogicalPartition::SetTo(const partition_descriptor* descriptor,
void
LogicalPartition::SetTo(off_t offset, off_t size, uint8 type, bool active,
off_t tableOffset, PrimaryPartition *primary)
off_t tableOffset, PrimaryPartition* primary)
{
Unset();
if (primary) {
@@ -622,6 +629,27 @@ LogicalPartition::Unset()
}
void
LogicalPartition::GetPartitionDescriptor(partition_descriptor* descriptor,
bool inner) const
{
PrimaryPartition* primary = GetPrimaryPartition();
if (inner) {
descriptor->start = (PartitionTableOffset() - primary->Offset())
/ BlockSize();
descriptor->type = primary->Type();
} else {
descriptor->start = (Offset() - PartitionTableOffset()) / BlockSize();
descriptor->type = Type();
}
descriptor->size = Size() / BlockSize();
descriptor->active = 0x00;
descriptor->begin.Unset();
descriptor->end.Unset();
}
// #pragma mark - PartitionMap
@@ -661,7 +689,7 @@ PartitionMap::Assign(const PartitionMap& other)
PrimaryPartition*
PartitionMap::PrimaryPartitionAt(int32 index)
{
PrimaryPartition *partition = NULL;
PrimaryPartition* partition = NULL;
if (index >= 0 && index < 4)
partition = fPrimaries + index;
return partition;
@@ -671,7 +699,7 @@ PartitionMap::PrimaryPartitionAt(int32 index)
const PrimaryPartition*
PartitionMap::PrimaryPartitionAt(int32 index) const
{
const PrimaryPartition *partition = NULL;
const PrimaryPartition* partition = NULL;
if (index >= 0 && index < 4)
partition = fPrimaries + index;
return partition;
@@ -729,7 +757,7 @@ PartitionMap::CountNonEmptyPartitions() const
Partition*
PartitionMap::PartitionAt(int32 index)
{
Partition *partition = NULL;
Partition* partition = NULL;
int32 count = CountPartitions();
if (index >= 0 && index < count) {
if (index < 4)
@@ -776,7 +804,7 @@ PartitionMap::Check(off_t sessionSize) const
int32 tableOffsetCount = 1; // primary partition table
tableOffsets[0] = 0; //
for (int32 i = 0; i < partitionCount; i++) {
const Partition *partition = PartitionAt(i);
const Partition* partition = PartitionAt(i);
if (!partition->IsExtended())
byOffset[byOffsetCount++] = partition;
@@ -795,7 +823,7 @@ PartitionMap::Check(off_t sessionSize) const
// check for overlappings
off_t nextOffset = 0;
for (int32 i = 0; i < byOffsetCount; i++) {
const Partition *partition = byOffset[i];
const Partition* partition = byOffset[i];
if (partition->Offset() < nextOffset) {
TRACE(("intel: PartitionMap::Check(): overlapping partitions!"
"\n"));
@@ -31,7 +31,7 @@
// partition_type
struct partition_type {
uint8 type;
const char *name;
const char* name;
bool used;
};
@@ -54,13 +54,13 @@ is_extended_type(uint8 type)
// fill_buffer
static inline void
fill_buffer(char *buffer, uint32 length, char ch)
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
// NOTE: The CHS cannot express locations within larger disks and is therefor
@@ -113,8 +113,8 @@ public:
PartitionType();
bool SetType(uint8 type);
bool SetType(const char *typeName);
bool SetContentType(const char *contentType);
bool SetType(const char* typeName);
bool SetContentType(const char* contentType);
bool IsValid() const { return fValid; }
bool IsEmpty() const { return is_empty_type(fType); }
@@ -122,7 +122,7 @@ public:
uint8 Type() const { return fType; }
bool FindNext();
void GetTypeString(char *buffer) const
void GetTypeString(char* buffer) const
{ get_partition_type_string(fType, buffer); }
private:
uint8 fType;
@@ -167,11 +167,8 @@ public:
uint8 Type() const { return fType; }
bool Active() const { return fActive; }
uint32 BlockSize() const { return fBlockSize; }
void GetTypeString(char *buffer) const
void GetTypeString(char* buffer) const
{ get_partition_type_string(fType, buffer); }
void GetPartitionDescriptor(
partition_descriptor* descriptor,
off_t baseOffset) const;
void SetPartitionTableOffset(off_t offset)
{ fPartitionTableOffset = offset; }
@@ -183,6 +180,8 @@ public:
{ fType = type; }
void SetActive(bool active)
{ fActive = active; }
void SetBlockSize(uint32 blockSize)
{ fBlockSize = blockSize; }
bool CheckLocation(off_t sessionSize) const;
#ifdef _BOOT_MODE
@@ -215,6 +214,9 @@ public:
int32 Index() const { return fIndex; }
void SetIndex(int32 index) { fIndex = index; }
void GetPartitionDescriptor(
partition_descriptor* descriptor) const;
// private
// only if extended
@@ -240,7 +242,7 @@ public:
LogicalPartition(
const partition_descriptor* descriptor,
off_t tableOffset,
PrimaryPartition *primary);
PrimaryPartition* primary);
void SetTo(const partition_descriptor* descriptor,
off_t tableOffset,
@@ -249,6 +251,10 @@ public:
bool active, off_t tableOffset,
PrimaryPartition* primary);
void Unset();
void GetPartitionDescriptor(
partition_descriptor* descriptor,
bool inner = false) const;
void SetPrimaryPartition(PrimaryPartition* primary)
{ fPrimary = primary; }
@@ -130,7 +130,7 @@ PartitionMapParser::_ParsePrimary(const partition_table* table)
// parse extended partitions
status_t error = B_OK;
for (int32 i = 0; error == B_OK && i < 4; i++) {
PrimaryPartition *primary = fMap->PrimaryPartitionAt(i);
PrimaryPartition* primary = fMap->PrimaryPartitionAt(i);
if (primary->IsExtended())
error = _ParseExtended(primary, primary->Offset());
}
@@ -145,7 +145,7 @@ PartitionMapParser::_ParsePrimary(const partition_table* table)
// _ParseExtended
status_t
PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
PartitionMapParser::_ParseExtended(PrimaryPartition* primary, off_t offset)
{
status_t error = B_OK;
int32 partitionCount = 0;
@@ -188,11 +188,11 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
LogicalPartition extended;
LogicalPartition nonExtended;
for (int32 i = 0; error == B_OK && i < 4; i++) {
const partition_descriptor *descriptor = &fPartitionTable->table[i];
const partition_descriptor* descriptor = &fPartitionTable->table[i];
if (descriptor->is_empty())
continue;
LogicalPartition *partition = NULL;
LogicalPartition* partition = NULL;
if (descriptor->is_extended()) {
if (extended.IsEmpty()) {
extended.SetTo(descriptor, offset, primary);
@@ -232,7 +232,7 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
// add non-extended partition to list
if (error == B_OK && !nonExtended.IsEmpty()) {
LogicalPartition *partition
LogicalPartition* partition
= new(nothrow) LogicalPartition(nonExtended);
if (partition)
primary->AddLogicalPartition(partition);
@@ -3,7 +3,7 @@
* Distributed under the terms of the MIT License.
*
* Authors:
* Tomas Kucera, [email protected]
* Bryce Groff, [email protected]
*/
#include "PartitionMapWriter.h"
@@ -34,293 +34,225 @@ using std::nothrow;
#endif
// TODO: get rid of this - there is no such thing as a fixed sector size!
static const uint32 SECTOR_SIZE = 512;
bool
check_logical_location(const LogicalPartition* child,
const PrimaryPartition* parent)
{
if (child->PartitionTableOffset() % child->BlockSize() != 0) {
TRACE(("check_logical_location() - PartitionTableOffset: %lld not a "
"multiple of media's block size: %ld\n",
child->PartitionTableOffset(), child->BlockSize()));
return false;
}
if (child->Offset() % child->BlockSize() != 0) {
TRACE(("check_logical_location() - Parition offset: %lld "
"is not a multiple of block size: %ld\n", child->Offset(),
child->BlockSize()));
return false;
}
if (child->Size() % child->BlockSize() != 0) {
TRACE(("check_logical_location() - Size: (%lld) is not a multiple of"
" block size: (%ld)\n", child->Size(), child->BlockSize()));
return false;
}
if (child->PartitionTableOffset() < parent->Offset()
|| child->PartitionTableOffset() >= parent->Offset()
+ parent->Size()) {
TRACE(("check_logical_location() - Partition table: (%lld) not within "
"extended partition (start: %lld), (end: %lld)\n",
child->PartitionTableOffset(), parent->Offset(), parent->Offset()
+ parent->Size()));
return false;
}
if (child->Offset() + child->Size() > parent->Offset() + parent->Size()) {
TRACE(("check_logical_location() - logical paritition does not lie "
"within extended partition\n"));
return false;
}
return true;
}
// constructor
/*! \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.
*/
PartitionMapWriter::PartitionMapWriter(int deviceFD, off_t sessionOffset,
off_t sessionSize)
PartitionMapWriter::PartitionMapWriter(int deviceFD, uint32 blockSize)
:
fDeviceFD(deviceFD),
fSessionOffset(sessionOffset),
fSessionSize(sessionSize),
fMap(NULL)
fBlockSize(blockSize)
{
}
// destructor
PartitionMapWriter::~PartitionMapWriter()
{
}
// WriteMBR
/*! \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 pts Pointer to \c partition_table.
\param map Pointer to the PartitionMap structure describing disk partitions.
*/
status_t
PartitionMapWriter::WriteMBR(const PartitionMap *map, bool clearSectors)
PartitionMapWriter::WriteMBR(const PartitionMap* map, bool clearCode)
{
if (!map)
if (map == NULL)
return B_BAD_VALUE;
fMap = map;
uint8 sector[SECTOR_SIZE];
partition_table* pts = (partition_table*)sector;
// If we shall not clear the first two sectors, we need to read the first
// sector in, first.
status_t error = B_OK;
if (clearSectors)
memset(sector, 0, SECTOR_SIZE);
else
error = _ReadSector(0, pts);
if (error == B_OK) {
error = _WritePrimary(pts);
if (error == B_OK)
error = _WriteSector(0, pts);
partition_table partitionTable;
if (clearCode) {
partitionTable.clear_code_area();
} else {
status_t error = _ReadBlock(0, partitionTable);
if (error != B_OK)
return error;
}
// Clear the second sector, if desired. We do that to make the partition
// unrecognizable by BFS.
if (error == B_OK && clearSectors) {
memset(sector, 0, SECTOR_SIZE);
error = _WriteSector(SECTOR_SIZE, pts);
partitionTable.signature = kPartitionTableSectorSignature;
for (int i = 0; i < 4; i++) {
partition_descriptor* descriptor = &partitionTable.table[i];
const PrimaryPartition* partition = map->PrimaryPartitionAt(i);
partition->GetPartitionDescriptor(descriptor);
}
fMap = NULL;
status_t error = _WriteBlock(0, partitionTable);
return error;
}
// WriteLogical
/*! \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 does nothing with the connection
of previous logical partitions (call this function on previous logical
partition to ensure it).
\param pts Pointer to \c partition_table.
\param partition Pointer to the logical partition.
*/
status_t
PartitionMapWriter::WriteLogical(partition_table* pts,
const LogicalPartition* partition)
PartitionMapWriter::WriteLogical(const LogicalPartition* logical,
const PrimaryPartition* primary, bool clearCode)
{
if (partition == NULL)
if (logical == NULL || primary == NULL)
return B_BAD_VALUE;
partition_table _pts;
if (pts == NULL) {
// no partition table given, use stack based partition table and read
// from disk first
pts = &_pts;
status_t error = _ReadSector(partition->PartitionTableOffset(), pts);
if (error != B_OK)
return error;
}
status_t error = _WriteExtended(pts, partition, partition->Next());
if (error != B_OK)
return error;
return _WriteSector(partition->PartitionTableOffset(), pts);
}
// WriteExtendedHead
/*! \brief Writes Extended Boot Record to the first sector of Extended
Partition.
Writes the head of linked list describing logical partitions.
If the \a firstPartition is not specified, it only initializes EBR and the
linked list contains no logical partitions.
\param pts Pointer to \c partition_table.
\param firstPartition Pointer to the first logical partition.
*/
status_t
PartitionMapWriter::WriteExtendedHead(partition_table* pts,
const LogicalPartition* firstPartition)
{
LogicalPartition partition;
if (firstPartition != NULL)
partition.SetPrimaryPartition(firstPartition->GetPrimaryPartition());
partition_table _pts;
if (pts == NULL) {
// no partition table given, use stack based partition table and read
// from disk first
pts = &_pts;
status_t error = _ReadSector(0, pts);
if (error != B_OK)
return error;
}
status_t error = _WriteExtended(pts, &partition, firstPartition);
if (error != B_OK)
return error;
return _WriteSector(0, pts);
}
// #pragma mark - fill a partition table in memory
// _WritePrimary
status_t
PartitionMapWriter::_WritePrimary(partition_table* 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)) {
TRACE(("intel: _WritePrimary(): partition %ld: bad location, "
"ignoring\n", i));
return B_BAD_DATA;
}
partition->GetPartitionDescriptor(descriptor, 0);
// TODO: Should this be fSessionOffset?!
}
return B_OK;
}
// _WriteExtended
status_t
PartitionMapWriter::_WriteExtended(partition_table *pts,
const LogicalPartition *partition, const LogicalPartition *next)
{
if (pts == NULL || partition == NULL)
return B_BAD_VALUE;
// write the signature
pts->signature = kPartitionTableSectorSignature;
// check the partition's location
if (!partition->CheckLocation(fSessionSize)) {
TRACE(("intel: _WriteExtended(): Invalid partition "
"location: pts: %lld, offset: %lld, size: %lld, "
"fSessionSize: %lld\n",
partition->PartitionTableOffset(), partition->Offset(),
partition->Size(), fSessionSize));
if (!check_logical_location(logical, primary))
return B_BAD_DATA;
partition_table partitionTable;
if (clearCode) {
partitionTable.clear_code_area();
} else {
status_t error = _ReadBlock(logical->PartitionTableOffset(),
partitionTable);
if (error != B_OK)
return error;
}
// NOTE: The OS/2 boot manager needs the first entry to describe the
// data partition, while the second entry should describe the "inner
// extended" partition.
partitionTable.signature = kPartitionTableSectorSignature;
// write the table
partition_descriptor* descriptor = &(pts->table[0]);
partition->GetPartitionDescriptor(descriptor,
partition->PartitionTableOffset());
// location is relative to this partition's table offset
partition_descriptor* descriptor = &partitionTable.table[0];
logical->GetPartitionDescriptor(descriptor);
// Set offset and size of the next partition in the linked list.
// This is done via a so called "inner extended" partition which is
// only used to point to the next partition table location (start sector of
// the inner extended partition).
descriptor = &pts->table[1];
LogicalPartition extended;
if (next) {
extended.SetPartitionTableOffset(partition->PartitionTableOffset());
extended.SetOffset(next->PartitionTableOffset());
descriptor = &partitionTable.table[1];
if (logical->Next() != NULL)
logical->Next()->GetPartitionDescriptor(descriptor, true);
else
memset(descriptor, 0, sizeof(partition_descriptor));
// Strictly speaking, the size is not relevant and just needs to
// be non-zero. But some operating systems check the size of
// inner extended partitions and it needs to include the next data
// partition. Therefor the size is the size of the next data partition
// plus the offset between the next partition table and the data
// partition start offset.
// This assumes of course that the start offset is behind the partition
// table offset, which is actually not dictated by a minimal
// specification.
extended.SetSize(next->Size()
+ (next->Offset() - next->PartitionTableOffset()));
// Use the same extended partition type as the primary extended
// partition.
extended.SetType(partition->GetPrimaryPartition()->Type());
extended.GetPartitionDescriptor(descriptor, 0);
// Unsetting to get an empty descriptor for the remaining slots.
extended.Unset();
} else
extended.GetPartitionDescriptor(descriptor, 0);
// last two descriptors are empty ("extended" is unset)
// last two descriptors are empty
for (int32 i = 2; i < 4; i++) {
descriptor = &(pts->table[i]);
extended.GetPartitionDescriptor(descriptor, 0);
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
}
status_t error = _WriteBlock(logical->PartitionTableOffset(),
partitionTable);
return error;
}
status_t
PartitionMapWriter::WriteExtendedHead(const LogicalPartition* logical,
const PrimaryPartition* primary, bool clearCode)
{
if (primary == NULL)
return B_BAD_VALUE;
partition_table partitionTable;
if (clearCode) {
partitionTable.clear_code_area();
} else {
status_t error = _ReadBlock(primary->Offset(), partitionTable);
if (error != B_OK)
return error;
}
partitionTable.signature = kPartitionTableSectorSignature;
partition_descriptor* descriptor;
if (logical == NULL) {
for (int32 i = 0; i < 4; i++) {
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
}
} else {
LogicalPartition partition;
partition.SetPartitionTableOffset(primary->Offset());
partition.SetBlockSize(logical->BlockSize());
partition.SetOffset(logical->Offset());
partition.SetSize(logical->Size());
partition.SetType(logical->Type());
// set the logicals partition table to the correct location
descriptor = &partitionTable.table[0];
partition.GetPartitionDescriptor(descriptor);
descriptor = &partitionTable.table[1];
LogicalPartition* next = logical->Next();
if (next != NULL)
next->GetPartitionDescriptor(descriptor, true);
else
memset(descriptor, 0, sizeof(partition_descriptor));
// last two descriptors are empty
for (int32 i = 2; i < 4; i++) {
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
}
}
status_t error = _WriteBlock(primary->Offset(), partitionTable);
if (error != B_OK)
return error;
return B_OK;
}
// #pragma mark - to/from disk
// _ReadSector
/*! \brief Reads the sector from the disk.
*/
status_t
PartitionMapWriter::_ReadSector(off_t offset, partition_table* pts)
PartitionMapWriter::ClearExtendedHead(const PrimaryPartition* primary)
{
int32 toRead = sizeof(partition_table);
// same as SECTOR_SIZE actually
// check the offset
if (offset < 0 || offset + toRead > fSessionSize) {
TRACE(("intel: _ReadSector(): bad offset: %Ld\n", offset));
if (primary == NULL)
return B_BAD_VALUE;
partition_table partitionTable;
partitionTable.clear_code_area();
partitionTable.signature = kPartitionTableSectorSignature;
partition_descriptor* descriptor;
for (int32 i = 0; i < 4; i++) {
descriptor = &partitionTable.table[i];
memset(descriptor, 0, sizeof(partition_descriptor));
}
// read
offset += fSessionOffset;
if (read_pos(fDeviceFD, offset, pts, toRead) != toRead) {
#ifndef _BOOT_MODE
status_t error = _WriteBlock(primary->Offset(), partitionTable);
if (error != B_OK)
return error;
return B_OK;
}
status_t
PartitionMapWriter::_ReadBlock(off_t partitionOffset,
partition_table& partitionTable)
{
if (partitionOffset < 0)
return B_BAD_VALUE;
// TODO: If fBlockSize > sizeof(partition_table) then stop/read NULL after
if (read_pos(fDeviceFD, partitionOffset, &partitionTable, fBlockSize)
!= fBlockSize) {
status_t error = errno;
if (error == B_OK)
error = B_IO_ERROR;
#else
status_t error = B_IO_ERROR;
#endif
TRACE(("intel: _ReadSector(): reading the partition table failed: %lx\n",
error));
return error;
}
@@ -328,31 +260,19 @@ PartitionMapWriter::_ReadSector(off_t offset, partition_table* pts)
}
// _WriteSector
/*! \brief Writes the sector to the disk.
*/
status_t
PartitionMapWriter::_WriteSector(off_t offset, const partition_table* pts)
PartitionMapWriter::_WriteBlock(off_t partitionOffset,
const partition_table& partitionTable)
{
int32 toWrite = sizeof(partition_table);
// same as SECTOR_SIZE actually
// check the offset
if (offset < 0 || offset + toWrite > fSessionSize) {
TRACE(("intel: _WriteSector(): bad offset: %Ld\n", offset));
if (partitionOffset < 0)
return B_BAD_VALUE;
}
offset += fSessionOffset;
// write
if (write_pos(fDeviceFD, offset, pts, toWrite) != toWrite) {
// TODO: If fBlockSize > sizeof(partition_table) then stop/write NULL after
if (write_pos(fDeviceFD, partitionOffset, &partitionTable, fBlockSize)
!= fBlockSize) {
status_t error = errno;
if (error == B_OK)
error = B_IO_ERROR;
TRACE(("intel: _WriteSector(): writing the partition table failed: "
"%lx\n", error));
return error;
}
@@ -4,6 +4,7 @@
*
* Authors:
* Tomas Kucera, kucerat@centrum.cz
* Bryce Groff, brycegroff@gmail.com
*/
/*!
@@ -26,8 +27,12 @@
class PartitionMap;
class LogicalPartition;
class PrimaryPartition;
struct partition_table;
bool check_logical_location(const LogicalPartition* logical,
const PrimaryPartition* primary);
/*!
\brief Writer for "Intel" style partitions.
@@ -36,33 +41,32 @@ struct partition_table;
class PartitionMapWriter {
public:
PartitionMapWriter(int deviceFD,
off_t sessionOffset, off_t sessionSize);
uint32 blockSize);
~PartitionMapWriter();
status_t WriteMBR(const PartitionMap* map,
bool clearSectors);
status_t WriteLogical(partition_table* pts,
const LogicalPartition* partition);
status_t WriteExtendedHead(partition_table* pts,
const LogicalPartition* firstPartition);
bool clearCode);
status_t WriteLogical(const LogicalPartition* logical,
const PrimaryPartition* primary,
bool clearCode);
status_t WriteExtendedHead(
const LogicalPartition* logical,
const PrimaryPartition* primary,
bool clearCode);
status_t ClearExtendedHead(
const PrimaryPartition* primary);
private:
status_t _WritePrimary(partition_table* pts);
status_t _WriteExtended(partition_table* pts,
const LogicalPartition* partition,
const LogicalPartition* next);
status_t _ReadSector(off_t offset,
partition_table* pts);
status_t _WriteSector(off_t offset,
const partition_table* pts);
status_t _ReadBlock(off_t offset,
partition_table& partitionTable);
status_t _WriteBlock(off_t offset,
const partition_table& partitionTable);
private:
int fDeviceFD;
off_t fSessionOffset;
off_t fSessionSize;
int32 fBlockSize;
const PartitionMap* fMap; // while writing
};
#endif // PARTITION_MAP_WRITER_H
File diff suppressed because it is too large Load Diff
@@ -154,6 +154,22 @@ get_child_partition(partition_id partitionID, int32 index)
}
int
open_partition(partition_id partitionID, int openMode)
{
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->FindPartition(partitionID);
if (partition == NULL)
return B_BAD_VALUE;
int fd = -1;
status_t result = partition->Open(openMode, &fd);
if (result != B_OK)
return -1;
return fd;
}
// create_child_partition
partition_data *
create_child_partition(partition_id partitionID, int32 index, off_t offset,