xref: /spdk/test/unit/lib/bdev/gpt/gpt.c/gpt_ut.c (revision 552e21cce6cccbf833ed9109827e08337377d7ce)
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 	/* spdk_gpt_check_mbr(NULL) does not exist, NULL is filtered out in spdk_gpt_parse() */
49 	gpt = calloc(1, sizeof(*gpt));
50 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
51 
52 	/* Set *gpt is "aaa...", all are mismatch include mbr_signature */
53 	memset(a, 'a', sizeof(a));
54 	gpt->buf = &a[0];
55 	re = spdk_gpt_check_mbr(gpt);
56 	CU_ASSERT(re == -1);
57 
58 	/* Set mbr->mbr_signature matched, start lba mismatch */
59 	mbr = (struct spdk_mbr *)gpt->buf;
60 	mbr->mbr_signature = 0xAA55;
61 	re = spdk_gpt_check_mbr(gpt);
62 	CU_ASSERT(re == -1);
63 
64 	/* Set mbr->partitions[0].start lba matched, os_type mismatch */
65 	mbr->partitions[0].start_lba = 1;
66 	re = spdk_gpt_check_mbr(gpt);
67 	CU_ASSERT(re == -1);
68 
69 	/* Set mbr->partitions[0].os_type matched, size_lba mismatch */
70 	mbr->partitions[0].os_type = 0xEE;
71 	re = spdk_gpt_check_mbr(gpt);
72 	CU_ASSERT(re == -1);
73 
74 	/* Set mbr->partitions[0].size_lba matched, passing case */
75 	mbr->partitions[0].size_lba = 0xFFFFFFFF;
76 	re = spdk_gpt_check_mbr(gpt);
77 	CU_ASSERT(re == 0);
78 
79 	free(gpt);
80 }
81 
82 static void
83 test_read_header(void)
84 {
85 	struct spdk_gpt *gpt;
86 	struct spdk_gpt_header *head;
87 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
88 	int re;
89 
90 	/* spdk_gpt_read_header(NULL) does not exist, NULL is filtered out in spdk_gpt_parse() */
91 	gpt = calloc(1, sizeof(*gpt));
92 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
93 
94 	/* Set *gpt is "aaa..." */
95 	memset(a, 'a', sizeof(a));
96 	gpt->buf = &a[0];
97 
98 	/* Set header_size mismatch */
99 	gpt->sector_size = 512;
100 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
101 	to_le32(&head->header_size, 0x258);
102 	re = spdk_gpt_read_header(gpt);
103 	CU_ASSERT(re == -1);
104 
105 	/* Set head->header_size matched, header_crc32 mismatch */
106 	head->header_size = sizeof(*head);
107 	to_le32(&head->header_crc32, 0x22D18C80);
108 	re = spdk_gpt_read_header(gpt);
109 	CU_ASSERT(re == -1);
110 
111 	/* Set head->header_crc32 matched, gpt_signature mismatch */
112 	to_le32(&head->header_crc32, 0xC5B2117E);
113 	re = spdk_gpt_read_header(gpt);
114 	CU_ASSERT(re == -1);
115 
116 	/* Set head->gpt_signature matched, head->my_lba mismatch */
117 	to_le32(&head->header_crc32, 0xD637335A);
118 	head->gpt_signature[0] = 'E';
119 	head->gpt_signature[1] = 'F';
120 	head->gpt_signature[2] = 'I';
121 	head->gpt_signature[3] = ' ';
122 	head->gpt_signature[4] = 'P';
123 	head->gpt_signature[5] = 'A';
124 	head->gpt_signature[6] = 'R';
125 	head->gpt_signature[7] = 'T';
126 	re = spdk_gpt_read_header(gpt);
127 	CU_ASSERT(re == -1);
128 
129 	/* Set head->my_lba matched, lba_end usable_lba mismatch */
130 	to_le32(&head->header_crc32, 0xB3CDB2D2);
131 	to_le64(&head->my_lba, 0x1);
132 	re = spdk_gpt_read_header(gpt);
133 	CU_ASSERT(re == -1);
134 
135 	/* Set gpt->lba_end usable_lba matched, passing case */
136 	to_le32(&head->header_crc32, 0x5531F2F0);
137 	to_le64(&gpt->lba_start, 0x0);
138 	to_le64(&gpt->lba_end, 0x2E935FFE);
139 	to_le64(&head->first_usable_lba, 0xA);
140 	to_le64(&head->last_usable_lba, 0xF4240);
141 	re = spdk_gpt_read_header(gpt);
142 	CU_ASSERT(re == 0);
143 
144 	free(gpt);
145 }
146 
147 static void
148 test_read_partitions(void)
149 {
150 	struct spdk_gpt *gpt;
151 	struct spdk_gpt_header *head;
152 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
153 	int re;
154 
155 	/* spdk_gpt_read_partitions(NULL) does not exist, NULL is filtered out in spdk_gpt_parse() */
156 	gpt = calloc(1, sizeof(*gpt));
157 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
158 
159 	/* Set *gpt is "aaa..." */
160 	memset(a, 'a', sizeof(a));
161 	gpt->buf = &a[0];
162 
163 	/* Set num_partition_entries exceeds Max value of entries GPT supported */
164 	gpt->sector_size = 512;
165 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
166 	gpt->header = head;
167 	to_le32(&head->num_partition_entries, 0x100);
168 	re = spdk_gpt_read_partitions(gpt);
169 	CU_ASSERT(re == -1);
170 
171 	/* Set num_partition_entries within Max value, size_of_partition_entry mismatch */
172 	to_le32(&head->header_crc32, 0x573857BE);
173 	to_le32(&head->num_partition_entries, 0x40);
174 	to_le32(&head->size_of_partition_entry, 0x0);
175 	re = spdk_gpt_read_partitions(gpt);
176 	CU_ASSERT(re == -1);
177 
178 	/* Set size_of_partition_entry matched, partition_entry_lba mismatch */
179 	to_le32(&head->header_crc32, 0x5279B712);
180 	to_le32(&head->size_of_partition_entry, 0x80);
181 	to_le64(&head->partition_entry_lba, 0x64);
182 	re = spdk_gpt_read_partitions(gpt);
183 	CU_ASSERT(re == -1);
184 
185 	/* Set partition_entry_lba matched, partition_entry_array_crc32 mismatch */
186 	to_le32(&head->header_crc32, 0xEC093B43);
187 	to_le64(&head->partition_entry_lba, 0x20);
188 	to_le32(&head->partition_entry_array_crc32, 0x0);
189 	re = spdk_gpt_read_partitions(gpt);
190 	CU_ASSERT(re == -1);
191 
192 	/* Set partition_entry_array_crc32 matched, passing case */
193 	to_le32(&head->header_crc32, 0xE1A08822);
194 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
195 	to_le32(&head->num_partition_entries, 0x80);
196 	re = spdk_gpt_read_partitions(gpt);
197 	CU_ASSERT(re == 0);
198 
199 	free(gpt);
200 }
201 
202 static void
203 test_parse(void)
204 {
205 	struct spdk_gpt *gpt;
206 	struct spdk_mbr *mbr;
207 	struct spdk_gpt_header *head;
208 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
209 	int re;
210 
211 	/* Set gpt is NULL */
212 	re = spdk_gpt_parse(NULL);
213 	CU_ASSERT(re == -1);
214 
215 	/* Set gpt->buf is NULL */
216 	gpt = calloc(1, sizeof(*gpt));
217 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
218 	re = spdk_gpt_parse(gpt);
219 	CU_ASSERT(re == -1);
220 
221 	/* Set *gpt is "aaa...", check_mbr failed */
222 	memset(a, 'a', sizeof(a));
223 	gpt->buf = &a[0];
224 	re = spdk_gpt_parse(gpt);
225 	CU_ASSERT(re == -1);
226 
227 	/* Set check_mbr passed, read_header failed */
228 	mbr = (struct spdk_mbr *)gpt->buf;
229 	mbr->mbr_signature = 0xAA55;
230 	mbr->partitions[0].start_lba = 1;
231 	mbr->partitions[0].os_type = 0xEE;
232 	mbr->partitions[0].size_lba = 0xFFFFFFFF;
233 	re = spdk_gpt_parse(gpt);
234 	CU_ASSERT(re == -1);
235 
236 	/* Set read_header passed, read_partitions failed */
237 	gpt->sector_size = 512;
238 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
239 	head->header_size = sizeof(*head);
240 	head->gpt_signature[0] = 'E';
241 	head->gpt_signature[1] = 'F';
242 	head->gpt_signature[2] = 'I';
243 	head->gpt_signature[3] = ' ';
244 	head->gpt_signature[4] = 'P';
245 	head->gpt_signature[5] = 'A';
246 	head->gpt_signature[6] = 'R';
247 	head->gpt_signature[7] = 'T';
248 	to_le32(&head->header_crc32, 0x5531F2F0);
249 	to_le64(&head->my_lba, 0x1);
250 	to_le64(&gpt->lba_start, 0x0);
251 	to_le64(&gpt->lba_end, 0x2E935FFE);
252 	to_le64(&head->first_usable_lba, 0xA);
253 	to_le64(&head->last_usable_lba, 0xF4240);
254 	re = spdk_gpt_parse(gpt);
255 	CU_ASSERT(re == -1);
256 
257 	/* Set read_partitions passed, all passed */
258 	to_le32(&head->size_of_partition_entry, 0x80);
259 	to_le64(&head->partition_entry_lba, 0x20);
260 	to_le32(&head->header_crc32, 0x845A09AA);
261 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
262 	to_le32(&head->num_partition_entries, 0x80);
263 	re = spdk_gpt_parse(gpt);
264 	CU_ASSERT(re == 0);
265 
266 	free(gpt);
267 }
268 
269 int
270 main(int argc, char **argv)
271 {
272 	CU_pSuite	suite = NULL;
273 	unsigned int	num_failures;
274 
275 	if (CU_initialize_registry() != CUE_SUCCESS) {
276 		return CU_get_error();
277 	}
278 
279 	suite = CU_add_suite("gpt_parse", NULL, NULL);
280 	if (suite == NULL) {
281 		CU_cleanup_registry();
282 		return CU_get_error();
283 	}
284 
285 	if (
286 		CU_add_test(suite, "parse",
287 			    test_parse) == NULL ||
288 		CU_add_test(suite, "check mbr",
289 			    test_check_mbr) == NULL ||
290 		CU_add_test(suite, "read header",
291 			    test_read_header) == NULL ||
292 		CU_add_test(suite, "read partitions",
293 			    test_read_partitions) == NULL
294 	) {
295 		CU_cleanup_registry();
296 		return CU_get_error();
297 	}
298 
299 	CU_basic_set_mode(CU_BRM_VERBOSE);
300 	CU_basic_run_tests();
301 	num_failures = CU_get_number_of_failures();
302 	CU_cleanup_registry();
303 	return num_failures;
304 }
305