1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-30 17:18:21 +03:00

filter: partitioned: also detect non-empty GPT partition table

We already detect msdos partition table. If it is empty, that is, there
is just the partition header and no actual partitions defined, then the
filter-partitioned passes, otherwise not.

Do the same for GPT partition table.
This commit is contained in:
Peter Rajnoha 2024-09-04 15:30:42 +02:00
parent 4708a354f6
commit 84cabd068b
No known key found for this signature in database
GPG Key ID: E776664036DF84AB

View File

@ -505,6 +505,11 @@ int dev_get_partition_number(struct device *dev, int *num)
#define PART_MAGIC 0xAA55
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
#define PART_OFFSET UINT64_C(0x1BE)
#define PART_TYPE_GPT_PMBR UINT8_C(0xEE)
#define PART_GPT_HEADER_OFFSET_LBA 0x01
#define PART_GPT_MAGIC 0x5452415020494645UL /* "EFI PART" string */
#define PART_GPT_ENTRIES_FIELDS_OFFSET UINT64_C(0x48)
struct partition {
uint8_t boot_ind;
@ -570,6 +575,65 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
return 1;
}
static int _has_gpt_partition_table(struct device *dev)
{
unsigned int pbs, lbs;
uint64_t entries_start;
uint32_t nr_entries, sz_entry, i;
struct {
uint64_t magic;
/* skip fields we're not interested in */
uint8_t skip[PART_GPT_ENTRIES_FIELDS_OFFSET - sizeof(uint64_t)];
uint64_t part_entries_lba;
uint32_t nr_part_entries;
uint32_t sz_part_entry;
} __attribute__((packed)) gpt_header;
struct {
uint64_t part_type_guid;
/* not interested in any other fields */
} __attribute__((packed)) gpt_part_entry;
if (!dev_get_direct_block_sizes(dev, &pbs, &lbs))
return_0;
if (!dev_read_bytes(dev, PART_GPT_HEADER_OFFSET_LBA * lbs, sizeof(gpt_header), &gpt_header))
return_0;
/* the gpt table is always written using LE on disk */
if (le64_to_cpu(gpt_header.magic) != PART_GPT_MAGIC)
return_0;
entries_start = le64_to_cpu(gpt_header.part_entries_lba) * lbs;
nr_entries = le32_to_cpu(gpt_header.nr_part_entries);
sz_entry = le32_to_cpu(gpt_header.sz_part_entry);
for (i = 0; i < nr_entries; i++) {
if (!dev_read_bytes(dev, entries_start + i * sz_entry,
sizeof(gpt_part_entry), &gpt_part_entry))
return_0;
/* just check if the guid is nonzero, no need to call le64_to_cpu here */
if (gpt_part_entry.part_type_guid)
return 1;
}
return 0;
}
/*
* Check if there's a partition table present on the device dev, either msdos or gpt.
* Returns:
*
* 1 - if it has a partition table with at least one real partition defined
* (note: the gpt's PMBR partition alone does not count as a real partition)
*
* 0 - if it has no partition table,
* - or if it does have a partition table, but without any partition defined,
* - or on error
*/
static int _has_partition_table(struct device *dev)
{
int ret = 0;
@ -594,10 +658,20 @@ static int _has_partition_table(struct device *dev)
break;
}
/* Must have at least one non-empty partition */
if (buf.part[p].nr_sects)
ret = 1;
if (buf.part[p].nr_sects) {
/*
* If this is GPT's PMBR, then also
* check for gpt partition table.
*/
if (buf.part[p].sys_ind == PART_TYPE_GPT_PMBR)
ret = _has_gpt_partition_table(dev);
else
ret = 1;
}
}
}
} else
/* Check for gpt partition table. */
ret = _has_gpt_partition_table(dev);
return ret;
}