diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index 9f251229e..268399dbd 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -239,6 +239,20 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
gs->insert( "allowManualPartitioning",
CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true ) );
+
+ if ( configurationMap.contains( "requiredPartitionTableType" ) &&
+ configurationMap.value( "requiredPartitionTableType" ).type() == QVariant::List )
+ {
+ m_requiredPartitionTableType.clear();
+ m_requiredPartitionTableType.append( configurationMap.value( "requiredPartitionTableType" ).toStringList() );
+ }
+ else if ( configurationMap.contains( "requiredPartitionTableType" ) &&
+ configurationMap.value( "requiredPartitionTableType" ).type() == QVariant::String )
+ {
+ m_requiredPartitionTableType.clear();
+ m_requiredPartitionTableType.append( configurationMap.value( "requiredPartitionTableType" ).toString() );
+ }
+ gs->insert( "requiredPartitionTableType", m_requiredPartitionTableType);
}
void
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
index 23ebdedf8..1629ccc22 100644
--- a/src/modules/partition/core/Config.h
+++ b/src/modules/partition/core/Config.h
@@ -114,6 +114,7 @@ private:
InstallChoice m_initialInstallChoice = NoChoice;
InstallChoice m_installChoice = NoChoice;
qreal m_requiredStorageGiB = 0.0; // May duplicate setting in the welcome module
+ QStringList m_requiredPartitionTableType;
};
/** @brief Given a set of swap choices, return a sensible value from it.
diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp
index 9f6e63c91..a78e8ff53 100644
--- a/src/modules/partition/core/PartitionActions.cpp
+++ b/src/modules/partition/core/PartitionActions.cpp
@@ -118,6 +118,14 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
// before that one, numbered 0..2047).
qint64 firstFreeSector = CalamaresUtils::bytesToSectors( empty_space_sizeB, dev->logicalSize() );
+ PartitionTable::TableType partType = PartitionTable::nameToTableType( o.defaultPartitionTableType );
+ if ( partType == PartitionTable::unknownTableType )
+ {
+ partType = isEfi ? PartitionTable::gpt : PartitionTable::msdos;
+ }
+
+ core->createPartitionTable( dev, partType );
+
if ( isEfi )
{
qint64 efiSectorCount = CalamaresUtils::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() );
@@ -127,7 +135,6 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
// at firstFreeSector, we need efiSectorCount sectors, numbered
// firstFreeSector..firstFreeSector+efiSectorCount-1.
qint64 lastSector = firstFreeSector + efiSectorCount - 1;
- core->createPartitionTable( dev, PartitionTable::gpt );
Partition* efiPartition = KPMHelpers::createNewPartition( dev->partitionTable(),
*dev,
PartitionRole( PartitionRole::Primary ),
@@ -144,10 +151,6 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
core->createPartition( dev, efiPartition, KPM_PARTITION_FLAG_ESP );
firstFreeSector = lastSector + 1;
}
- else
- {
- core->createPartitionTable( dev, PartitionTable::msdos );
- }
const bool mayCreateSwap
= ( o.swap == Config::SwapChoice::SmallSwap ) || ( o.swap == Config::SwapChoice::FullSwap );
diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h
index 15b7c1e1e..45d6f460a 100644
--- a/src/modules/partition/core/PartitionActions.h
+++ b/src/modules/partition/core/PartitionActions.h
@@ -29,11 +29,13 @@ namespace Choices
{
struct ReplacePartitionOptions
{
+ QString defaultPartitionTableType; // e.g. "gpt" or "msdos"
QString defaultFsType; // e.g. "ext4" or "btrfs"
QString luksPassphrase; // optional
- ReplacePartitionOptions( const QString& fs, const QString& luks )
- : defaultFsType( fs )
+ ReplacePartitionOptions( const QString& pt, const QString& fs, const QString& luks )
+ : defaultPartitionTableType ( pt )
+ , defaultFsType( fs )
, luksPassphrase( luks )
{
}
@@ -45,12 +47,13 @@ struct AutoPartitionOptions : ReplacePartitionOptions
quint64 requiredSpaceB; // estimated required space for root partition
Config::SwapChoice swap;
- AutoPartitionOptions( const QString& fs,
+ AutoPartitionOptions( const QString& pt,
+ const QString& fs,
const QString& luks,
const QString& efi,
qint64 requiredBytes,
Config::SwapChoice s )
- : ReplacePartitionOptions( fs, luks )
+ : ReplacePartitionOptions( pt, fs, luks )
, efiPartitionMountPoint( efi )
, requiredSpaceB( requiredBytes > 0 ? static_cast< quint64 >( requiredBytes ) : 0 )
, swap( s )
diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp
index 62e235c5c..c3ac14735 100644
--- a/src/modules/partition/gui/ChoicePage.cpp
+++ b/src/modules/partition/gui/ChoicePage.cpp
@@ -89,6 +89,7 @@ ChoicePage::ChoicePage( Config* config, QWidget* parent )
auto gs = Calamares::JobQueue::instance()->globalStorage();
+ m_requiredPartitionTableType = gs->value( "requiredPartitionTableType" ).toStringList();
m_defaultFsType = gs->value( "defaultFileSystemType" ).toString();
m_enableEncryptionWidget = gs->value( "enableLuksAutomatedPartitioning" ).toBool();
@@ -448,7 +449,8 @@ ChoicePage::applyActionChoice( InstallChoice choice )
{
auto gs = Calamares::JobQueue::instance()->globalStorage();
- PartitionActions::Choices::AutoPartitionOptions options { gs->value( "defaultFileSystemType" ).toString(),
+ PartitionActions::Choices::AutoPartitionOptions options { gs->value( "defaultPartitionTableType" ).toString(),
+ gs->value( "defaultFileSystemType" ).toString(),
m_encryptWidget->passphrase(),
gs->value( "efiSystemPartition" ).toString(),
CalamaresUtils::GiBtoBytes(
@@ -805,7 +807,9 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current )
m_core,
selectedDevice(),
selectedPartition,
- { gs->value( "defaultFileSystemType" ).toString(), m_encryptWidget->passphrase() } );
+ { gs->value( "defaultPartitionType" ).toString(),
+ gs->value( "defaultFileSystemType" ).toString(),
+ m_encryptWidget->passphrase() } );
Partition* homePartition = findPartitionByPath( { selectedDevice() }, *homePartitionPath );
if ( homePartition && doReuseHomePartition )
@@ -1249,6 +1253,7 @@ ChoicePage::setupActions()
bool atLeastOneCanBeReplaced = false;
bool atLeastOneIsMounted = false; // Suppress 'erase' if so
bool isInactiveRAID = false;
+ bool matchTableType = false;
#ifdef WITH_KPMCORE4API
if ( currentDevice->type() == Device::Type::SoftwareRAID_Device
@@ -1259,6 +1264,14 @@ ChoicePage::setupActions()
}
#endif
+ PartitionTable::TableType tableType = PartitionTable::unknownTableType;
+ if ( currentDevice->partitionTable() )
+ {
+ tableType = currentDevice->partitionTable()->type();
+ matchTableType = m_requiredPartitionTableType.size() == 0 ||
+ m_requiredPartitionTableType.contains( PartitionTable::tableTypeToName( tableType ) );
+ }
+
for ( auto it = PartitionIterator::begin( currentDevice ); it != PartitionIterator::end( currentDevice ); ++it )
{
if ( PartUtils::canBeResized( *it ) )
@@ -1431,6 +1444,27 @@ ChoicePage::setupActions()
m_replaceButton->hide();
}
+ if ( tableType != PartitionTable::unknownTableType && !matchTableType )
+ {
+ m_messageLabel->setText( tr( "This storage device already may has an operating system on it, "
+ "but its partition table %1 mismatch the"
+ "requirement %2.
" )
+ .arg( PartitionTable::tableTypeToName( tableType ) )
+ .arg( m_requiredPartitionTableType.join( " or " ) ) );
+ m_messageLabel->show();
+
+ cWarning() << "Partition table" << PartitionTable::tableTypeToName( tableType )
+ << "does not match the requirement " << m_requiredPartitionTableType.join( " or " ) << ", "
+ "ENABLING erease feature and ";
+ "DISABLING alongside, replace and manual features.";
+ m_eraseButton->show();
+ m_alongsideButton->hide();
+ m_replaceButton->hide();
+ m_somethingElseButton->hide();
+ cDebug() << "Replace button suppressed because partition table type mismatch.";
+ force_uncheck( m_grp, m_replaceButton );
+ }
+
if ( m_somethingElseButton->isHidden()
&& m_alongsideButton->isHidden()
&& m_replaceButton->isHidden()
diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h
index cce91e9cc..118f23a46 100644
--- a/src/modules/partition/gui/ChoicePage.h
+++ b/src/modules/partition/gui/ChoicePage.h
@@ -154,6 +154,7 @@ private:
int m_lastSelectedDeviceIndex = -1;
int m_lastSelectedActionIndex = -1;
+ QStringList m_requiredPartitionTableType;
QString m_defaultFsType;
bool m_enableEncryptionWidget;
diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp
index d0390aa86..a9860cd1e 100644
--- a/src/modules/partition/gui/PartitionViewStep.cpp
+++ b/src/modules/partition/gui/PartitionViewStep.cpp
@@ -574,6 +574,13 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
}
gs->insert( "defaultFileSystemType", fsRealName );
+ QString partitionTableName = CalamaresUtils::getString( configurationMap, "defaultPartitionTableType" );
+ if ( partitionTableName.isEmpty() )
+ {
+ cWarning() << "Partition-module setting *defaultPartitionTableType* is unset, "
+ "will use gpt for efi or msdos for bios";
+ }
+ gs->insert( "defaultPartitionTableType", partitionTableName );
// Now that we have the config, we load the PartitionCoreModule in the background
// because it could take a while. Then when it's done, we can set up the widgets
diff --git a/src/modules/partition/gui/ReplaceWidget.cpp b/src/modules/partition/gui/ReplaceWidget.cpp
index a316d98b2..69c89889b 100644
--- a/src/modules/partition/gui/ReplaceWidget.cpp
+++ b/src/modules/partition/gui/ReplaceWidget.cpp
@@ -85,7 +85,8 @@ ReplaceWidget::applyChanges()
Device* dev = model->device();
PartitionActions::doReplacePartition(
- m_core, dev, partition, { gs->value( "defaultFileSystemType" ).toString(), QString() } );
+ m_core, dev, partition, { gs->value( "defaultPartitionTableType" ).toString(),
+ gs->value( "defaultFileSystemType" ).toString(), QString() } );
if ( m_isEfi )
{
diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf
index efebe19f4..bfedddfca 100644
--- a/src/modules/partition/partition.conf
+++ b/src/modules/partition/partition.conf
@@ -88,6 +88,35 @@ initialPartitioningChoice: none
# one of the items from the options.
initialSwapChoice: none
+# Default partition table type, used when a "erase" disk is made.
+#
+# When erasing a disk, a new partition table is created on disk.
+# In other cases, e.g. Replace and Alongside, as well as when using
+# manual partitioning, this partition table exists already on disk
+# and it is left unmodified.
+#
+# Suggested values: gpt, msdos
+# If nothing is specified, Calamares defaults to "gpt" if system is
+# efi or "msdos".
+#
+# Names are case-sensitive and defined by KPMCore.
+# defaultPartitionTableType: msdos
+
+# Requirement for partition table type
+#
+# Restrict the installation on disks that match the type of partition
+# tables that are specified.
+#
+# Suggested values: msdos, gpt
+# If nothing is specified, Calamares defaults to both "msdos" and "mbr".
+#
+# Names are case-sensitive and defined by KPMCore.
+# requiredPartitionTableType: gpt
+# or,
+# requiredPartitionTableType:
+# - msdos
+# - gpt
+
# Default filesystem type, used when a "new" partition is made.
#
# When replacing a partition, the existing filesystem inside the