xref: /spdk/test/unit/lib/bdev/gpt/gpt.c/gpt_ut.c (revision 94a84ae98590bea46939eb1dcd7a9876bd393b54)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of the copyright holder nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk_cunit.h"
35 
36 #include "common/lib/test_env.c"
37 
38 #include "bdev/gpt/gpt.c"
39 
40 static void
41 test_check_mbr(void)
42 {
43 	struct spdk_gpt *gpt;
44 	struct spdk_mbr *mbr;
45 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
46 	int re;
47 
48 	/* Set gpt is NULL */
49 	re = spdk_gpt_parse_mbr(NULL);
50 	CU_ASSERT(re == -1);
51 
52 	/* Set gpt->buf is NULL */
53 	gpt = calloc(1, sizeof(*gpt));
54 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
55 	re = spdk_gpt_parse_mbr(gpt);
56 	CU_ASSERT(re == -1);
57 
58 	/* Set *gpt is "aaa...", all are mismatch include mbr_signature */
59 	memset(a, 'a', sizeof(a));
60 	gpt->buf = &a[0];
61 	re = spdk_gpt_check_mbr(gpt);
62 	CU_ASSERT(re == -1);
63 
64 	/* Set mbr->mbr_signature matched, start lba mismatch */
65 	mbr = (struct spdk_mbr *)gpt->buf;
66 	mbr->mbr_signature = 0xAA55;
67 	re = spdk_gpt_check_mbr(gpt);
68 	CU_ASSERT(re == -1);
69 
70 	/* Set mbr->partitions[0].start lba matched, os_type mismatch */
71 	mbr->partitions[0].start_lba = 1;
72 	re = spdk_gpt_check_mbr(gpt);
73 	CU_ASSERT(re == -1);
74 
75 	/* Set mbr->partitions[0].os_type matched, size_lba mismatch */
76 	mbr->partitions[0].os_type = 0xEE;
77 	re = spdk_gpt_check_mbr(gpt);
78 	CU_ASSERT(re == -1);
79 
80 	/* Set mbr->partitions[0].size_lba matched, passing case */
81 	mbr->partitions[0].size_lba = 0xFFFFFFFF;
82 	re = spdk_gpt_check_mbr(gpt);
83 	CU_ASSERT(re == 0);
84 
85 	free(gpt);
86 }
87 
88 static void
89 test_read_header(void)
90 {
91 	struct spdk_gpt *gpt;
92 	struct spdk_gpt_header *head;
93 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
94 	int re;
95 
96 	/* spdk_gpt_read_header(NULL) does not exist, NULL is filtered out in spdk_gpt_parse_mbr() */
97 	gpt = calloc(1, sizeof(*gpt));
98 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
99 	gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
100 	gpt->sector_size = 512;
101 
102 	/* Set *gpt is "aaa..." */
103 	memset(a, 'a', sizeof(a));
104 	gpt->buf = &a[0];
105 	gpt->buf_size = sizeof(a);
106 
107 	/* Set header_size mismatch */
108 	gpt->sector_size = 512;
109 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
110 	to_le32(&head->header_size, 0x258);
111 	re = spdk_gpt_read_header(gpt);
112 	CU_ASSERT(re == -1);
113 
114 	/* Set head->header_size matched, header_crc32 mismatch */
115 	head->header_size = sizeof(*head);
116 	to_le32(&head->header_crc32, 0x22D18C80);
117 	re = spdk_gpt_read_header(gpt);
118 	CU_ASSERT(re == -1);
119 
120 	/* Set head->header_crc32 matched, gpt_signature mismatch */
121 	to_le32(&head->header_crc32, 0xC5B2117E);
122 	re = spdk_gpt_read_header(gpt);
123 	CU_ASSERT(re == -1);
124 
125 	/* Set head->gpt_signature matched, head->my_lba mismatch */
126 	to_le32(&head->header_crc32, 0xD637335A);
127 	head->gpt_signature[0] = 'E';
128 	head->gpt_signature[1] = 'F';
129 	head->gpt_signature[2] = 'I';
130 	head->gpt_signature[3] = ' ';
131 	head->gpt_signature[4] = 'P';
132 	head->gpt_signature[5] = 'A';
133 	head->gpt_signature[6] = 'R';
134 	head->gpt_signature[7] = 'T';
135 	re = spdk_gpt_read_header(gpt);
136 	CU_ASSERT(re == -1);
137 
138 	/* Set head->my_lba matched, lba_end usable_lba mismatch */
139 	to_le32(&head->header_crc32, 0xB3CDB2D2);
140 	to_le64(&head->my_lba, 0x1);
141 	re = spdk_gpt_read_header(gpt);
142 	CU_ASSERT(re == -1);
143 
144 	/* Set gpt->lba_end usable_lba matched, passing case */
145 	to_le32(&head->header_crc32, 0x5531F2F0);
146 	to_le64(&gpt->lba_start, 0x0);
147 	to_le64(&gpt->lba_end, 0x2E935FFE);
148 	to_le64(&head->first_usable_lba, 0xA);
149 	to_le64(&head->last_usable_lba, 0xF4240);
150 	re = spdk_gpt_read_header(gpt);
151 	CU_ASSERT(re == 0);
152 
153 	free(gpt);
154 }
155 
156 static void
157 test_read_partitions(void)
158 {
159 	struct spdk_gpt *gpt;
160 	struct spdk_gpt_header *head;
161 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
162 	int re;
163 
164 	/* spdk_gpt_read_partitions(NULL) does not exist, NULL is filtered out in spdk_gpt_parse_mbr() */
165 	gpt = calloc(1, sizeof(*gpt));
166 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
167 	gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
168 	gpt->sector_size = 512;
169 
170 	/* Set *gpt is "aaa..." */
171 	memset(a, 'a', sizeof(a));
172 	gpt->buf = &a[0];
173 	gpt->buf_size = sizeof(a);
174 
175 	/* Set num_partition_entries exceeds Max value of entries GPT supported */
176 	gpt->sector_size = 512;
177 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
178 	gpt->header = head;
179 	to_le32(&head->num_partition_entries, 0x100);
180 	re = spdk_gpt_read_partitions(gpt);
181 	CU_ASSERT(re == -1);
182 
183 	/* Set num_partition_entries within Max value, size_of_partition_entry mismatch */
184 	to_le32(&head->header_crc32, 0x573857BE);
185 	to_le32(&head->num_partition_entries, 0x40);
186 	to_le32(&head->size_of_partition_entry, 0x0);
187 	re = spdk_gpt_read_partitions(gpt);
188 	CU_ASSERT(re == -1);
189 
190 	/* Set size_of_partition_entry matched, partition_entry_lba mismatch */
191 	to_le32(&head->header_crc32, 0x5279B712);
192 	to_le32(&head->size_of_partition_entry, 0x80);
193 	to_le64(&head->partition_entry_lba, 0x64);
194 	re = spdk_gpt_read_partitions(gpt);
195 	CU_ASSERT(re == -1);
196 
197 	/* Set partition_entry_lba matched, partition_entry_array_crc32 mismatch */
198 	to_le32(&head->header_crc32, 0xEC093B43);
199 	to_le64(&head->partition_entry_lba, 0x20);
200 	to_le32(&head->partition_entry_array_crc32, 0x0);
201 	re = spdk_gpt_read_partitions(gpt);
202 	CU_ASSERT(re == -1);
203 
204 	/* Set partition_entry_array_crc32 matched, passing case */
205 	to_le32(&head->header_crc32, 0xE1A08822);
206 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
207 	to_le32(&head->num_partition_entries, 0x80);
208 	re = spdk_gpt_read_partitions(gpt);
209 	CU_ASSERT(re == 0);
210 
211 	free(gpt);
212 }
213 
214 static void
215 test_parse_mbr_and_primary(void)
216 {
217 	struct spdk_gpt *gpt;
218 	struct spdk_mbr *mbr;
219 	struct spdk_gpt_header *head;
220 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
221 	int re;
222 
223 	/* Set gpt is NULL */
224 	re = spdk_gpt_parse_mbr(NULL);
225 	CU_ASSERT(re == -1);
226 
227 	/* Set gpt->buf is NULL */
228 	gpt = calloc(1, sizeof(*gpt));
229 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
230 	gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
231 	gpt->sector_size = 512;
232 	re = spdk_gpt_parse_mbr(gpt);
233 	CU_ASSERT(re == -1);
234 
235 	/* Set *gpt is "aaa...", check_mbr failed */
236 	memset(a, 'a', sizeof(a));
237 	gpt->buf = &a[0];
238 	gpt->buf_size = sizeof(a);
239 	re = spdk_gpt_parse_mbr(gpt);
240 	CU_ASSERT(re == -1);
241 
242 	/* Set check_mbr passed */
243 	mbr = (struct spdk_mbr *)gpt->buf;
244 	mbr->mbr_signature = 0xAA55;
245 	mbr->partitions[0].start_lba = 1;
246 	mbr->partitions[0].os_type = 0xEE;
247 	mbr->partitions[0].size_lba = 0xFFFFFFFF;
248 	re = spdk_gpt_parse_mbr(gpt);
249 	CU_ASSERT(re == 0);
250 
251 	/* Expect read_header failed */
252 	re = spdk_gpt_parse_partition_table(gpt);
253 	CU_ASSERT(re == -1);
254 
255 	/* Set read_header passed, read_partitions failed */
256 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
257 	head->header_size = sizeof(*head);
258 	head->gpt_signature[0] = 'E';
259 	head->gpt_signature[1] = 'F';
260 	head->gpt_signature[2] = 'I';
261 	head->gpt_signature[3] = ' ';
262 	head->gpt_signature[4] = 'P';
263 	head->gpt_signature[5] = 'A';
264 	head->gpt_signature[6] = 'R';
265 	head->gpt_signature[7] = 'T';
266 	to_le32(&head->header_crc32, 0x5531F2F0);
267 	to_le64(&head->my_lba, 0x1);
268 	to_le64(&gpt->lba_start, 0x0);
269 	to_le64(&gpt->lba_end, 0x2E935FFE);
270 	to_le64(&head->first_usable_lba, 0xA);
271 	to_le64(&head->last_usable_lba, 0xF4240);
272 	re = spdk_gpt_parse_partition_table(gpt);
273 	CU_ASSERT(re == -1);
274 
275 	/* Set read_partitions passed, all passed */
276 	to_le32(&head->size_of_partition_entry, 0x80);
277 	to_le64(&head->partition_entry_lba, 0x20);
278 	to_le32(&head->header_crc32, 0x845A09AA);
279 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
280 	to_le32(&head->num_partition_entries, 0x80);
281 	re = spdk_gpt_parse_partition_table(gpt);
282 	CU_ASSERT(re == 0);
283 
284 	free(gpt);
285 }
286 
287 static void
288 test_parse_secondary(void)
289 {
290 	struct spdk_gpt *gpt;
291 	struct spdk_gpt_header *head;
292 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
293 	int re;
294 
295 	/* spdk_gpt_parse_partition_table(NULL) does not exist, NULL is filtered out in spdk_gpt_parse_mbr() */
296 	gpt = calloc(1, sizeof(*gpt));
297 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
298 	gpt->parse_phase = SPDK_GPT_PARSE_PHASE_SECONDARY;
299 	gpt->sector_size = 512;
300 
301 	/* Set *gpt is "aaa...", read_header failed */
302 	memset(a, 'a', sizeof(a));
303 	gpt->buf = &a[0];
304 	gpt->buf_size = sizeof(a);
305 	re = spdk_gpt_parse_partition_table(gpt);
306 	CU_ASSERT(re == -1);
307 
308 	/* Set read_header passed, read_partitions failed */
309 	head = (struct spdk_gpt_header *)(gpt->buf + gpt->buf_size - gpt->sector_size);
310 	head->header_size = sizeof(*head);
311 	head->gpt_signature[0] = 'E';
312 	head->gpt_signature[1] = 'F';
313 	head->gpt_signature[2] = 'I';
314 	head->gpt_signature[3] = ' ';
315 	head->gpt_signature[4] = 'P';
316 	head->gpt_signature[5] = 'A';
317 	head->gpt_signature[6] = 'R';
318 	head->gpt_signature[7] = 'T';
319 	to_le32(&head->header_crc32, 0xAA68A167);
320 	to_le64(&head->my_lba, 0x63FFFFF);
321 	to_le64(&gpt->lba_start, 0x0);
322 	to_le64(&gpt->lba_end, 0x63FFFFF);
323 	to_le64(&gpt->total_sectors, 0x6400000);
324 	to_le64(&head->first_usable_lba, 0xA);
325 	to_le64(&head->last_usable_lba, 0x63FFFDE);
326 	re = spdk_gpt_parse_partition_table(gpt);
327 	CU_ASSERT(re == -1);
328 
329 	/* Set read_partitions passed, all passed */
330 	to_le32(&head->size_of_partition_entry, 0x80);
331 	to_le64(&head->partition_entry_lba, 0x63FFFDF);
332 	to_le32(&head->header_crc32, 0x204129E8);
333 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
334 	to_le32(&head->num_partition_entries, 0x80);
335 	re = spdk_gpt_parse_partition_table(gpt);
336 	CU_ASSERT(re == 0);
337 
338 	free(gpt);
339 }
340 
341 int
342 main(int argc, char **argv)
343 {
344 	CU_pSuite	suite = NULL;
345 	unsigned int	num_failures;
346 
347 	CU_set_error_action(CUEA_ABORT);
348 	CU_initialize_registry();
349 
350 	suite = CU_add_suite("gpt_parse", NULL, NULL);
351 
352 	CU_ADD_TEST(suite, test_parse_mbr_and_primary);
353 	CU_ADD_TEST(suite, test_parse_secondary);
354 	CU_ADD_TEST(suite, test_check_mbr);
355 	CU_ADD_TEST(suite, test_read_header);
356 	CU_ADD_TEST(suite, test_read_partitions);
357 
358 	CU_basic_set_mode(CU_BRM_VERBOSE);
359 	CU_basic_run_tests();
360 	num_failures = CU_get_number_of_failures();
361 	CU_cleanup_registry();
362 	return num_failures;
363 }
364