Beginnings of a userland intel disk system add-on.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22542 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2007-10-13 21:34:15 +00:00
parent 260bb9a2a1
commit 91c21ff4d6
8 changed files with 783 additions and 0 deletions

View File

@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons ;
SubInclude HAIKU_TOP src add-ons accelerants ; SubInclude HAIKU_TOP src add-ons accelerants ;
SubInclude HAIKU_TOP src add-ons decorators ; 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 input_server ;
SubInclude HAIKU_TOP src add-ons kernel ; SubInclude HAIKU_TOP src add-ons kernel ;
SubInclude HAIKU_TOP src add-ons mail_daemon ; SubInclude HAIKU_TOP src add-ons mail_daemon ;

View File

@ -0,0 +1,109 @@
/*
* Copyright 2007, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#include "ExtendedPartitionAddOn.h"
#include <new>
#include <DiskDeviceTypes.h>
#include <MutablePartition.h>
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;
}

View File

@ -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 <DiskSystemAddOn.h>
#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

View File

@ -0,0 +1,43 @@
/*
* Copyright 2007, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#include <new>
#include <List.h>
#include <AutoDeleter.h>
#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<PartitionMapAddOn> mapAddOnDeleter(partitionMapAddOn);
ObjectDeleter<ExtendedPartitionAddOn> 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;
}

View File

@ -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

View File

@ -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 <disk_system>intel :
IntelDiskSystem.cpp
ExtendedPartitionAddOn.cpp
PartitionMapAddOn.cpp
# kernel sources
PartitionMap.cpp
: be
;

View File

@ -0,0 +1,483 @@
/*
* Copyright 2007, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#include "PartitionMapAddOn.h"
#include <new>
#include <DiskDeviceTypes.h>
#include <MutablePartition.h>
#include <PartitioningInfo.h>
#include <AutoDeleter.h>
#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<PartitionMapHandle> 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;
}

View File

@ -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 <DiskSystemAddOn.h>
#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