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
| B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
| B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
| B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS
| 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
PartitionMapHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
BPartitionParameterEditor** editor)

View File

@ -49,6 +49,13 @@ public:
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(
B_PARAMETER_EDITOR_TYPE type,
BPartitionParameterEditor** editor);
@ -59,7 +66,7 @@ public:
const char* type, const char* name,
const char* parameters,
BMutablePartition** child);
virtual status_t DeleteChild(BMutablePartition* child);
virtual status_t DeleteChild(BMutablePartition* child);
private:
PartitionMap fPartitionMap;

View File

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

View File

@ -494,8 +494,8 @@ static partition_module_info intel_partition_map_module =
NULL, // set_name
NULL, // set_content_name
pm_set_type, // set_type
NULL, // set_parameters
NULL, // set_content_parameters
pm_set_parameters, // set_parameters
pm_set_parameters, // set_content_parameters
pm_initialize, // initialize
pm_uninitialize, // uninitialize
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
status_t
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);
status_t pm_set_type(int fd, partition_id partitionID, const char* type,
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,
const char* parameters, off_t partitionSize, disk_job_id job);
status_t pm_uninitialize(int fd, partition_id partitionID,

View File

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

View File

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

View File

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