xref: /spdk/test/unit/lib/bdev/gpt/gpt.c/gpt_ut.c (revision 22898a91b9b6f289933db19b0175821cfb7e7820)
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, lba_end usable_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 gpt->lba_end usable_lba matched, passing case */
130 	to_le32(&head->header_crc32, 0x30CB7378);
131 	to_le64(&gpt->lba_start, 0x0);
132 	to_le64(&gpt->lba_end, 0x2E935FFE);
133 	to_le64(&head->first_usable_lba, 0xA);
134 	to_le64(&head->last_usable_lba, 0xF4240);
135 	re = spdk_gpt_read_header(gpt);
136 	CU_ASSERT(re == 0);
137 
138 	free(gpt);
139 }
140 
141 static void
142 test_read_partitions(void)
143 {
144 	struct spdk_gpt *gpt;
145 	struct spdk_gpt_header *head;
146 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
147 	int re;
148 
149 	/* spdk_gpt_read_partitions(NULL) does not exist, NULL is filtered out in spdk_gpt_parse() */
150 	gpt = calloc(1, sizeof(*gpt));
151 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
152 
153 	/* Set *gpt is "aaa..." */
154 	memset(a, 'a', sizeof(a));
155 	gpt->buf = &a[0];
156 
157 	/* Set num_partition_entries exceeds Max vaule of entries GPT supported */
158 	gpt->sector_size = 512;
159 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
160 	gpt->header = head;
161 	to_le32(&head->num_partition_entries, 0x100);
162 	re = spdk_gpt_read_partitions(gpt);
163 	CU_ASSERT(re == -1);
164 
165 	/* Set num_partition_entries within Max vaule, size_of_partition_entry mismatch */
166 	to_le32(&head->header_crc32, 0x573857BE);
167 	to_le32(&head->num_partition_entries, 0x40);
168 	to_le32(&head->size_of_partition_entry, 0x0);
169 	re = spdk_gpt_read_partitions(gpt);
170 	CU_ASSERT(re == -1);
171 
172 	/* Set size_of_partition_entry matched, partition_entry_lba mismatch */
173 	to_le32(&head->header_crc32, 0x5279B712);
174 	to_le32(&head->size_of_partition_entry, 0x80);
175 	to_le64(&head->partition_entry_lba, 0x64);
176 	re = spdk_gpt_read_partitions(gpt);
177 	CU_ASSERT(re == -1);
178 
179 	/* Set partition_entry_lba matched, partition_entry_array_crc32 mismatch */
180 	to_le32(&head->header_crc32, 0xEC093B43);
181 	to_le64(&head->partition_entry_lba, 0x20);
182 	to_le32(&head->partition_entry_array_crc32, 0x0);
183 	re = spdk_gpt_read_partitions(gpt);
184 	CU_ASSERT(re == -1);
185 
186 	/* Set partition_entry_array_crc32 matched, passing case */
187 	to_le32(&head->header_crc32, 0xE1A08822);
188 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
189 	to_le32(&head->num_partition_entries, 0x80);
190 	re = spdk_gpt_read_partitions(gpt);
191 	CU_ASSERT(re == 0);
192 
193 	free(gpt);
194 }
195 
196 static void
197 test_parse(void)
198 {
199 	struct spdk_gpt *gpt;
200 	struct spdk_mbr *mbr;
201 	struct spdk_gpt_header *head;
202 	unsigned char a[SPDK_GPT_BUFFER_SIZE];
203 	int re;
204 
205 	/* Set gpt is NULL */
206 	re = spdk_gpt_parse(NULL);
207 	CU_ASSERT(re == -1);
208 
209 	/* Set gpt->buf is NULL */
210 	gpt = calloc(1, sizeof(*gpt));
211 	SPDK_CU_ASSERT_FATAL(gpt != NULL);
212 	re = spdk_gpt_parse(gpt);
213 	CU_ASSERT(re == -1);
214 
215 	/* Set *gpt is "aaa...", check_mbr failed */
216 	memset(a, 'a', sizeof(a));
217 	gpt->buf = &a[0];
218 	re = spdk_gpt_parse(gpt);
219 	CU_ASSERT(re == -1);
220 
221 	/* Set check_mbr passed, read_header failed */
222 	mbr = (struct spdk_mbr *)gpt->buf;
223 	mbr->mbr_signature = 0xAA55;
224 	mbr->partitions[0].start_lba = 1;
225 	mbr->partitions[0].os_type = 0xEE;
226 	mbr->partitions[0].size_lba = 0xFFFFFFFF;
227 	re = spdk_gpt_parse(gpt);
228 	CU_ASSERT(re == -1);
229 
230 	/* Set read_header passed, read_partitions failed */
231 	gpt->sector_size = 512;
232 	head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size);
233 	head->header_size = sizeof(*head);
234 	head->gpt_signature[0] = 'E';
235 	head->gpt_signature[1] = 'F';
236 	head->gpt_signature[2] = 'I';
237 	head->gpt_signature[3] = ' ';
238 	head->gpt_signature[4] = 'P';
239 	head->gpt_signature[5] = 'A';
240 	head->gpt_signature[6] = 'R';
241 	head->gpt_signature[7] = 'T';
242 	to_le32(&head->header_crc32, 0x30CB7378);
243 	to_le64(&gpt->lba_start, 0x0);
244 	to_le64(&gpt->lba_end, 0x2E935FFE);
245 	to_le64(&head->first_usable_lba, 0xA);
246 	to_le64(&head->last_usable_lba, 0xF4240);
247 	re = spdk_gpt_parse(gpt);
248 	CU_ASSERT(re == -1);
249 
250 	/* Set read_partitions passed, all passed */
251 	to_le32(&head->size_of_partition_entry, 0x80);
252 	to_le64(&head->partition_entry_lba, 0x20);
253 	to_le32(&head->header_crc32, 0xE1A08822);
254 	to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB);
255 	to_le32(&head->num_partition_entries, 0x80);
256 	re = spdk_gpt_parse(gpt);
257 	CU_ASSERT(re == 0);
258 
259 	free(gpt);
260 }
261 
262 int
263 main(int argc, char **argv)
264 {
265 	CU_pSuite	suite = NULL;
266 	unsigned int	num_failures;
267 
268 	if (CU_initialize_registry() != CUE_SUCCESS) {
269 		return CU_get_error();
270 	}
271 
272 	suite = CU_add_suite("gpt_parse", NULL, NULL);
273 	if (suite == NULL) {
274 		CU_cleanup_registry();
275 		return CU_get_error();
276 	}
277 
278 	if (
279 		CU_add_test(suite, "parse",
280 			    test_parse) == NULL ||
281 		CU_add_test(suite, "check mbr",
282 			    test_check_mbr) == NULL ||
283 		CU_add_test(suite, "read header",
284 			    test_read_header) == NULL ||
285 		CU_add_test(suite, "read partitions",
286 			    test_read_partitions) == NULL
287 	) {
288 		CU_cleanup_registry();
289 		return CU_get_error();
290 	}
291 
292 	CU_basic_set_mode(CU_BRM_VERBOSE);
293 	CU_basic_run_tests();
294 	num_failures = CU_get_number_of_failures();
295 	CU_cleanup_registry();
296 	return num_failures;
297 }
298