-
Notifications
You must be signed in to change notification settings - Fork 9
/
gpt.h
100 lines (85 loc) · 3.56 KB
/
gpt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright (c) 2008 David Caldwell, All Rights Reserved.
#ifndef __GPT_H__
#define __GPT_H__
#include <stdint.h>
// [1] Extensible Firmware Interface Specification, Version 1.10
// [2] Extensible Firmware Interface Specification, Version 1.10 Specification Update
// Both can be downloaded from here: http://www.intel.com/technology/efi/main_specification.htm
struct gpt_header {
char signature[8];
uint32_t revision;
uint32_t header_size;
uint32_t header_crc32;
uint32_t reserved;
uint64_t my_lba;
uint64_t alternate_lba;
uint64_t first_usable_lba;
uint64_t last_usable_lba;
GUID disk_guid;
uint64_t partition_entry_lba;
uint32_t partition_entries;
uint32_t partition_entry_size;
uint32_t partition_crc32;
} __attribute__((packed)); // odd number of 32bit items so 64bit machines might make this too big
#define PARTITION_REVISION 0x00010000 // [2] 11-9.1
struct gpt_partition {
GUID partition_type;
GUID partition_guid;
uint64_t first_lba;
uint64_t last_lba;
uint64_t attributes;
uint16_t name[36];
};
// gpt_partition.attribute
#define PA_SYSTEM_PARTITION (1LL << 0)
// GUID specific
#define PA_READ_ONLY (1LL << 60)
#define PA_HIDDEN (1LL << 62)
#define PA_NO_AUTOMOUNT (1LL << 63)
#include "endian.h"
static inline void gpt_header_to_host(struct gpt_header *h) {
h->revision = from_le32(h->revision);
h->header_size = from_le32(h->header_size);
h->header_crc32 = from_le32(h->header_crc32);
h->reserved = from_le32(h->reserved);
h->my_lba = from_le64(h->my_lba);
h->alternate_lba = from_le64(h->alternate_lba);
h->first_usable_lba = from_le64(h->first_usable_lba);
h->last_usable_lba = from_le64(h->last_usable_lba);
h->partition_entry_lba = from_le64(h->partition_entry_lba);
h->partition_entries = from_le32(h->partition_entries);
h->partition_entry_size = from_le32(h->partition_entry_size);
h->partition_crc32 = from_le32(h->partition_crc32);
}
static inline void gpt_partition_to_host(struct gpt_partition *partition, int entries) {
for (int p=0; p<entries; p++) {
partition[p].first_lba = from_le64(partition[p].first_lba);
partition[p].last_lba = from_le64(partition[p].last_lba);
partition[p].attributes = from_le64(partition[p].attributes);
for (int i=0; i<lengthof(partition[p].name); i++)
partition[p].name[i] = from_le16(partition[p].name[i]);
}
}
// No use in repeating the whole thing when it's going to turn out exactly the same.
#define gpt_partition_from_host gpt_partition_to_host
#define gpt_header_from_host gpt_header_to_host
#include <zlib.h>
static inline uint32_t gpt_partition_crc32(struct gpt_header *h, struct gpt_partition *partition)
{
uint32_t partition_crc32_old = h->partition_crc32; h->partition_crc32 = 0;
gpt_partition_from_host(partition, h->partition_entries);
uint32_t partition_crc32 = crc32(crc32(0L, Z_NULL, 0), (void*)partition, h->partition_entries * h->partition_entry_size);
gpt_partition_to_host(partition, h->partition_entries);
h->partition_crc32 = partition_crc32_old;
return partition_crc32;
}
static inline uint32_t gpt_header_crc32(struct gpt_header *h)
{
uint32_t headder_crc32_old = h->header_crc32; h->header_crc32 = 0;
gpt_header_from_host(h);
uint32_t header_crc32 = crc32(crc32(0L, Z_NULL, 0), (void*)h, h->header_size);
gpt_header_to_host(h);
h->header_crc32 = headder_crc32_old;
return header_crc32;
}
#endif /* __GPT_H__ */