[parted-devel] [PATCH v2 1/1] keep GUID specific attributes

Arvin Schnell aschnell at suse.com
Thu Sep 23 17:31:42 BST 2021


Keep GUID specific attributes when writing GPT.
---
 libparted/labels/gpt.c   | 30 +++++------------
 tests/Makefile.am        |  3 +-
 tests/gpt-attrs          | 72 ++++++++++++++++++++++++++++++++++++++++
 tests/t0215-gpt-attrs.sh | 46 +++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 22 deletions(-)
 create mode 100755 tests/gpt-attrs
 create mode 100644 tests/t0215-gpt-attrs.sh

diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 9b987c1..ba9a71a 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -297,18 +297,17 @@ typedef struct _GPTPartitionData
   efi_guid_t uuid;
   efi_char16_t name[37];
   char *translated_name;
+  GuidPartitionEntryAttributes_t attributes;
   int lvm;
   int swap;
   int raid;
   int boot;
   int bios_grub;
   int hp_service;
-  int hidden;
   int msftres;
   int msftdata;
   int atvrecv;
   int msftrecv;
-  int legacy_boot;
   int prep;
   int irst;
   int chromeos_kernel;
@@ -826,25 +825,20 @@ _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
     gpt_part_data->name[i] = (efi_char16_t) pte->PartitionName[i];
   gpt_part_data->name[i] = 0;
   gpt_part_data->translated_name = 0;
+  gpt_part_data->attributes = pte->Attributes;
 
   gpt_part_data->lvm = gpt_part_data->swap
     = gpt_part_data->raid
     = gpt_part_data->boot = gpt_part_data->hp_service
-    = gpt_part_data->hidden = gpt_part_data->msftres
+    = gpt_part_data->msftres
     = gpt_part_data->msftdata
     = gpt_part_data->msftrecv
-    = gpt_part_data->legacy_boot
     = gpt_part_data->prep
     = gpt_part_data->irst
     = gpt_part_data->chromeos_kernel
     = gpt_part_data->bls_boot
     = gpt_part_data->bios_grub = gpt_part_data->atvrecv = 0;
 
-  if (pte->Attributes.RequiredToFunction & 0x1)
-    gpt_part_data->hidden = 1;
-  if (pte->Attributes.LegacyBIOSBootable & 0x1)
-    gpt_part_data->legacy_boot = 1;
-
   if (!guid_cmp (gpt_part_data->type, PARTITION_SYSTEM_GUID))
     gpt_part_data->boot = 1;
   else if (!guid_cmp (gpt_part_data->type, PARTITION_BIOS_GRUB_GUID))
@@ -1241,12 +1235,7 @@ _partition_generate_part_entry (PedPartition *part, GuidPartitionEntry_t *pte)
   pte->UniquePartitionGuid = gpt_part_data->uuid;
   pte->StartingLBA = PED_CPU_TO_LE64 (part->geom.start);
   pte->EndingLBA = PED_CPU_TO_LE64 (part->geom.end);
-  memset (&pte->Attributes, 0, sizeof (GuidPartitionEntryAttributes_t));
-
-  if (gpt_part_data->hidden)
-    pte->Attributes.RequiredToFunction = 1;
-  if (gpt_part_data->legacy_boot)
-    pte->Attributes.LegacyBIOSBootable = 1;
+  pte->Attributes = gpt_part_data->attributes;
 
   for (i = 0; i < 36; i++)
     pte->PartitionName[i] = gpt_part_data->name[i];
