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