* 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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user