[parted-devel] [PATCH] support read-only and no-auto flags used by systemd-gpt-auto-generator
Arvin Schnell
aschnell at suse.com
Fri Oct 2 13:32:35 BST 2020
On Wed, Sep 30, 2020 at 10:58:49AM -0700, Brian C. Lane wrote:
> If you read Table 24 of the UEFI spec[1] you will see that it says that
> attributes are controlled by the owner of the PartitionTypeGUID.
>
> This means that you can't just arbitrarily carve out some bits and use
> them for new flags. They need to be tied to specific GUIDs and not
> effect other users of the GuidSpecific value.
>
> So if you:
>
> * restore the GuidSpecific struct entry to its previous state
The new patch has generic names for the bits in the struct.
> * tie read_only and no_auto to the systemd GUID(s)
And it is only possible to set the flags for swap. A new function
supports_read_only_and_no_auto_flag is used to control that.
Setting another partition type, e.g. RAID, clears the two
flags. Unsetting swap also does do.
Kind Regards,
Arvin
---
doc/C/parted.8 | 3 +-
doc/parted.texi | 8 ++
include/parted/disk.in.h | 6 +-
libparted/disk.c | 7 ++
libparted/labels/gpt.c | 135 ++++++++++++++++++++++++++-----
tests/Makefile.am | 1 +
tests/t3320-read_only-no_auto.sh | 47 +++++++++++
7 files changed, 185 insertions(+), 22 deletions(-)
create mode 100755 tests/t3320-read_only-no_auto.sh
diff --git a/doc/C/parted.8 b/doc/C/parted.8
index 297c39a..c3d634f 100644
--- a/doc/C/parted.8
+++ b/doc/C/parted.8
@@ -112,7 +112,8 @@ or an LVM logical volume if necessary.
.B set \fIpartition\fP \fIflag\fP \fIstate\fP
Change the state of the \fIflag\fP on \fIpartition\fP to \fIstate\fP.
Supported flags are: "boot", "root", "swap", "hidden", "raid", "lvm", "lba",
-"legacy_boot", "irst", "msftres", "esp", "chromeos_kernel", "bls_boot" and "palo".
+"legacy_boot", "irst", "msftres", "esp", "chromeos_kernel", "bls_boot", "palo",
+"read_only" and "no_auto".
\fIstate\fP should be either "on" or "off".
.TP
.B unit \fIunit\fP
diff --git a/doc/parted.texi b/doc/parted.texi
index 213fc84..f4761a3 100644
--- a/doc/parted.texi
+++ b/doc/parted.texi
@@ -918,6 +918,14 @@ as a PReP boot partition on PowerPC PReP or IBM RS6K/CHRP hardware.
(MS-DOS) - Enable this to indicate that a partition can be used
as a diagnostics / recovery partition.
+ at item read_only
+(GPT) - this flags tells systemd-gpt-auto-generator to mount the
+partition read-only. Only supported for swap.
+
+ at item no_auto
+(GPT) - this flags tells systemd-gpt-auto-generator to not automatically
+mount the partition. Only supported for swap.
+
@end table
The print command displays all enabled flags for each partition.
diff --git a/include/parted/disk.in.h b/include/parted/disk.in.h
index fadb995..4aa8af6 100644
--- a/include/parted/disk.in.h
+++ b/include/parted/disk.in.h
@@ -77,10 +77,12 @@ enum _PedPartitionFlag {
PED_PARTITION_IRST=17,
PED_PARTITION_ESP=18,
PED_PARTITION_CHROMEOS_KERNEL=19,
- PED_PARTITION_BLS_BOOT=20
+ PED_PARTITION_BLS_BOOT=20,
+ PED_PARTITION_READ_ONLY=21,
+ PED_PARTITION_NO_AUTO=22
};
#define PED_PARTITION_FIRST_FLAG PED_PARTITION_BOOT
-#define PED_PARTITION_LAST_FLAG PED_PARTITION_BLS_BOOT
+#define PED_PARTITION_LAST_FLAG PED_PARTITION_NO_AUTO
enum _PedDiskTypeFeature {
PED_DISK_TYPE_EXTENDED=1, /**< supports extended partitions */
diff --git a/libparted/disk.c b/libparted/disk.c
index 099837b..3521d88 100644
--- a/libparted/disk.c
+++ b/libparted/disk.c
@@ -1351,6 +1351,9 @@ ped_partition_is_active (const PedPartition* part)
* refers to the partition that will be booted from on startup. On PC98
* disk labels, the user can choose from any bootable partition on startup.
*
+ * Flags can also be partition type specific. That is the case for read_only
+ * and no_auto.
+ *
* \note It is an error to call this on an unavailable flag -- use
* ped_partition_is_flag_available() to determine which flags are available
* for a given disk label.
@@ -2411,6 +2414,10 @@ ped_partition_flag_get_name (PedPartitionFlag flag)
return N_("chromeos_kernel");
case PED_PARTITION_BLS_BOOT:
return N_("bls_boot");
+ case PED_PARTITION_READ_ONLY:
+ return N_("read_only");
+ case PED_PARTITION_NO_AUTO:
+ return N_("no_auto");
default:
ped_exception_throw (
diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 93f7add..9bde23a 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -190,16 +190,26 @@ struct __attribute__ ((packed)) _GuidPartitionEntryAttributes_t
uint64_t RequiredToFunction:1;
uint64_t NoBlockIOProtocol:1;
uint64_t LegacyBIOSBootable:1;
- uint64_t Reserved:45;
- uint64_t GuidSpecific:16;
+ uint64_t Reserved1:45;
+ /* The meaning of the upper 16 bits depends on the partition type and thus
+ have only generic names. */
+ uint64_t GuidSpecific1:12;
+ uint64_t SBit13:1;
+ uint64_t GuidSpecific2:2;
+ uint64_t SBit16:1;
#else
# warning "Using crippled partition entry type"
uint32_t RequiredToFunction:1;
uint32_t NoBlockIOProtocol:1;
uint32_t LegacyBIOSBootable:1;
- uint32_t Reserved:30;
- uint32_t LOST:5;
- uint32_t GuidSpecific:16;
+ uint32_t Reserved1:29;
+ uint32_t Reserved2:16;
+ /* The meaning of the upper 16 bits depends on the partition type and thus
+ have only generic names. */
+ uint64_t GuidSpecific1:12;
+ uint64_t SBit13:1;
+ uint64_t GuidSpecific2:2;
+ uint64_t SBit16:1;
#endif
};
@@ -313,6 +323,8 @@ typedef struct _GPTPartitionData
int irst;
int chromeos_kernel;
int bls_boot;
+ int read_only; /* only for swap */
+ int no_auto; /* only for swap */
} GPTPartitionData;
static PedDiskType gpt_disk_type;
@@ -399,6 +411,20 @@ pth_get_raw (const PedDevice *dev, const GuidPartitionTableHeader_t *pth)
return pth_raw;
}
+
+/**
+ * Return whether the read_only and no_auto flags are supported depending
+ * on the partition.
+ */
+static int _GL_ATTRIBUTE_PURE
+supports_read_only_and_no_auto_flag (const GPTPartitionData *gpt_part_data)
+{
+ PED_ASSERT (gpt_part_data != NULL);
+
+ return gpt_part_data->swap == 1;
+}
+
+
/**
* swap_uuid_and_efi_guid() - converts between uuid formats
* @uuid - uuid_t in either format (converts it to the other)
@@ -838,6 +864,8 @@ _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto
= gpt_part_data->bios_grub = gpt_part_data->atvrecv = 0;
if (pte->Attributes.RequiredToFunction & 0x1)
@@ -874,6 +902,14 @@ _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
else if (!guid_cmp (gpt_part_data->type, PARTITION_BLS_BOOT_GUID))
gpt_part_data->bls_boot = 1;
+ if (supports_read_only_and_no_auto_flag(gpt_part_data))
+ {
+ if (pte->Attributes.SBit13 & 0x1)
+ gpt_part_data->read_only = 1;
+ if (pte->Attributes.SBit16 & 0x1)
+ gpt_part_data->no_auto = 1;
+ }
+
return part;
}
@@ -1248,6 +1284,14 @@ _partition_generate_part_entry (PedPartition *part, GuidPartitionEntry_t *pte)
if (gpt_part_data->legacy_boot)
pte->Attributes.LegacyBIOSBootable = 1;
+ if (supports_read_only_and_no_auto_flag(gpt_part_data))
+ {
+ if (gpt_part_data->read_only)
+ pte->Attributes.SBit13 = 1;
+ if (gpt_part_data->no_auto)
+ pte->Attributes.SBit16 = 1;
+ }
+
for (i = 0; i < 36; i++)
pte->PartitionName[i] = gpt_part_data->name[i];
}
@@ -1395,6 +1439,8 @@ gpt_partition_new (const PedDisk *disk,
gpt_part_data->irst = 0;
gpt_part_data->chromeos_kernel = 0;
gpt_part_data->bls_boot = 0;
+ gpt_part_data->read_only = 0;
+ gpt_part_data->no_auto = 0;
uuid_generate ((unsigned char *) &gpt_part_data->uuid);
swap_uuid_and_efi_guid (&gpt_part_data->uuid);
memset (gpt_part_data->name, 0, sizeof gpt_part_data->name);
@@ -1683,7 +1729,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_BIOS_GRUB:
gpt_part_data->bios_grub = state;
@@ -1700,7 +1748,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_RAID:
gpt_part_data->raid = state;
@@ -1717,7 +1767,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_LVM:
gpt_part_data->lvm = state;
@@ -1734,7 +1786,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_SWAP:
gpt_part_data->swap = state;
@@ -1752,6 +1806,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
= gpt_part_data->atvrecv = 0;
+ else
+ gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_HPSERVICE:
gpt_part_data->hp_service = state;
@@ -1768,7 +1825,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_MSFT_RESERVED:
gpt_part_data->msftres = state;
@@ -1785,7 +1844,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_MSFT_DATA:
gpt_part_data->msftres = state;
@@ -1802,7 +1863,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
gpt_part_data->msftdata = 1;
} else {
gpt_part_data->msftdata = 0;
@@ -1822,7 +1885,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->prep
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_APPLE_TV_RECOVERY:
gpt_part_data->atvrecv = state;
@@ -1837,7 +1902,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->msftdata
= gpt_part_data->prep
= gpt_part_data->chromeos_kernel
- = gpt_part_data->msftrecv = 0;
+ = gpt_part_data->msftrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_PREP:
gpt_part_data->prep = state;
@@ -1853,7 +1920,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->atvrecv
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->msftrecv = 0;
+ = gpt_part_data->msftrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_IRST:
gpt_part_data->irst = state;
@@ -1870,7 +1939,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->prep
= gpt_part_data->chromeos_kernel
= gpt_part_data->bls_boot
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_CHROMEOS_KERNEL:
gpt_part_data->chromeos_kernel = state;
@@ -1887,7 +1958,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->atvrecv
= gpt_part_data->prep
= gpt_part_data->irst
- = gpt_part_data->bls_boot = 0;
+ = gpt_part_data->bls_boot
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_BLS_BOOT:
gpt_part_data->bls_boot = state;
@@ -1904,7 +1977,9 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
= gpt_part_data->prep
= gpt_part_data->irst
= gpt_part_data->chromeos_kernel
- = gpt_part_data->atvrecv = 0;
+ = gpt_part_data->atvrecv
+ = gpt_part_data->read_only
+ = gpt_part_data->no_auto = 0;
return gpt_partition_set_system (part, part->fs_type);
case PED_PARTITION_HIDDEN:
gpt_part_data->hidden = state;
@@ -1912,6 +1987,16 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
case PED_PARTITION_LEGACY_BOOT:
gpt_part_data->legacy_boot = state;
return 1;
+ case PED_PARTITION_READ_ONLY:
+ if (!supports_read_only_and_no_auto_flag(gpt_part_data))
+ return 0;
+ gpt_part_data->read_only = state;
+ return 1;
+ case PED_PARTITION_NO_AUTO:
+ if (!supports_read_only_and_no_auto_flag(gpt_part_data))
+ return 0;
+ gpt_part_data->no_auto = state;
+ return 1;
case PED_PARTITION_ROOT:
case PED_PARTITION_LBA:
default:
@@ -1958,6 +2043,10 @@ gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
return gpt_part_data->irst;
case PED_PARTITION_BLS_BOOT:
return gpt_part_data->bls_boot;
+ case PED_PARTITION_READ_ONLY:
+ return gpt_part_data->read_only;
+ case PED_PARTITION_NO_AUTO:
+ return gpt_part_data->no_auto;
case PED_PARTITION_SWAP:
return gpt_part_data->swap;
case PED_PARTITION_CHROMEOS_KERNEL:
@@ -1970,10 +2059,15 @@ gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
return 0;
}
-static int
+static int _GL_ATTRIBUTE_PURE
gpt_partition_is_flag_available (const PedPartition *part,
PedPartitionFlag flag)
{
+ PED_ASSERT (part != NULL);
+ PED_ASSERT (part->disk_specific != NULL);
+
+ const GPTPartitionData *gpt_part_data = part->disk_specific;
+
switch (flag)
{
case PED_PARTITION_RAID:
@@ -1994,6 +2088,9 @@ gpt_partition_is_flag_available (const PedPartition *part,
case PED_PARTITION_CHROMEOS_KERNEL:
case PED_PARTITION_BLS_BOOT:
return 1;
+ case PED_PARTITION_READ_ONLY:
+ case PED_PARTITION_NO_AUTO:
+ return supports_read_only_and_no_auto_flag(gpt_part_data);
case PED_PARTITION_ROOT:
case PED_PARTITION_LBA:
default:
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0d7c022..ce16448 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -58,6 +58,7 @@ TESTS = \
t3200-type-change.sh \
t3300-palo-prep.sh \
t3310-flags.sh \
+ t3320-read_only-no_auto.sh \
t3400-whole-disk-FAT-partition.sh \
t4000-sun-raid-type.sh \
t4001-sun-vtoc.sh \
diff --git a/tests/t3320-read_only-no_auto.sh b/tests/t3320-read_only-no_auto.sh
new file mode 100755
index 0000000..1e1a6e6
--- /dev/null
+++ b/tests/t3320-read_only-no_auto.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+# Ensure that read_only and no_auto flags work properly.
+
+# Copyright (C) 2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../parted
+ss=$sector_size_
+
+cat > exp <<EOF || framework_failure
+1:2048s:4095s:2048s:linux-swap(v1):test:swap, read_only;
+1:2048s:4095s:2048s:linux-swap(v1):test:swap, read_only, no_auto;
+1:2048s:4095s:2048s:linux-swap(v1):test:swap, no_auto;
+1:2048s:4095s:2048s:linux-swap(v1):test:swap;
+EOF
+
+dev=dev-file
+
+n_sectors=5000
+dd if=/dev/null of=$dev bs=$ss seek=$n_sectors || fail=1
+
+parted -m -s $dev mklabel gpt \
+ mkpart test linux-swap $((1*2048))s $((2*2048-1))s unit s \
+ set 1 swap on \
+ set 1 read_only on print \
+ set 1 no_auto on print \
+ set 1 read_only off print \
+ set 1 no_auto off print \
+ > out 2> err || fail=1
+
+grep -E '^1:2048s:4095s:2048s:linux-swap\(v1\):test:.*;$' out > k; mv k out
+
+compare exp out || fail=1
+
+Exit $fail
--
Arvin Schnell, <aschnell at suse.com>
Senior Software Engineer, Research & Development
SUSE Software Solutions Germany GmbH
Maxfeldstraße 5
90409 Nürnberg
Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer
More information about the parted-devel
mailing list