/src/wolfBoot/include/gpt.h
Line | Count | Source |
1 | | /* gpt.h |
2 | | * |
3 | | * Generic GPT (GUID Partition Table) parsing support. |
4 | | * |
5 | | * Copyright (C) 2026 wolfSSL Inc. |
6 | | * |
7 | | * This file is part of wolfBoot. |
8 | | * |
9 | | * wolfBoot is free software; you can redistribute it and/or modify |
10 | | * it under the terms of the GNU General Public License as published by |
11 | | * the Free Software Foundation; either version 3 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * wolfBoot is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU General Public License |
20 | | * along with this program; if not, write to the Free Software |
21 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
22 | | */ |
23 | | |
24 | | #ifndef GPT_H |
25 | | #define GPT_H |
26 | | |
27 | | #include <stdint.h> |
28 | | |
29 | | /* Every field in an MBR, a GPT structure, a FAT32 BPB and an ext4 superblock |
30 | | * is little-endian ON DISK. Casting a sector to a packed struct and |
31 | | * dereferencing it is therefore only correct on a little-endian host, so all |
32 | | * on-disk values are read through these instead. One definition, used by the |
33 | | * partition layer and by the filesystem parsers alike. */ |
34 | | static inline uint16_t gpt_le16(const uint8_t *p) |
35 | 3.21k | { |
36 | 3.21k | return (uint16_t)((uint16_t)p[0] | ((uint16_t)p[1] << 8)); |
37 | 3.21k | } Unexecuted instantiation: fuzz_gpt.c:gpt_le16 Line | Count | Source | 35 | 3.21k | { | 36 | 3.21k | return (uint16_t)((uint16_t)p[0] | ((uint16_t)p[1] << 8)); | 37 | 3.21k | } |
|
38 | | |
39 | | static inline uint32_t gpt_le32(const uint8_t *p) |
40 | 4.09k | { |
41 | 4.09k | return ((uint32_t)p[0]) | ((uint32_t)p[1] << 8) | |
42 | 4.09k | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); |
43 | 4.09k | } Unexecuted instantiation: fuzz_gpt.c:gpt_le32 Line | Count | Source | 40 | 4.09k | { | 41 | 4.09k | return ((uint32_t)p[0]) | ((uint32_t)p[1] << 8) | | 42 | 4.09k | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); | 43 | 4.09k | } |
|
44 | | |
45 | | static inline uint64_t gpt_le64(const uint8_t *p) |
46 | 1.83k | { |
47 | 1.83k | return (uint64_t)gpt_le32(p) | ((uint64_t)gpt_le32(p + 4) << 32); |
48 | 1.83k | } Unexecuted instantiation: fuzz_gpt.c:gpt_le64 Line | Count | Source | 46 | 1.83k | { | 47 | 1.83k | return (uint64_t)gpt_le32(p) | ((uint64_t)gpt_le32(p + 4) << 32); | 48 | 1.83k | } |
|
49 | | |
50 | | |
51 | | /* GPT Constants */ |
52 | 705 | #define GPT_SECTOR_SIZE 512 /* 0x200 */ |
53 | 574 | #define GPT_SIGNATURE 0x5452415020494645ULL /* "EFI PART" */ |
54 | 40 | #define GPT_PTYPE_PROTECTIVE 0xEE |
55 | 3.21k | #define GPT_PART_NAME_SIZE 36 |
56 | 40 | #define GPT_MBR_ENTRY_START 0x01BE |
57 | | |
58 | | /* MBR partition entry field offsets, shared by src/gpt.c and src/disk.c. */ |
59 | 40 | #define GPT_MBR_PTE_PTYPE 0x04 |
60 | 5 | #define GPT_MBR_PTE_LBA_FIRST 0x08 |
61 | | #define GPT_MBR_PTE_LBA_SIZE 0x0C |
62 | 40 | #define GPT_MBR_PTE_SIZE 0x10 |
63 | 87 | #define GPT_MBR_BOOTSIG_OFFSET 0x01FE |
64 | 87 | #define GPT_MBR_BOOTSIG_VALUE 0xAA55 |
65 | | #define GPT_PART_ENTRY_SIZE 256 |
66 | | /* UEFI reserves 128 partition entries by default; bound the partition-entry |
67 | | * array (n_part * array_sz) used by the CRC scan to this many entries so a |
68 | | * crafted header cannot force an unbounded number of disk reads. */ |
69 | | #define GPT_MAX_PART_ENTRIES 128 |
70 | | |
71 | | /** |
72 | | * @brief MBR partition table entry structure. |
73 | | * |
74 | | * This packed structure defines the layout of an MBR partition table entry |
75 | | * used to identify GPT partitions (protective MBR). |
76 | | */ |
77 | | struct __attribute__((packed)) gpt_mbr_part_entry { |
78 | | uint8_t stat; |
79 | | uint8_t chs_first[3]; |
80 | | uint8_t ptype; |
81 | | uint8_t chs_last[3]; |
82 | | uint32_t lba_first; |
83 | | uint32_t lba_size; |
84 | | }; |
85 | | |
86 | | /** |
87 | | * @brief GPT (GUID Partition Table) header structure. |
88 | | */ |
89 | | struct __attribute__((packed)) guid_ptable { |
90 | | uint64_t signature; |
91 | | uint32_t revision; |
92 | | uint32_t hdr_size; |
93 | | uint32_t hdr_crc32; |
94 | | uint32_t res0; |
95 | | uint64_t main_lba; |
96 | | uint64_t backup_lba; |
97 | | uint64_t first_usable; |
98 | | uint64_t last_usable; |
99 | | uint64_t disk_guid[2]; |
100 | | uint64_t start_array; |
101 | | uint32_t n_part; |
102 | | uint32_t array_sz; |
103 | | uint32_t part_crc; |
104 | | uint8_t res1[GPT_SECTOR_SIZE - 0x5C]; |
105 | | }; |
106 | | |
107 | | /** |
108 | | * @brief GPT partition entry structure. |
109 | | * |
110 | | * This packed structure defines the layout of a GPT partition entry |
111 | | * used to describe individual partitions on the disk. |
112 | | */ |
113 | | struct __attribute__((packed)) gpt_part_entry { |
114 | | uint64_t type[2]; |
115 | | uint64_t uuid[2]; |
116 | | uint64_t first; |
117 | | uint64_t last; |
118 | | uint64_t flags; |
119 | | uint16_t name[GPT_PART_NAME_SIZE]; |
120 | | }; |
121 | | |
122 | | /** |
123 | | * @brief Parsed partition information. |
124 | | * |
125 | | * This structure holds parsed information about a partition extracted |
126 | | * from a GPT partition entry. |
127 | | */ |
128 | | struct gpt_part_info { |
129 | | uint64_t start; /* Start offset in bytes */ |
130 | | uint64_t end; /* End offset in bytes */ |
131 | | uint16_t name[GPT_PART_NAME_SIZE]; |
132 | | }; |
133 | | |
134 | | /** |
135 | | * @brief CRC32 context for GPT header and partition-array validation. |
136 | | */ |
137 | | struct gpt_crc32_ctx { |
138 | | uint32_t value; |
139 | | }; |
140 | | |
141 | | /** |
142 | | * @brief Check MBR for protective GPT partition entry. |
143 | | * |
144 | | * Scans the MBR sector for a protective GPT partition entry (type 0xEE) |
145 | | * and validates the boot signature. |
146 | | * |
147 | | * @param[in] mbr_sector Pointer to 512-byte MBR sector data. |
148 | | * @param[out] gpt_lba If not NULL, receives the LBA of the GPT header. |
149 | | * |
150 | | * @return 0 on success (valid protective MBR found), -1 on error. |
151 | | */ |
152 | | int gpt_check_mbr_protective(const uint8_t *mbr_sector, uint32_t *gpt_lba); |
153 | | |
154 | | /** |
155 | | * @brief Parse and validate a GPT header. |
156 | | * |
157 | | * Validates the GPT signature and copies header data to the output structure. |
158 | | * |
159 | | * @param[in] sector Pointer to 512-byte GPT header sector data. |
160 | | * @param[out] hdr Pointer to structure to receive parsed header. |
161 | | * |
162 | | * @return 0 on success (valid GPT header), -1 on error. |
163 | | */ |
164 | | int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr); |
165 | | |
166 | | /** |
167 | | * @brief Parse a GPT partition entry. |
168 | | * |
169 | | * Parses a single partition entry and extracts partition information. |
170 | | * Returns success only if the partition entry is valid (non-zero type GUID). |
171 | | * |
172 | | * @param[in] entry_data Pointer to partition entry data. |
173 | | * @param[in] entry_size Size of the partition entry in bytes. |
174 | | * @param[out] part Pointer to structure to receive parsed partition info. |
175 | | * |
176 | | * @return 0 on success (valid partition entry), -1 if entry is empty/invalid. |
177 | | */ |
178 | | int gpt_parse_partition(const uint8_t *entry_data, uint32_t entry_size, |
179 | | struct gpt_part_info *part); |
180 | | |
181 | | /** |
182 | | * @brief Initialize a GPT CRC32 calculation. |
183 | | * |
184 | | * @param[out] ctx Pointer to CRC32 context. |
185 | | */ |
186 | | void gpt_crc32_init(struct gpt_crc32_ctx *ctx); |
187 | | |
188 | | /** |
189 | | * @brief Accumulate bytes into a GPT CRC32 calculation. |
190 | | * |
191 | | * @param[in,out] ctx Pointer to CRC32 context. |
192 | | * @param[in] data Pointer to input bytes. |
193 | | * @param[in] len Number of bytes to process. |
194 | | */ |
195 | | void gpt_crc32_update(struct gpt_crc32_ctx *ctx, const uint8_t *data, |
196 | | uint32_t len); |
197 | | |
198 | | /** |
199 | | * @brief Finalize a GPT CRC32 calculation. |
200 | | * |
201 | | * @param[in] ctx Pointer to CRC32 context. |
202 | | * |
203 | | * @return Final CRC32 value. |
204 | | */ |
205 | | uint32_t gpt_crc32_final(const struct gpt_crc32_ctx *ctx); |
206 | | |
207 | | /** |
208 | | * @brief Compare UTF-16 partition name with ASCII string. |
209 | | * |
210 | | * Compares a GPT partition name (UTF-16LE) with an ASCII string label. |
211 | | * |
212 | | * @param[in] utf16_name UTF-16LE partition name from GPT entry. |
213 | | * @param[in] ascii_label ASCII string to compare against. |
214 | | * |
215 | | * @return 1 if names match, 0 if they don't match. |
216 | | */ |
217 | | int gpt_part_name_eq(const uint16_t *utf16_name, const char *ascii_label); |
218 | | |
219 | | #endif /* GPT_H */ |