diff --git a/src/libcalamares/GlobalStorage.cpp b/src/libcalamares/GlobalStorage.cpp
index 717b8fff77a5d9b80fb199f6572e3a9c2cd106c0..0c78201d333c9508c984582e2a456afb171ed80c 100644
--- a/src/libcalamares/GlobalStorage.cpp
+++ b/src/libcalamares/GlobalStorage.cpp
@@ -88,6 +88,13 @@ GlobalStorage::remove( const QString& key )
     return nItems;
 }
 
+void
+GlobalStorage::clear()
+{
+    WriteLock l( this );
+    m.clear();
+}
+
 QVariant
 GlobalStorage::value( const QString& key ) const
 {
diff --git a/src/libcalamares/GlobalStorage.h b/src/libcalamares/GlobalStorage.h
index a0a1940f24c34c7e1105642308ad09c3d6ddb1d1..da17243d3ea742039a3ba309c77a4ec16cf96dc9 100644
--- a/src/libcalamares/GlobalStorage.h
+++ b/src/libcalamares/GlobalStorage.h
@@ -70,6 +70,9 @@ public:
      */
     int remove( const QString& key );
 
+    /// @brief Clears all keys in this GS object
+    void clear();
+
     /** @brief dump keys and values to the debug log
      *
      * All the keys and their values are written to the debug log.
diff --git a/src/modules/partition/Config.cpp b/src/modules/partition/Config.cpp
index 4a84046b36f68fde15566b58dc567715da5d6d62..0962e960375c5e14f5a743c888ccfdfaf5852a01 100644
--- a/src/modules/partition/Config.cpp
+++ b/src/modules/partition/Config.cpp
@@ -274,39 +274,66 @@ fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configu
     QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) );
     gs->insert( "firmwareType", firmwareType );
 
-    gs->insert( "efiSystemPartition",
-                Calamares::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) ) );
+    bool ok = false;
+    auto efiConfiguration = Calamares::getSubMap( configurationMap, "efi", ok );
 
-    // Read and parse key efiSystemPartitionSize
-    if ( configurationMap.contains( "efiSystemPartitionSize" ) )
+    // Mount Point
     {
-        const QString sizeString = Calamares::getString( configurationMap, "efiSystemPartitionSize" );
-        Calamares::Partition::PartitionSize part_size = Calamares::Partition::PartitionSize( sizeString );
-        if ( part_size.isValid() )
+        const auto efiSystemPartition = Calamares::getString(
+            efiConfiguration,
+            "mountPoint",
+            Calamares::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) ) );
+        // This specific GS key is also used by bootloader and grubcfg modules,
+        // as well as partition module internalls.
+        gs->insert( "efiSystemPartition", efiSystemPartition );
+    }
+
+    // Sizes
+    {
+        const auto efiRecommendedSize = Calamares::getString(
+            efiConfiguration, "recommendedSize", Calamares::getString( configurationMap, "efiSystemPartitionSize" ) );
+        if ( !efiRecommendedSize.isEmpty() )
         {
-            // Insert once as string, once as a size-in-bytes;
-            // changes to these keys should be synchronized with PartUtils.cpp
-            gs->insert( "efiSystemPartitionSize", sizeString );
-            gs->insert( "efiSystemPartitionSize_i", part_size.toBytes() );
-
-            // Assign long long int to long unsigned int to prevent compilation warning
-            auto byte_part_size = part_size.toBytes();
-            if ( byte_part_size != PartUtils::efiFilesystemMinimumSize() )
+            Calamares::Partition::PartitionSize part_size = Calamares::Partition::PartitionSize( efiRecommendedSize );
+            if ( part_size.isValid() )
             {
-                cWarning() << "EFI partition size" << sizeString << "has been adjusted to"
-                           << PartUtils::efiFilesystemMinimumSize() << "bytes";
+                gs->insert( PartUtils::efiFilesystemRecommendedSizeGSKey(), part_size.toBytes() );
+
+                // Assign long long int to long unsigned int to prevent compilation warning,
+                // checks for loss-of-precision in the conversion.
+                auto byte_part_size = part_size.toBytes();
+                if ( byte_part_size != PartUtils::efiFilesystemRecommendedSize() )
+                {
+                    cWarning() << "EFI partition size" << efiRecommendedSize << "has been adjusted to"
+                               << PartUtils::efiFilesystemRecommendedSize() << "bytes";
+                }
+            }
+            else
+            {
+                cWarning() << "EFI partition size" << efiRecommendedSize << "is invalid, ignored";
             }
         }
-        else
+
+        const auto efiMinimumSize = Calamares::getString( efiConfiguration, "minimumSize" );
+        if ( !efiMinimumSize.isEmpty() )
         {
-            cWarning() << "EFI partition size" << sizeString << "is invalid, ignored";
+            Calamares::Partition::PartitionSize part_size = Calamares::Partition::PartitionSize( efiMinimumSize );
+            if ( part_size.isValid() )
+            {
+                gs->insert( PartUtils::efiFilesystemMinimumSizeGSKey(), part_size.toBytes() );
+            }
         }
     }
 
-    // Read and parse key efiSystemPartitionName
-    if ( configurationMap.contains( "efiSystemPartitionName" ) )
+    // Name (label) of partition
     {
-        gs->insert( "efiSystemPartitionName", Calamares::getString( configurationMap, "efiSystemPartitionName" ) );
+        const auto efiLabel = Calamares::getString(
+            efiConfiguration, "label", Calamares::getString( configurationMap, "efiSystemPartitionName" ) );
+
+        if ( !efiLabel.isEmpty() )
+        {
+            gs->insert( "efiSystemPartitionName", efiLabel );
+        }
     }
 }
 
diff --git a/src/modules/partition/PartitionViewStep.cpp b/src/modules/partition/PartitionViewStep.cpp
index a012938bfb0bfee1a69ed6fb8bf0f39dc11bbe7b..9bf9e26422e573f60a78190964afd310a40c4994 100644
--- a/src/modules/partition/PartitionViewStep.cpp
+++ b/src/modules/partition/PartitionViewStep.cpp
@@ -527,8 +527,8 @@ PartitionViewStep::onLeave()
             Logger::Once o;
 
             const bool okType = esp && PartUtils::isEfiFilesystemSuitableType( esp );
-            const bool okRecommendedSize = esp && PartUtils::isEfiFilesystemSuitableSize( esp );
-            const bool okMinimumSize = esp && PartUtils::isEfiFilesystemSuitableMinimumSize( esp );
+            const bool okRecommendedSize = esp && PartUtils::isEfiFilesystemRecommendedSize( esp );
+            const bool okMinimumSize = esp && PartUtils::isEfiFilesystemMinimumSize( esp );
             const bool okFlag = esp && PartUtils::isEfiBootable( esp );
 
             const bool espExistsButIsWrong = esp && !( okType && okMinimumSize && okFlag );
@@ -552,24 +552,21 @@ PartitionViewStep::onLeave()
             const QString wrongFlagMessage = tr( "The filesystem must have flag <strong>%1</strong> set." )
                                                  .arg( PartitionTable::flagName( PartitionTable::Flag::Boot ) );
 
-            // Three flavors of size-is-wrong
-            using Calamares::Units::operator""_MiB;
-
-            const qint64 atLeastBytes = static_cast< qint64 >( PartUtils::efiFilesystemMinimumSize() );
-            const auto atLeastMiB = Calamares::BytesToMiB( atLeastBytes );
+            const auto recommendedMiB = Calamares::BytesToMiB( PartUtils::efiFilesystemRecommendedSize() );
+            const auto minimumMiB = Calamares::BytesToMiB( PartUtils::efiFilesystemMinimumSize() );
 
+            // Three flavors of size-is-wrong
             const QString requireConfiguredSize
-                = tr( "The filesystem must be at least %1 MiB in size." ).arg( atLeastMiB );
+                = tr( "The filesystem must be at least %1 MiB in size." ).arg( recommendedMiB );
             const QString requiredMinimumSize
-                = tr( "The filesystem must be at least %1 MiB in size." ).arg( Calamares::BytesToMiB( 32_MiB ) );
+                = tr( "The filesystem must be at least %1 MiB in size." ).arg( minimumMiB );
             const QString suggestConfiguredSize
-                = tr( "The minimum recommended size for the filesystem is %1 MiB." ).arg( atLeastMiB );
-
+                = tr( "The minimum recommended size for the filesystem is %1 MiB." ).arg( recommendedMiB );
 
             const QString mayFail = tr( "You can continue without setting up an EFI system "
                                         "partition but your system may fail to start." );
             const QString possibleFail = tr( "You can continue with this EFI system "
-                                        "partition configuration but your system may fail to start." );
+                                             "partition configuration but your system may fail to start." );
 
             const QString startList = QStringLiteral( "<br/><br/><ul>" );
             const QString endList = QStringLiteral( "</ul><br/><br/>" );
diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp
index ad39bba3753889521ccfdc37159c1ff28df7b27d..bc3e6f5a027b6b98f6c023f12aa6300ece1e1ae2 100644
--- a/src/modules/partition/core/PartUtils.cpp
+++ b/src/modules/partition/core/PartUtils.cpp
@@ -35,6 +35,10 @@
 using Calamares::Partition::isPartitionFreeSpace;
 using Calamares::Partition::isPartitionNew;
 
+using Calamares::Units::operator""_MiB;
+
+static constexpr qint64 efiSpecificationHardMinimumSize = 32_MiB;
+
 namespace PartUtils
 {
 
@@ -471,7 +475,7 @@ isEfiFilesystemSuitableType( const Partition* candidate )
 }
 
 bool
-isEfiFilesystemSuitableSize( const Partition* candidate )
+isEfiFilesystemRecommendedSize( const Partition* candidate )
 {
     auto size = candidate->capacity();  // bytes
     if ( size <= 0 )
@@ -479,7 +483,7 @@ isEfiFilesystemSuitableSize( const Partition* candidate )
         return false;
     }
 
-    if ( size >= efiFilesystemMinimumSize() )
+    if ( size >= efiFilesystemRecommendedSize() )
     {
         return true;
     }
@@ -491,7 +495,7 @@ isEfiFilesystemSuitableSize( const Partition* candidate )
 }
 
 bool
-isEfiFilesystemSuitableMinimumSize( const Partition* candidate )
+isEfiFilesystemMinimumSize( const Partition* candidate )
 {
     using Calamares::Units::operator""_MiB;
 
@@ -500,8 +504,12 @@ isEfiFilesystemSuitableMinimumSize( const Partition* candidate )
     {
         return false;
     }
+    if ( size < efiSpecificationHardMinimumSize )
+    {
+        return false;
+    }
 
-    if ( size >= 32_MiB )
+    if ( size >= efiFilesystemMinimumSize() )
     {
         return true;
     }
@@ -522,28 +530,63 @@ isEfiBootable( const Partition* candidate )
     return flags.testFlag( KPM_PARTITION_FLAG_ESP );
 }
 
-// TODO: this is configurable via the config file **already**
+QString
+efiFilesystemRecommendedSizeGSKey()
+{
+    return QStringLiteral( "efiSystemPartitionSize_i" );
+}
+
 qint64
-efiFilesystemMinimumSize()
+efiFilesystemRecommendedSize()
 {
-    using Calamares::Units::operator""_MiB;
+    const QString key = efiFilesystemRecommendedSizeGSKey();
 
     qint64 uefisys_part_sizeB = 300_MiB;
 
     // The default can be overridden; the key used here comes
     // from the partition module Config.cpp
     auto* gs = Calamares::JobQueue::instance()->globalStorage();
-    if ( gs->contains( "efiSystemPartitionSize_i" ) )
+    if ( gs->contains( key ) )
+    {
+        qint64 v = gs->value( key ).toLongLong();
+        uefisys_part_sizeB = v > 0 ? v : 0;
+    }
+    // There is a lower limit of what can be configured
+    if ( uefisys_part_sizeB < efiSpecificationHardMinimumSize )
+    {
+        uefisys_part_sizeB = efiSpecificationHardMinimumSize;
+    }
+    return uefisys_part_sizeB;
+}
+
+QString
+efiFilesystemMinimumSizeGSKey()
+{
+    return QStringLiteral( "efiSystemPartitionMinimumSize_i" );
+}
+
+qint64
+efiFilesystemMinimumSize()
+{
+    const QString key = efiFilesystemMinimumSizeGSKey();
+
+    qint64 uefisys_part_sizeB = efiFilesystemRecommendedSize();
+
+    // The default can be overridden; the key used here comes
+    // from the partition module Config.cpp
+    auto* gs = Calamares::JobQueue::instance()->globalStorage();
+    if ( gs->contains( key ) )
     {
-        qint64 v = gs->value( "efiSystemPartitionSize_i" ).toLongLong();
+        qint64 v = gs->value( key ).toLongLong();
         uefisys_part_sizeB = v > 0 ? v : 0;
     }
     // There is a lower limit of what can be configured
-    if ( uefisys_part_sizeB < 32_MiB )
+    if ( uefisys_part_sizeB < efiSpecificationHardMinimumSize )
     {
-        uefisys_part_sizeB = 32_MiB;
+        uefisys_part_sizeB = efiSpecificationHardMinimumSize;
     }
     return uefisys_part_sizeB;
+    return efiSpecificationHardMinimumSize;
 }
 
 QString
diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h
index 98a1c1ab3736de73366ee77501ea03acbfeab64c..7813a98c475cd487abb2449ae9d14d284f7f41f5 100644
--- a/src/modules/partition/core/PartUtils.h
+++ b/src/modules/partition/core/PartUtils.h
@@ -95,15 +95,15 @@ bool isEfiFilesystemSuitableType( const Partition* candidate );
 
 /**
  * @brief Is the @p partition suitable as an EFI boot partition?
- * Checks for filesystem size (300MiB, see efiFilesystemMinimumSize).
+ * Checks for filesystem size (300MiB, see efi.recommendedSize).
  */
-bool isEfiFilesystemSuitableSize( const Partition* candidate );
+bool isEfiFilesystemRecommendedSize( const Partition* candidate );
 
 /**
  * @brief Is the @p candidate suitable as an EFI boot partition?
- * This checks the bonkers-small minimum of 32MiB.
+ * Checks for filesystem size (32MiB at least, see efi.minimumSize).
  */
-bool isEfiFilesystemSuitableMinimumSize( const Partition* candidate );
+bool isEfiFilesystemMinimumSize( const Partition* candidate );
 
 /** @brief Returns the minimum size of an EFI boot partition in bytes.
  *
@@ -113,13 +113,25 @@ bool isEfiFilesystemSuitableMinimumSize( const Partition* candidate );
  * by the standard and how all of those are different).
  *
  * This can be configured through the `partition.conf` file,
- * key *efiSystemPartitionSize*, which will then apply to both
+ * key *efi.recommendedSize*, which will then apply to both
  * automatic partitioning **and** the warning for manual partitioning.
  *
  * A minimum of 32MiB (which is bonkers-small) is enforced.
  */
+qint64 efiFilesystemRecommendedSize();
+
+// Helper for consistency: the GS key used to share the recommended size
+QString efiFilesystemRecommendedSizeGSKey();
+
+/** @brief Returns the hard-minimum size of an EFI boot partition in bytes.
+ *
+ * This is 32MiB, based on the FAT32 standard and EFI documentation.
+ */
 qint64 efiFilesystemMinimumSize();
 
+// Helper for consistency: the GS key used to share the minimum size
+QString efiFilesystemMinimumSizeGSKey();
+
 /**
  * @brief Is the given @p partition bootable in EFI? Depending on
  * the partition table layout, this may mean different flags.
diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp
index 25e4a01a5b112a8c17a723fd5c5cbd6a0c840c42..b5fb0cafb00140b3bf1284f53a3e97ea43d21396 100644
--- a/src/modules/partition/core/PartitionActions.cpp
+++ b/src/modules/partition/core/PartitionActions.cpp
@@ -118,7 +118,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
 
     if ( isEfi )
     {
-        qint64 uefisys_part_sizeB = PartUtils::efiFilesystemMinimumSize();
+        qint64 uefisys_part_sizeB = PartUtils::efiFilesystemRecommendedSize();
         qint64 efiSectorCount = Calamares::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() );
         Q_ASSERT( efiSectorCount > 0 );
 
diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf
index 13b6a1b92d3496777012bc4bde1b26ecde15d77c..59b7db2d80b6db1b1f0c2bb0c4ca787793142bef 100644
--- a/src/modules/partition/partition.conf
+++ b/src/modules/partition/partition.conf
@@ -1,26 +1,49 @@
 # SPDX-FileCopyrightText: no
 # SPDX-License-Identifier: CC0-1.0
 #
-# This setting specifies the mount point of the EFI system partition. Some
-# distributions (Fedora, Debian, Manjaro, etc.) use /boot/efi, others (KaOS,
-# etc.) use just /boot.
-#
-# Defaults to "/boot/efi", may be empty (but weird effects ensue)
-efiSystemPartition:     "/boot/efi"
 
-# This optional setting specifies the size of the EFI system partition.
-# If nothing is specified, the default size of 300MiB will be used.
-#
-# This size applies both to automatic partitioning and the checks
-# during manual partitioning. A minimum of 32MiB is enforced,
-# 300MiB is the default, M is treated as MiB, and if you really want
-# one-million (10^6) bytes, use MB.
-#
-# efiSystemPartitionSize:     300M
+# Options for EFI system partition.
+#
+# - *mountPoint*
+#   This setting specifies the mount point of the EFI system partition. Some
+#   distributions (Fedora, Debian, Manjaro, etc.) use /boot/efi, others (KaOS,
+#   etc.) use just /boot.
+#
+#   Defaults to "/boot/efi", may be empty (but weird effects ensue)
+# - *recommendedSize*
+#   This optional setting specifies the size of the EFI system partition.
+#   If nothing is specified, the default size of 300MiB will be used.
+#   When writing quantities here, M is treated as MiB, and if you really
+#   want one-million (10^6) bytes, use MB.
+# - *minimumSize*
+#   This optional setting specifies the absolute minimum size of the EFI
+#   system partition. If nothing is specified, the *recommendedSize*
+#   is used instead.
+# - *label*
+#   This optional setting specifies the name of the EFI system partition (see
+#   PARTLABEL; gpt only; requires KPMCore >= 4.2.0).
+#   If nothing is specified, the partition name is left unset.
+#
+# Going below the *recommended* size is allowed, but the user will
+# get a warning that it might not work. Going below the *minimum*
+# size is not allowed and the user will be told it will not work.
+#
+# Both quantities must be at least 32MiB, this is enforced by the EFI
+# spec. If minimum is not specified, it defaults to the recommended
+# size. Distro's that allow more user latitude can set the minimum lower.
+efi:
+    mountPoint:         "/boot/efi"
+    recommendedSize:    300MiB
+    minimumSize:        32MiB
+    label:              "EFI"
 
-# This optional setting specifies the name of the EFI system partition (see
-# PARTLABEL; gpt only; requires KPMCore >= 4.2.0).
-# If nothing is specified, the partition name is left unset.
+# Deprecated alias of efi.mountPoint
+# efiSystemPartition:     "/boot/efi"
+
+# Deprecated alias of efi.recommendedSize
+# efiSystemPartitionSize:          300MiB
+
+# Deprecated alias of efi.label
 # efiSystemPartitionName:     EFI
 
 # In autogenerated partitioning, allow the user to select a swap size?
diff --git a/src/modules/partition/partition.schema.yaml b/src/modules/partition/partition.schema.yaml
index 5207c03722a10edbfc10ebd756cd0ff64809e07c..769c1abae56a4fe44e7838923b9d6e3027530602 100644
--- a/src/modules/partition/partition.schema.yaml
+++ b/src/modules/partition/partition.schema.yaml
@@ -7,9 +7,18 @@ $id: https://calamares.io/schemas/partition
 additionalProperties: false
 type: object
 properties:
-    efiSystemPartition: { type: string }  # Mount point
-    efiSystemPartitionSize: { type: string }
-    efiSystemPartitionName: { type: string }
+    efiSystemPartition: { type: string }  # Deprecated alias of efi.mountPoint
+    efiSystemPartitionSize: { type: string } # Deprecated alias of efi.recommendedSize
+    efiSystemPartitionName: { type: string } # Deprecated alias of efi.label
+
+    efi:
+        type: object
+        properties:
+            recommendedSize: { type: string }
+            minimumSize: { type: string }
+            label: { type: string }
+            mountPoint: { type: string }
+        additionalProperties: false
 
     userSwapChoices: { type: array, items: { type: string, enum: [ none, reuse, small, suspend, file ] } }
     # ensureSuspendToDisk: { type: boolean, default: true }  # Legacy
@@ -34,5 +43,4 @@ properties:
 
     requiredStorage: { type: number }
 required:
-    - efiSystemPartition
     - userSwapChoices
diff --git a/src/modules/partition/tests/1a-legacy.conf b/src/modules/partition/tests/1a-legacy.conf
new file mode 100644
index 0000000000000000000000000000000000000000..f3435a262cffbc7ba60b9acebaee48298cd405c9
--- /dev/null
+++ b/src/modules/partition/tests/1a-legacy.conf
@@ -0,0 +1,2 @@
+---
+efiSystemPartitionSize:          100MiB
diff --git a/src/modules/partition/tests/1b-legacy.conf b/src/modules/partition/tests/1b-legacy.conf
new file mode 100644
index 0000000000000000000000000000000000000000..9792e815579e2374a58dac655a19a7610fbc99b3
--- /dev/null
+++ b/src/modules/partition/tests/1b-legacy.conf
@@ -0,0 +1,2 @@
+---
+efiSystemPartitionSize:          100MB
diff --git a/src/modules/partition/tests/2a-legacy.conf b/src/modules/partition/tests/2a-legacy.conf
new file mode 100644
index 0000000000000000000000000000000000000000..47111a66fb91ef4296570829268e20d339c47cc5
--- /dev/null
+++ b/src/modules/partition/tests/2a-legacy.conf
@@ -0,0 +1,9 @@
+---
+# Deprecated alias of efi.mountPoint
+efiSystemPartition:     "/boot/thisisatest"
+
+# Deprecated alias of efi.recommendedSize
+efiSystemPartitionSize:          75MiB
+
+# Deprecated alias of efi.label
+efiSystemPartitionName:     testLabel
diff --git a/src/modules/partition/tests/2b-modern.conf b/src/modules/partition/tests/2b-modern.conf
new file mode 100644
index 0000000000000000000000000000000000000000..5b6a6ddf641a4b5933269f5531dfe4bc534098da
--- /dev/null
+++ b/src/modules/partition/tests/2b-modern.conf
@@ -0,0 +1,6 @@
+---
+efi:
+    mountPoint:         "/boot/thisismodern"
+    recommendedSize:    80MiB
+    minimumSize:        65MiB
+    label:              "UEFI"
diff --git a/src/modules/partition/tests/2c-mixed.conf b/src/modules/partition/tests/2c-mixed.conf
new file mode 100644
index 0000000000000000000000000000000000000000..f472ebef6ba48d3bcb20923d66269881de9450f2
--- /dev/null
+++ b/src/modules/partition/tests/2c-mixed.conf
@@ -0,0 +1,7 @@
+---
+efi:
+    mountPoint:         "/boot/thisismixed"
+    minimumSize:    80MiB
+
+efiSystemPartitionSize:     175MiB
+efiSystemPartitionName:     legacy
diff --git a/src/modules/partition/tests/2d-overlap.conf b/src/modules/partition/tests/2d-overlap.conf
new file mode 100644
index 0000000000000000000000000000000000000000..9ddfa56df00bf32f4abea62bff40100a760797a7
--- /dev/null
+++ b/src/modules/partition/tests/2d-overlap.conf
@@ -0,0 +1,9 @@
+---
+efi:
+    mountPoint:         "/boot/thisoverlaps"
+    minimumSize:        100MiB
+    recommendedSize:    300MiB
+
+efiSystemPartition:         "/boot/ignored"
+efiSystemPartitionSize:     175MiB
+efiSystemPartitionName:     legacy
diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt
index 9c5dd32575204d19d8bfc755158993ae917c5271..17b79265fb1bb6cc2db91e77a8f995621d5337bd 100644
--- a/src/modules/partition/tests/CMakeLists.txt
+++ b/src/modules/partition/tests/CMakeLists.txt
@@ -61,3 +61,16 @@ calamares_add_test(
     LIBRARIES calamares::kpmcore
     DEFINITIONS ${_partition_defs}
 )
+
+calamares_add_test(
+    partitionconfigtest
+    SOURCES
+        ConfigTests.cpp
+        ${PartitionModule_SOURCE_DIR}/core/DeviceModel.cpp
+        ${PartitionModule_SOURCE_DIR}/core/PartitionInfo.cpp
+        ${PartitionModule_SOURCE_DIR}/core/PartUtils.cpp
+        ${PartitionModule_SOURCE_DIR}/Config.cpp
+    LIBRARIES calamares::kpmcore Calamares::calamaresui
+    DEFINITIONS
+        ${_partition_defs}
+)
diff --git a/src/modules/partition/tests/ConfigTests.cpp b/src/modules/partition/tests/ConfigTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ee815050184555eb6fc8090a31963ad9c1dee2d5
--- /dev/null
+++ b/src/modules/partition/tests/ConfigTests.cpp
@@ -0,0 +1,203 @@
+/* === This file is part of Calamares - <https://calamares.io> ===
+ *
+ *   SPDX-FileCopyrightText: 2023 Adriaan de Groot <groot@kde.org>
+ *   SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ *   Calamares is Free Software: see the License-Identifier above.
+ *
+ */
+
+#include "Config.h"
+
+#include "core/PartUtils.h"
+
+#include "GlobalStorage.h"
+#include "JobQueue.h"
+#include "utils/Logger.h"
+#include "utils/System.h"
+#include "utils/Yaml.h"
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+using Calamares::Units::operator""_MiB;
+
+class ConfigTests : public QObject
+{
+    Q_OBJECT
+
+public:
+    ConfigTests();
+
+private Q_SLOTS:
+    void initTestCase();
+    void testEmptyConfig();
+    void testLegacySize();
+    void testAll();
+};
+
+ConfigTests::ConfigTests() = default;
+
+void
+ConfigTests::initTestCase()
+{
+    Logger::setupLogLevel( Logger::LOGVERBOSE );
+
+    // Ensure we have a system object, expect it to be a "bogus" one
+    Calamares::System* system = Calamares::System::instance();
+    QVERIFY( system );
+    QVERIFY( system->doChroot() );
+
+    // Ensure we have a system-wide GlobalStorage with /tmp as root
+    if ( !Calamares::JobQueue::instance() )
+    {
+        cDebug() << "Creating new JobQueue";
+        (void)new Calamares::JobQueue();
+    }
+    Calamares::GlobalStorage* gs
+        = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
+    QVERIFY( gs );
+}
+
+
+void
+ConfigTests::testEmptyConfig()
+{
+    Config c( nullptr );
+    c.setConfigurationMap( {} );
+
+    const auto* gs = Calamares::JobQueue::instanceGlobalStorage();
+    QVERIFY( gs );
+
+    QVERIFY( c.initialInstallChoice() == Config::InstallChoice::NoChoice );
+    QVERIFY( !gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).isValid() );  // Nothing filled in
+    QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 300_MiB );  // Default value
+    QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 300_MiB );  // Default value
+
+    const auto firmware = gs->value( "firmwareType" ).toString();
+    QVERIFY( firmware == "efi" || firmware == "bios" );
+
+    QCOMPARE( gs->value( "efiSystemPartition" ).toString(), "/boot/efi" );  // Default
+}
+
+void
+ConfigTests::testLegacySize()
+{
+    Config c( nullptr );
+
+    auto* gs = Calamares::JobQueue::instanceGlobalStorage();
+    QVERIFY( gs );
+
+
+    // Config with just one legacy key
+    {
+        const auto file = QStringLiteral( BUILD_AS_TEST "/1a-legacy.conf" );
+        bool ok = false;
+        c.setConfigurationMap( Calamares::YAML::load( file, &ok ) );
+
+        cDebug() << "Tried to load" << file << "success?" << ok;
+
+        QVERIFY( ok );
+
+        QVERIFY( gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).isValid() );  // Something was filled in
+        QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 100_MiB );  // From config
+        QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 100_MiB );  // Taken from config
+    }
+
+    // Different legacy key value
+    {
+        bool ok = false;
+        c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/1b-legacy.conf" ), &ok ) );
+
+        QVERIFY( ok );
+
+        QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 100000000 );  // From config, MB
+        QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 100000000 );  // Taken from config
+    }
+}
+
+void
+ConfigTests::testAll()
+{
+    Config c( nullptr );
+
+    auto* gs = Calamares::JobQueue::instanceGlobalStorage();
+    QVERIFY( gs );
+
+
+    // Legacy only
+    {
+        gs->clear();
+        const auto file = QStringLiteral( BUILD_AS_TEST "/2a-legacy.conf" );
+        bool ok = false;
+        c.setConfigurationMap( Calamares::YAML::load( file, &ok ) );
+
+        cDebug() << "Tried to load" << file << "success?" << ok;
+
+        QVERIFY( ok );
+
+        QVERIFY( gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).isValid() );  // Something was filled in
+        QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 75_MiB );  // From config
+        QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 75_MiB );  // No separate setting
+
+        QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisisatest" ) );
+        QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "testLabel" ) );
+    }
+
+    // Modern only
+    {
+        gs->clear();
+        bool ok = false;
+        c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/2b-modern.conf" ), &ok ) );
+
+        QVERIFY( ok );
+
+        QVERIFY( PartUtils::efiFilesystemRecommendedSizeGSKey() != PartUtils::efiFilesystemMinimumSizeGSKey() );
+        QCOMPARE( gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).toString(),
+                  QStringLiteral( "83886080" ) );
+        QCOMPARE( gs->value( PartUtils::efiFilesystemMinimumSizeGSKey() ).toString(), QStringLiteral( "68157440" ) );
+
+        QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 80_MiB );  // From config
+        QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 65_MiB );  // Taken from config
+
+        QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisismodern" ) );
+        QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "UEFI" ) );
+    }
+
+    // Mixed settings
+    {
+        gs->clear();
+        bool ok = false;
+        c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/2c-mixed.conf" ), &ok ) );
+
+        QVERIFY( ok );
+
+        QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 175_MiB );  // From config
+        QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 80_MiB );  // Taken from config
+
+        QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisismixed" ) );
+        QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "legacy" ) );
+    }
+
+    // Mixed settings with overlap
+    {
+        gs->clear();
+        bool ok = false;
+        c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/2d-overlap.conf" ), &ok ) );
+
+        QVERIFY( ok );
+
+        QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 300_MiB );  // From modern config
+        QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 100_MiB );  // Taken from modern config, legacy ignored
+
+        QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisoverlaps" ) );
+        QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "legacy" ) );
+    }
+}
+
+
+QTEST_GUILESS_MAIN( ConfigTests )
+
+#include "utils/moc-warnings.h"
+
+#include "ConfigTests.moc"