1/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include <errno.h>
7#include <string.h>
8
9#include "../cgpt/cgpt.h"
10#include "cgptlib_internal.h"
11#include "cgptlib_test.h"
12#include "crc32.h"
13#include "crc32_test.h"
14#include "gpt.h"
15#include "test_common.h"
16#define _STUB_IMPLEMENTATION_
17#include "utility.h"
18
19/*
20 * Testing partition layout (sector_bytes=512)
21 *
22 *     LBA   Size  Usage
23 * ---------------------------------------------------------
24 *       0      1  PMBR
25 *       1      1  primary partition header
26 *       2     32  primary partition entries (128B * 128)
27 *      34    100  kernel A (index: 0)
28 *     134    100  root A (index: 1)
29 *     234    100  root B (index: 2)
30 *     334    100  kernel B (index: 3)
31 *     434     32  secondary partition entries
32 *     466      1  secondary partition header
33 *     467
34 */
35#define KERNEL_A 0
36#define KERNEL_B 1
37#define ROOTFS_A 2
38#define ROOTFS_B 3
39#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
40#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
41
42#define DEFAULT_SECTOR_SIZE 512
43#define MAX_SECTOR_SIZE 4096
44#define DEFAULT_DRIVE_SECTORS 467
45#define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 16384 */
46#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
47
48static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
49static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
50static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
51
52// cgpt_common.c requires these be defined if linked in.
53const char *progname = "CGPT-TEST";
54const char *command = "TEST";
55
56/*
57 * Copy a random-for-this-program-only Guid into the dest. The num parameter
58 * completely determines the Guid.
59 */
60static void SetGuid(void *dest, uint32_t num)
61{
62	Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,
63		    {0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
64	Memcpy(dest, &g, sizeof(Guid));
65}
66
67/*
68 * Given a GptData pointer, first re-calculate entries CRC32 value, then reset
69 * header CRC32 value to 0, and calculate header CRC32 value.  Both primary and
70 * secondary are updated.
71 */
72static void RefreshCrc32(GptData *gpt)
73{
74	GptHeader *header, *header2;
75	GptEntry *entries, *entries2;
76
77	header = (GptHeader *)gpt->primary_header;
78	entries = (GptEntry *)gpt->primary_entries;
79	header2 = (GptHeader *)gpt->secondary_header;
80	entries2 = (GptEntry *)gpt->secondary_entries;
81
82	header->entries_crc32 =
83		Crc32((uint8_t *)entries,
84		      header->number_of_entries * header->size_of_entry);
85	header->header_crc32 = 0;
86	header->header_crc32 = Crc32((uint8_t *)header, header->size);
87	header2->entries_crc32 =
88		Crc32((uint8_t *)entries2,
89		      header2->number_of_entries * header2->size_of_entry);
90	header2->header_crc32 = 0;
91	header2->header_crc32 = Crc32((uint8_t *)header2, header2->size);
92}
93
94static void ZeroHeaders(GptData *gpt)
95{
96	Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
97	Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
98}
99
100static void ZeroEntries(GptData *gpt)
101{
102	Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
103	Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
104}
105
106static void ZeroHeadersEntries(GptData *gpt)
107{
108	ZeroHeaders(gpt);
109	ZeroEntries(gpt);
110}
111
112/*
113 * Return a pointer to a static GptData instance (no free is required).
114 * All fields are zero except 4 pointers linking to header and entries.
115 * All content of headers and entries are zero.
116 */
117static GptData *GetEmptyGptData(void)
118{
119	static GptData gpt;
120	static uint8_t primary_header[MAX_SECTOR_SIZE];
121	static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
122	static uint8_t secondary_header[MAX_SECTOR_SIZE];
123	static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
124
125	Memset(&gpt, 0, sizeof(gpt));
126	gpt.primary_header = primary_header;
127	gpt.primary_entries = primary_entries;
128	gpt.secondary_header = secondary_header;
129	gpt.secondary_entries = secondary_entries;
130	ZeroHeadersEntries(&gpt);
131
132	/* Initialize GptData internal states. */
133	gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
134
135	return &gpt;
136}
137
138/*
139 * Fill in most of fields and creates the layout described in the top of this
140 * file. Before calling this function, primary/secondary header/entries must
141 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
142 * This function returns a good (valid) copy of GPT layout described in top of
143 * this file.
144 */
145static void BuildTestGptData(GptData *gpt)
146{
147	GptHeader *header, *header2;
148	GptEntry *entries, *entries2;
149	Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
150	Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
151
152	gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
153	gpt->streaming_drive_sectors =
154		gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
155	gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
156	gpt->valid_headers = MASK_BOTH;
157	gpt->valid_entries = MASK_BOTH;
158	gpt->modified = 0;
159
160	/* Build primary */
161	header = (GptHeader *)gpt->primary_header;
162	entries = (GptEntry *)gpt->primary_entries;
163	Memcpy(header->signature, GPT_HEADER_SIGNATURE,
164	       sizeof(GPT_HEADER_SIGNATURE));
165	header->revision = GPT_HEADER_REVISION;
166	header->size = sizeof(GptHeader);
167	header->reserved_zero = 0;
168	header->my_lba = 1;
169	header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
170	header->first_usable_lba = 34;
171	header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1;  /* 433 */
172	header->entries_lba = 2;
173	  /* 512B / 128B * 32sectors = 128 entries */
174	header->number_of_entries = 128;
175	header->size_of_entry = 128;  /* bytes */
176	Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
177	SetGuid(&entries[0].unique, 0);
178	entries[0].starting_lba = 34;
179	entries[0].ending_lba = 133;
180	Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
181	SetGuid(&entries[1].unique, 1);
182	entries[1].starting_lba = 134;
183	entries[1].ending_lba = 232;
184	Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
185	SetGuid(&entries[2].unique, 2);
186	entries[2].starting_lba = 234;
187	entries[2].ending_lba = 331;
188	Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
189	SetGuid(&entries[3].unique, 3);
190	entries[3].starting_lba = 334;
191	entries[3].ending_lba = 430;
192
193	/* Build secondary */
194	header2 = (GptHeader *)gpt->secondary_header;
195	entries2 = (GptEntry *)gpt->secondary_entries;
196	Memcpy(header2, header, sizeof(GptHeader));
197	Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
198	header2->my_lba = DEFAULT_DRIVE_SECTORS - 1;  /* 466 */
199	header2->alternate_lba = 1;
200	header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32;  /* 434 */
201
202	RefreshCrc32(gpt);
203}
204
205/*
206 * Test if the structures are the expected size; if this fails, struct packing
207 * is not working properly.
208 */
209static int StructSizeTest(void)
210{
211
212	EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
213	EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
214	EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
215	return TEST_OK;
216}
217
218
219/* Test if the default structure returned by BuildTestGptData() is good. */
220static int TestBuildTestGptData(void)
221{
222	GptData *gpt;
223
224	gpt = GetEmptyGptData();
225	BuildTestGptData(gpt);
226	EXPECT(GPT_SUCCESS == GptInit(gpt));
227	gpt->sector_bytes = 0;
228	EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
229	return TEST_OK;
230}
231
232/*
233 * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
234 * Currently we only support 512 bytes per sector.  In the future, we may
235 * support other sizes.  A too small drive_sectors should be rejected by
236 * GptInit().
237 */
238static int ParameterTests(void)
239{
240	GptData *gpt;
241	struct {
242		uint32_t sector_bytes;
243		uint64_t drive_sectors;
244		int expected_retval;
245	} cases[] = {
246		{512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
247		{520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
248		{512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
249		{512, 10, GPT_ERROR_INVALID_SECTOR_NUMBER},
250		{512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
251		 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
252		{4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
253	};
254	int i;
255
256	gpt = GetEmptyGptData();
257	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
258		BuildTestGptData(gpt);
259		gpt->sector_bytes = cases[i].sector_bytes;
260		gpt->streaming_drive_sectors =
261			gpt->gpt_drive_sectors = cases[i].drive_sectors;
262		EXPECT(cases[i].expected_retval == CheckParameters(gpt));
263	}
264
265	return TEST_OK;
266}
267
268/* Test if header CRC in two copies are calculated. */
269static int HeaderCrcTest(void)
270{
271	GptData *gpt = GetEmptyGptData();
272	GptHeader *h1 = (GptHeader *)gpt->primary_header;
273
274	BuildTestGptData(gpt);
275	EXPECT(HeaderCrc(h1) == h1->header_crc32);
276
277	/* CRC covers first byte of header */
278	BuildTestGptData(gpt);
279	gpt->primary_header[0] ^= 0xa5;
280	EXPECT(HeaderCrc(h1) != h1->header_crc32);
281
282	/* CRC covers last byte of header */
283	BuildTestGptData(gpt);
284	gpt->primary_header[h1->size - 1] ^= 0x5a;
285	EXPECT(HeaderCrc(h1) != h1->header_crc32);
286
287	/* CRC only covers header */
288	BuildTestGptData(gpt);
289	gpt->primary_header[h1->size] ^= 0x5a;
290	EXPECT(HeaderCrc(h1) == h1->header_crc32);
291
292	return TEST_OK;
293}
294
295/* Test if header-same comparison works. */
296static int HeaderSameTest(void)
297{
298	GptData *gpt = GetEmptyGptData();
299	GptHeader *h1 = (GptHeader *)gpt->primary_header;
300	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
301	GptHeader h3;
302
303	EXPECT(0 == HeaderFieldsSame(h1, h2));
304
305	Memcpy(&h3, h2, sizeof(h3));
306	h3.signature[0] ^= 0xba;
307	EXPECT(1 == HeaderFieldsSame(h1, &h3));
308
309	Memcpy(&h3, h2, sizeof(h3));
310	h3.revision++;
311	EXPECT(1 == HeaderFieldsSame(h1, &h3));
312
313	Memcpy(&h3, h2, sizeof(h3));
314	h3.size++;
315	EXPECT(1 == HeaderFieldsSame(h1, &h3));
316
317	Memcpy(&h3, h2, sizeof(h3));
318	h3.reserved_zero++;
319	EXPECT(1 == HeaderFieldsSame(h1, &h3));
320
321	Memcpy(&h3, h2, sizeof(h3));
322	h3.first_usable_lba++;
323	EXPECT(1 == HeaderFieldsSame(h1, &h3));
324
325	Memcpy(&h3, h2, sizeof(h3));
326	h3.last_usable_lba++;
327	EXPECT(1 == HeaderFieldsSame(h1, &h3));
328
329	Memcpy(&h3, h2, sizeof(h3));
330	h3.disk_uuid.u.raw[0] ^= 0xba;
331	EXPECT(1 == HeaderFieldsSame(h1, &h3));
332
333	Memcpy(&h3, h2, sizeof(h3));
334	h3.number_of_entries++;
335	EXPECT(1 == HeaderFieldsSame(h1, &h3));
336
337	Memcpy(&h3, h2, sizeof(h3));
338	h3.size_of_entry++;
339	EXPECT(1 == HeaderFieldsSame(h1, &h3));
340
341	Memcpy(&h3, h2, sizeof(h3));
342	h3.entries_crc32++;
343	EXPECT(1 == HeaderFieldsSame(h1, &h3));
344
345	return TEST_OK;
346}
347
348/* Test if signature ("EFI PART") is checked. */
349static int SignatureTest(void)
350{
351	GptData *gpt = GetEmptyGptData();
352	GptHeader *h1 = (GptHeader *)gpt->primary_header;
353	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
354	int i;
355
356	EXPECT(1 == CheckHeader(NULL, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
357
358	for (i = 0; i < 8; ++i) {
359		BuildTestGptData(gpt);
360		h1->signature[i] ^= 0xff;
361		h2->signature[i] ^= 0xff;
362		RefreshCrc32(gpt);
363		EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
364		EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
365	}
366
367	return TEST_OK;
368}
369
370/*
371 * The revision we currently support is GPT_HEADER_REVISION.  If the revision
372 * in header is not that, we expect the header is invalid.
373 */
374static int RevisionTest(void)
375{
376	GptData *gpt = GetEmptyGptData();
377	GptHeader *h1 = (GptHeader *)gpt->primary_header;
378	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
379	int i;
380
381	struct {
382		uint32_t value_to_test;
383		int expect_rv;
384	} cases[] = {
385		{0x01000000, 1},
386		{0x00010000, 0},  /* GPT_HEADER_REVISION */
387		{0x00000100, 1},
388		{0x00000001, 1},
389		{0x23010456, 1},
390	};
391
392	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
393		BuildTestGptData(gpt);
394		h1->revision = cases[i].value_to_test;
395		h2->revision = cases[i].value_to_test;
396		RefreshCrc32(gpt);
397
398		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
399		       cases[i].expect_rv);
400		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
401		       cases[i].expect_rv);
402	}
403	return TEST_OK;
404}
405
406static int SizeTest(void)
407{
408	GptData *gpt = GetEmptyGptData();
409	GptHeader *h1 = (GptHeader *)gpt->primary_header;
410	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
411	int i;
412
413	struct {
414		uint32_t value_to_test;
415		int expect_rv;
416	} cases[] = {
417		{91, 1},
418		{92, 0},
419		{93, 0},
420		{511, 0},
421		{512, 0},
422		{513, 1},
423	};
424
425	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
426		BuildTestGptData(gpt);
427		h1->size = cases[i].value_to_test;
428		h2->size = cases[i].value_to_test;
429		RefreshCrc32(gpt);
430
431		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
432		       cases[i].expect_rv);
433		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
434		       cases[i].expect_rv);
435	}
436	return TEST_OK;
437}
438
439/* Test if CRC is checked. */
440static int CrcFieldTest(void)
441{
442	GptData *gpt = GetEmptyGptData();
443	GptHeader *h1 = (GptHeader *)gpt->primary_header;
444	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
445
446	BuildTestGptData(gpt);
447	/* Modify a field that the header verification doesn't care about */
448	h1->entries_crc32++;
449	h2->entries_crc32++;
450	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
451	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
452	/* Refresh the CRC; should pass now */
453	RefreshCrc32(gpt);
454	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
455	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
456
457	return TEST_OK;
458}
459
460/* Test if reserved fields are checked.  We'll try non-zero values to test. */
461static int ReservedFieldsTest(void)
462{
463	GptData *gpt = GetEmptyGptData();
464	GptHeader *h1 = (GptHeader *)gpt->primary_header;
465	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
466
467	BuildTestGptData(gpt);
468	h1->reserved_zero ^= 0x12345678;  /* whatever random */
469	h2->reserved_zero ^= 0x12345678;  /* whatever random */
470	RefreshCrc32(gpt);
471	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
472	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
473
474#ifdef PADDING_CHECKED
475	/* TODO: padding check is currently disabled */
476	BuildTestGptData(gpt);
477	h1->padding[12] ^= 0x34;  /* whatever random */
478	h2->padding[56] ^= 0x78;  /* whatever random */
479	RefreshCrc32(gpt);
480	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
481	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
482#endif
483
484	return TEST_OK;
485}
486
487/*
488 * Technically, any size which is 2^N where N > 6 should work, but our
489 * library only supports one size.
490 */
491static int SizeOfPartitionEntryTest(void) {
492	GptData *gpt = GetEmptyGptData();
493	GptHeader *h1 = (GptHeader *)gpt->primary_header;
494	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
495	int i;
496
497	struct {
498		uint32_t value_to_test;
499		int expect_rv;
500	} cases[] = {
501		{127, 1},
502		{128, 0},
503		{129, 1},
504		{256, 1},
505		{512, 1},
506	};
507
508	/* Check size of entryes */
509	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
510		BuildTestGptData(gpt);
511		h1->size_of_entry = cases[i].value_to_test;
512		h2->size_of_entry = cases[i].value_to_test;
513		h1->number_of_entries = TOTAL_ENTRIES_SIZE /
514			cases[i].value_to_test;
515		h2->number_of_entries = TOTAL_ENTRIES_SIZE /
516			cases[i].value_to_test;
517		RefreshCrc32(gpt);
518
519		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
520		       cases[i].expect_rv);
521		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
522		       cases[i].expect_rv);
523	}
524
525	return TEST_OK;
526}
527
528/*
529 * Technically, any size which is 2^N where N > 6 should work, but our library
530 * only supports one size.
531 */
532static int NumberOfPartitionEntriesTest(void)
533{
534	GptData *gpt = GetEmptyGptData();
535	GptHeader *h1 = (GptHeader *)gpt->primary_header;
536	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
537
538	BuildTestGptData(gpt);
539	h1->number_of_entries--;
540	h2->number_of_entries /= 2;
541	/* Because we halved h2 entries, its entries_lba is going to change. */
542	h2->entries_lba = h2->my_lba - CalculateEntriesSectors(h2);
543	RefreshCrc32(gpt);
544	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
545	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
546	/* But it's okay to have less if the GPT structs are stored elsewhere. */
547	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
548	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
549
550	return TEST_OK;
551}
552
553
554/* Test if myLBA field is checked (1 for primary, last for secondary). */
555static int MyLbaTest(void)
556{
557	GptData *gpt = GetEmptyGptData();
558	GptHeader *h1 = (GptHeader *)gpt->primary_header;
559	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
560
561	/* myLBA depends on primary vs secondary flag */
562	BuildTestGptData(gpt);
563	EXPECT(1 == CheckHeader(h1, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
564	EXPECT(1 == CheckHeader(h2, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
565
566	BuildTestGptData(gpt);
567	h1->my_lba--;
568	h2->my_lba--;
569	RefreshCrc32(gpt);
570	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
571	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
572
573	BuildTestGptData(gpt);
574	h1->my_lba = 2;
575	h2->my_lba--;
576	RefreshCrc32(gpt);
577	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
578	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
579
580	/* We should ignore the alternate_lba field entirely */
581	BuildTestGptData(gpt);
582	h1->alternate_lba++;
583	h2->alternate_lba++;
584	RefreshCrc32(gpt);
585	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
586	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
587
588	BuildTestGptData(gpt);
589	h1->alternate_lba--;
590	h2->alternate_lba--;
591	RefreshCrc32(gpt);
592	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
593	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
594
595	BuildTestGptData(gpt);
596	h1->entries_lba++;
597	h2->entries_lba++;
598	RefreshCrc32(gpt);
599	/*
600	 * We support a padding between primary GPT header and its entries. So
601	 * this still passes.
602	 */
603	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
604	/*
605	 * But the secondary table should fail because it would overlap the
606	 * header, which is now lying after its entry array.
607	 */
608	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
609
610	BuildTestGptData(gpt);
611	h1->entries_lba--;
612	h2->entries_lba--;
613	RefreshCrc32(gpt);
614	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
615	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
616
617	return TEST_OK;
618}
619
620/* Test if FirstUsableLBA and LastUsableLBA are checked.
621 * FirstUsableLBA must be after the end of the primary GPT table array.
622 * LastUsableLBA must be before the start of the secondary GPT table array.
623 * FirstUsableLBA <= LastUsableLBA.
624 * Also see CheckHeaderOffDevice() test. */
625static int FirstUsableLbaAndLastUsableLbaTest(void)
626{
627	GptData *gpt = GetEmptyGptData();
628	GptHeader *h1 = (GptHeader *)gpt->primary_header;
629	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
630	int i;
631
632	struct {
633		uint64_t primary_entries_lba;
634		uint64_t primary_first_usable_lba;
635		uint64_t primary_last_usable_lba;
636		uint64_t secondary_first_usable_lba;
637		uint64_t secondary_last_usable_lba;
638		uint64_t secondary_entries_lba;
639		int primary_rv;
640		int secondary_rv;
641	} cases[] = {
642		{2,  34, 433,   34, 433, 434,  0, 0},
643		{2,  34, 432,   34, 430, 434,  0, 0},
644		{2,  33, 433,   33, 433, 434,  1, 1},
645		{2,  34, 434,   34, 433, 434,  1, 0},
646		{2,  34, 433,   34, 434, 434,  0, 1},
647		{2,  35, 433,   35, 433, 434,  0, 0},
648		{2, 433, 433,  433, 433, 434,  0, 0},
649		{2, 434, 433,  434, 434, 434,  1, 1},
650		{2, 433,  34,   34, 433, 434,  1, 0},
651		{2,  34, 433,  433,  34, 434,  0, 1},
652	};
653
654	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
655		BuildTestGptData(gpt);
656		h1->entries_lba = cases[i].primary_entries_lba;
657		h1->first_usable_lba = cases[i].primary_first_usable_lba;
658		h1->last_usable_lba = cases[i].primary_last_usable_lba;
659		h2->entries_lba = cases[i].secondary_entries_lba;
660		h2->first_usable_lba = cases[i].secondary_first_usable_lba;
661		h2->last_usable_lba = cases[i].secondary_last_usable_lba;
662		RefreshCrc32(gpt);
663
664		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
665		       cases[i].primary_rv);
666		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
667		       cases[i].secondary_rv);
668	}
669
670	return TEST_OK;
671}
672
673/*
674 * Test if PartitionEntryArrayCRC32 is checked.  PartitionEntryArrayCRC32 must
675 * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
676 */
677static int EntriesCrcTest(void)
678{
679	GptData *gpt = GetEmptyGptData();
680	GptHeader *h1 = (GptHeader *)gpt->primary_header;
681	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
682	GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
683
684	/* Modify first byte of primary entries, and expect the CRC is wrong. */
685	BuildTestGptData(gpt);
686	EXPECT(0 == CheckEntries(e1, h1));
687	EXPECT(0 == CheckEntries(e2, h1));
688	gpt->primary_entries[0] ^= 0xa5;  /* just XOR a non-zero value */
689	gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
690	EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
691	EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
692
693	return TEST_OK;
694}
695
696/*
697 * Test if partition geometry is checked.
698 * All active (non-zero PartitionTypeGUID) partition entries should have:
699 *   entry.StartingLBA >= header.FirstUsableLBA
700 *   entry.EndingLBA <= header.LastUsableLBA
701 *   entry.StartingLBA <= entry.EndingLBA
702 */
703static int ValidEntryTest(void)
704{
705	GptData *gpt = GetEmptyGptData();
706	GptHeader *h1 = (GptHeader *)gpt->primary_header;
707	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
708
709	/* error case: entry.StartingLBA < header.FirstUsableLBA */
710	BuildTestGptData(gpt);
711	e1[0].starting_lba = h1->first_usable_lba - 1;
712	RefreshCrc32(gpt);
713	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
714
715	/* error case: entry.EndingLBA > header.LastUsableLBA */
716	BuildTestGptData(gpt);
717	e1[2].ending_lba = h1->last_usable_lba + 1;
718	RefreshCrc32(gpt);
719	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
720
721	/* error case: entry.StartingLBA > entry.EndingLBA */
722	BuildTestGptData(gpt);
723	e1[3].starting_lba = e1[3].ending_lba + 1;
724	RefreshCrc32(gpt);
725	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
726
727	/* case: non active entry should be ignored. */
728	BuildTestGptData(gpt);
729	Memset(&e1[1].type, 0, sizeof(e1[1].type));
730	e1[1].starting_lba = e1[1].ending_lba + 1;
731	RefreshCrc32(gpt);
732	EXPECT(0 == CheckEntries(e1, h1));
733
734	return TEST_OK;
735}
736
737/* Test if overlapped partition tables can be detected. */
738static int OverlappedPartitionTest(void) {
739	GptData *gpt = GetEmptyGptData();
740	GptHeader *h = (GptHeader *)gpt->primary_header;
741	GptEntry *e = (GptEntry *)gpt->primary_entries;
742	int i, j;
743
744	struct {
745		int overlapped;
746		struct {
747			int active;
748			uint64_t starting_lba;
749			uint64_t ending_lba;
750		} entries[16];  /* enough for testing. */
751	} cases[] = {
752		{GPT_SUCCESS, {{0, 100, 199}}},
753		{GPT_SUCCESS, {{1, 100, 199}}},
754		{GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
755		{GPT_ERROR_START_LBA_OVERLAP,
756		 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
757		{GPT_ERROR_END_LBA_OVERLAP,
758		 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
759		{GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
760		{GPT_ERROR_END_LBA_OVERLAP,
761		 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
762		{GPT_ERROR_START_LBA_OVERLAP,
763		 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
764		{GPT_ERROR_START_LBA_OVERLAP,
765		 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
766		{GPT_ERROR_END_LBA_OVERLAP,
767		 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
768		{GPT_ERROR_START_LBA_OVERLAP,
769		 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
770		{GPT_SUCCESS,
771		 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
772		{GPT_ERROR_START_LBA_OVERLAP,
773		 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
774		{GPT_ERROR_START_LBA_OVERLAP,
775		 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
776		{GPT_SUCCESS,
777		 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
778		{GPT_ERROR_END_LBA_OVERLAP,
779		 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
780		{GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
781		{GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
782		{GPT_ERROR_START_LBA_OVERLAP,
783		 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
784		  {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
785		  {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
786		{GPT_SUCCESS,
787		 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
788		  {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
789		  {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
790	};
791
792	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
793		BuildTestGptData(gpt);
794		ZeroEntries(gpt);
795		for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
796			if (!cases[i].entries[j].starting_lba)
797				break;
798
799			if (cases[i].entries[j].active) {
800				Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
801			}
802			SetGuid(&e[j].unique, j);
803			e[j].starting_lba = cases[i].entries[j].starting_lba;
804			e[j].ending_lba = cases[i].entries[j].ending_lba;
805		}
806		RefreshCrc32(gpt);
807
808		EXPECT(cases[i].overlapped == CheckEntries(e, h));
809	}
810	return TEST_OK;
811}
812
813/* Test both sanity checking and repair. */
814static int SanityCheckTest(void)
815{
816	GptData *gpt = GetEmptyGptData();
817	GptHeader *h1 = (GptHeader *)gpt->primary_header;
818	GptEntry *e1 = (GptEntry *)gpt->primary_entries;
819	uint8_t *tempptr;
820
821	/* Unmodified test data is completely sane */
822	BuildTestGptData(gpt);
823	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
824	EXPECT(MASK_BOTH == gpt->valid_headers);
825	EXPECT(MASK_BOTH == gpt->valid_entries);
826	/* Repair doesn't damage it */
827	GptRepair(gpt);
828	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
829	EXPECT(MASK_BOTH == gpt->valid_headers);
830	EXPECT(MASK_BOTH == gpt->valid_entries);
831	EXPECT(0 == gpt->modified);
832
833	/* Invalid sector size should fail */
834	BuildTestGptData(gpt);
835	gpt->sector_bytes = 1024;
836	EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
837
838	/* Modify headers */
839	BuildTestGptData(gpt);
840	gpt->primary_header[0]++;
841	gpt->secondary_header[0]++;
842	EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
843	EXPECT(0 == gpt->valid_headers);
844	EXPECT(0 == gpt->valid_entries);
845	/* Repair can't fix completely busted headers */
846	GptRepair(gpt);
847	EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
848	EXPECT(0 == gpt->valid_headers);
849	EXPECT(0 == gpt->valid_entries);
850	EXPECT(0 == gpt->modified);
851
852	BuildTestGptData(gpt);
853	gpt->primary_header[0]++;
854	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
855	EXPECT(MASK_SECONDARY == gpt->valid_headers);
856	EXPECT(MASK_BOTH == gpt->valid_entries);
857	GptRepair(gpt);
858	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
859	EXPECT(MASK_BOTH == gpt->valid_headers);
860	EXPECT(MASK_BOTH == gpt->valid_entries);
861	EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
862
863	BuildTestGptData(gpt);
864	gpt->secondary_header[0]++;
865	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
866	EXPECT(MASK_PRIMARY == gpt->valid_headers);
867	EXPECT(MASK_BOTH == gpt->valid_entries);
868	GptRepair(gpt);
869	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
870	EXPECT(MASK_BOTH == gpt->valid_headers);
871	EXPECT(MASK_BOTH == gpt->valid_entries);
872	EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
873
874	/*
875	 * Modify header1 and update its CRC.  Since header2 is now different
876	 * than header1, it'll be the one considered invalid.
877	 */
878	BuildTestGptData(gpt);
879	h1->size++;
880	RefreshCrc32(gpt);
881	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
882	EXPECT(MASK_PRIMARY == gpt->valid_headers);
883	EXPECT(MASK_BOTH == gpt->valid_entries);
884	GptRepair(gpt);
885	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
886	EXPECT(MASK_BOTH == gpt->valid_headers);
887	EXPECT(MASK_BOTH == gpt->valid_entries);
888	EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
889
890	/* Modify entries */
891	BuildTestGptData(gpt);
892	gpt->primary_entries[0]++;
893	gpt->secondary_entries[0]++;
894	EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
895	EXPECT(MASK_BOTH == gpt->valid_headers);
896	EXPECT(MASK_NONE == gpt->valid_entries);
897	/* Repair can't fix both copies of entries being bad, either. */
898	GptRepair(gpt);
899	EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
900	EXPECT(MASK_BOTH == gpt->valid_headers);
901	EXPECT(MASK_NONE == gpt->valid_entries);
902	EXPECT(0 == gpt->modified);
903
904	BuildTestGptData(gpt);
905	gpt->primary_entries[0]++;
906	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
907	EXPECT(MASK_BOTH == gpt->valid_headers);
908	EXPECT(MASK_SECONDARY == gpt->valid_entries);
909	GptRepair(gpt);
910	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
911	EXPECT(MASK_BOTH == gpt->valid_headers);
912	EXPECT(MASK_BOTH == gpt->valid_entries);
913	EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
914
915	BuildTestGptData(gpt);
916	gpt->secondary_entries[0]++;
917	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
918	EXPECT(MASK_BOTH == gpt->valid_headers);
919	EXPECT(MASK_PRIMARY == gpt->valid_entries);
920	GptRepair(gpt);
921	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
922	EXPECT(MASK_BOTH == gpt->valid_headers);
923	EXPECT(MASK_BOTH == gpt->valid_entries);
924	EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
925
926	/*
927	 * Modify entries and recompute CRCs, then make both primary and
928	 * secondary entry pointers use the secondary data.  The primary
929	 * header will have the wrong entries CRC, so we should fall back
930	 * to the secondary header.
931	 */
932	BuildTestGptData(gpt);
933	e1->starting_lba++;
934	RefreshCrc32(gpt);
935	tempptr = gpt->primary_entries;
936	gpt->primary_entries = gpt->secondary_entries;
937	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
938	EXPECT(MASK_SECONDARY == gpt->valid_headers);
939	EXPECT(MASK_BOTH == gpt->valid_entries);
940	gpt->primary_entries = tempptr;
941
942	/* Modify both header and entries */
943	BuildTestGptData(gpt);
944	gpt->primary_header[0]++;
945	gpt->primary_entries[0]++;
946	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
947	EXPECT(MASK_SECONDARY == gpt->valid_headers);
948	EXPECT(MASK_SECONDARY == gpt->valid_entries);
949	GptRepair(gpt);
950	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
951	EXPECT(MASK_BOTH == gpt->valid_headers);
952	EXPECT(MASK_BOTH == gpt->valid_entries);
953	EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
954
955	BuildTestGptData(gpt);
956	gpt->secondary_header[0]++;
957	gpt->secondary_entries[0]++;
958	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
959	EXPECT(MASK_PRIMARY == gpt->valid_headers);
960	EXPECT(MASK_PRIMARY == gpt->valid_entries);
961	GptRepair(gpt);
962	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
963	EXPECT(MASK_BOTH == gpt->valid_headers);
964	EXPECT(MASK_BOTH == gpt->valid_entries);
965	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
966
967	/* Test cross-correction (h1+e2, h2+e1) */
968	BuildTestGptData(gpt);
969	gpt->primary_header[0]++;
970	gpt->secondary_entries[0]++;
971	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
972	EXPECT(MASK_SECONDARY == gpt->valid_headers);
973	EXPECT(MASK_PRIMARY == gpt->valid_entries);
974	GptRepair(gpt);
975	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
976	EXPECT(MASK_BOTH == gpt->valid_headers);
977	EXPECT(MASK_BOTH == gpt->valid_entries);
978	EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
979
980	BuildTestGptData(gpt);
981	gpt->secondary_header[0]++;
982	gpt->primary_entries[0]++;
983	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
984	EXPECT(MASK_PRIMARY == gpt->valid_headers);
985	EXPECT(MASK_SECONDARY == gpt->valid_entries);
986	GptRepair(gpt);
987	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
988	EXPECT(MASK_BOTH == gpt->valid_headers);
989	EXPECT(MASK_BOTH == gpt->valid_entries);
990	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
991
992	/*
993	 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.  This
994	 * simulates a partial update of the drive.
995	 */
996	BuildTestGptData(gpt);
997	gpt->secondary_entries[0]++;
998	RefreshCrc32(gpt);
999	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1000	EXPECT(MASK_PRIMARY == gpt->valid_headers);
1001	EXPECT(MASK_PRIMARY == gpt->valid_entries);
1002	GptRepair(gpt);
1003	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1004	EXPECT(MASK_BOTH == gpt->valid_headers);
1005	EXPECT(MASK_BOTH == gpt->valid_entries);
1006	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
1007
1008	/* Test unloaded entry array. */
1009	gpt = GetEmptyGptData();
1010	BuildTestGptData(gpt);
1011	gpt->primary_entries = NULL;
1012	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1013	EXPECT(MASK_SECONDARY == gpt->valid_entries);
1014	gpt = GetEmptyGptData();
1015	BuildTestGptData(gpt);
1016	gpt->secondary_entries = NULL;
1017	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1018	EXPECT(MASK_PRIMARY == gpt->valid_entries);
1019
1020	/* Test unloaded header. */
1021	gpt = GetEmptyGptData();
1022	BuildTestGptData(gpt);
1023	gpt->primary_header = NULL;
1024	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1025	EXPECT(MASK_SECONDARY == gpt->valid_headers);
1026	gpt = GetEmptyGptData();
1027	BuildTestGptData(gpt);
1028	gpt->secondary_header = NULL;
1029	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1030	EXPECT(MASK_PRIMARY == gpt->valid_headers);
1031
1032	return TEST_OK;
1033}
1034
1035static int EntryAttributeGetSetTest(void)
1036{
1037	GptData *gpt = GetEmptyGptData();
1038	GptEntry *e = (GptEntry *)(gpt->primary_entries);
1039
1040	e->attrs.whole = 0x0000000000000000ULL;
1041	SetEntrySuccessful(e, 1);
1042	EXPECT(0x0100000000000000ULL == e->attrs.whole);
1043	EXPECT(1 == GetEntrySuccessful(e));
1044	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1045	SetEntrySuccessful(e, 0);
1046	EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1047	EXPECT(0 == GetEntrySuccessful(e));
1048
1049	e->attrs.whole = 0x0000000000000000ULL;
1050	SetEntryTries(e, 15);
1051	EXPECT(15 == GetEntryTries(e));
1052	EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1053	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1054	SetEntryTries(e, 0);
1055	EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1056	EXPECT(0 == GetEntryTries(e));
1057
1058	e->attrs.whole = 0x0000000000000000ULL;
1059	SetEntryPriority(e, 15);
1060	EXPECT(0x000F000000000000ULL == e->attrs.whole);
1061	EXPECT(15 == GetEntryPriority(e));
1062	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1063	SetEntryPriority(e, 0);
1064	EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1065	EXPECT(0 == GetEntryPriority(e));
1066
1067	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1068	EXPECT(1 == GetEntrySuccessful(e));
1069	EXPECT(15 == GetEntryPriority(e));
1070	EXPECT(15 == GetEntryTries(e));
1071
1072	e->attrs.whole = 0x0123000000000000ULL;
1073	EXPECT(1 == GetEntrySuccessful(e));
1074	EXPECT(2 == GetEntryTries(e));
1075	EXPECT(3 == GetEntryPriority(e));
1076
1077	return TEST_OK;
1078}
1079
1080static int EntryTypeTest(void)
1081{
1082	GptData *gpt = GetEmptyGptData();
1083	GptEntry *e = (GptEntry *)(gpt->primary_entries);
1084
1085	Memcpy(&e->type, &guid_zero, sizeof(Guid));
1086	EXPECT(1 == IsUnusedEntry(e));
1087	EXPECT(0 == IsKernelEntry(e));
1088
1089	Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1090	EXPECT(0 == IsUnusedEntry(e));
1091	EXPECT(1 == IsKernelEntry(e));
1092
1093	Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1094	EXPECT(0 == IsUnusedEntry(e));
1095	EXPECT(0 == IsKernelEntry(e));
1096
1097	return TEST_OK;
1098}
1099
1100/* Make an entry unused by clearing its type. */
1101static void FreeEntry(GptEntry *e)
1102{
1103	Memset(&e->type, 0, sizeof(Guid));
1104}
1105
1106/* Set up an entry. */
1107static void FillEntry(GptEntry *e, int is_kernel,
1108                      int priority, int successful, int tries)
1109{
1110	Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1111	SetEntryPriority(e, priority);
1112	SetEntrySuccessful(e, successful);
1113	SetEntryTries(e, tries);
1114}
1115
1116/*
1117 * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
1118 * any usable kernel entry.
1119 */
1120static int NoValidKernelEntryTest(void)
1121{
1122	GptData *gpt = GetEmptyGptData();
1123	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1124
1125	BuildTestGptData(gpt);
1126	SetEntryPriority(e1 + KERNEL_A, 0);
1127	FreeEntry(e1 + KERNEL_B);
1128	RefreshCrc32(gpt);
1129	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1130	       GptNextKernelEntry(gpt, NULL, NULL));
1131
1132	return TEST_OK;
1133}
1134
1135static int GetNextNormalTest(void)
1136{
1137	GptData *gpt = GetEmptyGptData();
1138	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1139	uint64_t start, size;
1140
1141	/* Normal case - both kernels successful */
1142	BuildTestGptData(gpt);
1143	FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1144	FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1145	RefreshCrc32(gpt);
1146	GptInit(gpt);
1147
1148	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1149	EXPECT(KERNEL_A == gpt->current_kernel);
1150	EXPECT(34 == start);
1151	EXPECT(100 == size);
1152
1153	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1154	EXPECT(KERNEL_B == gpt->current_kernel);
1155	EXPECT(134 == start);
1156	EXPECT(99 == size);
1157
1158	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1159	       GptNextKernelEntry(gpt, &start, &size));
1160	EXPECT(-1 == gpt->current_kernel);
1161
1162	/* Call as many times as you want; you won't get another kernel... */
1163	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1164	       GptNextKernelEntry(gpt, &start, &size));
1165	EXPECT(-1 == gpt->current_kernel);
1166
1167	return TEST_OK;
1168}
1169
1170static int GetNextPrioTest(void)
1171{
1172	GptData *gpt = GetEmptyGptData();
1173	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1174	uint64_t start, size;
1175
1176	/* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1177	BuildTestGptData(gpt);
1178	FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1179	FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1180	FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1181	FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1182	RefreshCrc32(gpt);
1183	GptInit(gpt);
1184
1185	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1186	EXPECT(KERNEL_B == gpt->current_kernel);
1187	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1188	EXPECT(KERNEL_Y == gpt->current_kernel);
1189	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1190	EXPECT(KERNEL_A == gpt->current_kernel);
1191	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1192	       GptNextKernelEntry(gpt, &start, &size));
1193
1194	return TEST_OK;
1195}
1196
1197static int GetNextTriesTest(void)
1198{
1199	GptData *gpt = GetEmptyGptData();
1200	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1201	uint64_t start, size;
1202
1203	/* Tries=nonzero is attempted just like success, but tries=0 isn't */
1204	BuildTestGptData(gpt);
1205	FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1206	FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1207	FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1208	FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1209	RefreshCrc32(gpt);
1210	GptInit(gpt);
1211
1212	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1213	EXPECT(KERNEL_X == gpt->current_kernel);
1214	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1215	EXPECT(KERNEL_A == gpt->current_kernel);
1216	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1217	       GptNextKernelEntry(gpt, &start, &size));
1218
1219	return TEST_OK;
1220}
1221
1222static int GptUpdateTest(void)
1223{
1224	GptData *gpt = GetEmptyGptData();
1225	GptEntry *e = (GptEntry *)(gpt->primary_entries);
1226	GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1227	uint64_t start, size;
1228
1229	/* Tries=nonzero is attempted just like success, but tries=0 isn't */
1230	BuildTestGptData(gpt);
1231	FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1232	FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1233	FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1234	RefreshCrc32(gpt);
1235	GptInit(gpt);
1236	gpt->modified = 0;  /* Nothing modified yet */
1237
1238	/* Successful kernel */
1239	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1240	EXPECT(KERNEL_A == gpt->current_kernel);
1241	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1242	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1243	EXPECT(0 == GetEntryTries(e + KERNEL_A));
1244	EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1245	EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1246	EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1247	/* Trying successful kernel changes nothing */
1248	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1249	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1250	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1251	EXPECT(0 == GetEntryTries(e + KERNEL_A));
1252	EXPECT(0 == gpt->modified);
1253	/* Marking it bad also does not update it. */
1254	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1255	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1256	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1257	EXPECT(0 == GetEntryTries(e + KERNEL_A));
1258	EXPECT(0 == gpt->modified);
1259
1260	/* Kernel with tries */
1261	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1262	EXPECT(KERNEL_B == gpt->current_kernel);
1263	EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1264	EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1265	EXPECT(2 == GetEntryTries(e + KERNEL_B));
1266	/* Marking it bad clears it */
1267	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1268	EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1269	EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1270	EXPECT(0 == GetEntryTries(e + KERNEL_B));
1271	/* Which affects both copies of the partition entries */
1272	EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1273	EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1274	EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1275	/* And that's caused the GPT to need updating */
1276	EXPECT(0x0F == gpt->modified);
1277
1278	/* Another kernel with tries */
1279	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1280	EXPECT(KERNEL_X == gpt->current_kernel);
1281	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1282	EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1283	EXPECT(2 == GetEntryTries(e + KERNEL_X));
1284	/* Trying it uses up a try */
1285	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1286	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1287	EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1288	EXPECT(1 == GetEntryTries(e + KERNEL_X));
1289	EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1290	EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1291	EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1292	/* Trying it again marks it inactive */
1293	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1294	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1295	EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1296	EXPECT(0 == GetEntryTries(e + KERNEL_X));
1297
1298	/* Can't update if entry isn't a kernel, or there isn't an entry */
1299	Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
1300	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1301	       GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1302	gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1303	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1304	       GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1305
1306
1307	return TEST_OK;
1308}
1309
1310/*
1311 * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1312 * GPT_ERROR_INVALID_UPDATE_TYPE.
1313 */
1314static int UpdateInvalidKernelTypeTest(void)
1315{
1316	GptData *gpt = GetEmptyGptData();
1317
1318	BuildTestGptData(gpt);
1319	/* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1320	gpt->current_kernel = 0;
1321	/* any invalid update_type value */
1322	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1323	       GptUpdateKernelEntry(gpt, 99));
1324
1325	return TEST_OK;
1326}
1327
1328/* Test duplicate UniqueGuids can be detected. */
1329static int DuplicateUniqueGuidTest(void)
1330{
1331	GptData *gpt = GetEmptyGptData();
1332	GptHeader *h = (GptHeader *)gpt->primary_header;
1333	GptEntry *e = (GptEntry *)gpt->primary_entries;
1334	int i, j;
1335
1336	struct {
1337		int duplicate;
1338		struct {
1339			uint64_t starting_lba;
1340			uint64_t ending_lba;
1341			uint32_t type_guid;
1342			uint32_t unique_guid;
1343		} entries[16];   /* enough for testing. */
1344	} cases[] = {
1345		{GPT_SUCCESS, {{100, 109, 1, 1},
1346			       {110, 119, 2, 2},
1347			       {120, 129, 3, 3},
1348			       {130, 139, 4, 4},
1349			}},
1350		{GPT_SUCCESS, {{100, 109, 1, 1},
1351			       {110, 119, 1, 2},
1352			       {120, 129, 2, 3},
1353			       {130, 139, 2, 4},
1354			}},
1355		{GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1356				      {110, 119, 2, 2},
1357				      {120, 129, 3, 1},
1358				      {130, 139, 4, 4},
1359			}},
1360		{GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1361				      {110, 119, 1, 2},
1362				      {120, 129, 2, 3},
1363				      {130, 139, 2, 2},
1364			}},
1365	};
1366
1367	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1368		BuildTestGptData(gpt);
1369		ZeroEntries(gpt);
1370		for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1371			if (!cases[i].entries[j].starting_lba)
1372				break;
1373
1374			e[j].starting_lba = cases[i].entries[j].starting_lba;
1375			e[j].ending_lba = cases[i].entries[j].ending_lba;
1376			SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1377			SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1378		}
1379		RefreshCrc32(gpt);
1380
1381		EXPECT(cases[i].duplicate == CheckEntries(e, h));
1382	}
1383
1384	return TEST_OK;
1385}
1386
1387/* Test getting the current kernel GUID */
1388static int GetKernelGuidTest(void)
1389{
1390	GptData *gpt = GetEmptyGptData();
1391	GptEntry *e = (GptEntry *)gpt->primary_entries;
1392	Guid g;
1393
1394	BuildTestGptData(gpt);
1395	gpt->current_kernel = 0;
1396	GetCurrentKernelUniqueGuid(gpt, &g);
1397	EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
1398	gpt->current_kernel = 1;
1399	GetCurrentKernelUniqueGuid(gpt, &g);
1400	EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
1401
1402	return TEST_OK;
1403}
1404
1405/* Test getting GPT error text strings */
1406static int ErrorTextTest(void)
1407{
1408	int i;
1409
1410	/* Known errors are not unknown */
1411	for (i = 0; i < GPT_ERROR_COUNT; i++) {
1412		EXPECT(GptErrorText(i));
1413		EXPECT(strcmp(GptErrorText(i), "Unknown"));
1414	}
1415
1416	/* But other error values are */
1417	EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
1418
1419	return TEST_OK;
1420}
1421
1422static int CheckHeaderOffDevice()
1423{
1424	GptData* gpt = GetEmptyGptData();
1425	BuildTestGptData(gpt);
1426
1427	GptHeader* primary_header = (GptHeader*)gpt->primary_header;
1428	primary_header->first_usable_lba = 0;
1429	RefreshCrc32(gpt);
1430	// GPT is stored on the same device so first usable lba should not
1431	// start at 0.
1432	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1433		gpt->gpt_drive_sectors, 0));
1434	// But off device, it is okay to accept this GPT header.
1435	EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1436		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
1437
1438	BuildTestGptData(gpt);
1439	primary_header->number_of_entries = 100;
1440	RefreshCrc32(gpt);
1441	// Normally, number of entries is 128. So this should fail.
1442	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1443		gpt->gpt_drive_sectors, 0));
1444	// But off device, it is okay.
1445	EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1446		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
1447
1448	primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1449	RefreshCrc32(gpt);
1450	// However, too few entries is not good.
1451	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1452		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
1453
1454	// Repeat for secondary header.
1455	BuildTestGptData(gpt);
1456	GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
1457	secondary_header->first_usable_lba = 0;
1458	RefreshCrc32(gpt);
1459	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1460		gpt->gpt_drive_sectors, 0));
1461	EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1462		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
1463
1464	BuildTestGptData(gpt);
1465	secondary_header->number_of_entries = 100;
1466	/* Because we change number of entries, we need to also update entrie_lba. */
1467	secondary_header->entries_lba = secondary_header->my_lba -
1468		CalculateEntriesSectors(secondary_header);
1469	RefreshCrc32(gpt);
1470	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1471		gpt->gpt_drive_sectors, 0));
1472	EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1473		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
1474
1475	secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1476	RefreshCrc32(gpt);
1477	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1478		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
1479
1480	return TEST_OK;
1481}
1482
1483int main(int argc, char *argv[])
1484{
1485	int i;
1486	int error_count = 0;
1487	struct {
1488		char *name;
1489		test_func fp;
1490		int retval;
1491	} test_cases[] = {
1492		{ TEST_CASE(StructSizeTest), },
1493		{ TEST_CASE(TestBuildTestGptData), },
1494		{ TEST_CASE(ParameterTests), },
1495		{ TEST_CASE(HeaderCrcTest), },
1496		{ TEST_CASE(HeaderSameTest), },
1497		{ TEST_CASE(SignatureTest), },
1498		{ TEST_CASE(RevisionTest), },
1499		{ TEST_CASE(SizeTest), },
1500		{ TEST_CASE(CrcFieldTest), },
1501		{ TEST_CASE(ReservedFieldsTest), },
1502		{ TEST_CASE(SizeOfPartitionEntryTest), },
1503		{ TEST_CASE(NumberOfPartitionEntriesTest), },
1504		{ TEST_CASE(MyLbaTest), },
1505		{ TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1506		{ TEST_CASE(EntriesCrcTest), },
1507		{ TEST_CASE(ValidEntryTest), },
1508		{ TEST_CASE(OverlappedPartitionTest), },
1509		{ TEST_CASE(SanityCheckTest), },
1510		{ TEST_CASE(NoValidKernelEntryTest), },
1511		{ TEST_CASE(EntryAttributeGetSetTest), },
1512		{ TEST_CASE(EntryTypeTest), },
1513		{ TEST_CASE(GetNextNormalTest), },
1514		{ TEST_CASE(GetNextPrioTest), },
1515		{ TEST_CASE(GetNextTriesTest), },
1516		{ TEST_CASE(GptUpdateTest), },
1517		{ TEST_CASE(UpdateInvalidKernelTypeTest), },
1518		{ TEST_CASE(DuplicateUniqueGuidTest), },
1519		{ TEST_CASE(TestCrc32TestVectors), },
1520		{ TEST_CASE(GetKernelGuidTest), },
1521		{ TEST_CASE(ErrorTextTest), },
1522		{ TEST_CASE(CheckHeaderOffDevice), },
1523	};
1524
1525	for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1526		printf("Running %s() ...\n", test_cases[i].name);
1527		test_cases[i].retval = test_cases[i].fp();
1528		if (test_cases[i].retval) {
1529			printf(COL_RED "[ERROR]\n\n" COL_STOP);
1530			++error_count;
1531		} else {
1532			printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1533		}
1534	}
1535
1536	if (error_count) {
1537		printf("\n------------------------------------------------\n");
1538		printf(COL_RED "The following %d test cases are failed:\n"
1539		       COL_STOP, error_count);
1540		for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1541			if (test_cases[i].retval)
1542				printf("  %s()\n", test_cases[i].name);
1543		}
1544	}
1545
1546	return error_count ? 1 : 0;
1547}
1548