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