@@ -1388,12 +1377,10 @@ gpt_partition_new (const PedDisk *disk,
   gpt_part_data->boot = 0;
   gpt_part_data->bios_grub = 0;
   gpt_part_data->hp_service = 0;
-  gpt_part_data->hidden = 0;
   gpt_part_data->msftres = 0;
   gpt_part_data->msftdata = 0;
   gpt_part_data->msftrecv = 0;
   gpt_part_data->atvrecv = 0;
-  gpt_part_data->legacy_boot = 0;
   gpt_part_data->prep = 0;
   gpt_part_data->translated_name = 0;
   gpt_part_data->irst = 0;
@@ -1402,6 +1389,7 @@ gpt_partition_new (const PedDisk *disk,
   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);
+  memset (&gpt_part_data->attributes, 0, sizeof gpt_part_data->attributes);
   return part;
 
 error_free_part:
@@ -1911,10 +1899,10 @@ gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
           = gpt_part_data->atvrecv = 0;
       return gpt_partition_set_system (part, part->fs_type);
     case PED_PARTITION_HIDDEN:
-      gpt_part_data->hidden = state;
+      gpt_part_data->attributes.RequiredToFunction = state;
       return 1;
     case PED_PARTITION_LEGACY_BOOT:
-      gpt_part_data->legacy_boot = state;
+      gpt_part_data->attributes.LegacyBIOSBootable = state;
       return 1;
     case PED_PARTITION_ROOT:
     case PED_PARTITION_LBA:
@@ -1953,9 +1941,9 @@ gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
     case PED_PARTITION_APPLE_TV_RECOVERY:
       return gpt_part_data->atvrecv;
     case PED_PARTITION_HIDDEN:
-      return gpt_part_data->hidden;
+      return gpt_part_data->attributes.RequiredToFunction;
     case PED_PARTITION_LEGACY_BOOT:
-      return gpt_part_data->legacy_boot;
+      return gpt_part_data->attributes.LegacyBIOSBootable;
     case PED_PARTITION_PREP:
       return gpt_part_data->prep;
     case PED_PARTITION_IRST:
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f9340aa..3dc6e72 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -26,6 +26,7 @@ TESTS = \
   t0211-gpt-rewrite-header.sh \
   t0212-gpt-many-partitions.sh \
   t0213-mkpart-start-negative.sh \
+  t0215-gpt-attrs.sh \
   t0220-gpt-msftres.sh \
   t0250-gpt.sh \
   t0251-gpt-unicode.sh \
@@ -98,7 +99,7 @@ TESTS = \
 EXTRA_DIST = \
   $(TESTS) t-local.sh t-lvm.sh \
   init.cfg init.sh t-lib-helpers.sh gpt-header-munge \
-  gpt-header-move msdos-overlap
+  gpt-header-move msdos-overlap gpt-attrs
 
 check_PROGRAMS = print-align print-flags print-max dup-clobber duplicate \
   fs-resize
diff --git a/tests/gpt-attrs b/tests/gpt-attrs
new file mode 100755
index 0000000..0a01447
--- /dev/null
+++ b/tests/gpt-attrs
@@ -0,0 +1,72 @@
+#!/usr/bin/python3
+
+# Copyright (C) 2021 SUSE LLC
+
+# program to show gpt partition attributes or set attributes of
+# partition 1
+
+# only works with 512 sectors and standard GPT header layout (128
+# partition entires with 128 bytes each, secondary header at end of
+# device)
+
+
+from struct import unpack_from, pack_into
+from zipfile import crc32
+import array
+import sys
+
+
+class Gpt:
+
+    # Calculate and insert the CRCs of the partition entires and the
+    # header.
+    def calc_crcs(self, header, entries):
+        # compute crc of partition entries
+        crc2 = crc32(entries) & 0xFFFFFFFF
+        pack_into('<L', header, 88, crc2)
+
+        # compute crc of header
+        pack_into('<L', header, 16, 0)
+        crc1 = crc32(header[:92]) & 0xFFFFFFFF
+        pack_into('<L', header, 16, crc1)
+
+    def read(self, name):
+        self.name = name
+
+        file = open(name, 'rb+')
+
+        file.seek(512)
+        self.primary_header = array.array('B', file.read(512))
+        self.primary_entries = array.array('B', file.read(32 * 512))
+
+        file.seek(-33 * 512, 2)
+        self.secondary_entries = array.array('B', file.read(32 * 512))
+        self.secondary_header = array.array('B', file.read(512))
+
+    def write(self):
+        file = open(self.name, 'rb+')
+
+        self.calc_crcs(self.primary_header, self.primary_entries)
+        file.seek(512)
+        file.write(self.primary_header)
+        file.write(self.primary_entries)
+
+        self.calc_crcs(self.secondary_header, self.secondary_entries)
+        file.seek(-33 * 512, 2)
+        file.write(self.secondary_entries)
+        file.write(self.secondary_header)
+
+
+gpt = Gpt()
+
+gpt.read(sys.argv[1])
+
+if sys.argv[2] == "show":
+    attrs = unpack_from('<Q', gpt.primary_entries, 48)[0]
+    print(hex(attrs))
+
+if sys.argv[2] == "set":
+    attrs = int(sys.argv[3], 0)
+    pack_into('<Q', gpt.primary_entries, 48, attrs)
+    pack_into('<Q', gpt.secondary_entries, 48, attrs)
+    gpt.write()
diff --git a/tests/t0215-gpt-attrs.sh b/tests/t0215-gpt-attrs.sh
new file mode 100644
index 0000000..216a966
--- /dev/null
+++ b/tests/t0215-gpt-attrs.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Test that GUID specific bits are preserved
+
+# Copyright (C) 2021 SUSE LLC
+
+# 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 $srcdir
+require_512_byte_sector_size_
+
+dev=loop-file
+
+# create device
+truncate --size 50MiB "$dev" || fail=1
+
+# create gpt label and one partitions
+parted --script "$dev" mklabel gpt > out 2>&1 || fail=1
+parted --script "$dev" mkpart "test1" ext4 0% 10% > out 2>&1 || fail=1
+
+# set guid specific bit
+gpt-attrs "$dev" set 0x100000000000000 || fail=1
+
+# create additional partition
+parted --script "$dev" mkpart "test2" ext4 10% 20% > out 2>&1 || fail=1
+
+cat <<EOF > exp || fail=1
+0x100000000000000
+EOF
+
+# check guid specific bit
+gpt-attrs "$dev" show > out || fail=1
+compare exp out || fail=1
+
+Exit $fail
-- 
2.33.0




More information about the parted-devel mailing list