1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2017 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "gpt.h"
7
8 #include "spdk/crc32.h"
9 #include "spdk/endian.h"
10 #include "spdk/event.h"
11
12 #include "spdk/log.h"
13
14 #define GPT_PRIMARY_PARTITION_TABLE_LBA 0x1
15 #define PRIMARY_PARTITION_NUMBER 4
16 #define GPT_PROTECTIVE_MBR 1
17 #define SPDK_MAX_NUM_PARTITION_ENTRIES 128
18
19 static uint64_t
gpt_get_expected_head_lba(struct spdk_gpt * gpt)20 gpt_get_expected_head_lba(struct spdk_gpt *gpt)
21 {
22 switch (gpt->parse_phase) {
23 case SPDK_GPT_PARSE_PHASE_PRIMARY:
24 return GPT_PRIMARY_PARTITION_TABLE_LBA;
25 case SPDK_GPT_PARSE_PHASE_SECONDARY:
26 return gpt->lba_end;
27 default:
28 assert(false);
29 }
30 return 0;
31 }
32
33 static struct spdk_gpt_header *
gpt_get_header_buf(struct spdk_gpt * gpt)34 gpt_get_header_buf(struct spdk_gpt *gpt)
35 {
36 switch (gpt->parse_phase) {
37 case SPDK_GPT_PARSE_PHASE_PRIMARY:
38 return (struct spdk_gpt_header *)
39 (gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
40 case SPDK_GPT_PARSE_PHASE_SECONDARY:
41 return (struct spdk_gpt_header *)
42 (gpt->buf + (gpt->buf_size - gpt->sector_size));
43 default:
44 assert(false);
45 }
46 return NULL;
47 }
48
49 static struct spdk_gpt_partition_entry *
gpt_get_partitions_buf(struct spdk_gpt * gpt,uint64_t total_partition_size,uint64_t partition_start_lba)50 gpt_get_partitions_buf(struct spdk_gpt *gpt, uint64_t total_partition_size,
51 uint64_t partition_start_lba)
52 {
53 uint64_t secondary_total_size;
54
55 switch (gpt->parse_phase) {
56 case SPDK_GPT_PARSE_PHASE_PRIMARY:
57 if ((total_partition_size + partition_start_lba * gpt->sector_size) >
58 gpt->buf_size) {
59 SPDK_ERRLOG("Buffer size is not enough\n");
60 return NULL;
61 }
62 return (struct spdk_gpt_partition_entry *)
63 (gpt->buf + partition_start_lba * gpt->sector_size);
64 case SPDK_GPT_PARSE_PHASE_SECONDARY:
65 secondary_total_size = (gpt->lba_end - partition_start_lba + 1) * gpt->sector_size;
66 if (secondary_total_size > gpt->buf_size) {
67 SPDK_ERRLOG("Buffer size is not enough\n");
68 return NULL;
69 }
70 return (struct spdk_gpt_partition_entry *)
71 (gpt->buf + (gpt->buf_size - secondary_total_size));
72 default:
73 assert(false);
74 }
75 return NULL;
76 }
77
78 static int
gpt_read_partitions(struct spdk_gpt * gpt)79 gpt_read_partitions(struct spdk_gpt *gpt)
80 {
81 uint32_t total_partition_size, num_partition_entries, partition_entry_size;
82 uint64_t partition_start_lba;
83 struct spdk_gpt_header *head = gpt->header;
84 uint32_t crc32;
85
86 num_partition_entries = from_le32(&head->num_partition_entries);
87 if (num_partition_entries > SPDK_MAX_NUM_PARTITION_ENTRIES) {
88 SPDK_ERRLOG("Num_partition_entries=%u which exceeds max=%u\n",
89 num_partition_entries, SPDK_MAX_NUM_PARTITION_ENTRIES);
90 return -1;
91 }
92
93 partition_entry_size = from_le32(&head->size_of_partition_entry);
94 if (partition_entry_size != sizeof(struct spdk_gpt_partition_entry)) {
95 SPDK_ERRLOG("Partition_entry_size(%x) != expected(%zx)\n",
96 partition_entry_size, sizeof(struct spdk_gpt_partition_entry));
97 return -1;
98 }
99
100 total_partition_size = num_partition_entries * partition_entry_size;
101 partition_start_lba = from_le64(&head->partition_entry_lba);
102 gpt->partitions = gpt_get_partitions_buf(gpt, total_partition_size,
103 partition_start_lba);
104 if (!gpt->partitions) {
105 SPDK_ERRLOG("Failed to get gpt partitions buf\n");
106 return -1;
107 }
108
109 crc32 = spdk_crc32_ieee_update(gpt->partitions, total_partition_size, ~0);
110 crc32 ^= ~0;
111
112 if (crc32 != from_le32(&head->partition_entry_array_crc32)) {
113 SPDK_ERRLOG("GPT partition entry array crc32 did not match\n");
114 return -1;
115 }
116
117 return 0;
118 }
119
120 static int
gpt_lba_range_check(struct spdk_gpt_header * head,uint64_t lba_end)121 gpt_lba_range_check(struct spdk_gpt_header *head, uint64_t lba_end)
122 {
123 uint64_t usable_lba_start, usable_lba_end;
124
125 usable_lba_start = from_le64(&head->first_usable_lba);
126 usable_lba_end = from_le64(&head->last_usable_lba);
127
128 if (usable_lba_end < usable_lba_start) {
129 SPDK_ERRLOG("Head's usable_lba_end(%" PRIu64 ") < usable_lba_start(%" PRIu64 ")\n",
130 usable_lba_end, usable_lba_start);
131 return -1;
132 }
133
134 if (usable_lba_end > lba_end) {
135 SPDK_ERRLOG("Head's usable_lba_end(%" PRIu64 ") > lba_end(%" PRIu64 ")\n",
136 usable_lba_end, lba_end);
137 return -1;
138 }
139
140 if ((usable_lba_start < GPT_PRIMARY_PARTITION_TABLE_LBA) &&
141 (GPT_PRIMARY_PARTITION_TABLE_LBA < usable_lba_end)) {
142 SPDK_ERRLOG("Head lba is not in the usable range\n");
143 return -1;
144 }
145
146 return 0;
147 }
148
149 static int
gpt_read_header(struct spdk_gpt * gpt)150 gpt_read_header(struct spdk_gpt *gpt)
151 {
152 uint32_t head_size;
153 uint32_t new_crc, original_crc;
154 uint64_t my_lba, head_lba;
155 struct spdk_gpt_header *head;
156
157 head = gpt_get_header_buf(gpt);
158 if (!head) {
159 SPDK_ERRLOG("Failed to get gpt header buf\n");
160 return -1;
161 }
162
163 head_size = from_le32(&head->header_size);
164 if (head_size < sizeof(*head) || head_size > gpt->sector_size) {
165 SPDK_ERRLOG("head_size=%u\n", head_size);
166 return -1;
167 }
168
169 original_crc = from_le32(&head->header_crc32);
170 head->header_crc32 = 0;
171 new_crc = spdk_crc32_ieee_update(head, from_le32(&head->header_size), ~0);
172 new_crc ^= ~0;
173 /* restore header crc32 */
174 to_le32(&head->header_crc32, original_crc);
175
176 if (new_crc != original_crc) {
177 SPDK_ERRLOG("head crc32 does not match, provided=%u, calculated=%u\n",
178 original_crc, new_crc);
179 return -1;
180 }
181
182 if (memcmp(SPDK_GPT_SIGNATURE, head->gpt_signature,
183 sizeof(head->gpt_signature))) {
184 SPDK_ERRLOG("signature did not match\n");
185 return -1;
186 }
187
188 head_lba = gpt_get_expected_head_lba(gpt);
189 my_lba = from_le64(&head->my_lba);
190 if (my_lba != head_lba) {
191 SPDK_ERRLOG("head my_lba(%" PRIu64 ") != expected(%" PRIu64 ")\n",
192 my_lba, head_lba);
193 return -1;
194 }
195
196 if (gpt_lba_range_check(head, gpt->lba_end)) {
197 SPDK_ERRLOG("lba range check error\n");
198 return -1;
199 }
200
201 gpt->header = head;
202 return 0;
203 }
204
205 static int
gpt_check_mbr(struct spdk_gpt * gpt)206 gpt_check_mbr(struct spdk_gpt *gpt)
207 {
208 int i, primary_partition = 0;
209 uint32_t total_lba_size = 0, ret = 0, expected_start_lba;
210 struct spdk_mbr *mbr;
211
212 mbr = (struct spdk_mbr *)gpt->buf;
213 if (from_le16(&mbr->mbr_signature) != SPDK_MBR_SIGNATURE) {
214 SPDK_DEBUGLOG(gpt_parse, "Signature mismatch, provided=%x,"
215 "expected=%x\n", from_le16(&mbr->disk_signature),
216 SPDK_MBR_SIGNATURE);
217 return -1;
218 }
219
220 for (i = 0; i < PRIMARY_PARTITION_NUMBER; i++) {
221 if (mbr->partitions[i].os_type == SPDK_MBR_OS_TYPE_GPT_PROTECTIVE) {
222 primary_partition = i;
223 ret = GPT_PROTECTIVE_MBR;
224 break;
225 }
226 }
227
228 if (ret == GPT_PROTECTIVE_MBR) {
229 expected_start_lba = GPT_PRIMARY_PARTITION_TABLE_LBA;
230 if (from_le32(&mbr->partitions[primary_partition].start_lba) != expected_start_lba) {
231 SPDK_DEBUGLOG(gpt_parse, "start lba mismatch, provided=%u, expected=%u\n",
232 from_le32(&mbr->partitions[primary_partition].start_lba),
233 expected_start_lba);
234 return -1;
235 }
236
237 total_lba_size = from_le32(&mbr->partitions[primary_partition].size_lba);
238 if ((total_lba_size != ((uint32_t) gpt->total_sectors - 1)) &&
239 (total_lba_size != 0xFFFFFFFF)) {
240 SPDK_DEBUGLOG(gpt_parse,
241 "GPT Primary MBR size does not equal: (record_size %u != actual_size %u)!\n",
242 total_lba_size, (uint32_t) gpt->total_sectors - 1);
243 return -1;
244 }
245 } else {
246 SPDK_DEBUGLOG(gpt_parse, "Currently only support GPT Protective MBR format\n");
247 return -1;
248 }
249
250 return 0;
251 }
252
253 int
gpt_parse_mbr(struct spdk_gpt * gpt)254 gpt_parse_mbr(struct spdk_gpt *gpt)
255 {
256 int rc;
257
258 if (!gpt || !gpt->buf) {
259 SPDK_ERRLOG("Gpt and the related buffer should not be NULL\n");
260 return -1;
261 }
262
263 rc = gpt_check_mbr(gpt);
264 if (rc) {
265 SPDK_DEBUGLOG(gpt_parse, "Failed to detect gpt in MBR\n");
266 return rc;
267 }
268
269 return 0;
270 }
271
272 int
gpt_parse_partition_table(struct spdk_gpt * gpt)273 gpt_parse_partition_table(struct spdk_gpt *gpt)
274 {
275 int rc;
276
277 rc = gpt_read_header(gpt);
278 if (rc) {
279 SPDK_ERRLOG("Failed to read gpt header\n");
280 return rc;
281 }
282
283 rc = gpt_read_partitions(gpt);
284 if (rc) {
285 SPDK_ERRLOG("Failed to read gpt partitions\n");
286 return rc;
287 }
288
289 return 0;
290 }
291
292 SPDK_LOG_REGISTER_COMPONENT(gpt_parse)
293