xref: /spdk/test/unit/lib/bdev/gpt/gpt.c/gpt_ut.c (revision 1fc4165fe9bf8512483356ad8e6d27f793f2e3db)
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  	if (CU_initialize_registry() != CUE_SUCCESS) {
348  		return CU_get_error();
349  	}
350  
351  	suite = CU_add_suite("gpt_parse", NULL, NULL);
352  	if (suite == NULL) {
353  		CU_cleanup_registry();
354  		return CU_get_error();
355  	}
356  
357  	if (
358  		CU_add_test(suite, "parse",
359  			    test_parse_mbr_and_primary) == NULL ||
360  		CU_add_test(suite, "parse secondary",
361  			    test_parse_secondary) == NULL ||
362  		CU_add_test(suite, "check mbr",
363  			    test_check_mbr) == NULL ||
364  		CU_add_test(suite, "read header",
365  			    test_read_header) == NULL ||
366  		CU_add_test(suite, "read partitions",
367  			    test_read_partitions) == NULL
368  	) {
369  		CU_cleanup_registry();
370  		return CU_get_error();
371  	}
372  
373  	CU_basic_set_mode(CU_BRM_VERBOSE);
374  	CU_basic_run_tests();
375  	num_failures = CU_get_number_of_failures();
376  	CU_cleanup_registry();
377  	return num_failures;
378  }
379