1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-08 08:58:27 +03:00

gpt: move basic header/partition structure of GPT into common code

This way we can use it at other places too, not just when dissecting
images.
This commit is contained in:
Lennart Poettering 2023-08-15 09:52:38 +02:00
parent 24ae45cb65
commit 6b0651df60
3 changed files with 56 additions and 33 deletions

View File

@ -111,27 +111,10 @@ int dissect_fstype_ok(const char *fstype) {
int probe_sector_size(int fd, uint32_t *ret) {
struct gpt_header {
char signature[8];
le32_t revision;
le32_t header_size;
le32_t crc32;
le32_t reserved;
le64_t my_lba;
le64_t alternate_lba;
le64_t first_usable_lba;
le64_t last_usable_lba;
sd_id128_t disk_guid;
le64_t partition_entry_lba;
le32_t number_of_partition_entries;
le32_t size_of_partition_entry;
le32_t partition_entry_array_crc32;
} _packed_;
/* Disk images might be for 512B or for 4096 sector sizes, let's try to auto-detect that by searching
* for the GPT headers at the relevant byte offsets */
assert_cc(sizeof(struct gpt_header) == 92);
assert_cc(sizeof(GptHeader) == 92);
/* We expect a sector size in the range 512…4096. The GPT header is located in the second
* sector. Hence it could be at byte 512 at the earliest, and at byte 4096 at the latest. And we must
@ -151,24 +134,12 @@ int probe_sector_size(int fd, uint32_t *ret) {
/* Let's see if we find the GPT partition header with various expected sector sizes */
for (uint32_t sz = 512; sz <= 4096; sz <<= 1) {
struct gpt_header *p;
const GptHeader *p;
assert(sizeof(sectors) >= sz * 2);
p = (struct gpt_header*) (sectors + sz);
p = (const GptHeader*) (sectors + sz);
if (memcmp(p->signature, (const char[8]) { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }, 8) != 0)
continue;
if (le32toh(p->revision) != UINT32_C(0x00010000)) /* the only known revision of the spec: 1.0 */
continue;
if (le32toh(p->header_size) < sizeof(struct gpt_header))
continue;
if (le32toh(p->header_size) > 4096) /* larger than a sector? something is off… */
continue;
if (le64toh(p->my_lba) != 1) /* this sector must claim to be at sector offset 1 */
if (!gpt_header_has_signature(p))
continue;
if (found != 0)

View File

@ -336,3 +336,24 @@ bool gpt_partition_type_knows_no_auto(GptPartitionType type) {
PARTITION_XBOOTLDR,
PARTITION_SWAP);
}
bool gpt_header_has_signature(const GptHeader *p) {
assert(p);
if (memcmp(p->signature, (const char[8]) { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }, 8) != 0)
return false;
if (le32toh(p->revision) != UINT32_C(0x00010000)) /* the only known revision of the spec: 1.0 */
return false;
if (le32toh(p->header_size) < sizeof(GptHeader))
return false;
if (le32toh(p->header_size) > 4096) /* larger than a sector? something is off… */
return false;
if (le64toh(p->my_lba) != 1) /* this sector must claim to be at sector offset 1 */
return false;
return true;
}

View File

@ -1,11 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <uchar.h>
#include "sd-gpt.h"
#include "sd-id128.h"
#include "architecture.h"
#include "id128-util.h"
#include "sparse-endian.h"
/* maximum length of gpt label */
#define GPT_LABEL_MAX 36
@ -69,3 +72,31 @@ const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type);
bool gpt_partition_type_knows_read_only(GptPartitionType type);
bool gpt_partition_type_knows_growfs(GptPartitionType type);
bool gpt_partition_type_knows_no_auto(GptPartitionType type);
typedef struct {
uint8_t partition_type_guid[16];
uint8_t unique_partition_guid[16];
le64_t starting_lba;
le64_t ending_lba;
le64_t attributes;
char16_t partition_name[36];
} _packed_ GptPartitionEntry;
typedef struct {
char signature[8];
le32_t revision;
le32_t header_size;
le32_t crc32;
le32_t reserved;
le64_t my_lba;
le64_t alternate_lba;
le64_t first_usable_lba;
le64_t last_usable_lba;
uint8_t disk_guid[16];
le64_t partition_entry_lba;
le32_t number_of_partition_entries;
le32_t size_of_partition_entry;
le32_t partition_entry_array_crc32;
} _packed_ GptHeader;
bool gpt_header_has_signature(const GptHeader *p);