From 1987b05aa02e2c9b2ff9f852cff73a249af7175a Mon Sep 17 00:00:00 2001 From: Bryce Groff Date: Mon, 10 Aug 2009 22:28:47 +0000 Subject: [PATCH] * 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 --- headers/os/drivers/disk_device_manager.h | 2 + .../intel/ExtendedPartitionAddOn.cpp | 339 ++++++----- .../intel/ExtendedPartitionAddOn.h | 2 + .../intel/PartitionMap.cpp | 96 ++-- .../partitioning_systems/intel/PartitionMap.h | 28 +- .../intel/PartitionMapParser.cpp | 10 +- .../intel/PartitionMapWriter.cpp | 430 ++++++-------- .../intel/PartitionMapWriter.h | 40 +- .../intel/write_support.cpp | 528 +++++++++--------- .../disk_device_manager.cpp | 16 + 10 files changed, 744 insertions(+), 747 deletions(-) diff --git a/headers/os/drivers/disk_device_manager.h b/headers/os/drivers/disk_device_manager.h index 8795742176..17c1b782c2 100644 --- a/headers/os/drivers/disk_device_manager.h +++ b/headers/os/drivers/disk_device_manager.h @@ -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, diff --git a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp index feebe0813f..21236a04b2 100644 --- a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp +++ b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp @@ -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; +} + diff --git a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h index 7fda49fe4e..99551a084b 100644 --- a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h +++ b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h @@ -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; }; diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index e4907ee18e..6d2ef66e42 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -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")); diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h index a20075fadf..36d0a02113 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h @@ -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; } diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp index be01c69ab0..5f16265e95 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp @@ -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); diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp index c881170420..6a064b1e6c 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp @@ -3,7 +3,7 @@ * Distributed under the terms of the MIT License. * * Authors: - * Tomas Kucera, kucerat@centrum.cz + * Bryce Groff, brycegroff@gmail.com */ #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; } diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.h index c6c1e7bffd..76b388a693 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.h @@ -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 diff --git a/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp b/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp index 81a78ecef1..5c9c549ad9 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp @@ -40,9 +40,9 @@ static const int32 MAX_MOVE_BUFFER = 2 * 1024 * 4; // for logical partitions in Intel Extended Partition // Count of free sectors after Partition Table Sector (at logical partition). -static const uint32 FREE_SECTORS_AFTER_PTS = 0; +static const uint32 FREE_SECTORS_AFTER_PTS = 63; // Count of free sectors after Master Boot Record. -static const uint32 FREE_SECTORS_AFTER_MBR = 0; +static const uint32 FREE_SECTORS_AFTER_MBR = 63; // size of logical partition header in blocks static const uint32 PTS_OFFSET = FREE_SECTORS_AFTER_PTS + 1; static const uint32 MBR_OFFSET = FREE_SECTORS_AFTER_MBR + 1; @@ -50,19 +50,19 @@ static const uint32 MBR_OFFSET = FREE_SECTORS_AFTER_MBR + 1; typedef partitionable_space_data PartitionPosition; -typedef void (*fc_get_sibling_partitions)(partition_data *partition, - partition_data *child, off_t childOffset, partition_data **prec, - partition_data **follow, off_t *prec_offset, off_t *prec_size, - off_t *follow_offset, off_t *follow_size); +typedef void (*fc_get_sibling_partitions)(partition_data* partition, + partition_data* child, off_t childOffset, partition_data** prec, + partition_data** follow, off_t* prec_offset, off_t* prec_size, + off_t* follow_offset, off_t* follow_size); -typedef int32 (*fc_fill_partitionable_spaces_buffer)(partition_data *partition, - PartitionPosition *positions); +typedef int32 (*fc_fill_partitionable_spaces_buffer)(partition_data* partition, + PartitionPosition* positions); -status_t pm_get_partitionable_spaces(partition_data *partition, - partitionable_space_data *buffer, int32 count, int32 *actualCount); -status_t ep_get_partitionable_spaces(partition_data *partition, - partitionable_space_data *buffer, int32 count, int32 *actualCount); +status_t pm_get_partitionable_spaces(partition_data* partition, + partitionable_space_data* buffer, int32 count, int32* actualCount); +status_t ep_get_partitionable_spaces(partition_data* partition, + partitionable_space_data* buffer, int32 count, int32* actualCount); // #pragma mark - Intel Partition Map - support functions @@ -105,7 +105,7 @@ pm_get_supported_child_operations(partition_data* partition, // pm_is_sub_system_for bool -pm_is_sub_system_for(partition_data *partition) +pm_is_sub_system_for(partition_data* partition) { // primary partition map doesn't naturally live in any other child partition return false; @@ -133,7 +133,7 @@ sector_align_up(off_t offset) // validate_resize (auxiliary function) static bool -validate_resize(partition_data *partition, off_t *size) +validate_resize(partition_data* partition, off_t* size) { off_t newSize = *size; // size remains the same? @@ -157,7 +157,7 @@ validate_resize(partition_data *partition, off_t *size) // If child->offset is relative to parent, then yes! off_t currentEnd = partition->offset + newSize; for (int32 i = 0; i < partition->child_count; i++) { - partition_data *child = get_child_partition(partition->id, i); + partition_data* child = get_child_partition(partition->id, i); if (child && child->offset + child->size > currentEnd) currentEnd = child->offset + child->size; } @@ -171,7 +171,7 @@ validate_resize(partition_data *partition, off_t *size) // pm_validate_resize bool -pm_validate_resize(partition_data *partition, off_t *size) +pm_validate_resize(partition_data* partition, off_t* size) { TRACE(("intel: pm_validate_resize\n")); @@ -184,7 +184,7 @@ pm_validate_resize(partition_data *partition, off_t *size) // get_offset_ep (auxiliary function) static inline off_t -get_offset_ep(const partition_data *partition) +get_offset_ep(const partition_data* partition) { LogicalPartition *logical = (LogicalPartition *)partition->cookie; off_t diff_offset = logical->Offset() - logical->PartitionTableOffset(); @@ -194,7 +194,7 @@ get_offset_ep(const partition_data *partition) // get_size_ep (auxiliary function) static inline off_t -get_size_ep(const partition_data *partition) +get_size_ep(const partition_data* partition) { LogicalPartition *logical = (LogicalPartition *)partition->cookie; off_t diff_offset = logical->Offset() - logical->PartitionTableOffset(); @@ -209,16 +209,16 @@ get_size_ep(const partition_data *partition) partition - Intel Partition Map */ static void -get_sibling_partitions_pm(partition_data *partition, - partition_data *child, off_t childOffset, partition_data **previous, - partition_data **next, off_t *previousOffset, off_t *previousSize, - off_t *nextOffset, off_t *nextSize) +get_sibling_partitions_pm(partition_data* partition, + partition_data* child, off_t childOffset, partition_data** previous, + partition_data** next, off_t* previousOffset, off_t* previousSize, + off_t* nextOffset, off_t* nextSize) { // finding out sibling partitions - partition_data *previousSibling = NULL; - partition_data *nextSibling = NULL; + partition_data* previousSibling = NULL; + partition_data* nextSibling = NULL; for (int32 i = 0; i < partition->child_count; i++) { - partition_data *sibling = get_child_partition(partition->id, i); + partition_data* sibling = get_child_partition(partition->id, i); if (sibling && sibling != child) { if (sibling->offset <= childOffset) { if (!previousSibling || previousSibling->offset < sibling->offset) @@ -250,16 +250,16 @@ get_sibling_partitions_pm(partition_data *partition, partition - Intel Extended Partition */ static void -get_sibling_partitions_ep(partition_data *partition, - partition_data *child, off_t childOffset, partition_data **previous, - partition_data **next, off_t *previousOffset, off_t *previousSize, - off_t *nextOffset, off_t *nextSize) +get_sibling_partitions_ep(partition_data* partition, + partition_data* child, off_t childOffset, partition_data** previous, + partition_data** next, off_t* previousOffset, off_t* previousSize, + off_t* nextOffset, off_t* nextSize) { // finding out sibling partitions - partition_data *previousSibling = NULL; - partition_data *nextSibling = NULL; + partition_data* previousSibling = NULL; + partition_data* nextSibling = NULL; for (int32 i = 0; i < partition->child_count; i++) { - partition_data *sibling = get_child_partition(partition->id, i); + partition_data* sibling = get_child_partition(partition->id, i); if (sibling && sibling != child) { if (get_offset_ep(sibling) <= childOffset) { if (!previousSibling || previousSibling->offset < sibling->offset) @@ -286,8 +286,8 @@ get_sibling_partitions_ep(partition_data *partition, // validate_resize_child (auxiliary function) static bool -validate_resize_child(partition_data *partition, partition_data *child, - off_t childOffset, off_t childSize, off_t *size, +validate_resize_child(partition_data* partition, partition_data* child, + off_t childOffset, off_t childSize, off_t* size, fc_get_sibling_partitions getSiblingPartitions) { // size remains the same? @@ -308,8 +308,8 @@ validate_resize_child(partition_data *partition, partition_data *child, // child must not intersect with sibling partitions // finding out sibling partitions - partition_data *previousSibling = NULL; - partition_data *nextSibling = NULL; + partition_data* previousSibling = NULL; + partition_data* nextSibling = NULL; off_t previousOffset = 0, previousSize = 0, nextOffset = 0, nextSize = 0; getSiblingPartitions(partition, child, childOffset, &previousSibling, @@ -324,8 +324,8 @@ validate_resize_child(partition_data *partition, partition_data *child, // pm_validate_resize_child bool -pm_validate_resize_child(partition_data *partition, partition_data *child, - off_t *size) +pm_validate_resize_child(partition_data* partition, partition_data* child, + off_t* size) { TRACE(("intel: pm_validate_resize_child\n")); @@ -339,7 +339,7 @@ pm_validate_resize_child(partition_data *partition, partition_data *child, // pm_validate_move bool -pm_validate_move(partition_data *partition, off_t *start) +pm_validate_move(partition_data* partition, off_t* start) { TRACE(("intel: pm_validate_move\n")); @@ -352,8 +352,8 @@ pm_validate_move(partition_data *partition, off_t *start) // validate_move_child (auxiliary function) static bool -validate_move_child(partition_data *partition, partition_data *child, - off_t childOffset, off_t childSize, off_t *_start, +validate_move_child(partition_data* partition, partition_data* child, + off_t childOffset, off_t childSize, off_t* _start, fc_get_sibling_partitions getSiblingPartitions) { off_t start = *_start; @@ -366,8 +366,8 @@ validate_move_child(partition_data *partition, partition_data *child, start = sector_align(start); // finding out sibling partitions - partition_data *previousSibling = NULL; - partition_data *nextSibling = NULL; + partition_data* previousSibling = NULL; + partition_data* nextSibling = NULL; off_t previousOffset = 0, previousSize = 0, nextOffset = 0, nextSize = 0; getSiblingPartitions(partition, child, childOffset, &previousSibling, @@ -394,8 +394,8 @@ validate_move_child(partition_data *partition, partition_data *child, // pm_validate_move_child bool -pm_validate_move_child(partition_data *partition, partition_data *child, - off_t *start) +pm_validate_move_child(partition_data* partition, partition_data* child, + off_t* start) { TRACE(("intel: pm_validate_move_child\n")); @@ -415,8 +415,8 @@ pm_validate_move_child(partition_data *partition, partition_data *child, child can be NULL */ static bool -is_type_valid_pm(const char *type, partition_data *partition, - PrimaryPartition *child = NULL) +is_type_valid_pm(const char* type, partition_data* partition, + PrimaryPartition* child = NULL) { // validity check of the type PartitionType ptype; @@ -426,11 +426,11 @@ is_type_valid_pm(const char *type, partition_data *partition, // only one extended partition is allowed if (ptype.IsExtended()) { - PartitionMap *map = (PartitionMap*)partition->content_cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; if (!map) return false; for (int32 i = 0; i < partition->child_count; i++) { - PrimaryPartition *primary = map->PrimaryPartitionAt(i); + PrimaryPartition* primary = map->PrimaryPartitionAt(i); if (primary && primary->IsExtended() && primary != child) return false; } @@ -441,28 +441,28 @@ is_type_valid_pm(const char *type, partition_data *partition, // pm_validate_set_type bool -pm_validate_set_type(partition_data *partition, const char *type) +pm_validate_set_type(partition_data* partition, const char* type) { TRACE(("intel: pm_validate_set_type\n")); if (!partition || !type) return false; - partition_data *father = get_parent_partition(partition->id); - if (!father) + partition_data* parent = get_parent_partition(partition->id); + if (!parent) return false; - PrimaryPartition *child = (PrimaryPartition*)partition->cookie; + PrimaryPartition* child = (PrimaryPartition*)partition->cookie; if (!child) return false; // validity check of the type - return is_type_valid_pm(type, father, child); + return is_type_valid_pm(type, parent, child); } // pm_validate_initialize bool -pm_validate_initialize(partition_data *partition, char *name, - const char *parameters) +pm_validate_initialize(partition_data* partition, char* name, + const char* parameters) { TRACE(("intel: pm_validate_initialize\n")); @@ -483,8 +483,8 @@ pm_validate_initialize(partition_data *partition, char *name, // validate_create_child_partition (auxiliary function) static bool -validate_create_child_partition(partition_data *partition, off_t *start, - off_t *size, fc_get_sibling_partitions getSiblingPartitions) +validate_create_child_partition(partition_data* partition, off_t* start, + off_t* size, fc_get_sibling_partitions getSiblingPartitions) { // make the start and size a multiple of the block size *start = sector_align(*start); @@ -501,8 +501,8 @@ validate_create_child_partition(partition_data *partition, off_t *start, // new child must not intersect with sibling partitions // finding out sibling partitions - partition_data *previousSibling = NULL; - partition_data *nextSibling = NULL; + partition_data* previousSibling = NULL; + partition_data* nextSibling = NULL; off_t previousOffset = 0, previousSize = 0, nextOffset = 0, nextSize = 0; getSiblingPartitions(partition, NULL, *start, &previousSibling, @@ -529,8 +529,8 @@ validate_create_child_partition(partition_data *partition, off_t *start, index - returns position of the new partition (first free record in MBR) */ bool -pm_validate_create_child(partition_data *partition, off_t *start, off_t *size, - const char *type, const char *name, const char *parameters, int32 *index) +pm_validate_create_child(partition_data* partition, off_t* start, off_t* size, + const char* type, const char* name, const char* parameters, int32* index) { TRACE(("intel: pm_validate_create_child\n")); @@ -548,12 +548,12 @@ pm_validate_create_child(partition_data *partition, off_t *start, off_t *size, // finding out index of the new partition (first free record in MBR) // at least one record has to be free - PartitionMap *map = (PartitionMap*)partition->content_cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; if (!map) return false; int32 newIndex = -1; for (int32 i = 0; i < 4; i++) { - PrimaryPartition *primary = map->PrimaryPartitionAt(i); + PrimaryPartition* primary = map->PrimaryPartitionAt(i); if (primary->IsEmpty()) { newIndex = i; break; @@ -564,8 +564,8 @@ pm_validate_create_child(partition_data *partition, off_t *start, off_t *size, return false; *index = newIndex; - if (*start < partition->offset + MBR_OFFSET * SECTOR_SIZE) { - *start = partition->offset + MBR_OFFSET * SECTOR_SIZE; + if (*start < partition->offset + MBR_OFFSET * partition->block_size) { + *start = partition->offset + MBR_OFFSET * partition->block_size; *start = sector_align_up(*start); } @@ -576,7 +576,7 @@ pm_validate_create_child(partition_data *partition, off_t *start, off_t *size, // cmp_partition_position static int -cmp_partition_position(const void *o1, const void *o2) +cmp_partition_position(const void* o1, const void* o2) { off_t offset1 = ((PartitionPosition*)o1)->offset; off_t offset2 = ((PartitionPosition*)o2)->offset; @@ -596,12 +596,12 @@ cmp_partition_position(const void *o1, const void *o2) returns partition count */ static int32 -fill_partitionable_spaces_buffer_pm(partition_data *partition, - PartitionPosition *positions) +fill_partitionable_spaces_buffer_pm(partition_data* partition, + PartitionPosition* positions) { int32 partition_count = 0; for (int32 i = 0; i < partition->child_count; i++) { - const partition_data *child = get_child_partition(partition->id, i); + const partition_data* child = get_child_partition(partition->id, i); if (child) { positions[partition_count].offset = child->offset; positions[partition_count].size = child->size; @@ -618,12 +618,12 @@ fill_partitionable_spaces_buffer_pm(partition_data *partition, returns partition count */ static int32 -fill_partitionable_spaces_buffer_ep(partition_data *partition, - PartitionPosition *positions) +fill_partitionable_spaces_buffer_ep(partition_data* partition, + PartitionPosition* positions) { int32 partition_count = 0; for (int32 i = 0; i < partition->child_count; i++) { - const partition_data *child = get_child_partition(partition->id, i); + const partition_data* child = get_child_partition(partition->id, i); if (child) { positions[partition_count].offset = get_offset_ep(child); positions[partition_count].size = get_size_ep(child); @@ -636,12 +636,12 @@ fill_partitionable_spaces_buffer_ep(partition_data *partition, // get_partitionable_spaces (auxiliary function) static status_t -get_partitionable_spaces(partition_data *partition, - partitionable_space_data *buffer, int32 count, int32 *_actualCount, +get_partitionable_spaces(partition_data* partition, + partitionable_space_data* buffer, int32 count, int32* _actualCount, fc_fill_partitionable_spaces_buffer fillBuffer, off_t startOffset, off_t limitSize = 0, off_t headerSize = 0) { - PartitionPosition *positions + PartitionPosition* positions = new(nothrow) PartitionPosition[partition->child_count]; if (!positions) return B_NO_MEMORY; @@ -658,12 +658,11 @@ get_partitionable_spaces(partition_data *partition, // offset alignment (to upper bound) offset = sector_align_up(offset); - // finding out all partitionable spaces for (int32 i = 0; i < partition_count; i++) { size = positions[i].offset - offset; size = sector_align(size); - if (size > limitSize) { + if (size >= limitSize) { if (actualCount < count) { buffer[actualCount].offset = offset; buffer[actualCount].size = size; @@ -700,8 +699,8 @@ get_partitionable_spaces(partition_data *partition, // pm_get_partitionable_spaces status_t -pm_get_partitionable_spaces(partition_data *partition, - partitionable_space_data *buffer, int32 count, int32 *actualCount) +pm_get_partitionable_spaces(partition_data* partition, + partitionable_space_data* buffer, int32 count, int32* actualCount) { TRACE(("intel: pm_get_partitionable_spaces\n")); @@ -714,15 +713,15 @@ pm_get_partitionable_spaces(partition_data *partition, return B_BAD_VALUE; return get_partitionable_spaces(partition, buffer, count, actualCount, - fill_partitionable_spaces_buffer_pm, MBR_OFFSET * SECTOR_SIZE, + fill_partitionable_spaces_buffer_pm, MBR_OFFSET * partition->block_size, 0, 0); } // pm_get_next_supported_type status_t -pm_get_next_supported_type(partition_data *partition, int32 *cookie, - char *_type) +pm_get_next_supported_type(partition_data* partition, int32* cookie, + char* _type) { TRACE(("intel: pm_get_next_supported_type\n")); @@ -758,7 +757,7 @@ pm_get_next_supported_type(partition_data *partition, int32 *cookie, // pm_shadow_changed status_t -pm_shadow_changed(partition_data *partition, partition_data *child, +pm_shadow_changed(partition_data* partition, partition_data* child, uint32 operation) { TRACE(("intel: pm_shadow_changed(%p, %p, %lu)\n", partition, child, @@ -934,7 +933,7 @@ pm_resize(int fd, partition_id partitionID, off_t size, disk_job_id job) return B_ERROR; // get out partition - partition_data *partition = get_partition(partitionID); + partition_data* partition = get_partition(partitionID); if (!partition) return B_BAD_VALUE; @@ -972,12 +971,12 @@ pm_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job) return B_ERROR; // get out partition, child and partition map structure - partition_data *partition = get_parent_partition(partitionID); - partition_data *child = get_partition(partitionID); + partition_data* partition = get_parent_partition(partitionID); + partition_data* child = get_partition(partitionID); if (!partition || !child) return B_BAD_VALUE; - PartitionMap *map = (PartitionMap*)partition->content_cookie; - PrimaryPartition *primary = (PrimaryPartition*)child->cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; + PrimaryPartition* primary = (PrimaryPartition*)child->cookie; if (!map || !primary) return B_BAD_VALUE; @@ -994,7 +993,7 @@ pm_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job) primary->SetSize(validatedSize); // TODO: The partition is not supposed to be locked here! - PartitionMapWriter writer(fd, 0, partition->size); + PartitionMapWriter writer(fd, primary->BlockSize()); // TODO: disk size? status_t error = writer.WriteMBR(map, false); if (error != B_OK) { @@ -1028,7 +1027,7 @@ pm_move(int fd, partition_id partitionID, off_t offset, disk_job_id job) return B_ERROR; // get out partition - partition_data *partition = get_partition(partitionID); + partition_data* partition = get_partition(partitionID); if (!partition) return B_BAD_VALUE; @@ -1049,7 +1048,7 @@ pm_move(int fd, partition_id partitionID, off_t offset, disk_job_id job) or returns NULL - B_NO_MEMORY */ static uint8* -allocate_buffer(uint32 blockSize, int32 tryAlloc, int32 *allocated) +allocate_buffer(uint32 blockSize, int32 tryAlloc, int32* allocated) { uint8* buffer = NULL; for (int32 i = tryAlloc; i > 1; i /= 2) { @@ -1066,7 +1065,7 @@ allocate_buffer(uint32 blockSize, int32 tryAlloc, int32 *allocated) // move_block (auxiliary function) static status_t -move_block(int fd, off_t fromOffset, off_t toOffset, uint8 *buffer, int32 size) +move_block(int fd, off_t fromOffset, off_t toOffset, uint8* buffer, int32 size) { status_t error = B_OK; // read block to buffer @@ -1093,7 +1092,7 @@ move_block(int fd, off_t fromOffset, off_t toOffset, uint8 *buffer, int32 size) // move_partition (auxiliary function) static status_t move_partition(int fd, off_t fromOffset, off_t toOffset, off_t size, - uint8 *buffer, int32 buffer_size, disk_job_id job) + uint8* buffer, int32 buffer_size, disk_job_id job) { // TODO: This should be a service function of the DDM! // TODO: This seems to be broken if source and destination overlap. @@ -1131,12 +1130,12 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID, return B_ERROR; // get partition, child and partition map structure - partition_data *partition = get_partition(partitionID); - partition_data *child = get_partition(childID); + partition_data* partition = get_partition(partitionID); + partition_data* child = get_partition(childID); if (!partition || !child) return B_BAD_VALUE; - PartitionMap *map = (PartitionMap*)partition->content_cookie; - PrimaryPartition *primary = (PrimaryPartition*)child->cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; + PrimaryPartition* primary = (PrimaryPartition*)child->cookie; if (!map || !primary) return B_BAD_VALUE; @@ -1151,7 +1150,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID, // buffer allocation int32 allocated; - uint8 *buffer = allocate_buffer(SECTOR_SIZE, MAX_MOVE_BUFFER, + uint8* buffer = allocate_buffer(partition->block_size, MAX_MOVE_BUFFER, &allocated); if (!buffer) return B_NO_MEMORY; @@ -1161,7 +1160,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID, update_disk_device_job_progress(job, 0.0); status_t error = B_OK; error = move_partition(fd, child->offset, validatedOffset, child->size, - buffer, allocated * SECTOR_SIZE, job); + buffer, allocated * partition->block_size, job); delete[] buffer; if (error != B_OK) return error; @@ -1171,7 +1170,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID, child->offset = validatedOffset; primary->SetOffset(validatedOffset); - PartitionMapWriter writer(fd, 0, partition->size); + PartitionMapWriter writer(fd, partition->block_size); // TODO: disk size? error = writer.WriteMBR(map, false); if (error != B_OK) @@ -1188,7 +1187,7 @@ pm_move_child(int fd, partition_id partitionID, partition_id childID, // pm_set_type status_t -pm_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) +pm_set_type(int fd, partition_id partitionID, const char* type, disk_job_id job) { TRACE(("intel: pm_set_type\n")); @@ -1200,12 +1199,12 @@ pm_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) return B_ERROR; // get parent partition, child and partition map structure - partition_data *partition = get_parent_partition(partitionID); - partition_data *child = get_partition(partitionID); + partition_data* partition = get_parent_partition(partitionID); + partition_data* child = get_partition(partitionID); if (!partition || !child) return B_BAD_VALUE; - PartitionMap *map = (PartitionMap*)partition->content_cookie; - PrimaryPartition *primary = (PrimaryPartition*)child->cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; + PrimaryPartition* primary = (PrimaryPartition*)child->cookie; if (!map || !primary) return B_BAD_VALUE; @@ -1230,7 +1229,7 @@ pm_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) primary->SetType(ptype.Type()); // TODO: The partition is not supposed to be locked at this point! - PartitionMapWriter writer(fd, 0, partition->size); + PartitionMapWriter writer(fd, primary->BlockSize()); // TODO: disk size? status_t error = writer.WriteMBR(map, false); if (error != B_OK) { @@ -1253,21 +1252,29 @@ pm_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) // pm_initialize status_t -pm_initialize(int fd, partition_id partitionID, const char *name, - const char *parameters, off_t partitionSize, disk_job_id job) +pm_initialize(int fd, partition_id partitionID, const char* name, + const char* parameters, off_t partitionSize, disk_job_id job) { TRACE(("intel: pm_initialize\n")); if (fd < 0) return B_ERROR; + PartitionWriteLocker locker(partitionID); + if (!locker.IsLocked()) + return B_ERROR; + + // get partition and partition map structure + partition_data* partition = get_partition(partitionID); + if (!partition) + return B_BAD_VALUE; update_disk_device_job_progress(job, 0.0); // we will write an empty partition map PartitionMap map; // write the sector to disk - PartitionMapWriter writer(fd, 0, partitionSize); + PartitionMapWriter writer(fd, partition->block_size); // TODO: disk size or 2 * SECTOR_SIZE? status_t error = writer.WriteMBR(&map, true); if (error != B_OK) @@ -1292,8 +1299,8 @@ pm_initialize(int fd, partition_id partitionID, const char *name, */ status_t pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, - const char *type, const char *name, const char *parameters, - disk_job_id job, partition_id *childID) + const char* type, const char* name, const char* parameters, + disk_job_id job, partition_id* childID) { TRACE(("intel: pm_create_child\n")); @@ -1305,10 +1312,10 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, return B_ERROR; // get partition and partition map structure - partition_data *partition = get_partition(partitionID); + partition_data* partition = get_partition(partitionID); if (!partition) return B_BAD_VALUE; - PartitionMap *map = (PartitionMap*)partition->content_cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; if (!map) return B_BAD_VALUE; @@ -1325,13 +1332,13 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, // finding out free primary partition in the map (index from // pm_validate_create_child) - PrimaryPartition *primary = map->PrimaryPartitionAt(index); + PrimaryPartition* primary = map->PrimaryPartitionAt(index); if (!primary->IsEmpty()) return B_BAD_DATA; // creating partition update_disk_device_job_progress(job, 0.0); - partition_data *child = create_child_partition(partition->id, index, + partition_data* child = create_child_partition(partition->id, index, validatedOffset, validatedSize, *childID); if (!child) return B_ERROR; @@ -1340,16 +1347,17 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, ptype.SetType(type); // check parameters - void *handle = parse_driver_settings_string(parameters); + void* handle = parse_driver_settings_string(parameters); if (handle == NULL) return B_ERROR; bool active = get_driver_boolean_parameter(handle, "active", false, true); + delete_driver_settings(handle); // set the active flags to false if (active) { for (int i = 0; i < 4; i++) { - PrimaryPartition *partition = map->PrimaryPartitionAt(i); + PrimaryPartition* partition = map->PrimaryPartitionAt(i); partition->SetActive(false); } } @@ -1361,8 +1369,8 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, primary->SetActive(active); // write changes to disk - PartitionMapWriter writer(fd, 0, partition->size); - // TODO: disk size or 2 * SECTOR_SIZE? + PartitionMapWriter writer(fd, primary->BlockSize()); + // TODO: The partition is not supposed to be locked at this point! status_t error = writer.WriteMBR(map, false); if (error != B_OK) { @@ -1374,7 +1382,7 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, *childID = child->id; - child->block_size = SECTOR_SIZE; + child->block_size = primary->BlockSize(); // (no name) child->type = strdup(type); // parameters @@ -1384,6 +1392,14 @@ pm_create_child(int fd, partition_id partitionID, off_t offset, off_t size, if (!child->type || !child->parameters) return B_NO_MEMORY; + // rescan partition if needed + if (strcmp(type, INTEL_EXTENDED_PARTITION_NAME) == 0) { + writer.ClearExtendedHead(primary); + error = scan_partition(partitionID); + if (error != B_OK) + return error; + } + // all changes applied update_disk_device_job_progress(job, 1.0); partition_modified(partitionID); @@ -1405,13 +1421,13 @@ pm_delete_child(int fd, partition_id partitionID, partition_id childID, if (!locker.IsLocked()) return B_ERROR; - partition_data *partition = get_partition(partitionID); - partition_data *child = get_partition(childID); + partition_data* partition = get_partition(partitionID); + partition_data* child = get_partition(childID); if (!partition || !child) return B_BAD_VALUE; - PartitionMap *map = (PartitionMap*)partition->content_cookie; - PrimaryPartition *primary = (PrimaryPartition*)child->cookie; + PartitionMap* map = (PartitionMap*)partition->content_cookie; + PrimaryPartition* primary = (PrimaryPartition*)child->cookie; if (!map || !primary) return B_BAD_VALUE; @@ -1422,7 +1438,7 @@ pm_delete_child(int fd, partition_id partitionID, partition_id childID, primary->Unset(); // write changes to disk - PartitionMapWriter writer(fd, 0, partition->size); + PartitionMapWriter writer(fd, primary->BlockSize()); // TODO: disk size or 2 * SECTOR_SIZE? // TODO: The partition is not supposed to be locked at this point! status_t error = writer.WriteMBR(map, false); @@ -1458,7 +1474,7 @@ ep_get_supported_operations(partition_data* partition, uint32 mask) // creating child int32 countSpaces = 0; - if (pm_get_partitionable_spaces(partition, NULL, 0, &countSpaces) + if (ep_get_partitionable_spaces(partition, NULL, 0, &countSpaces) == B_BUFFER_OVERFLOW && countSpaces > 0) { flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; @@ -1482,7 +1498,7 @@ ep_get_supported_child_operations(partition_data* partition, // ep_is_sub_system_for bool -ep_is_sub_system_for(partition_data *partition) +ep_is_sub_system_for(partition_data* partition) { if (partition == NULL) return false; @@ -1503,7 +1519,7 @@ ep_is_sub_system_for(partition_data *partition) // ep_validate_resize bool -ep_validate_resize(partition_data *partition, off_t *size) +ep_validate_resize(partition_data* partition, off_t* size) { TRACE(("intel: ep_validate_resize\n")); @@ -1516,8 +1532,8 @@ ep_validate_resize(partition_data *partition, off_t *size) // ep_validate_resize_child bool -ep_validate_resize_child(partition_data *partition, partition_data *child, - off_t *_size) +ep_validate_resize_child(partition_data* partition, partition_data* child, + off_t* _size) { TRACE(("intel: ep_validate_resize_child\n")); @@ -1537,7 +1553,7 @@ ep_validate_resize_child(partition_data *partition, partition_data *child, // ep_validate_move bool -ep_validate_move(partition_data *partition, off_t *start) +ep_validate_move(partition_data* partition, off_t* start) { TRACE(("intel: ep_validate_move\n")); @@ -1550,8 +1566,8 @@ ep_validate_move(partition_data *partition, off_t *start) // ep_validate_move_child bool -ep_validate_move_child(partition_data *partition, partition_data *child, - off_t *_start) +ep_validate_move_child(partition_data* partition, partition_data* child, + off_t* _start) { TRACE(("intel: ep_validate_move_child\n")); @@ -1573,7 +1589,7 @@ ep_validate_move_child(partition_data *partition, partition_data *child, // is_type_valid_ep (auxiliary function) static inline bool -is_type_valid_ep(const char *type) +is_type_valid_ep(const char* type) { // validity check of the type - it has to be known PartitionType ptype; @@ -1584,7 +1600,7 @@ is_type_valid_ep(const char *type) // ep_validate_set_type bool -ep_validate_set_type(partition_data *partition, const char *type) +ep_validate_set_type(partition_data* partition, const char* type) { TRACE(("intel: ep_validate_set_type\n")); @@ -1598,8 +1614,8 @@ ep_validate_set_type(partition_data *partition, const char *type) // ep_validate_initialize bool -ep_validate_initialize(partition_data *partition, char *name, - const char *parameters) +ep_validate_initialize(partition_data* partition, char* name, + const char* parameters) { TRACE(("intel: ep_validate_initialize\n")); @@ -1616,8 +1632,8 @@ ep_validate_initialize(partition_data *partition, char *name, // ep_validate_create_child bool -ep_validate_create_child(partition_data *partition, off_t *_start, off_t *_size, - const char *type, const char *name, const char *parameters, int32 *index) +ep_validate_create_child(partition_data* partition, off_t* _start, off_t* _size, + const char* type, const char* name, const char* parameters, int32* index) // index - returns position of the new partition (the last one) { TRACE(("intel: ep_validate_create_child\n")); @@ -1635,21 +1651,20 @@ ep_validate_create_child(partition_data *partition, off_t *_start, off_t *_size, // finding out index of the new partition (it will be the last child) *index = partition->child_count; - // validate position - off_t diffOffset = PTS_OFFSET * SECTOR_SIZE; - off_t start = *_start - diffOffset; - off_t size = *_size + diffOffset; - if (start < partition->offset + PTS_OFFSET * SECTOR_SIZE) { - start = partition->offset + PTS_OFFSET * SECTOR_SIZE; + off_t start = *_start + FREE_SECTORS_AFTER_PTS * partition->block_size; + off_t size = *_size - FREE_SECTORS_AFTER_PTS * partition->block_size; + if (start < partition->offset + FREE_SECTORS_AFTER_PTS * partition->block_size) { + start = partition->offset + FREE_SECTORS_AFTER_PTS * partition->block_size; start = sector_align_up(start); } if (!validate_create_child_partition(partition, &start, &size, get_sibling_partitions_ep)) { return false; } - *_start = start + diffOffset; - *_size = size - diffOffset; + + *_start = start; + *_size = size; if (*_size == 0) return false; return true; @@ -1658,8 +1673,8 @@ ep_validate_create_child(partition_data *partition, off_t *_start, off_t *_size, // ep_get_partitionable_spaces status_t -ep_get_partitionable_spaces(partition_data *partition, - partitionable_space_data *buffer, int32 count, int32 *actualCount) +ep_get_partitionable_spaces(partition_data* partition, + partitionable_space_data* buffer, int32 count, int32* actualCount) { TRACE(("intel: ep_get_partitionable_spaces\n")); @@ -1673,16 +1688,16 @@ ep_get_partitionable_spaces(partition_data *partition, return get_partitionable_spaces(partition, buffer, count, actualCount, fill_partitionable_spaces_buffer_ep, - partition->offset + PTS_OFFSET * SECTOR_SIZE, - PTS_OFFSET * SECTOR_SIZE, - PTS_OFFSET * SECTOR_SIZE); + partition->offset + PTS_OFFSET * partition->block_size, + PTS_OFFSET * partition->block_size, + PTS_OFFSET * partition->block_size); } // ep_get_next_supported_type status_t -ep_get_next_supported_type(partition_data *partition, int32 *cookie, - char *_type) +ep_get_next_supported_type(partition_data* partition, int32* cookie, + char* _type) { TRACE(("intel: ep_get_next_supported_type\n")); @@ -1722,7 +1737,7 @@ ep_get_next_supported_type(partition_data *partition, int32 *cookie, // ep_shadow_changed status_t -ep_shadow_changed(partition_data *partition, partition_data *child, +ep_shadow_changed(partition_data* partition, partition_data* child, uint32 operation) { TRACE(("intel: ep_shadow_changed\n")); @@ -1752,7 +1767,7 @@ ep_resize(int fd, partition_id partitionID, off_t size, disk_job_id job) return B_ERROR; // get out partition - partition_data *partition = get_partition(partitionID); + partition_data* partition = get_partition(partitionID); if (!partition) return B_BAD_VALUE; @@ -1790,12 +1805,13 @@ ep_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job) return B_ERROR; // get out partition, child and LogicalPartition structure - partition_data *partition = get_parent_partition(partitionID); - partition_data *child = get_partition(partitionID); + partition_data* partition = get_parent_partition(partitionID); + partition_data* child = get_partition(partitionID); if (!partition || !child) return B_BAD_VALUE; - LogicalPartition *logical = (LogicalPartition*)child->cookie; - if (!logical) + LogicalPartition* logical = (LogicalPartition*)child->cookie; + PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; + if (!logical || !primary) return B_BAD_VALUE; // validate the new size @@ -1810,17 +1826,17 @@ ep_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job) update_disk_device_job_progress(job, 0.0); logical->SetSize(validatedSize); - PartitionMapWriter writer(fd, partition->offset, partition->size); + PartitionMapWriter writer(fd, partition->block_size); // TODO: The partition is not supposed to be locked here! - status_t error = writer.WriteLogical(NULL, logical); + status_t error = writer.WriteLogical(logical, primary, false); if (error != B_OK) { // putting into previous state logical->SetSize(child->size); return error; } - LogicalPartition *prev = logical->Previous(); - error = prev ? writer.WriteLogical(NULL, prev) - : writer.WriteExtendedHead(NULL, logical); + LogicalPartition* prev = logical->Previous(); + error = prev ? writer.WriteLogical(prev, primary, false) + : writer.WriteLogical(logical, primary, false); if (error != B_OK) // this should be not so fatal return error; @@ -1848,7 +1864,7 @@ ep_move(int fd, partition_id partitionID, off_t offset, disk_job_id job) return B_ERROR; // get out partition - partition_data *partition = get_partition(partitionID); + partition_data* partition = get_partition(partitionID); if (!partition) return B_BAD_VALUE; @@ -1877,12 +1893,13 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID, return B_ERROR; // get partition, child and LogicalPartition structure - partition_data *partition = get_partition(partitionID); - partition_data *child = get_partition(childID); + partition_data* partition = get_partition(partitionID); + partition_data* child = get_partition(childID); if (!partition || !child) return B_BAD_VALUE; - LogicalPartition *logical = (LogicalPartition*)child->cookie; - if (!logical) + LogicalPartition* logical = (LogicalPartition*)child->cookie; + PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; + if (!logical || !primary) return B_BAD_VALUE; // TODO: The parameter has already been checked and must not be altered! @@ -1898,7 +1915,8 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID, // buffer allocation int32 allocated; - uint8 *buffer = allocate_buffer(SECTOR_SIZE, MAX_MOVE_BUFFER, &allocated); + uint8* buffer = allocate_buffer(partition->block_size, MAX_MOVE_BUFFER, + &allocated); if (!buffer) return B_NO_MEMORY; @@ -1909,7 +1927,7 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID, off_t pts_offset = logical->Offset() - logical->PartitionTableOffset(); error = move_partition(fd, child->offset - pts_offset, validatedOffset - pts_offset, child->size + pts_offset, buffer, - allocated * SECTOR_SIZE, job); + allocated * partition->block_size, job); delete[] buffer; if (error != B_OK) return error; @@ -1920,18 +1938,18 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID, logical->SetOffset(logical->Offset() + diffOffset); logical->SetPartitionTableOffset(logical->PartitionTableOffset() + diffOffset); - PartitionMapWriter writer(fd, partition->offset, partition->size); + PartitionMapWriter writer(fd, partition->block_size); // TODO: If partition->offset is > prev->offset, then writing // the previous logical partition table will fail! // TODO: The partition is not supposed to be locked here! - error = writer.WriteLogical(NULL, logical); + error = writer.WriteLogical(logical, primary, false); if (error != B_OK) // something went wrong - this is fatal (partition has been moved) // but EBR is not updated return error; - LogicalPartition *prev = logical->Previous(); - error = prev ? writer.WriteLogical(NULL, prev) - : writer.WriteExtendedHead(NULL, logical); + LogicalPartition* prev = logical->Previous(); + error = prev ? writer.WriteLogical(prev, primary, false) + : writer.WriteLogical(logical, primary, false); if (error != B_OK) // this is fatal - linked list is not updated return error; @@ -1945,7 +1963,7 @@ ep_move_child(int fd, partition_id partitionID, partition_id childID, // ep_set_type status_t -ep_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) +ep_set_type(int fd, partition_id partitionID, const char* type, disk_job_id job) { TRACE(("intel: ep_set_type\n")); @@ -1957,12 +1975,13 @@ ep_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) return B_ERROR; // get partition, child and LogicalPartition structure - partition_data *partition = get_parent_partition(partitionID); - partition_data *child = get_partition(partitionID); + partition_data* partition = get_parent_partition(partitionID); + partition_data* child = get_partition(partitionID); if (!partition || !child) return B_BAD_VALUE; - LogicalPartition *logical = (LogicalPartition*)child->cookie; - if (!logical) + LogicalPartition* logical = (LogicalPartition*)child->cookie; + PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; + if (!logical || !primary) return B_BAD_VALUE; // TODO: The parameter has already been checked and must not be altered! @@ -1984,9 +2003,9 @@ ep_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) uint8 oldType = logical->Type(); logical->SetType(ptype.Type()); - PartitionMapWriter writer(fd, partition->offset, partition->size); + PartitionMapWriter writer(fd, partition->block_size); // TODO: The partition is not supposed to be locked here! - status_t error = writer.WriteLogical(NULL, logical); + status_t error = writer.WriteLogical(logical, primary, false); if (error != B_OK) { // something went wrong - putting into previous state logical->SetType(oldType); @@ -2007,8 +2026,8 @@ ep_set_type(int fd, partition_id partitionID, const char *type, disk_job_id job) // ep_initialize status_t -ep_initialize(int fd, partition_id partitionID, const char *name, - const char *parameters, off_t partitionSize, disk_job_id job) +ep_initialize(int fd, partition_id partitionID, const char* name, + const char* parameters, off_t partitionSize, disk_job_id job) { TRACE(("intel: ep_initialize\n")); @@ -2020,8 +2039,9 @@ ep_initialize(int fd, partition_id partitionID, const char *name, return B_ERROR; // get partition - partition_data *partition = get_partition(partitionID); - if (!partition) + partition_data* partition = get_partition(partitionID); + PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; + if (!partition || !primary) return B_BAD_VALUE; // name is ignored - we cannot set it to the Intel Extended Partition @@ -2031,7 +2051,6 @@ ep_initialize(int fd, partition_id partitionID, const char *name, // partition init (we have no child partition) update_disk_device_job_progress(job, 0.0); - PrimaryPartition *primary = (PrimaryPartition*)partition->cookie; // fill in the partition_data structure partition->status = B_PARTITION_VALID; partition->flags |= B_PARTITION_PARTITIONING_SYSTEM; @@ -2044,9 +2063,9 @@ ep_initialize(int fd, partition_id partitionID, const char *name, partition_table table; table.clear_code_area(); - PartitionMapWriter writer(fd, partition->offset, partition->size); + PartitionMapWriter writer(fd, partition->block_size); // TODO: The partition is not supposed to be locked here! - status_t error = writer.WriteExtendedHead(&table, NULL); + status_t error = writer.ClearExtendedHead(primary); if (error != B_OK) return error; @@ -2064,8 +2083,8 @@ ep_initialize(int fd, partition_id partitionID, const char *name, */ status_t ep_create_child(int fd, partition_id partitionID, off_t offset, off_t size, - const char *type, const char *name, const char *parameters, disk_job_id job, - partition_id *childID) + const char* type, const char* name, const char* parameters, disk_job_id job, + partition_id* childID) { TRACE(("intel: ep_create_child\n")); @@ -2076,82 +2095,85 @@ ep_create_child(int fd, partition_id partitionID, off_t offset, off_t size, if (!locker.IsLocked()) return B_ERROR; - // get parent, partition and PrimaryPartition structure - partition_data *parent = get_parent_partition(partitionID); - partition_data *partition = get_partition(partitionID); - if (!parent || !partition) + partition_data* partition = get_partition(partitionID); + partition_data* device = get_parent_partition(partitionID); + if (partition == NULL || device == NULL) return B_BAD_VALUE; - PrimaryPartition *primary = (PrimaryPartition*)partition->cookie; + + PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; if (!primary) return B_BAD_VALUE; // validate the offset, size and get index of the new partition - // TODO: The parameter has already been checked and must not be altered! off_t validatedOffset = offset; off_t validatedSize = size; int32 index = 0; - if (!ep_validate_create_child(partition, &validatedOffset, &validatedSize, - type, name, parameters, &index)) { + type, name, parameters, &index)) return B_BAD_VALUE; - } - LogicalPartition *logical = new(nothrow) LogicalPartition; + LogicalPartition* logical = new(nothrow) LogicalPartition; if (!logical) return B_NO_MEMORY; // creating partition update_disk_device_job_progress(job, 0.0); - partition_data *child = create_child_partition(partition->id, index, + partition_data* child = create_child_partition(partition->id, index, validatedOffset, validatedSize, *childID); - if (!child) { - delete logical; + if (!child) return B_ERROR; - } PartitionType ptype; ptype.SetType(type); - - logical->SetPartitionTableOffset(validatedOffset - PTS_OFFSET * SECTOR_SIZE - - partition->offset); - logical->SetOffset(validatedOffset - partition->offset); + logical->SetPartitionTableOffset( + validatedOffset - FREE_SECTORS_AFTER_PTS * partition->block_size); + logical->SetOffset(validatedOffset); logical->SetSize(validatedSize); logical->SetType(ptype.Type()); - // TODO: correctly fill active parameter logical->SetActive(false); + logical->SetPrimaryPartition(primary); + logical->SetBlockSize(partition->block_size); + primary->AddLogicalPartition(logical); - // we delete code area in EBR - nothing should be there - partition_table table; - table.clear_code_area(); + // If the table offset of this partition is supposed to be at the start + // of the extended partition, but is not the first logical partition to + // be written, then increased the table offset by one block. + if (logical->PartitionTableOffset() == primary->Offset() + && logical->Previous() != NULL) { + logical->SetPartitionTableOffset(logical->PartitionTableOffset() + + logical->BlockSize()); + } + + int deviceFD = open_partition(device->id, O_RDWR); + if (deviceFD < 0) + return B_IO_ERROR; // write changes to disk - PartitionMapWriter writer(fd, partition->offset, partition->size); - // TODO: wrong offset range, writing prev will fail + PartitionMapWriter writer(deviceFD, primary->BlockSize()); + // Write the logical partition's EBR first in case of failure. + // This way we will not add a partition to the previous logical + // partition. If there is no previous logical partition then write + // the current partition's EBR to the first sector of the primary partition - // TODO: The partition is not supposed to be locked here! - status_t error = writer.WriteLogical(&table, logical); + status_t error = writer.WriteLogical(logical, primary, true); if (error != B_OK) { - // putting into previous state - delete_partition(child->id); - delete logical; - return error; - } - // update linked list - primary->AddLogicalPartition(logical); - LogicalPartition *prev = logical->Previous(); - error = prev ? writer.WriteLogical(NULL, prev) - : writer.WriteExtendedHead(NULL, logical); - if (error != B_OK) { - // putting into previous state - delete_partition(child->id); primary->RemoveLogicalPartition(logical); delete logical; return error; } + LogicalPartition* previous = logical->Previous(); + if (previous != NULL) { + error = writer.WriteLogical(previous, primary, true); + if (error != B_OK) { + primary->RemoveLogicalPartition(logical); + delete logical; + return error; + } + } *childID = child->id; - child->block_size = SECTOR_SIZE; + child->block_size = logical->BlockSize(); // (no name) child->type = strdup(type); // parameters @@ -2182,35 +2204,43 @@ ep_delete_child(int fd, partition_id partitionID, partition_id childID, if (!locker.IsLocked()) return B_ERROR; - partition_data *partition = get_partition(partitionID); - partition_data *child = get_partition(childID); - if (!partition || !child) + partition_data* partition = get_partition(partitionID); + partition_data* device = get_parent_partition(partitionID); + partition_data* child = get_partition(childID); + if (partition == NULL || device == NULL || child == NULL) return B_BAD_VALUE; - PrimaryPartition *primary = (PrimaryPartition*)partition->cookie; - LogicalPartition *logical = (LogicalPartition*)child->cookie; - if (!primary || !logical) + PrimaryPartition* primary = (PrimaryPartition*)partition->cookie; + LogicalPartition* logical = (LogicalPartition*)child->cookie; + if (primary == NULL || logical == NULL) return B_BAD_VALUE; + // deleting child update_disk_device_job_progress(job, 0.0); if (!delete_partition(childID)) return B_ERROR; - LogicalPartition *next_logical = logical->Next(); - LogicalPartition *prev_logical = logical->Previous(); + LogicalPartition* previous = logical->Previous(); + LogicalPartition* next = logical->Next(); + primary->RemoveLogicalPartition(logical); delete logical; + int deviceFD = open_partition(device->id, O_RDWR); + if (deviceFD < 0) + return B_IO_ERROR; + // write changes to disk - PartitionMapWriter writer(fd, partition->offset, partition->size); - // TODO: Check offset range! Writing "prev/next_logical"? - // Should be parent->offset and parent->size? - // TODO: The partition is not supposed to be locked here! - status_t error = prev_logical ? writer.WriteLogical(NULL, prev_logical) - : writer.WriteExtendedHead(NULL, next_logical); - if (error != B_OK) + PartitionMapWriter writer(deviceFD, primary->BlockSize()); + + status_t error = previous ? writer.WriteLogical(previous, primary, true) + : writer.WriteExtendedHead(next, primary, true); + + if (error != B_OK) { + delete logical; return error; + } // all changes applied update_disk_device_job_progress(job, 1.0); diff --git a/src/system/kernel/disk_device_manager/disk_device_manager.cpp b/src/system/kernel/disk_device_manager/disk_device_manager.cpp index bafd81bf33..a7dd2c82b2 100644 --- a/src/system/kernel/disk_device_manager/disk_device_manager.cpp +++ b/src/system/kernel/disk_device_manager/disk_device_manager.cpp @@ -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,