diff --git a/src/add-ons/Jamfile b/src/add-ons/Jamfile index 55d4e0d610..cc610a6112 100644 --- a/src/add-ons/Jamfile +++ b/src/add-ons/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons ; SubInclude HAIKU_TOP src add-ons accelerants ; SubInclude HAIKU_TOP src add-ons decorators ; +SubInclude HAIKU_TOP src add-ons disk_systems ; SubInclude HAIKU_TOP src add-ons input_server ; SubInclude HAIKU_TOP src add-ons kernel ; SubInclude HAIKU_TOP src add-ons mail_daemon ; diff --git a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp new file mode 100644 index 0000000000..94bb48a572 --- /dev/null +++ b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + +#include "ExtendedPartitionAddOn.h" + +#include + +#include +#include + + +using std::nothrow; + + +// #pragma mark - ExtendedPartitionAddOn + + +// constructor +ExtendedPartitionAddOn::ExtendedPartitionAddOn() + : BDiskSystemAddOn(kPartitionTypeIntel, 0) +{ +} + + +// destructor +ExtendedPartitionAddOn::~ExtendedPartitionAddOn() +{ +} + + +// CreatePartitionHandle +status_t +ExtendedPartitionAddOn::CreatePartitionHandle(BMutablePartition* partition, + BPartitionHandle** _handle) +{ + ExtendedPartitionHandle* handle + = new(nothrow) ExtendedPartitionHandle(partition); + if (!handle) + return B_NO_MEMORY; + + status_t error = handle->Init(); + if (error != B_OK) { + delete handle; + return error; + } + + *_handle = handle; + return B_OK; +} + + +// #pragma mark - ExtendedPartitionHandle + + +// constructor +ExtendedPartitionHandle::ExtendedPartitionHandle(BMutablePartition* partition) + : BPartitionHandle(partition) +{ +} + + +// destructor +ExtendedPartitionHandle::~ExtendedPartitionHandle() +{ +} + + +// Init +status_t +ExtendedPartitionHandle::Init() +{ + // initialize the extended partition from the mutable partition + + BMutablePartition* partition = Partition(); + + // our parent has already set the child cookie to the primary partition. + fPrimaryPartition = (PrimaryPartition*)partition->ChildCookie(); + if (!fPrimaryPartition) + return B_BAD_VALUE; + + if (!fPrimaryPartition->IsExtended()) + return B_BAD_VALUE; + + // init the child partitions + int32 count = partition->CountChildren(); + for (int32 i = 0; i < count; i++) { + BMutablePartition* child = partition->ChildAt(i); + PartitionType type; + if (!type.SetType(child->Type())) + return B_BAD_VALUE; + + // TODO: Get these from the parameters. + bool active = false; + off_t ptsOffset = 0; + + LogicalPartition* logical = new(nothrow) LogicalPartition; + if (!logical) + return B_NO_MEMORY; + + logical->SetTo(child->Offset(), child->Size(), type.Type(), active, + ptsOffset, fPrimaryPartition); + + child->SetChildCookie(logical); + } + + return B_OK; +} diff --git a/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h new file mode 100644 index 0000000000..97dcad75cd --- /dev/null +++ b/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.h @@ -0,0 +1,38 @@ +/* + * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ +#ifndef _EXTENDED_PARTITION_ADD_ON_H +#define _EXTENDED_PARTITION_ADD_ON_H + +#include + +#include "PartitionMap.h" + + +class ExtendedPartitionAddOn : public BDiskSystemAddOn { +public: + ExtendedPartitionAddOn(); + virtual ~ExtendedPartitionAddOn(); + + virtual status_t CreatePartitionHandle( + BMutablePartition* partition, + BPartitionHandle** handle); + +}; + + +class ExtendedPartitionHandle : public BPartitionHandle { +public: + ExtendedPartitionHandle( + BMutablePartition* partition); + virtual ~ExtendedPartitionHandle(); + + status_t Init(); + +private: + PrimaryPartition* fPrimaryPartition; +}; + + +#endif // _EXTENDED_PARTITION_ADD_ON_H diff --git a/src/add-ons/disk_systems/intel/IntelDiskSystem.cpp b/src/add-ons/disk_systems/intel/IntelDiskSystem.cpp new file mode 100644 index 0000000000..1bb793a096 --- /dev/null +++ b/src/add-ons/disk_systems/intel/IntelDiskSystem.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + +#include + +#include + +#include + +#include "ExtendedPartitionAddOn.h" +#include "PartitionMapAddOn.h" + + +using std::nothrow; + + +// get_disk_system_add_ons +status_t +get_disk_system_add_ons(BList* addOns) +{ + PartitionMapAddOn* partitionMapAddOn = new(nothrow) PartitionMapAddOn; + ExtendedPartitionAddOn* extendedPartitionAddOn + = new(nothrow) ExtendedPartitionAddOn; + + ObjectDeleter mapAddOnDeleter(partitionMapAddOn); + ObjectDeleter extendedAddOnDeleter( + extendedPartitionAddOn); + + BList list; + if (!partitionMapAddOn || !extendedPartitionAddOn + || !list.AddItem(partitionMapAddOn) + || !list.AddItem(extendedPartitionAddOn) + || !addOns->AddList(&list)) { + return B_NO_MEMORY; + } + + mapAddOnDeleter.Detach(); + extendedAddOnDeleter.Detach(); + + return B_OK; +} diff --git a/src/add-ons/disk_systems/intel/IntelDiskSystem.h b/src/add-ons/disk_systems/intel/IntelDiskSystem.h new file mode 100644 index 0000000000..6aed0842e1 --- /dev/null +++ b/src/add-ons/disk_systems/intel/IntelDiskSystem.h @@ -0,0 +1,18 @@ +/* + * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ +#ifndef _INTEL_DISK_SYSTEM_H +#define _INTEL_DISK_SYSTEM_H + +#include "PartitionMap.h" + + +static inline off_t +sector_align(off_t offset) +{ + return offset / SECTOR_SIZE * SECTOR_SIZE; +} + + +#endif // _INTEL_DISK_SYSTEM_H diff --git a/src/add-ons/disk_systems/intel/Jamfile b/src/add-ons/disk_systems/intel/Jamfile new file mode 100644 index 0000000000..ee934e7d35 --- /dev/null +++ b/src/add-ons/disk_systems/intel/Jamfile @@ -0,0 +1,24 @@ +SubDir HAIKU_TOP src add-ons disk_systems intel ; + +UsePrivateHeaders shared ; +UsePrivateHeaders storage ; + +SEARCH_SOURCE + += [ FDirName $(HAIKU_TOP) src add-ons kernel partitioning_systems intel ] ; + +{ + local defines = [ FDefines _USER_MODE ] ; + SubDirCcFlags $(defines) ; + SubDirC++Flags $(defines) ; +} + +Addon intel : + IntelDiskSystem.cpp + ExtendedPartitionAddOn.cpp + PartitionMapAddOn.cpp + + # kernel sources + PartitionMap.cpp + + : be +; diff --git a/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp b/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp new file mode 100644 index 0000000000..f420134012 --- /dev/null +++ b/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp @@ -0,0 +1,483 @@ +/* + * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + +#include "PartitionMapAddOn.h" + +#include + +#include +#include +#include + +#include + +#include "IntelDiskSystem.h" + + +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 - PartitionMapAddOn + + +// constructor +PartitionMapAddOn::PartitionMapAddOn() + : BDiskSystemAddOn(kPartitionTypeIntel, kDiskSystemFlags) +{ +} + + +// destructor +PartitionMapAddOn::~PartitionMapAddOn() +{ +} + + +// CreatePartitionHandle +status_t +PartitionMapAddOn::CreatePartitionHandle(BMutablePartition* partition, + BPartitionHandle** _handle) +{ + PartitionMapHandle* handle = new(nothrow) PartitionMapHandle(partition); + if (!handle) + return B_NO_MEMORY; + + status_t error = handle->Init(); + if (error != B_OK) { + delete handle; + return error; + } + + *_handle = handle; + return B_OK; +} + + +// CanInitialize +bool +PartitionMapAddOn::CanInitialize(const BMutablePartition* partition) +{ + // If it's big enough, we can initialize it. + return partition->Size() >= 2 * SECTOR_SIZE; +} + + +// GetInitializationParameterEditor +status_t +PartitionMapAddOn::GetInitializationParameterEditor( + const BMutablePartition* partition, BDiskDeviceParameterEditor** editor) +{ + // Nothing to edit, really. + *editor = NULL; + return B_OK; +} + + +// ValidateInitialize +status_t +PartitionMapAddOn::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 +PartitionMapAddOn::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 + PartitionMapHandle* handle = new(nothrow) PartitionMapHandle(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 - PartitionMapHandle + + +// constructor +PartitionMapHandle::PartitionMapHandle(BMutablePartition* partition) + : BPartitionHandle(partition) +{ +} + + +// destructor +PartitionMapHandle::~PartitionMapHandle() +{ +} + + +// Init +status_t +PartitionMapHandle::Init() +{ + // initialize the partition map from the mutable partition + + BMutablePartition* partition = Partition(); + + int32 count = partition->CountChildren(); + if (count > 4) + return B_BAD_VALUE; + + int32 extendedCount = 0; + + for (int32 i = 0; i < count; i++) { + BMutablePartition* child = partition->ChildAt(i); + PartitionType type; + if (!type.SetType(child->Type())) + return B_BAD_VALUE; + + // only one extended partition is allowed + if (type.IsExtended()) { + if (++extendedCount > 1) + return B_BAD_VALUE; + } + + // TODO: Get these from the parameters. + int32 index = i; + bool active = false; + + PrimaryPartition* primary = fPartitionMap.PrimaryPartitionAt(index); + primary->SetTo(child->Offset(), child->Size(), type.Type(), active); + + child->SetChildCookie(primary); + } + + // The extended partition (if any) is initialized by + // ExtendedPartitionHandle::Init(). + + return B_OK; +} + + +// SupportedOperations +uint32 +PartitionMapHandle::SupportedOperations(uint32 mask) +{ + BMutablePartition* partition = Partition(); + + uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING + | B_DISK_SYSTEM_SUPPORTS_MOVING + | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS + | B_DISK_SYSTEM_SUPPORTS_INITIALIZING; + + // creating child + if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) { + BPartitioningInfo info; + if (partition->CountChildren() < 4 + && GetPartitioningInfo(&info) == B_OK + && info.CountPartitionableSpaces() > 1) { + flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; + } + } + + return flags; +} + + +// SupportedChildOperations +uint32 +PartitionMapHandle::SupportedChildOperations(const BMutablePartition* child, + uint32 mask) +{ + return B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD + | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD + | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE + | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; +} + + +// GetPartitioningInfo +status_t +PartitionMapHandle::GetPartitioningInfo(BPartitioningInfo* info) +{ + // init to the full size (minus the first sector) + off_t size = Partition()->ContentSize(); + status_t error = info->SetTo(SECTOR_SIZE, size - SECTOR_SIZE); + if (error != B_OK) + return error; + + // exclude the space of the existing partitions + for (int32 i = 0; i < 4; i++) { + PrimaryPartition* primary = fPartitionMap.PrimaryPartitionAt(i); + if (!primary->IsEmpty()) { + error = info->ExcludeOccupiedSpace(primary->Offset(), + primary->Size()); + if (error != B_OK) + return error; + } + } + + return B_OK; +} + + +// GetChildCreationParameterEditor +status_t +PartitionMapHandle::GetChildCreationParameterEditor(const char* type, + BDiskDeviceParameterEditor** editor) +{ + // TODO: We actually need an editor here. + *editor = NULL; + return B_OK; +} + + +// ValidateCreateChild +status_t +PartitionMapHandle::ValidateCreateChild(off_t* _offset, off_t* _size, + const char* typeString, BString* name, const char* parameters) +{ + // check type + PartitionType type; + if (!type.SetType(typeString) || type.IsEmpty()) + return B_BAD_VALUE; + if (type.IsExtended() && fPartitionMap.ExtendedPartitionIndex() >= 0) + return B_BAD_VALUE; + + // check name + if (name) + name->Truncate(0); + + // check parameters + // TODO:... + + // do we have a spare primary partition? + if (fPartitionMap.CountNonEmptyPrimaryPartitions() == 4) + return B_BAD_VALUE; + + // 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 +PartitionMapHandle::CreateChild(off_t offset, off_t size, + const char* typeString, const char* name, const char* parameters, + BMutablePartition** _child) +{ + // check type + PartitionType type; + if (!type.SetType(typeString) || type.IsEmpty()) + return B_BAD_VALUE; + if (type.IsExtended() && fPartitionMap.ExtendedPartitionIndex() >= 0) + return B_BAD_VALUE; + + // check name + if (name && strlen(name) > 0) + return B_BAD_VALUE; + + // check parameters + // TODO:... + + // get a spare primary partition + PrimaryPartition* primary = NULL; + for (int32 i = 0; i < 4; i++) { + if (fPartitionMap.PrimaryPartitionAt(i)->IsEmpty()) { + primary = fPartitionMap.PrimaryPartitionAt(i); + break; + } + } + if (!primary) + return B_BAD_VALUE; + + // 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/PartitionMapAddOn.h b/src/add-ons/disk_systems/intel/PartitionMapAddOn.h new file mode 100644 index 0000000000..04077a79b7 --- /dev/null +++ b/src/add-ons/disk_systems/intel/PartitionMapAddOn.h @@ -0,0 +1,67 @@ +/* + * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ +#ifndef _PARTITION_MAP_ADD_ON_H +#define _PARTITION_MAP_ADD_ON_H + +#include + +#include "PartitionMap.h" + + +class PartitionMapAddOn : public BDiskSystemAddOn { +public: + PartitionMapAddOn(); + virtual ~PartitionMapAddOn(); + + virtual status_t CreatePartitionHandle( + 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); +}; + + +class PartitionMapHandle : public BPartitionHandle { +public: + PartitionMapHandle( + BMutablePartition* partition); + virtual ~PartitionMapHandle(); + + status_t Init(); + + virtual uint32 SupportedOperations(uint32 mask); + virtual uint32 SupportedChildOperations( + const BMutablePartition* child, + uint32 mask); + + 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: + PartitionMap fPartitionMap; +}; + + +#endif // _PARTITION_MAP_ADD_ON_H