intel partition map: implement changing the active partition

Implement the needed parts in both the userland add-on (loaded in
DriveSetup) and the kernel side one (used by disk system manager in the
kernel).

This allows changing the active partition in DriveSetup.

Change-Id: Ia65768b5f8f11d626ef24621ae7735723dcbc39d
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3771
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
Adrien Destugues 2021-03-11 22:18:16 +01:00 committed by Adrien Destugues
parent 8f5c5225da
commit 9274ca847b
9 changed files with 155 additions and 22 deletions

View File

@ -236,7 +236,6 @@ PartitionMapHandle::SupportedChildOperations(const BMutablePartition* child,
{ {
return B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD return B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
| B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
| B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
| B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD;
} }
@ -295,6 +294,44 @@ PartitionMapHandle::GetPartitioningInfo(BPartitioningInfo* info)
} }
status_t
PartitionMapHandle::ValidateSetParameters(const BMutablePartition* child,
const char* parameters)
{
if (child == NULL || parameters == NULL)
return B_NO_INIT;
void* handle = parse_driver_settings_string(parameters);
if (handle == NULL)
return B_BAD_DATA;
delete_driver_settings(handle);
return B_OK;
}
status_t
PartitionMapHandle::SetParameters(BMutablePartition* child,
const char* parameters)
{
void* handle = parse_driver_settings_string(parameters);
if (handle == NULL)
return B_BAD_DATA;
bool active = get_driver_boolean_parameter(handle, "active", false, true);
delete_driver_settings(handle);
// Update our local state
PrimaryPartition* partition = (PrimaryPartition*)child->ChildCookie();
partition->SetActive(active);
// Forward the request to the BMutablePartition so it can be committed to
// disk
return child->SetParameters(parameters);
}
status_t status_t
PartitionMapHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type, PartitionMapHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
BPartitionParameterEditor** editor) BPartitionParameterEditor** editor)

View File

@ -49,6 +49,13 @@ public:
virtual status_t GetPartitioningInfo(BPartitioningInfo* info); virtual status_t GetPartitioningInfo(BPartitioningInfo* info);
virtual status_t ValidateSetParameters(
const BMutablePartition* child,
const char* parameters);
virtual status_t SetParameters(
BMutablePartition* child,
const char* parameters);
virtual status_t GetParameterEditor( virtual status_t GetParameterEditor(
B_PARAMETER_EDITOR_TYPE type, B_PARAMETER_EDITOR_TYPE type,
BPartitionParameterEditor** editor); BPartitionParameterEditor** editor);
@ -59,7 +66,7 @@ public:
const char* type, const char* name, const char* type, const char* name,
const char* parameters, const char* parameters,
BMutablePartition** child); BMutablePartition** child);
virtual status_t DeleteChild(BMutablePartition* child); virtual status_t DeleteChild(BMutablePartition* child);
private: private:
PartitionMap fPartitionMap; PartitionMap fPartitionMap;

View File

@ -44,10 +44,15 @@ status_t
PrimaryPartitionEditor::ParameterChanged(const char* name, PrimaryPartitionEditor::ParameterChanged(const char* name,
const BVariant& variant) const BVariant& variant)
{ {
if (!strcmp(name, "type")) { if (strcmp(name, "type") == 0) {
fActiveCheckBox->SetEnabled(strcmp(variant.ToString(), fActiveCheckBox->SetEnabled(strcmp(variant.ToString(),
kPartitionTypeIntelExtended) != 0); kPartitionTypeIntelExtended) != 0);
fActiveCheckBox->SetValue(false);
} }
if (strcmp(name, "active") == 0)
fActiveCheckBox->SetValue(variant.ToBool());
return B_OK; return B_OK;
} }

View File

@ -494,8 +494,8 @@ static partition_module_info intel_partition_map_module =
NULL, // set_name NULL, // set_name
NULL, // set_content_name NULL, // set_content_name
pm_set_type, // set_type pm_set_type, // set_type
NULL, // set_parameters pm_set_parameters, // set_parameters
NULL, // set_content_parameters pm_set_parameters, // set_content_parameters
pm_initialize, // initialize pm_initialize, // initialize
pm_uninitialize, // uninitialize pm_uninitialize, // uninitialize
pm_create_child, // create_child pm_create_child, // create_child

View File

