blob: fd5cda1671b0662f3adf234cc43be223028c9e0e [file] [log] [blame]
Randall Spanglere9213a72013-01-24 11:19:55 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Alex Deymof5109732014-08-25 16:34:52 -07006#include <errno.h>
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07007#include <string.h>
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07008
Albert Chaulk534723a2013-03-20 14:46:50 -07009#include "../cgpt/cgpt.h"
Louis Yung-Chieh Lo0dce41c2010-05-17 22:45:30 -070010#include "cgptlib_internal.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070011#include "cgptlib_test.h"
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070012#include "crc32.h"
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +080013#include "crc32_test.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070014#include "gpt.h"
vbendeb3ecaf772010-06-24 16:19:53 -070015#include "test_common.h"
Albert Chaulk534723a2013-03-20 14:46:50 -070016#define _STUB_IMPLEMENTATION_
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070017#include "utility.h"
18
Randall Spanglere9213a72013-01-24 11:19:55 -080019/*
20 * Testing partition layout (sector_bytes=512)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070021 *
22 * LBA Size Usage
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070023 * ---------------------------------------------------------
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070024 * 0 1 PMBR
25 * 1 1 primary partition header
26 * 2 32 primary partition entries (128B * 128)
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070027 * 34 100 kernel A (index: 0)
28 * 134 100 root A (index: 1)
29 * 234 100 root B (index: 2)
30 * 334 100 kernel B (index: 3)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070031 * 434 32 secondary partition entries
32 * 466 1 secondary partition header
33 * 467
34 */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070035#define KERNEL_A 0
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070036#define KERNEL_B 1
37#define ROOTFS_A 2
38#define ROOTFS_B 3
39#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
40#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070041
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070042#define DEFAULT_SECTOR_SIZE 512
43#define MAX_SECTOR_SIZE 4096
44#define DEFAULT_DRIVE_SECTORS 467
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070045#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070046
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070047static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
48static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
49static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
50
Albert Chaulk534723a2013-03-20 14:46:50 -070051// cgpt_common.c requires these be defined if linked in.
52const char *progname = "CGPT-TEST";
53const char *command = "TEST";
54
Randall Spanglere9213a72013-01-24 11:19:55 -080055/*
56 * Copy a random-for-this-program-only Guid into the dest. The num parameter
Bill Richardsonaa8eda42010-08-27 09:31:26 -070057 * completely determines the Guid.
58 */
Randall Spanglere9213a72013-01-24 11:19:55 -080059static void SetGuid(void *dest, uint32_t num)
60{
61 Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,
62 {0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
63 Memcpy(dest, &g, sizeof(Guid));
Bill Richardsonaa8eda42010-08-27 09:31:26 -070064}
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070065
Randall Spanglere9213a72013-01-24 11:19:55 -080066/*
67 * Given a GptData pointer, first re-calculate entries CRC32 value, then reset
68 * header CRC32 value to 0, and calculate header CRC32 value. Both primary and
69 * secondary are updated.
70 */
71static void RefreshCrc32(GptData *gpt)
72{
73 GptHeader *header, *header2;
74 GptEntry *entries, *entries2;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070075
Randall Spanglere9213a72013-01-24 11:19:55 -080076 header = (GptHeader *)gpt->primary_header;
77 entries = (GptEntry *)gpt->primary_entries;
78 header2 = (GptHeader *)gpt->secondary_header;
79 entries2 = (GptEntry *)gpt->secondary_entries;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070080
Randall Spanglere9213a72013-01-24 11:19:55 -080081 header->entries_crc32 =
82 Crc32((uint8_t *)entries,
83 header->number_of_entries * header->size_of_entry);
84 header->header_crc32 = 0;
85 header->header_crc32 = Crc32((uint8_t *)header, header->size);
86 header2->entries_crc32 =
87 Crc32((uint8_t *)entries2,
88 header2->number_of_entries * header2->size_of_entry);
89 header2->header_crc32 = 0;
90 header2->header_crc32 = Crc32((uint8_t *)header2, header2->size);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070091}
92
Randall Spanglere9213a72013-01-24 11:19:55 -080093static void ZeroHeaders(GptData *gpt)
94{
95 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
96 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070097}
98
Randall Spanglere9213a72013-01-24 11:19:55 -080099static void ZeroEntries(GptData *gpt)
100{
101 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
102 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700103}
104
Randall Spanglere9213a72013-01-24 11:19:55 -0800105static void ZeroHeadersEntries(GptData *gpt)
106{
107 ZeroHeaders(gpt);
108 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700109}
110
Randall Spanglere9213a72013-01-24 11:19:55 -0800111/*
112 * Return a pointer to a static GptData instance (no free is required).
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700113 * All fields are zero except 4 pointers linking to header and entries.
Randall Spanglere9213a72013-01-24 11:19:55 -0800114 * All content of headers and entries are zero.
115 */
116static GptData *GetEmptyGptData(void)
117{
118 static GptData gpt;
119 static uint8_t primary_header[MAX_SECTOR_SIZE];
120 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
121 static uint8_t secondary_header[MAX_SECTOR_SIZE];
122 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700123
Randall Spanglere9213a72013-01-24 11:19:55 -0800124 Memset(&gpt, 0, sizeof(gpt));
125 gpt.primary_header = primary_header;
126 gpt.primary_entries = primary_entries;
127 gpt.secondary_header = secondary_header;
128 gpt.secondary_entries = secondary_entries;
129 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700130
Randall Spanglere9213a72013-01-24 11:19:55 -0800131 /* Initialize GptData internal states. */
132 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700133
Randall Spanglere9213a72013-01-24 11:19:55 -0800134 return &gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700135}
136
Randall Spanglere9213a72013-01-24 11:19:55 -0800137/*
138 * Fill in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700139 * file. Before calling this function, primary/secondary header/entries must
140 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
141 * This function returns a good (valid) copy of GPT layout described in top of
Randall Spanglere9213a72013-01-24 11:19:55 -0800142 * this file.
143 */
144static void BuildTestGptData(GptData *gpt)
145{
146 GptHeader *header, *header2;
147 GptEntry *entries, *entries2;
148 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
149 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700150
Randall Spanglere9213a72013-01-24 11:19:55 -0800151 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700152 gpt->drive_sectors = gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
Randall Spanglere9213a72013-01-24 11:19:55 -0800153 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
154 gpt->valid_headers = MASK_BOTH;
155 gpt->valid_entries = MASK_BOTH;
156 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700157
Randall Spanglere9213a72013-01-24 11:19:55 -0800158 /* Build primary */
159 header = (GptHeader *)gpt->primary_header;
160 entries = (GptEntry *)gpt->primary_entries;
161 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
162 sizeof(GPT_HEADER_SIGNATURE));
163 header->revision = GPT_HEADER_REVISION;
164 header->size = sizeof(GptHeader);
165 header->reserved_zero = 0;
166 header->my_lba = 1;
167 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
168 header->first_usable_lba = 34;
169 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
170 header->entries_lba = 2;
171 /* 512B / 128B * 32sectors = 128 entries */
172 header->number_of_entries = 128;
173 header->size_of_entry = 128; /* bytes */
174 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
175 SetGuid(&entries[0].unique, 0);
176 entries[0].starting_lba = 34;
177 entries[0].ending_lba = 133;
178 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
179 SetGuid(&entries[1].unique, 1);
180 entries[1].starting_lba = 134;
181 entries[1].ending_lba = 232;
182 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
183 SetGuid(&entries[2].unique, 2);
184 entries[2].starting_lba = 234;
185 entries[2].ending_lba = 331;
186 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
187 SetGuid(&entries[3].unique, 3);
188 entries[3].starting_lba = 334;
189 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700190
Randall Spanglere9213a72013-01-24 11:19:55 -0800191 /* Build secondary */
192 header2 = (GptHeader *)gpt->secondary_header;
193 entries2 = (GptEntry *)gpt->secondary_entries;
194 Memcpy(header2, header, sizeof(GptHeader));
195 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
196 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
197 header2->alternate_lba = 1;
198 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700199
Randall Spanglere9213a72013-01-24 11:19:55 -0800200 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700201}
202
Randall Spanglere9213a72013-01-24 11:19:55 -0800203/*
204 * Test if the structures are the expected size; if this fails, struct packing
205 * is not working properly.
206 */
207static int StructSizeTest(void)
208{
Randall Spangler81d09962010-06-23 10:15:38 -0700209
Randall Spanglere9213a72013-01-24 11:19:55 -0800210 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
211 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
212 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
213 return TEST_OK;
Randall Spangler81d09962010-06-23 10:15:38 -0700214}
215
216
Randall Spanglere9213a72013-01-24 11:19:55 -0800217/* Test if the default structure returned by BuildTestGptData() is good. */
218static int TestBuildTestGptData(void)
219{
220 GptData *gpt;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700221
Randall Spanglere9213a72013-01-24 11:19:55 -0800222 gpt = GetEmptyGptData();
223 BuildTestGptData(gpt);
224 EXPECT(GPT_SUCCESS == GptInit(gpt));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800225 gpt->sector_bytes = 0;
226 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
Randall Spanglere9213a72013-01-24 11:19:55 -0800227 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700228}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700229
Randall Spanglere9213a72013-01-24 11:19:55 -0800230/*
231 * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
232 * Currently we only support 512 bytes per sector. In the future, we may
233 * support other sizes. A too small drive_sectors should be rejected by
234 * GptInit().
235 */
236static int ParameterTests(void)
237{
238 GptData *gpt;
239 struct {
240 uint32_t sector_bytes;
241 uint64_t drive_sectors;
242 int expected_retval;
243 } cases[] = {
244 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
245 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
246 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
247 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
Nam T. Nguyen88458d92014-08-28 10:58:47 -0700248 {512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
Randall Spanglere9213a72013-01-24 11:19:55 -0800249 GPT_ENTRIES_SECTORS * 2, GPT_SUCCESS},
250 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
251 };
252 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700253
Randall Spanglere9213a72013-01-24 11:19:55 -0800254 gpt = GetEmptyGptData();
255 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
256 BuildTestGptData(gpt);
257 gpt->sector_bytes = cases[i].sector_bytes;
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700258 gpt->drive_sectors = gpt->gpt_drive_sectors = cases[i].drive_sectors;
Randall Spanglere9213a72013-01-24 11:19:55 -0800259 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
260 }
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700261
Randall Spanglere9213a72013-01-24 11:19:55 -0800262 return TEST_OK;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700263}
264
Randall Spanglere9213a72013-01-24 11:19:55 -0800265/* Test if header CRC in two copies are calculated. */
266static int HeaderCrcTest(void)
267{
268 GptData *gpt = GetEmptyGptData();
269 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700270
Randall Spanglere9213a72013-01-24 11:19:55 -0800271 BuildTestGptData(gpt);
272 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700273
Randall Spanglere9213a72013-01-24 11:19:55 -0800274 /* CRC covers first byte of header */
275 BuildTestGptData(gpt);
276 gpt->primary_header[0] ^= 0xa5;
277 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700278
Randall Spanglere9213a72013-01-24 11:19:55 -0800279 /* CRC covers last byte of header */
280 BuildTestGptData(gpt);
281 gpt->primary_header[h1->size - 1] ^= 0x5a;
282 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700283
Randall Spanglere9213a72013-01-24 11:19:55 -0800284 /* CRC only covers header */
285 BuildTestGptData(gpt);
286 gpt->primary_header[h1->size] ^= 0x5a;
287 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700288
Randall Spanglere9213a72013-01-24 11:19:55 -0800289 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700290}
291
Randall Spangler0bda13f2013-01-24 12:25:26 -0800292/* Test if header-same comparison works. */
293static int HeaderSameTest(void)
294{
295 GptData *gpt = GetEmptyGptData();
296 GptHeader *h1 = (GptHeader *)gpt->primary_header;
297 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
298 GptHeader h3;
299
300 EXPECT(0 == HeaderFieldsSame(h1, h2));
301
302 Memcpy(&h3, h2, sizeof(h3));
303 h3.signature[0] ^= 0xba;
304 EXPECT(1 == HeaderFieldsSame(h1, &h3));
305
306 Memcpy(&h3, h2, sizeof(h3));
307 h3.revision++;
308 EXPECT(1 == HeaderFieldsSame(h1, &h3));
309
310 Memcpy(&h3, h2, sizeof(h3));
311 h3.size++;
312 EXPECT(1 == HeaderFieldsSame(h1, &h3));
313
314 Memcpy(&h3, h2, sizeof(h3));
315 h3.reserved_zero++;
316 EXPECT(1 == HeaderFieldsSame(h1, &h3));
317
318 Memcpy(&h3, h2, sizeof(h3));
319 h3.first_usable_lba++;
320 EXPECT(1 == HeaderFieldsSame(h1, &h3));
321
322 Memcpy(&h3, h2, sizeof(h3));
323 h3.last_usable_lba++;
324 EXPECT(1 == HeaderFieldsSame(h1, &h3));
325
326 Memcpy(&h3, h2, sizeof(h3));
327 h3.disk_uuid.u.raw[0] ^= 0xba;
328 EXPECT(1 == HeaderFieldsSame(h1, &h3));
329
330 Memcpy(&h3, h2, sizeof(h3));
331 h3.number_of_entries++;
332 EXPECT(1 == HeaderFieldsSame(h1, &h3));
333
334 Memcpy(&h3, h2, sizeof(h3));
335 h3.size_of_entry++;
336 EXPECT(1 == HeaderFieldsSame(h1, &h3));
337
338 Memcpy(&h3, h2, sizeof(h3));
339 h3.entries_crc32++;
340 EXPECT(1 == HeaderFieldsSame(h1, &h3));
341
342 return TEST_OK;
343}
344
Randall Spanglere9213a72013-01-24 11:19:55 -0800345/* Test if signature ("EFI PART") is checked. */
346static int SignatureTest(void)
347{
348 GptData *gpt = GetEmptyGptData();
349 GptHeader *h1 = (GptHeader *)gpt->primary_header;
350 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
351 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700352
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800353 EXPECT(1 == CheckHeader(NULL, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800354
Randall Spanglere9213a72013-01-24 11:19:55 -0800355 for (i = 0; i < 8; ++i) {
356 BuildTestGptData(gpt);
357 h1->signature[i] ^= 0xff;
358 h2->signature[i] ^= 0xff;
359 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800360 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
361 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800362 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700363
Randall Spanglere9213a72013-01-24 11:19:55 -0800364 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700365}
366
Randall Spanglere9213a72013-01-24 11:19:55 -0800367/*
368 * The revision we currently support is GPT_HEADER_REVISION. If the revision
369 * in header is not that, we expect the header is invalid.
370 */
371static int RevisionTest(void)
372{
373 GptData *gpt = GetEmptyGptData();
374 GptHeader *h1 = (GptHeader *)gpt->primary_header;
375 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
376 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700377
Randall Spanglere9213a72013-01-24 11:19:55 -0800378 struct {
379 uint32_t value_to_test;
380 int expect_rv;
381 } cases[] = {
382 {0x01000000, 1},
383 {0x00010000, 0}, /* GPT_HEADER_REVISION */
384 {0x00000100, 1},
385 {0x00000001, 1},
386 {0x23010456, 1},
387 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700388
Randall Spanglere9213a72013-01-24 11:19:55 -0800389 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
390 BuildTestGptData(gpt);
391 h1->revision = cases[i].value_to_test;
392 h2->revision = cases[i].value_to_test;
393 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700394
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800395 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800396 cases[i].expect_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800397 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800398 cases[i].expect_rv);
399 }
400 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700401}
402
Randall Spanglere9213a72013-01-24 11:19:55 -0800403static int SizeTest(void)
404{
405 GptData *gpt = GetEmptyGptData();
406 GptHeader *h1 = (GptHeader *)gpt->primary_header;
407 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
408 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700409
Randall Spanglere9213a72013-01-24 11:19:55 -0800410 struct {
411 uint32_t value_to_test;
412 int expect_rv;
413 } cases[] = {
414 {91, 1},
415 {92, 0},
416 {93, 0},
417 {511, 0},
418 {512, 0},
419 {513, 1},
420 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700421
Randall Spanglere9213a72013-01-24 11:19:55 -0800422 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
423 BuildTestGptData(gpt);
424 h1->size = cases[i].value_to_test;
425 h2->size = cases[i].value_to_test;
426 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700427
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800428 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800429 cases[i].expect_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800430 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800431 cases[i].expect_rv);
432 }
433 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700434}
435
Randall Spanglere9213a72013-01-24 11:19:55 -0800436/* Test if CRC is checked. */
437static int CrcFieldTest(void)
438{
439 GptData *gpt = GetEmptyGptData();
440 GptHeader *h1 = (GptHeader *)gpt->primary_header;
441 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700442
Randall Spanglere9213a72013-01-24 11:19:55 -0800443 BuildTestGptData(gpt);
444 /* Modify a field that the header verification doesn't care about */
445 h1->entries_crc32++;
446 h2->entries_crc32++;
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800447 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
448 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800449 /* Refresh the CRC; should pass now */
450 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800451 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
452 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700453
Randall Spanglere9213a72013-01-24 11:19:55 -0800454 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700455}
456
Randall Spanglere9213a72013-01-24 11:19:55 -0800457/* Test if reserved fields are checked. We'll try non-zero values to test. */
458static int ReservedFieldsTest(void)
459{
460 GptData *gpt = GetEmptyGptData();
461 GptHeader *h1 = (GptHeader *)gpt->primary_header;
462 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700463
Randall Spanglere9213a72013-01-24 11:19:55 -0800464 BuildTestGptData(gpt);
465 h1->reserved_zero ^= 0x12345678; /* whatever random */
466 h2->reserved_zero ^= 0x12345678; /* whatever random */
467 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800468 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
469 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700470
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700471#ifdef PADDING_CHECKED
Randall Spanglere9213a72013-01-24 11:19:55 -0800472 /* TODO: padding check is currently disabled */
473 BuildTestGptData(gpt);
474 h1->padding[12] ^= 0x34; /* whatever random */
475 h2->padding[56] ^= 0x78; /* whatever random */
476 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800477 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
478 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700479#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700480
Randall Spanglere9213a72013-01-24 11:19:55 -0800481 return TEST_OK;
482}
483
484/*
485 * Technically, any size which is 2^N where N > 6 should work, but our
486 * library only supports one size.
487 */
488static int SizeOfPartitionEntryTest(void) {
489 GptData *gpt = GetEmptyGptData();
490 GptHeader *h1 = (GptHeader *)gpt->primary_header;
491 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
492 int i;
493
494 struct {
495 uint32_t value_to_test;
496 int expect_rv;
497 } cases[] = {
498 {127, 1},
499 {128, 0},
500 {129, 1},
501 {256, 1},
502 {512, 1},
503 };
504
505 /* Check size of entryes */
506 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
507 BuildTestGptData(gpt);
508 h1->size_of_entry = cases[i].value_to_test;
509 h2->size_of_entry = cases[i].value_to_test;
510 h1->number_of_entries = TOTAL_ENTRIES_SIZE /
511 cases[i].value_to_test;
512 h2->number_of_entries = TOTAL_ENTRIES_SIZE /
513 cases[i].value_to_test;
514 RefreshCrc32(gpt);
515
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800516 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800517 cases[i].expect_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800518 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800519 cases[i].expect_rv);
520 }
521
522 return TEST_OK;
523}
524
525/*
526 * Technically, any size which is 2^N where N > 6 should work, but our library
527 * only supports one size.
528 */
529static int NumberOfPartitionEntriesTest(void)
530{
531 GptData *gpt = GetEmptyGptData();
532 GptHeader *h1 = (GptHeader *)gpt->primary_header;
533 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
534
535 BuildTestGptData(gpt);
536 h1->number_of_entries--;
537 h2->number_of_entries /= 2;
538 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800539 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
540 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700541 /* But it's okay to have less if the GPT structs are stored elsewhere. */
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800542 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
543 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800544
545 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700546}
547
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700548
Randall Spanglere9213a72013-01-24 11:19:55 -0800549/* Test if myLBA field is checked (1 for primary, last for secondary). */
550static int MyLbaTest(void)
551{
552 GptData *gpt = GetEmptyGptData();
553 GptHeader *h1 = (GptHeader *)gpt->primary_header;
554 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700555
Randall Spanglere9213a72013-01-24 11:19:55 -0800556 /* myLBA depends on primary vs secondary flag */
557 BuildTestGptData(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800558 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
559 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700560
Randall Spanglere9213a72013-01-24 11:19:55 -0800561 BuildTestGptData(gpt);
562 h1->my_lba--;
563 h2->my_lba--;
564 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800565 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
566 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700567
Randall Spanglere9213a72013-01-24 11:19:55 -0800568 BuildTestGptData(gpt);
569 h1->my_lba = 2;
570 h2->my_lba--;
571 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800572 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
573 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700574
Randall Spanglere9213a72013-01-24 11:19:55 -0800575 /* We should ignore the alternate_lba field entirely */
576 BuildTestGptData(gpt);
577 h1->alternate_lba++;
578 h2->alternate_lba++;
579 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800580 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
581 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800582
583 BuildTestGptData(gpt);
584 h1->alternate_lba--;
585 h2->alternate_lba--;
586 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800587 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
588 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800589
590 BuildTestGptData(gpt);
591 h1->entries_lba++;
592 h2->entries_lba++;
593 RefreshCrc32(gpt);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700594 /*
595 * We support a padding between primary GPT header and its entries. So
596 * this still passes.
597 */
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800598 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700599 /*
600 * But the secondary table should fail because it would overlap the
601 * header, which is now lying after its entry array.
602 */
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800603 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800604
605 BuildTestGptData(gpt);
606 h1->entries_lba--;
607 h2->entries_lba--;
608 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800609 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
610 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800611
612 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700613}
614
Randall Spanglere9213a72013-01-24 11:19:55 -0800615/* Test if FirstUsableLBA and LastUsableLBA are checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700616 * FirstUsableLBA must be after the end of the primary GPT table array.
617 * LastUsableLBA must be before the start of the secondary GPT table array.
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700618 * FirstUsableLBA <= LastUsableLBA.
619 * Also see CheckHeaderOffDevice() test. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800620static int FirstUsableLbaAndLastUsableLbaTest(void)
621{
622 GptData *gpt = GetEmptyGptData();
623 GptHeader *h1 = (GptHeader *)gpt->primary_header;
624 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
625 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700626
Randall Spanglere9213a72013-01-24 11:19:55 -0800627 struct {
628 uint64_t primary_entries_lba;
629 uint64_t primary_first_usable_lba;
630 uint64_t primary_last_usable_lba;
631 uint64_t secondary_first_usable_lba;
632 uint64_t secondary_last_usable_lba;
633 uint64_t secondary_entries_lba;
634 int primary_rv;
635 int secondary_rv;
636 } cases[] = {
637 {2, 34, 433, 34, 433, 434, 0, 0},
638 {2, 34, 432, 34, 430, 434, 0, 0},
639 {2, 33, 433, 33, 433, 434, 1, 1},
640 {2, 34, 434, 34, 433, 434, 1, 0},
641 {2, 34, 433, 34, 434, 434, 0, 1},
642 {2, 35, 433, 35, 433, 434, 0, 0},
643 {2, 433, 433, 433, 433, 434, 0, 0},
644 {2, 434, 433, 434, 434, 434, 1, 1},
645 {2, 433, 34, 34, 433, 434, 1, 0},
646 {2, 34, 433, 433, 34, 434, 0, 1},
647 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700648
Randall Spanglere9213a72013-01-24 11:19:55 -0800649 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
650 BuildTestGptData(gpt);
651 h1->entries_lba = cases[i].primary_entries_lba;
652 h1->first_usable_lba = cases[i].primary_first_usable_lba;
653 h1->last_usable_lba = cases[i].primary_last_usable_lba;
654 h2->entries_lba = cases[i].secondary_entries_lba;
655 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
656 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
657 RefreshCrc32(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700658
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800659 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800660 cases[i].primary_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800661 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800662 cases[i].secondary_rv);
663 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700664
Randall Spanglere9213a72013-01-24 11:19:55 -0800665 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700666}
667
Randall Spanglere9213a72013-01-24 11:19:55 -0800668/*
669 * Test if PartitionEntryArrayCRC32 is checked. PartitionEntryArrayCRC32 must
670 * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700671 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800672static int EntriesCrcTest(void)
673{
674 GptData *gpt = GetEmptyGptData();
675 GptHeader *h1 = (GptHeader *)gpt->primary_header;
676 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
677 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700678
Randall Spanglere9213a72013-01-24 11:19:55 -0800679 /* Modify first byte of primary entries, and expect the CRC is wrong. */
680 BuildTestGptData(gpt);
681 EXPECT(0 == CheckEntries(e1, h1));
682 EXPECT(0 == CheckEntries(e2, h1));
683 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
684 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
685 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
686 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700687
Randall Spanglere9213a72013-01-24 11:19:55 -0800688 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700689}
690
Randall Spanglere9213a72013-01-24 11:19:55 -0800691/*
692 * Test if partition geometry is checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700693 * All active (non-zero PartitionTypeGUID) partition entries should have:
694 * entry.StartingLBA >= header.FirstUsableLBA
695 * entry.EndingLBA <= header.LastUsableLBA
696 * entry.StartingLBA <= entry.EndingLBA
697 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800698static int ValidEntryTest(void)
699{
700 GptData *gpt = GetEmptyGptData();
701 GptHeader *h1 = (GptHeader *)gpt->primary_header;
702 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700703
Randall Spanglere9213a72013-01-24 11:19:55 -0800704 /* error case: entry.StartingLBA < header.FirstUsableLBA */
705 BuildTestGptData(gpt);
706 e1[0].starting_lba = h1->first_usable_lba - 1;
707 RefreshCrc32(gpt);
708 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700709
Randall Spanglere9213a72013-01-24 11:19:55 -0800710 /* error case: entry.EndingLBA > header.LastUsableLBA */
711 BuildTestGptData(gpt);
712 e1[2].ending_lba = h1->last_usable_lba + 1;
713 RefreshCrc32(gpt);
714 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700715
Randall Spanglere9213a72013-01-24 11:19:55 -0800716 /* error case: entry.StartingLBA > entry.EndingLBA */
717 BuildTestGptData(gpt);
718 e1[3].starting_lba = e1[3].ending_lba + 1;
719 RefreshCrc32(gpt);
720 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700721
Randall Spanglere9213a72013-01-24 11:19:55 -0800722 /* case: non active entry should be ignored. */
723 BuildTestGptData(gpt);
724 Memset(&e1[1].type, 0, sizeof(e1[1].type));
725 e1[1].starting_lba = e1[1].ending_lba + 1;
726 RefreshCrc32(gpt);
727 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700728
Randall Spanglere9213a72013-01-24 11:19:55 -0800729 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700730}
731
Randall Spanglere9213a72013-01-24 11:19:55 -0800732/* Test if overlapped partition tables can be detected. */
733static int OverlappedPartitionTest(void) {
734 GptData *gpt = GetEmptyGptData();
735 GptHeader *h = (GptHeader *)gpt->primary_header;
736 GptEntry *e = (GptEntry *)gpt->primary_entries;
737 int i, j;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700738
Randall Spanglere9213a72013-01-24 11:19:55 -0800739 struct {
740 int overlapped;
741 struct {
742 int active;
743 uint64_t starting_lba;
744 uint64_t ending_lba;
745 } entries[16]; /* enough for testing. */
746 } cases[] = {
747 {GPT_SUCCESS, {{0, 100, 199}}},
748 {GPT_SUCCESS, {{1, 100, 199}}},
749 {GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
750 {GPT_ERROR_START_LBA_OVERLAP,
751 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
752 {GPT_ERROR_END_LBA_OVERLAP,
753 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
754 {GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
755 {GPT_ERROR_END_LBA_OVERLAP,
756 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
757 {GPT_ERROR_START_LBA_OVERLAP,
758 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
759 {GPT_ERROR_START_LBA_OVERLAP,
760 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
761 {GPT_ERROR_END_LBA_OVERLAP,
762 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
763 {GPT_ERROR_START_LBA_OVERLAP,
764 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
765 {GPT_SUCCESS,
766 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
767 {GPT_ERROR_START_LBA_OVERLAP,
768 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
769 {GPT_ERROR_START_LBA_OVERLAP,
770 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
771 {GPT_SUCCESS,
772 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
773 {GPT_ERROR_END_LBA_OVERLAP,
774 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
775 {GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
776 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
777 {GPT_ERROR_START_LBA_OVERLAP,
778 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
779 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
780 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
781 {GPT_SUCCESS,
782 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
783 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
784 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
785 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700786
Randall Spanglere9213a72013-01-24 11:19:55 -0800787 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
788 BuildTestGptData(gpt);
789 ZeroEntries(gpt);
790 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
791 if (!cases[i].entries[j].starting_lba)
792 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700793
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700794 if (cases[i].entries[j].active) {
Randall Spanglere9213a72013-01-24 11:19:55 -0800795 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700796 }
Randall Spanglere9213a72013-01-24 11:19:55 -0800797 SetGuid(&e[j].unique, j);
798 e[j].starting_lba = cases[i].entries[j].starting_lba;
799 e[j].ending_lba = cases[i].entries[j].ending_lba;
800 }
801 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700802
Randall Spanglere9213a72013-01-24 11:19:55 -0800803 EXPECT(cases[i].overlapped == CheckEntries(e, h));
804 }
805 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700806}
807
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700808/* Test both sanity checking and repair. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800809static int SanityCheckTest(void)
810{
811 GptData *gpt = GetEmptyGptData();
812 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler0bda13f2013-01-24 12:25:26 -0800813 GptEntry *e1 = (GptEntry *)gpt->primary_entries;
814 uint8_t *tempptr;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700815
Randall Spanglere9213a72013-01-24 11:19:55 -0800816 /* Unmodified test data is completely sane */
817 BuildTestGptData(gpt);
818 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
819 EXPECT(MASK_BOTH == gpt->valid_headers);
820 EXPECT(MASK_BOTH == gpt->valid_entries);
821 /* Repair doesn't damage it */
822 GptRepair(gpt);
823 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
824 EXPECT(MASK_BOTH == gpt->valid_headers);
825 EXPECT(MASK_BOTH == gpt->valid_entries);
826 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700827
Randall Spangler0bda13f2013-01-24 12:25:26 -0800828 /* Invalid sector size should fail */
829 BuildTestGptData(gpt);
830 gpt->sector_bytes = 1024;
831 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
832
Randall Spanglere9213a72013-01-24 11:19:55 -0800833 /* Modify headers */
834 BuildTestGptData(gpt);
835 gpt->primary_header[0]++;
836 gpt->secondary_header[0]++;
837 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
838 EXPECT(0 == gpt->valid_headers);
839 EXPECT(0 == gpt->valid_entries);
840 /* Repair can't fix completely busted headers */
841 GptRepair(gpt);
842 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
843 EXPECT(0 == gpt->valid_headers);
844 EXPECT(0 == gpt->valid_entries);
845 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700846
Randall Spanglere9213a72013-01-24 11:19:55 -0800847 BuildTestGptData(gpt);
848 gpt->primary_header[0]++;
849 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
850 EXPECT(MASK_SECONDARY == gpt->valid_headers);
851 EXPECT(MASK_BOTH == gpt->valid_entries);
852 GptRepair(gpt);
853 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
854 EXPECT(MASK_BOTH == gpt->valid_headers);
855 EXPECT(MASK_BOTH == gpt->valid_entries);
856 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700857
Randall Spanglere9213a72013-01-24 11:19:55 -0800858 BuildTestGptData(gpt);
859 gpt->secondary_header[0]++;
860 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
861 EXPECT(MASK_PRIMARY == gpt->valid_headers);
862 EXPECT(MASK_BOTH == gpt->valid_entries);
863 GptRepair(gpt);
864 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
865 EXPECT(MASK_BOTH == gpt->valid_headers);
866 EXPECT(MASK_BOTH == gpt->valid_entries);
867 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700868
Randall Spanglere9213a72013-01-24 11:19:55 -0800869 /*
870 * Modify header1 and update its CRC. Since header2 is now different
871 * than header1, it'll be the one considered invalid.
872 */
873 BuildTestGptData(gpt);
874 h1->size++;
875 RefreshCrc32(gpt);
876 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
877 EXPECT(MASK_PRIMARY == gpt->valid_headers);
878 EXPECT(MASK_BOTH == gpt->valid_entries);
879 GptRepair(gpt);
880 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
881 EXPECT(MASK_BOTH == gpt->valid_headers);
882 EXPECT(MASK_BOTH == gpt->valid_entries);
883 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700884
Randall Spanglere9213a72013-01-24 11:19:55 -0800885 /* Modify entries */
886 BuildTestGptData(gpt);
887 gpt->primary_entries[0]++;
888 gpt->secondary_entries[0]++;
889 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
890 EXPECT(MASK_BOTH == gpt->valid_headers);
891 EXPECT(MASK_NONE == gpt->valid_entries);
892 /* Repair can't fix both copies of entries being bad, either. */
893 GptRepair(gpt);
894 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
895 EXPECT(MASK_BOTH == gpt->valid_headers);
896 EXPECT(MASK_NONE == gpt->valid_entries);
897 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700898
Randall Spanglere9213a72013-01-24 11:19:55 -0800899 BuildTestGptData(gpt);
900 gpt->primary_entries[0]++;
901 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
902 EXPECT(MASK_BOTH == gpt->valid_headers);
903 EXPECT(MASK_SECONDARY == gpt->valid_entries);
904 GptRepair(gpt);
905 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
906 EXPECT(MASK_BOTH == gpt->valid_headers);
907 EXPECT(MASK_BOTH == gpt->valid_entries);
908 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700909
Randall Spanglere9213a72013-01-24 11:19:55 -0800910 BuildTestGptData(gpt);
911 gpt->secondary_entries[0]++;
912 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
913 EXPECT(MASK_BOTH == gpt->valid_headers);
914 EXPECT(MASK_PRIMARY == gpt->valid_entries);
915 GptRepair(gpt);
916 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
917 EXPECT(MASK_BOTH == gpt->valid_headers);
918 EXPECT(MASK_BOTH == gpt->valid_entries);
919 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700920
Randall Spangler0bda13f2013-01-24 12:25:26 -0800921 /*
922 * Modify entries and recompute CRCs, then make both primary and
923 * secondary entry pointers use the secondary data. The primary
924 * header will have the wrong entries CRC, so we should fall back
925 * to the secondary header.
926 */
927 BuildTestGptData(gpt);
928 e1->starting_lba++;
929 RefreshCrc32(gpt);
930 tempptr = gpt->primary_entries;
931 gpt->primary_entries = gpt->secondary_entries;
932 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
933 EXPECT(MASK_SECONDARY == gpt->valid_headers);
934 EXPECT(MASK_BOTH == gpt->valid_entries);
935 gpt->primary_entries = tempptr;
936
Randall Spanglere9213a72013-01-24 11:19:55 -0800937 /* Modify both header and entries */
938 BuildTestGptData(gpt);
939 gpt->primary_header[0]++;
940 gpt->primary_entries[0]++;
941 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
942 EXPECT(MASK_SECONDARY == gpt->valid_headers);
943 EXPECT(MASK_SECONDARY == gpt->valid_entries);
944 GptRepair(gpt);
945 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
946 EXPECT(MASK_BOTH == gpt->valid_headers);
947 EXPECT(MASK_BOTH == gpt->valid_entries);
948 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700949
Randall Spanglere9213a72013-01-24 11:19:55 -0800950 BuildTestGptData(gpt);
951 gpt->secondary_header[0]++;
952 gpt->secondary_entries[0]++;
953 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
954 EXPECT(MASK_PRIMARY == gpt->valid_headers);
955 EXPECT(MASK_PRIMARY == gpt->valid_entries);
956 GptRepair(gpt);
957 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
958 EXPECT(MASK_BOTH == gpt->valid_headers);
959 EXPECT(MASK_BOTH == gpt->valid_entries);
960 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700961
Randall Spanglere9213a72013-01-24 11:19:55 -0800962 /* Test cross-correction (h1+e2, h2+e1) */
963 BuildTestGptData(gpt);
964 gpt->primary_header[0]++;
965 gpt->secondary_entries[0]++;
966 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
967 EXPECT(MASK_SECONDARY == gpt->valid_headers);
968 EXPECT(MASK_PRIMARY == gpt->valid_entries);
969 GptRepair(gpt);
970 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
971 EXPECT(MASK_BOTH == gpt->valid_headers);
972 EXPECT(MASK_BOTH == gpt->valid_entries);
973 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700974
Randall Spanglere9213a72013-01-24 11:19:55 -0800975 BuildTestGptData(gpt);
976 gpt->secondary_header[0]++;
977 gpt->primary_entries[0]++;
978 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
979 EXPECT(MASK_PRIMARY == gpt->valid_headers);
980 EXPECT(MASK_SECONDARY == gpt->valid_entries);
981 GptRepair(gpt);
982 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
983 EXPECT(MASK_BOTH == gpt->valid_headers);
984 EXPECT(MASK_BOTH == gpt->valid_entries);
985 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700986
Randall Spanglere9213a72013-01-24 11:19:55 -0800987 /*
988 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different. This
989 * simulates a partial update of the drive.
990 */
991 BuildTestGptData(gpt);
992 gpt->secondary_entries[0]++;
993 RefreshCrc32(gpt);
994 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
995 EXPECT(MASK_PRIMARY == gpt->valid_headers);
996 EXPECT(MASK_PRIMARY == gpt->valid_entries);
997 GptRepair(gpt);
998 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
999 EXPECT(MASK_BOTH == gpt->valid_headers);
1000 EXPECT(MASK_BOTH == gpt->valid_entries);
1001 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001002
Nam T. Nguyen5ce83252014-10-30 15:09:43 -07001003 /* Test unloaded entry array. */
1004 gpt = GetEmptyGptData();
1005 BuildTestGptData(gpt);
1006 gpt->primary_entries = NULL;
1007 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1008 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1009 gpt = GetEmptyGptData();
1010 BuildTestGptData(gpt);
1011 gpt->secondary_entries = NULL;
1012 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1013 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1014
1015 /* Test unloaded header. */
1016 gpt = GetEmptyGptData();
1017 BuildTestGptData(gpt);
1018 gpt->primary_header = NULL;
1019 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1020 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1021 gpt = GetEmptyGptData();
1022 BuildTestGptData(gpt);
1023 gpt->secondary_header = NULL;
1024 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1025 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1026
Randall Spanglere9213a72013-01-24 11:19:55 -08001027 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001028}
1029
Randall Spanglere9213a72013-01-24 11:19:55 -08001030static int EntryAttributeGetSetTest(void)
1031{
1032 GptData *gpt = GetEmptyGptData();
1033 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001034
Randall Spanglere9213a72013-01-24 11:19:55 -08001035 e->attrs.whole = 0x0000000000000000ULL;
1036 SetEntrySuccessful(e, 1);
1037 EXPECT(0x0100000000000000ULL == e->attrs.whole);
1038 EXPECT(1 == GetEntrySuccessful(e));
1039 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1040 SetEntrySuccessful(e, 0);
1041 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1042 EXPECT(0 == GetEntrySuccessful(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001043
Randall Spanglere9213a72013-01-24 11:19:55 -08001044 e->attrs.whole = 0x0000000000000000ULL;
1045 SetEntryTries(e, 15);
1046 EXPECT(15 == GetEntryTries(e));
1047 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1048 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1049 SetEntryTries(e, 0);
1050 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1051 EXPECT(0 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001052
Randall Spanglere9213a72013-01-24 11:19:55 -08001053 e->attrs.whole = 0x0000000000000000ULL;
1054 SetEntryPriority(e, 15);
1055 EXPECT(0x000F000000000000ULL == e->attrs.whole);
1056 EXPECT(15 == GetEntryPriority(e));
1057 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1058 SetEntryPriority(e, 0);
1059 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1060 EXPECT(0 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001061
Randall Spanglere9213a72013-01-24 11:19:55 -08001062 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1063 EXPECT(1 == GetEntrySuccessful(e));
1064 EXPECT(15 == GetEntryPriority(e));
1065 EXPECT(15 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001066
Randall Spanglere9213a72013-01-24 11:19:55 -08001067 e->attrs.whole = 0x0123000000000000ULL;
1068 EXPECT(1 == GetEntrySuccessful(e));
1069 EXPECT(2 == GetEntryTries(e));
1070 EXPECT(3 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001071
Randall Spanglere9213a72013-01-24 11:19:55 -08001072 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001073}
1074
Randall Spanglere9213a72013-01-24 11:19:55 -08001075static int EntryTypeTest(void)
1076{
1077 GptData *gpt = GetEmptyGptData();
1078 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001079
Randall Spanglere9213a72013-01-24 11:19:55 -08001080 Memcpy(&e->type, &guid_zero, sizeof(Guid));
1081 EXPECT(1 == IsUnusedEntry(e));
1082 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001083
Randall Spanglere9213a72013-01-24 11:19:55 -08001084 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1085 EXPECT(0 == IsUnusedEntry(e));
1086 EXPECT(1 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001087
Randall Spanglere9213a72013-01-24 11:19:55 -08001088 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1089 EXPECT(0 == IsUnusedEntry(e));
1090 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001091
Randall Spanglere9213a72013-01-24 11:19:55 -08001092 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001093}
1094
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001095/* Make an entry unused by clearing its type. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001096static void FreeEntry(GptEntry *e)
1097{
1098 Memset(&e->type, 0, sizeof(Guid));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001099}
1100
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001101/* Set up an entry. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001102static void FillEntry(GptEntry *e, int is_kernel,
1103 int priority, int successful, int tries)
1104{
1105 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1106 SetEntryPriority(e, priority);
1107 SetEntrySuccessful(e, successful);
1108 SetEntryTries(e, tries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001109}
1110
Randall Spanglere9213a72013-01-24 11:19:55 -08001111/*
1112 * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001113 * any usable kernel entry.
1114 */
Randall Spanglere9213a72013-01-24 11:19:55 -08001115static int NoValidKernelEntryTest(void)
1116{
1117 GptData *gpt = GetEmptyGptData();
1118 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001119
Randall Spanglere9213a72013-01-24 11:19:55 -08001120 BuildTestGptData(gpt);
1121 SetEntryPriority(e1 + KERNEL_A, 0);
1122 FreeEntry(e1 + KERNEL_B);
1123 RefreshCrc32(gpt);
1124 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1125 GptNextKernelEntry(gpt, NULL, NULL));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001126
Randall Spanglere9213a72013-01-24 11:19:55 -08001127 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001128}
1129
Randall Spanglere9213a72013-01-24 11:19:55 -08001130static int GetNextNormalTest(void)
1131{
1132 GptData *gpt = GetEmptyGptData();
1133 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1134 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001135
Randall Spanglere9213a72013-01-24 11:19:55 -08001136 /* Normal case - both kernels successful */
1137 BuildTestGptData(gpt);
1138 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1139 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1140 RefreshCrc32(gpt);
1141 GptInit(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001142
Randall Spanglere9213a72013-01-24 11:19:55 -08001143 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1144 EXPECT(KERNEL_A == gpt->current_kernel);
1145 EXPECT(34 == start);
1146 EXPECT(100 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001147
Randall Spanglere9213a72013-01-24 11:19:55 -08001148 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1149 EXPECT(KERNEL_B == gpt->current_kernel);
1150 EXPECT(134 == start);
1151 EXPECT(99 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001152
Randall Spanglere9213a72013-01-24 11:19:55 -08001153 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1154 GptNextKernelEntry(gpt, &start, &size));
1155 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001156
Randall Spanglere9213a72013-01-24 11:19:55 -08001157 /* Call as many times as you want; you won't get another kernel... */
1158 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1159 GptNextKernelEntry(gpt, &start, &size));
1160 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001161
Randall Spanglere9213a72013-01-24 11:19:55 -08001162 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001163}
1164
Randall Spanglere9213a72013-01-24 11:19:55 -08001165static int GetNextPrioTest(void)
1166{
1167 GptData *gpt = GetEmptyGptData();
1168 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1169 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001170
Randall Spanglere9213a72013-01-24 11:19:55 -08001171 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1172 BuildTestGptData(gpt);
1173 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1174 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1175 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1176 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1177 RefreshCrc32(gpt);
1178 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001179
Randall Spanglere9213a72013-01-24 11:19:55 -08001180 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1181 EXPECT(KERNEL_B == gpt->current_kernel);
1182 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1183 EXPECT(KERNEL_Y == gpt->current_kernel);
1184 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1185 EXPECT(KERNEL_A == gpt->current_kernel);
1186 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1187 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001188
Randall Spanglere9213a72013-01-24 11:19:55 -08001189 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001190}
1191
Randall Spanglere9213a72013-01-24 11:19:55 -08001192static int GetNextTriesTest(void)
1193{
1194 GptData *gpt = GetEmptyGptData();
1195 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1196 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001197
Randall Spanglere9213a72013-01-24 11:19:55 -08001198 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1199 BuildTestGptData(gpt);
1200 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1201 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1202 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1203 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1204 RefreshCrc32(gpt);
1205 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001206
Randall Spanglere9213a72013-01-24 11:19:55 -08001207 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1208 EXPECT(KERNEL_X == gpt->current_kernel);
1209 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1210 EXPECT(KERNEL_A == gpt->current_kernel);
1211 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1212 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001213
Randall Spanglere9213a72013-01-24 11:19:55 -08001214 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001215}
1216
Randall Spanglere9213a72013-01-24 11:19:55 -08001217static int GptUpdateTest(void)
1218{
1219 GptData *gpt = GetEmptyGptData();
1220 GptEntry *e = (GptEntry *)(gpt->primary_entries);
1221 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1222 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001223
Randall Spanglere9213a72013-01-24 11:19:55 -08001224 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1225 BuildTestGptData(gpt);
1226 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1227 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1228 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1229 RefreshCrc32(gpt);
1230 GptInit(gpt);
1231 gpt->modified = 0; /* Nothing modified yet */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001232
Randall Spanglere9213a72013-01-24 11:19:55 -08001233 /* Successful kernel */
1234 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1235 EXPECT(KERNEL_A == gpt->current_kernel);
1236 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1237 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1238 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1239 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1240 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1241 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1242 /* Trying successful kernel changes nothing */
1243 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1244 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1245 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1246 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1247 EXPECT(0 == gpt->modified);
1248 /* Marking it bad also does not update it. */
1249 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1250 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1251 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1252 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1253 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001254
Randall Spanglere9213a72013-01-24 11:19:55 -08001255 /* Kernel with tries */
1256 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1257 EXPECT(KERNEL_B == gpt->current_kernel);
1258 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1259 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1260 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1261 /* Marking it bad clears it */
1262 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1263 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1264 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1265 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1266 /* Which affects both copies of the partition entries */
1267 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1268 EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1269 EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1270 /* And that's caused the GPT to need updating */
1271 EXPECT(0x0F == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001272
Randall Spanglere9213a72013-01-24 11:19:55 -08001273 /* Another kernel with tries */
1274 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1275 EXPECT(KERNEL_X == gpt->current_kernel);
1276 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1277 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1278 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1279 /* Trying it uses up a try */
1280 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1281 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1282 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1283 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1284 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1285 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1286 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1287 /* Trying it again marks it inactive */
1288 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1289 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1290 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1291 EXPECT(0 == GetEntryTries(e + KERNEL_X));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001292
Randall Spangler0bda13f2013-01-24 12:25:26 -08001293 /* Can't update if entry isn't a kernel, or there isn't an entry */
1294 Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
1295 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1296 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1297 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1298 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1299 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1300
1301
Randall Spanglere9213a72013-01-24 11:19:55 -08001302 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001303}
1304
Randall Spanglere9213a72013-01-24 11:19:55 -08001305/*
1306 * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1307 * GPT_ERROR_INVALID_UPDATE_TYPE.
1308 */
1309static int UpdateInvalidKernelTypeTest(void)
1310{
1311 GptData *gpt = GetEmptyGptData();
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001312
Randall Spanglere9213a72013-01-24 11:19:55 -08001313 BuildTestGptData(gpt);
1314 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1315 gpt->current_kernel = 0;
1316 /* any invalid update_type value */
1317 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1318 GptUpdateKernelEntry(gpt, 99));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001319
Randall Spanglere9213a72013-01-24 11:19:55 -08001320 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001321}
1322
Randall Spanglere9213a72013-01-24 11:19:55 -08001323/* Test duplicate UniqueGuids can be detected. */
1324static int DuplicateUniqueGuidTest(void)
1325{
1326 GptData *gpt = GetEmptyGptData();
1327 GptHeader *h = (GptHeader *)gpt->primary_header;
1328 GptEntry *e = (GptEntry *)gpt->primary_entries;
1329 int i, j;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001330
Randall Spanglere9213a72013-01-24 11:19:55 -08001331 struct {
1332 int duplicate;
1333 struct {
1334 uint64_t starting_lba;
1335 uint64_t ending_lba;
1336 uint32_t type_guid;
1337 uint32_t unique_guid;
1338 } entries[16]; /* enough for testing. */
1339 } cases[] = {
1340 {GPT_SUCCESS, {{100, 109, 1, 1},
1341 {110, 119, 2, 2},
1342 {120, 129, 3, 3},
1343 {130, 139, 4, 4},
1344 }},
1345 {GPT_SUCCESS, {{100, 109, 1, 1},
1346 {110, 119, 1, 2},
1347 {120, 129, 2, 3},
1348 {130, 139, 2, 4},
1349 }},
1350 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1351 {110, 119, 2, 2},
1352 {120, 129, 3, 1},
1353 {130, 139, 4, 4},
1354 }},
1355 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1356 {110, 119, 1, 2},
1357 {120, 129, 2, 3},
1358 {130, 139, 2, 2},
1359 }},
1360 };
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001361
Randall Spanglere9213a72013-01-24 11:19:55 -08001362 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1363 BuildTestGptData(gpt);
1364 ZeroEntries(gpt);
1365 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1366 if (!cases[i].entries[j].starting_lba)
1367 break;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001368
Randall Spanglere9213a72013-01-24 11:19:55 -08001369 e[j].starting_lba = cases[i].entries[j].starting_lba;
1370 e[j].ending_lba = cases[i].entries[j].ending_lba;
1371 SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1372 SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1373 }
1374 RefreshCrc32(gpt);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001375
Randall Spanglere9213a72013-01-24 11:19:55 -08001376 EXPECT(cases[i].duplicate == CheckEntries(e, h));
1377 }
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001378
Randall Spanglere9213a72013-01-24 11:19:55 -08001379 return TEST_OK;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001380}
1381
Randall Spangler0bda13f2013-01-24 12:25:26 -08001382/* Test getting the current kernel GUID */
1383static int GetKernelGuidTest(void)
1384{
1385 GptData *gpt = GetEmptyGptData();
1386 GptEntry *e = (GptEntry *)gpt->primary_entries;
1387 Guid g;
1388
1389 BuildTestGptData(gpt);
1390 gpt->current_kernel = 0;
1391 GetCurrentKernelUniqueGuid(gpt, &g);
1392 EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
1393 gpt->current_kernel = 1;
1394 GetCurrentKernelUniqueGuid(gpt, &g);
1395 EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
1396
1397 return TEST_OK;
1398}
1399
1400/* Test getting GPT error text strings */
1401static int ErrorTextTest(void)
1402{
1403 int i;
1404
1405 /* Known errors are not unknown */
1406 for (i = 0; i < GPT_ERROR_COUNT; i++) {
1407 EXPECT(GptErrorText(i));
1408 EXPECT(strcmp(GptErrorText(i), "Unknown"));
1409 }
1410
1411 /* But other error values are */
1412 EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
1413
1414 return TEST_OK;
1415}
1416
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001417static int CheckHeaderOffDevice()
1418{
1419 GptData* gpt = GetEmptyGptData();
1420 BuildTestGptData(gpt);
1421
1422 GptHeader* primary_header = (GptHeader*)gpt->primary_header;
1423 primary_header->first_usable_lba = 0;
1424 RefreshCrc32(gpt);
1425 // GPT is stored on the same device so first usable lba should not
1426 // start at 0.
1427 EXPECT(1 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001428 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001429 // But off device, it is okay to accept this GPT header.
1430 EXPECT(0 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001431 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001432
1433 BuildTestGptData(gpt);
1434 primary_header->number_of_entries = 100;
1435 RefreshCrc32(gpt);
1436 // Normally, number of entries is 128. So this should fail.
1437 EXPECT(1 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001438 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001439 // But off device, it is okay.
1440 EXPECT(0 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001441 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001442
1443 primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1444 RefreshCrc32(gpt);
1445 // However, too few entries is not good.
1446 EXPECT(1 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001447 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001448
1449 // Repeat for secondary header.
1450 BuildTestGptData(gpt);
1451 GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
1452 secondary_header->first_usable_lba = 0;
1453 RefreshCrc32(gpt);
1454 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001455 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001456 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001457 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001458
1459 BuildTestGptData(gpt);
1460 secondary_header->number_of_entries = 100;
1461 RefreshCrc32(gpt);
1462 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001463 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001464 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001465 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001466
1467 secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1468 RefreshCrc32(gpt);
1469 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001470 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001471
1472 return TEST_OK;
1473}
1474
Randall Spanglere9213a72013-01-24 11:19:55 -08001475int main(int argc, char *argv[])
1476{
1477 int i;
1478 int error_count = 0;
1479 struct {
1480 char *name;
1481 test_func fp;
1482 int retval;
1483 } test_cases[] = {
1484 { TEST_CASE(StructSizeTest), },
1485 { TEST_CASE(TestBuildTestGptData), },
1486 { TEST_CASE(ParameterTests), },
1487 { TEST_CASE(HeaderCrcTest), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001488 { TEST_CASE(HeaderSameTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001489 { TEST_CASE(SignatureTest), },
1490 { TEST_CASE(RevisionTest), },
1491 { TEST_CASE(SizeTest), },
1492 { TEST_CASE(CrcFieldTest), },
1493 { TEST_CASE(ReservedFieldsTest), },
1494 { TEST_CASE(SizeOfPartitionEntryTest), },
1495 { TEST_CASE(NumberOfPartitionEntriesTest), },
1496 { TEST_CASE(MyLbaTest), },
1497 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1498 { TEST_CASE(EntriesCrcTest), },
1499 { TEST_CASE(ValidEntryTest), },
1500 { TEST_CASE(OverlappedPartitionTest), },
1501 { TEST_CASE(SanityCheckTest), },
1502 { TEST_CASE(NoValidKernelEntryTest), },
1503 { TEST_CASE(EntryAttributeGetSetTest), },
1504 { TEST_CASE(EntryTypeTest), },
1505 { TEST_CASE(GetNextNormalTest), },
1506 { TEST_CASE(GetNextPrioTest), },
1507 { TEST_CASE(GetNextTriesTest), },
1508 { TEST_CASE(GptUpdateTest), },
1509 { TEST_CASE(UpdateInvalidKernelTypeTest), },
1510 { TEST_CASE(DuplicateUniqueGuidTest), },
1511 { TEST_CASE(TestCrc32TestVectors), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001512 { TEST_CASE(GetKernelGuidTest), },
1513 { TEST_CASE(ErrorTextTest), },
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001514 { TEST_CASE(CheckHeaderOffDevice), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001515 };
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001516
Randall Spanglere9213a72013-01-24 11:19:55 -08001517 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1518 printf("Running %s() ...\n", test_cases[i].name);
1519 test_cases[i].retval = test_cases[i].fp();
1520 if (test_cases[i].retval) {
1521 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1522 ++error_count;
1523 } else {
1524 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1525 }
1526 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001527
Randall Spanglere9213a72013-01-24 11:19:55 -08001528 if (error_count) {
1529 printf("\n------------------------------------------------\n");
1530 printf(COL_RED "The following %d test cases are failed:\n"
1531 COL_STOP, error_count);
1532 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1533 if (test_cases[i].retval)
1534 printf(" %s()\n", test_cases[i].name);
1535 }
1536 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001537
Randall Spanglere9213a72013-01-24 11:19:55 -08001538 return error_count ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001539}