1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2017 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "spdk_internal/cunit.h"
7
8 #include "common/lib/test_env.c"
9
10 #include "bdev/gpt/gpt.c"
11
12 static void
test_check_mbr(void)13 test_check_mbr(void)
14 {
15 struct spdk_gpt *gpt;
16 struct spdk_mbr *mbr;
17 unsigned char a[SPDK_GPT_BUFFER_SIZE];
18 int re;
19
20 /* Set gpt is NULL */
21 re = gpt_parse_mbr(NULL);
22 CU_ASSERT(re == -1);
23
24 /* Set gpt->buf is NULL */
25 gpt = calloc(1, sizeof(*gpt));
26 SPDK_CU_ASSERT_FATAL(gpt != NULL);
27 re = gpt_parse_mbr(gpt);
28 CU_ASSERT(re == -1);
29
30 /* Set *gpt is "aaa...", all are mismatch include mbr_signature */
31 memset(a, 'a', sizeof(a));
32 gpt->buf = &a[0];
33 re = gpt_check_mbr(gpt);
34 CU_ASSERT(re == -1);
35
36 /* Set mbr->mbr_signature matched, start lba mismatch */
37 mbr = (struct spdk_mbr *)gpt->buf;
38 mbr->mbr_signature = 0xAA55;
39 re = gpt_check_mbr(gpt);
40 CU_ASSERT(re == -1);
41
42 /* Set mbr->partitions[0].start lba matched, os_type mismatch */
43 mbr->partitions[0].start_lba = 1;
44 re = gpt_check_mbr(gpt);
45 CU_ASSERT(re == -1);
46
47 /* Set mbr->partitions[0].os_type matched, size_lba mismatch */
48 mbr->partitions[0].os_type = 0xEE;
49 re = gpt_check_mbr(gpt);
50 CU_ASSERT(re == -1);
51
52 /* Set mbr->partitions[0].size_lba matched, passing case */
53 mbr->partitions[0].size_lba = 0xFFFFFFFF;
54 re = gpt_check_mbr(gpt);
55 CU_ASSERT(re == 0);
56
57 free(gpt);
58 }
59
60 static void
test_read_header(void)61 test_read_header(void)
62 {
63 struct spdk_gpt *gpt;
64 struct spdk_gpt_header *head;
65 unsigned char a[SPDK_GPT_BUFFER_SIZE];
66 int re;
67
68 /* gpt_read_header(NULL) does not exist, NULL is filtered out in gpt_parse_mbr() */
69 gpt = calloc(1, sizeof(*gpt));
70 SPDK_CU_ASSERT_FATAL(gpt != NULL);
71 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
72 gpt->sector_size = 512;
73
74 /* Set *gpt is "aaa..." */
75 memset(a, 'a', sizeof(a));
76 gpt->buf = &a[0];
77 gpt->buf_size = sizeof(a);
78
79 /* Set header_size mismatch */
80 gpt->sector_size = 512;
81 head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
82 to_le32(&head->header_size, 0x258);
83 re = gpt_read_header(gpt);
84 CU_ASSERT(re == -1);
85
86 /* Set head->header_size matched, header_crc32 mismatch */
87 head->header_size = sizeof(*head);
88 to_le32(&head->header_crc32, 0x22D18C80);
89 re = gpt_read_header(gpt);
90 CU_ASSERT(re == -1);
91
92 /* Set head->header_crc32 matched, gpt_signature mismatch */
93 to_le32(&head->header_crc32, 0xC5B2117E);
94 re = gpt_read_header(gpt);
95 CU_ASSERT(re == -1);
96
97 /* Set head->gpt_signature matched, head->my_lba mismatch */
98 to_le32(&head->header_crc32, 0xD637335A);
99 head->gpt_signature[0] = 'E';
100 head->gpt_signature[1] = 'F';
101 head->gpt_signature[2] = 'I';
102 head->gpt_signature[3] = ' ';
103 head->gpt_signature[4] = 'P';
104 head->gpt_signature[5] = 'A';
105 head->gpt_signature[6] = 'R';
106 head->gpt_signature[7] = 'T';
107 re = gpt_read_header(gpt);
108 CU_ASSERT(re == -1);
109
110 /* Set head->my_lba matched, lba_end usable_lba mismatch */
111 to_le32(&head->header_crc32, 0xB3CDB2D2);
112 to_le64(&head->my_lba, 0x1);
113 re = gpt_read_header(gpt);
114 CU_ASSERT(re == -1);
115
116 /* Set gpt->lba_end usable_lba matched, passing case */
117 to_le32(&head->header_crc32, 0x5531F2F0);
118 to_le64(&gpt->lba_start, 0x0);
119 to_le64(&gpt->lba_end, 0x2E935FFE);
120 to_le64(&head->first_usable_lba, 0xA);
121 to_le64(&head->last_usable_lba, 0xF4240);
122 re = gpt_read_header(gpt);
123 CU_ASSERT(re == 0);
124
125 free(gpt);
126 }
127
128 static void
test_read_partitions(void)129 test_read_partitions(void)
130 {
131 struct spdk_gpt *gpt;
132 struct spdk_gpt_header *head;
133 unsigned char a[SPDK_GPT_BUFFER_SIZE];
134 int re;
135
136 /* gpt_read_partitions(NULL) does not exist, NULL is filtered out in gpt_parse_mbr() */
137 gpt = calloc(1, sizeof(*gpt));
138 SPDK_CU_ASSERT_FATAL(gpt != NULL);
139 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
140 gpt->sector_size = 512;
141
142 /* Set *gpt is "aaa..." */
143 memset(a, 'a', sizeof(a));
144 gpt->buf = &a[0];
145 gpt->buf_size = sizeof(a);
146
147 /* Set num_partition_entries exceeds Max value of entries GPT supported */
148 gpt->sector_size = 512;
149 head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
150 gpt->header = head;
151 to_le32(&head->num_partition_entries, 0x100);
152 re = gpt_read_partitions(gpt);
153 CU_ASSERT(re == -1);
154
155 /* Set num_partition_entries within Max value, size_of_partition_entry mismatch */
156 to_le32(&head->header_crc32, 0x573857BE);
157 to_le32(&head->num_partition_entries, 0x40);
158 to_le32(&head->size_of_partition_entry, 0x0);
159 re = gpt_read_partitions(gpt);
160 CU_ASSERT(re == -1);
161
162 /* Set size_of_partition_entry matched, partition_entry_lba mismatch */
163 to_le32(&head->header_crc32, 0x5279B712);
164 to_le32(&head->size_of_partition_entry, 0x80);
165 to_le64(&head->partition_entry_lba, 0x64);
166 re = gpt_read_partitions(gpt);
167 CU_ASSERT(re == -1);
168
169 /* Set partition_entry_lba matched, partition_entry_array_crc32 mismatch */
170 to_le32(&head->header_crc32, 0xEC093B43);
171 to_le64(&head->partition_entry_lba, 0x20);
172 to_le32(&head->partition_entry_array_crc32, 0x0);
173 re = gpt_read_partitions(gpt);
174 CU_ASSERT(re == -1);
175
176 /* Set partition_entry_array_crc32 matched, passing case */
177 to_le32(&head->header_crc32, 0xE1A08822);
178 to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
179 to_le32(&head->num_partition_entries, 0x80);
180 re = gpt_read_partitions(gpt);
181 CU_ASSERT(re == 0);
182
183 free(gpt);
184 }
185
186 static void
test_parse_mbr_and_primary(void)187 test_parse_mbr_and_primary(void)
188 {
189 struct spdk_gpt *gpt;
190 struct spdk_mbr *mbr;
191 struct spdk_gpt_header *head;
192 unsigned char a[SPDK_GPT_BUFFER_SIZE];
193 int re;
194
195 /* Set gpt is NULL */
196 re = gpt_parse_mbr(NULL);
197 CU_ASSERT(re == -1);
198
199 /* Set gpt->buf is NULL */
200 gpt = calloc(1, sizeof(*gpt));
201 SPDK_CU_ASSERT_FATAL(gpt != NULL);
202 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
203 gpt->sector_size = 512;
204 re = gpt_parse_mbr(gpt);
205 CU_ASSERT(re == -1);
206
207 /* Set *gpt is "aaa...", check_mbr failed */
208 memset(a, 'a', sizeof(a));
209 gpt->buf = &a[0];
210 gpt->buf_size = sizeof(a);
211 re = gpt_parse_mbr(gpt);
212 CU_ASSERT(re == -1);
213
214 /* Set check_mbr passed */
215 mbr = (struct spdk_mbr *)gpt->buf;
216 mbr->mbr_signature = 0xAA55;
217 mbr->partitions[0].start_lba = 1;
218 mbr->partitions[0].os_type = 0xEE;
219 mbr->partitions[0].size_lba = 0xFFFFFFFF;
220 re = gpt_parse_mbr(gpt);
221 CU_ASSERT(re == 0);
222
223 /* Expect read_header failed */
224 re = gpt_parse_partition_table(gpt);
225 CU_ASSERT(re == -1);
226
227 /* Set read_header passed, read_partitions failed */
228 head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
229 head->header_size = sizeof(*head);
230 head->gpt_signature[0] = 'E';
231 head->gpt_signature[1] = 'F';
232 head->gpt_signature[2] = 'I';
233 head->gpt_signature[3] = ' ';
234 head->gpt_signature[4] = 'P';
235 head->gpt_signature[5] = 'A';
236 head->gpt_signature[6] = 'R';
237 head->gpt_signature[7] = 'T';
238 to_le32(&head->header_crc32, 0x5531F2F0);
239 to_le64(&head->my_lba, 0x1);
240 to_le64(&gpt->lba_start, 0x0);
241 to_le64(&gpt->lba_end, 0x2E935FFE);
242 to_le64(&head->first_usable_lba, 0xA);
243 to_le64(&head->last_usable_lba, 0xF4240);
244 re = gpt_parse_partition_table(gpt);
245 CU_ASSERT(re == -1);
246
247 /* Set read_partitions passed, all passed */
248 to_le32(&head->size_of_partition_entry, 0x80);
249 to_le64(&head->partition_entry_lba, 0x20);
250 to_le32(&head->header_crc32, 0x845A09AA);
251 to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
252 to_le32(&head->num_partition_entries, 0x80);
253 re = gpt_parse_partition_table(gpt);
254 CU_ASSERT(re == 0);
255
256 free(gpt);
257 }
258
259 static void
test_parse_secondary(void)260 test_parse_secondary(void)
261 {
262 struct spdk_gpt *gpt;
263 struct spdk_gpt_header *head;
264 unsigned char a[SPDK_GPT_BUFFER_SIZE];
265 int re;
266
267 /* gpt_parse_partition_table(NULL) does not exist, NULL is filtered out in gpt_parse_mbr() */
268 gpt = calloc(1, sizeof(*gpt));
269 SPDK_CU_ASSERT_FATAL(gpt != NULL);
270 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_SECONDARY;
271 gpt->sector_size = 512;
272
273 /* Set *gpt is "aaa...", read_header failed */
274 memset(a, 'a', sizeof(a));
275 gpt->buf = &a[0];
276 gpt->buf_size = sizeof(a);
277 re = gpt_parse_partition_table(gpt);
278 CU_ASSERT(re == -1);
279
280 /* Set read_header passed, read_partitions failed */
281 head = (struct spdk_gpt_header *)(gpt->buf + gpt->buf_size - gpt->sector_size);
282 head->header_size = sizeof(*head);
283 head->gpt_signature[0] = 'E';
284 head->gpt_signature[1] = 'F';
285 head->gpt_signature[2] = 'I';
286 head->gpt_signature[3] = ' ';
287 head->gpt_signature[4] = 'P';
288 head->gpt_signature[5] = 'A';
289 head->gpt_signature[6] = 'R';
290 head->gpt_signature[7] = 'T';
291 to_le32(&head->header_crc32, 0xAA68A167);
292 to_le64(&head->my_lba, 0x63FFFFF);
293 to_le64(&gpt->lba_start, 0x0);
294 to_le64(&gpt->lba_end, 0x63FFFFF);
295 to_le64(&gpt->total_sectors, 0x6400000);
296 to_le64(&head->first_usable_lba, 0xA);
297 to_le64(&head->last_usable_lba, 0x63FFFDE);
298 re = gpt_parse_partition_table(gpt);
299 CU_ASSERT(re == -1);
300
301 /* Set read_partitions passed, all passed */
302 to_le32(&head->size_of_partition_entry, 0x80);
303 to_le64(&head->partition_entry_lba, 0x63FFFDF);
304 to_le32(&head->header_crc32, 0x204129E8);
305 to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
306 to_le32(&head->num_partition_entries, 0x80);
307 re = gpt_parse_partition_table(gpt);
308 CU_ASSERT(re == 0);
309
310 free(gpt);
311 }
312
313 int
main(int argc,char ** argv)314 main(int argc, char **argv)
315 {
316 CU_pSuite suite = NULL;
317 unsigned int num_failures;
318
319 CU_initialize_registry();
320
321 suite = CU_add_suite("gpt_parse", NULL, NULL);
322
323 CU_ADD_TEST(suite, test_parse_mbr_and_primary);
324 CU_ADD_TEST(suite, test_parse_secondary);
325 CU_ADD_TEST(suite, test_check_mbr);
326 CU_ADD_TEST(suite, test_read_header);
327 CU_ADD_TEST(suite, test_read_partitions);
328
329 num_failures = spdk_ut_run_tests(argc, argv, NULL);
330 CU_cleanup_registry();
331 return num_failures;
332 }
333