@ -1249,6 +1249,80 @@ pm_set_type(int fd, partition_id partitionID, const char* type, disk_job_id job)
} }
// pm_set_parameters
status_t
pm_set_parameters(int fd, partition_id partitionID, const char* parameters,
disk_job_id job)
{
TRACE(("intel: pm_set_parameters\n"));
if (fd < 0)
return B_BAD_VALUE;
// Nothing to do if there are no parameters provided
if (parameters == NULL)
return B_OK;
PartitionWriteLocker locker(partitionID);
if (!locker.IsLocked())
return B_ERROR;
// get parent partition, child and partition map structure
partition_data* partition = get_parent_partition(partitionID);
partition_data* child = get_partition(partitionID);
if (partition == NULL || child == NULL)
return B_BAD_VALUE;
PartitionMap* map = (PartitionMap*)partition->content_cookie;
PrimaryPartition* primary = (PrimaryPartition*)child->cookie;
if (map ==NULL || primary == NULL)
return B_BAD_VALUE;
// check 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);
// if the old type is the same, there is nothing to do
if (primary->Active() == active) {
TRACE(("intel: pm_set_parameters: no changes required.\n"));
return B_OK;
}
update_disk_device_job_progress(job, 0.0);
// set the active flags to false for other partitions
if (active) {
for (int i = 0; i < 4; i++) {
PrimaryPartition* partition = map->PrimaryPartitionAt(i);
partition->SetActive(false);
}
}
bool oldActive = primary->Active();
primary->SetActive(active);
// TODO: The partition is not supposed to be locked at this point!
PartitionMapWriter writer(fd, primary->BlockSize());
// TODO: disk size?
status_t error = writer.WriteMBR(map, false);
if (error != B_OK) {
TRACE(("intel: pm_set_parameters: Failed to rewrite MBR: %s\n",
strerror(error)));
// something went wrong - putting into previous state
primary->SetType(oldActive);
return error;
}
// all changes applied
update_disk_device_job_progress(job, 1.0);
partition_modified(partitionID);
return B_OK;
}
// pm_initialize // pm_initialize
status_t status_t
pm_initialize(int fd, partition_id partitionID, const char* name, pm_initialize(int fd, partition_id partitionID, const char* name,

View File

@ -46,6 +46,8 @@ status_t pm_move_child(int fd, partition_id partitionID,
partition_id childID, off_t offset, disk_job_id job); partition_id childID, off_t offset, disk_job_id job);
status_t pm_set_type(int fd, partition_id partitionID, const char* type, status_t pm_set_type(int fd, partition_id partitionID, const char* type,
disk_job_id job); disk_job_id job);
status_t pm_set_parameters(int fd, partition_id partitionID,
const char* parameters, disk_job_id job);
status_t pm_initialize(int fd, partition_id partitionID, const char* name, status_t pm_initialize(int fd, partition_id partitionID, const char* name,
const char* parameters, off_t partitionSize, disk_job_id job); const char* parameters, off_t partitionSize, disk_job_id job);
status_t pm_uninitialize(int fd, partition_id partitionID, status_t pm_uninitialize(int fd, partition_id partitionID,

View File

@ -109,24 +109,28 @@ ChangeParametersPanel::Go(BString& name, BString& type, BString& parameters,
void void
ChangeParametersPanel::CreateChangeControls(BPartition* parent) ChangeParametersPanel::CreateChangeControls(BPartition* partition)
{ {
fNameTextControl = new BTextControl("Name Control", fNameTextControl = new BTextControl("Name Control",
B_TRANSLATE("Partition name:"), "", NULL); B_TRANSLATE("Partition name:"), partition->Name(), NULL);
fSupportsName = parent->SupportsChildName(); fSupportsName = partition->CanSetName();
fTypePopUpMenu = new BPopUpMenu("Partition Type"); fTypePopUpMenu = new BPopUpMenu("Partition Type");
int32 cookie = 0; int32 cookie = 0;
BString supportedType; BString supportedType;
while (parent->GetNextSupportedChildType(&cookie, &supportedType) == B_OK) { BPartition* parent = partition->Parent();
BMessage* message = new BMessage(MSG_PARTITION_TYPE); if (parent != NULL) {
message->AddString("type", supportedType); while (parent->GetNextSupportedChildType(&cookie, &supportedType)
BMenuItem* item = new BMenuItem(supportedType, message); == B_OK) {
fTypePopUpMenu->AddItem(item); BMessage* message = new BMessage(MSG_PARTITION_TYPE);
message->AddString("type", supportedType);
BMenuItem* item = new BMenuItem(supportedType, message);
fTypePopUpMenu->AddItem(item);
if (strcmp(supportedType, kPartitionTypeBFS) == 0) if (strcmp(supportedType, kPartitionTypeBFS) == 0)
item->SetMarked(true); item->SetMarked(true);
}
} }
fTypeMenuField = new BMenuField(B_TRANSLATE("Partition type:"), fTypeMenuField = new BMenuField(B_TRANSLATE("Partition type:"),

View File

@ -410,9 +410,10 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* parent,
} }
// parameters // parameters
if ((changeFlags & B_PARTITION_CHANGED_PARAMETERS) if ((partition->Parameters() != NULL)
|| compare_string(partition->Parameters(), && ((changeFlags & B_PARTITION_CHANGED_PARAMETERS) != 0
partitionData->parameters)) { || compare_string(partition->Parameters(),
partitionData->parameters))) {
if (!parent) if (!parent)
return B_BAD_VALUE; return B_BAD_VALUE;
@ -441,9 +442,10 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* parent,
} }
// content parameters // content parameters
if ((changeFlags & B_PARTITION_CHANGED_PARAMETERS) if ((partition->ContentParameters() != NULL)
|| compare_string(partition->ContentParameters(), && ((changeFlags & B_PARTITION_CHANGED_PARAMETERS) != 0
partitionData->content_parameters)) { || compare_string(partition->ContentParameters(),
partitionData->content_parameters))) {
status_t error = _GenerateSetContentParametersJob(partition); status_t error = _GenerateSetContentParametersJob(partition);
if (error != B_OK) if (error != B_OK)
return error; return error;

View File

@ -6,6 +6,7 @@
#include "DiskDeviceJobQueue.h" #include "DiskDeviceJobQueue.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <typeinfo> #include <typeinfo>
@ -54,7 +55,8 @@ DiskDeviceJobQueue::Execute()
status_t error = job->Do(); status_t error = job->Do();
if (error != B_OK) { if (error != B_OK) {
TRACE("DiskDeviceJobQueue::Execute(): executing job failed\n"); TRACE("DiskDeviceJobQueue::Execute(): executing job failed: %s\n",
strerror(error));
return error; return error;
} }
} }