diff --git a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp index e3aadba828..2d93acfe18 100644 --- a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp +++ b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp @@ -9,17 +9,42 @@ #include #include +#include + +#include using std::nothrow; +static const uint32 kDiskSystemFlags = + 0 +// | B_DISK_SYSTEM_SUPPORTS_CHECKING +// | B_DISK_SYSTEM_SUPPORTS_REPAIRING +// | B_DISK_SYSTEM_SUPPORTS_RESIZING +// | 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_CONTENT_NAME + +// | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD +// | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD +// | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME + | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE +// | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS + | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD + | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD +// | B_DISK_SYSTEM_SUPPORTS_NAME +; + + // #pragma mark - ExtendedPartitionAddOn // constructor ExtendedPartitionAddOn::ExtendedPartitionAddOn() - : BDiskSystemAddOn(kPartitionTypeIntelExtended, 0) + : BDiskSystemAddOn(kPartitionTypeIntelExtended, kDiskSystemFlags) { } @@ -51,6 +76,79 @@ ExtendedPartitionAddOn::CreatePartitionHandle(BMutablePartition* partition, } +// CanInitialize +bool +ExtendedPartitionAddOn::CanInitialize(const BMutablePartition* partition) +{ + // If it's big enough, we can initialize it. + return partition->Size() >= 2 * SECTOR_SIZE; +} + + +// GetInitializationParameterEditor +status_t +ExtendedPartitionAddOn::GetInitializationParameterEditor( + const BMutablePartition* partition, BDiskDeviceParameterEditor** editor) +{ + // Nothing to edit, really. + *editor = NULL; + return B_OK; +} + + +// ValidateInitialize +status_t +ExtendedPartitionAddOn::ValidateInitialize(const BMutablePartition* partition, + BString* name, const char* parameters) +{ + if (!CanInitialize(partition) + || parameters != NULL && strlen(parameters) > 0) { + return B_BAD_VALUE; + } + + // we don't support a content name + if (name != NULL) + name->Truncate(0); + + return B_OK; +} + + +// Initialize +status_t +ExtendedPartitionAddOn::Initialize(BMutablePartition* partition, + const char* name, const char* parameters, BPartitionHandle** _handle) +{ + if (!CanInitialize(partition) + || name != NULL && strlen(name) > 0 + || parameters != NULL && strlen(parameters) > 0) { + return B_BAD_VALUE; + } + + // create the handle + ExtendedPartitionHandle* handle + = new(nothrow) ExtendedPartitionHandle(partition); + if (!handle) + return B_NO_MEMORY; + ObjectDeleter handleDeleter(handle); + + // init the partition + status_t error = partition->SetContentType(Name()); + if (error != B_OK) + return error; +// TODO: The content type could as well be set by the caller. + + partition->SetContentName(NULL); + partition->SetContentParameters(NULL); + partition->SetBlockSize(SECTOR_SIZE); + partition->SetContentSize(partition->Size() / SECTOR_SIZE * SECTOR_SIZE); + + *_handle = handleDeleter.Detach(); + + return B_OK; +} + + // #pragma mark - ExtendedPartitionHandle @@ -107,3 +205,281 @@ ExtendedPartitionHandle::Init() return B_OK; } + + +// SupportedOperations +uint32 +ExtendedPartitionHandle::SupportedOperations(uint32 mask) +{ + uint32 flags = B_DISK_SYSTEM_SUPPORTS_INITIALIZING; + + // creating child + if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) { + BPartitioningInfo info; + if (GetPartitioningInfo(&info) == B_OK + && info.CountPartitionableSpaces() > 1) { + flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; + } + } + + return flags; +} + + +// SupportedChildOperations +uint32 +ExtendedPartitionHandle::SupportedChildOperations( + const BMutablePartition* child, uint32 mask) +{ + return B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; +} + + +// GetNextSupportedType +status_t +ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child, + int32* cookie, BString* type) +{ + if (*cookie != 0) + return B_ENTRY_NOT_FOUND; + *cookie = *cookie + 1; + *type = kPartitionTypeIntelLogical; + return B_OK; +} + + +// GetPartitioningInfo +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; + 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; +} + + +// GetChildCreationParameterEditor +status_t +ExtendedPartitionHandle::GetChildCreationParameterEditor(const char* type, + BDiskDeviceParameterEditor** editor) +{ + // TODO: We actually need an editor here. + *editor = NULL; + return B_OK; +} + + +// ValidateCreateChild +status_t +ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size, + const char* typeString, BString* name, const char* parameters) +{ + // check type + if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0) + return B_BAD_VALUE; + + // check name + if (name) + name->Truncate(0); + + // check parameters + // TODO:... + +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; +} + + +// CreateChild +status_t +ExtendedPartitionHandle::CreateChild(off_t offset, off_t size, + const char* typeString, const char* name, const char* parameters, + BMutablePartition** _child) +{ + // check type + if (!typeString || strcmp(typeString, kPartitionTypeIntelLogical) != 0) + return B_BAD_VALUE; + + // check name + if (name && strlen(name) > 0) + return B_BAD_VALUE; + + // check parameters + // TODO:... + +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; +} + + diff --git a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h index 97dcad75cd..78da7b2382 100644 --- a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h +++ b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h @@ -19,6 +19,17 @@ public: BMutablePartition* partition, BPartitionHandle** handle); + virtual bool CanInitialize( + const BMutablePartition* partition); + virtual status_t GetInitializationParameterEditor( + const BMutablePartition* partition, + BDiskDeviceParameterEditor** editor); + virtual status_t ValidateInitialize( + const BMutablePartition* partition, + BString* name, const char* parameters); + virtual status_t Initialize(BMutablePartition* partition, + const char* name, const char* parameters, + BPartitionHandle** handle); }; @@ -30,6 +41,27 @@ public: status_t Init(); + virtual uint32 SupportedOperations(uint32 mask); + virtual uint32 SupportedChildOperations( + const BMutablePartition* child, + uint32 mask); + + virtual status_t GetNextSupportedType( + const BMutablePartition* child, + int32* cookie, BString* type); + + virtual status_t GetPartitioningInfo(BPartitioningInfo* info); + + virtual status_t GetChildCreationParameterEditor( + const char* type, + BDiskDeviceParameterEditor** editor); + virtual status_t ValidateCreateChild(off_t* offset, + off_t* size, const char* type, + BString* name, const char* parameters); + virtual status_t CreateChild(off_t offset, off_t size, + const char* type, const char* name, + const char* parameters, + BMutablePartition** child); private: PrimaryPartition* fPrimaryPartition; };