blob: 759fa500ebcc5000441507ed5677915d06c5ec15 [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;
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800152 gpt->streaming_drive_sectors =
153 gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
Randall Spanglere9213a72013-01-24 11:19:55 -0800154 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
155 gpt->valid_headers = MASK_BOTH;
156 gpt->valid_entries = MASK_BOTH;
157 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700158
Randall Spanglere9213a72013-01-24 11:19:55 -0800159 /* Build primary */
160 header = (GptHeader *)gpt->primary_header;
161 entries = (GptEntry *)gpt->primary_entries;
162 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
163 sizeof(GPT_HEADER_SIGNATURE));
164 header->revision = GPT_HEADER_REVISION;
165 header->size = sizeof(GptHeader);
166 header->reserved_zero = 0;
167 header->my_lba = 1;
168 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
169 header->first_usable_lba = 34;
170 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
171 header->entries_lba = 2;
172 /* 512B / 128B * 32sectors = 128 entries */
173 header->number_of_entries = 128;
174 header->size_of_entry = 128; /* bytes */
175 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
176 SetGuid(&entries[0].unique, 0);
177 entries[0].starting_lba = 34;
178 entries[0].ending_lba = 133;
179 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
180 SetGuid(&entries[1].unique, 1);
181 entries[1].starting_lba = 134;
182 entries[1].ending_lba = 232;
183 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
184 SetGuid(&entries[2].unique, 2);
185 entries[2].starting_lba = 234;
186 entries[2].ending_lba = 331;
187 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
188 SetGuid(&entries[3].unique, 3);
189 entries[3].starting_lba = 334;
190 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700191
Randall Spanglere9213a72013-01-24 11:19:55 -0800192 /* Build secondary */
193 header2 = (GptHeader *)gpt->secondary_header;
194 entries2 = (GptEntry *)gpt->secondary_entries;
195 Memcpy(header2, header, sizeof(GptHeader));
196 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
197 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
198 header2->alternate_lba = 1;
199 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700200
Randall Spanglere9213a72013-01-24 11:19:55 -0800201 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700202}
203
Randall Spanglere9213a72013-01-24 11:19:55 -0800204/*
205 * Test if the structures are the expected size; if this fails, struct packing
206 * is not working properly.
207 */
208static int StructSizeTest(void)
209{
Randall Spangler81d09962010-06-23 10:15:38 -0700210
Randall Spanglere9213a72013-01-24 11:19:55 -0800211 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
212 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
213 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
214 return TEST_OK;
Randall Spangler81d09962010-06-23 10:15:38 -0700215}
216
217
Randall Spanglere9213a72013-01-24 11:19:55 -0800218/* Test if the default structure returned by BuildTestGptData() is good. */
219static int TestBuildTestGptData(void)
220{
221 GptData *gpt;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700222
Randall Spanglere9213a72013-01-24 11:19:55 -0800223 gpt = GetEmptyGptData();
224 BuildTestGptData(gpt);
225 EXPECT(GPT_SUCCESS == GptInit(gpt));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800226 gpt->sector_bytes = 0;
227 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
Randall Spanglere9213a72013-01-24 11:19:55 -0800228 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700229}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700230
Randall Spanglere9213a72013-01-24 11:19:55 -0800231/*
232 * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
233 * Currently we only support 512 bytes per sector. In the future, we may
234 * support other sizes. A too small drive_sectors should be rejected by
235 * GptInit().
236 */
237static int ParameterTests(void)
238{
239 GptData *gpt;
240 struct {
241 uint32_t sector_bytes;
242 uint64_t drive_sectors;
243 int expected_retval;
244 } cases[] = {
245 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
246 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
247 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
248 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
Nam T. Nguyen88458d92014-08-28 10:58:47 -0700249 {512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
Nam T. Nguyen32004012014-12-12 09:38:35 -0800250 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
Randall Spanglere9213a72013-01-24 11:19:55 -0800251 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
252 };
253 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700254
Randall Spanglere9213a72013-01-24 11:19:55 -0800255 gpt = GetEmptyGptData();
256 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
257 BuildTestGptData(gpt);
258 gpt->sector_bytes = cases[i].sector_bytes;
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800259 gpt->streaming_drive_sectors =
260 gpt->gpt_drive_sectors = cases[i].drive_sectors;
Randall Spanglere9213a72013-01-24 11:19:55 -0800261 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
262 }
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700263
Randall Spanglere9213a72013-01-24 11:19:55 -0800264 return TEST_OK;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700265}
266
Randall Spanglere9213a72013-01-24 11:19:55 -0800267/* Test if header CRC in two copies are calculated. */
268static int HeaderCrcTest(void)
269{
270 GptData *gpt = GetEmptyGptData();
271 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700272
Randall Spanglere9213a72013-01-24 11:19:55 -0800273 BuildTestGptData(gpt);
274 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700275
Randall Spanglere9213a72013-01-24 11:19:55 -0800276 /* CRC covers first byte of header */
277 BuildTestGptData(gpt);
278 gpt->primary_header[0] ^= 0xa5;
279 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700280
Randall Spanglere9213a72013-01-24 11:19:55 -0800281 /* CRC covers last byte of header */
282 BuildTestGptData(gpt);
283 gpt->primary_header[h1->size - 1] ^= 0x5a;
284 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700285
Randall Spanglere9213a72013-01-24 11:19:55 -0800286 /* CRC only covers header */
287 BuildTestGptData(gpt);
288 gpt->primary_header[h1->size] ^= 0x5a;
289 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700290
Randall Spanglere9213a72013-01-24 11:19:55 -0800291 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700292}
293
Randall Spangler0bda13f2013-01-24 12:25:26 -0800294/* Test if header-same comparison works. */
295static int HeaderSameTest(void)
296{
297 GptData *gpt = GetEmptyGptData();
298 GptHeader *h1 = (GptHeader *)gpt->primary_header;
299 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
300 GptHeader h3;
301
302 EXPECT(0 == HeaderFieldsSame(h1, h2));
303
304 Memcpy(&h3, h2, sizeof(h3));
305 h3.signature[0] ^= 0xba;
306 EXPECT(1 == HeaderFieldsSame(h1, &h3));
307
308 Memcpy(&h3, h2, sizeof(h3));
309 h3.revision++;
310 EXPECT(1 == HeaderFieldsSame(h1, &h3));
311
312 Memcpy(&h3, h2, sizeof(h3));
313 h3.size++;
314 EXPECT(1 == HeaderFieldsSame(h1, &h3));
315
316 Memcpy(&h3, h2, sizeof(h3));
317 h3.reserved_zero++;
318 EXPECT(1 == HeaderFieldsSame(h1, &h3));
319
320 Memcpy(&h3, h2, sizeof(h3));
321 h3.first_usable_lba++;
322 EXPECT(1 == HeaderFieldsSame(h1, &h3));
323
324 Memcpy(&h3, h2, sizeof(h3));
325 h3.last_usable_lba++;
326 EXPECT(1 == HeaderFieldsSame(h1, &h3));
327
328 Memcpy(&h3, h2, sizeof(h3));
329 h3.disk_uuid.u.raw[0] ^= 0xba;
330 EXPECT(1 == HeaderFieldsSame(h1, &h3));
331
332 Memcpy(&h3, h2, sizeof(h3));
333 h3.number_of_entries++;
334 EXPECT(1 == HeaderFieldsSame(h1, &h3));
335
336 Memcpy(&h3, h2, sizeof(h3));
337 h3.size_of_entry++;
338 EXPECT(1 == HeaderFieldsSame(h1, &h3));
339
340 Memcpy(&h3, h2, sizeof(h3));
341 h3.entries_crc32++;
342 EXPECT(1 == HeaderFieldsSame(h1, &h3));
343
344 return TEST_OK;
345}
346
Randall Spanglere9213a72013-01-24 11:19:55 -0800347/* Test if signature ("EFI PART") is checked. */
348static int SignatureTest(void)
349{
350 GptData *gpt = GetEmptyGptData();
351 GptHeader *h1 = (GptHeader *)gpt->primary_header;
352 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
353 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700354
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800355 EXPECT(1 == CheckHeader(NULL, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800356
Randall Spanglere9213a72013-01-24 11:19:55 -0800357 for (i = 0; i < 8; ++i) {
358 BuildTestGptData(gpt);
359 h1->signature[i] ^= 0xff;
360 h2->signature[i] ^= 0xff;
361 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800362 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
363 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800364 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700365
Randall Spanglere9213a72013-01-24 11:19:55 -0800366 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700367}
368
Randall Spanglere9213a72013-01-24 11:19:55 -0800369/*
370 * The revision we currently support is GPT_HEADER_REVISION. If the revision
371 * in header is not that, we expect the header is invalid.
372 */
373static int RevisionTest(void)
374{
375 GptData *gpt = GetEmptyGptData();
376 GptHeader *h1 = (GptHeader *)gpt->primary_header;
377 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
378 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700379
Randall Spanglere9213a72013-01-24 11:19:55 -0800380 struct {
381 uint32_t value_to_test;
382 int expect_rv;
383 } cases[] = {
384 {0x01000000, 1},
385 {0x00010000, 0}, /* GPT_HEADER_REVISION */
386 {0x00000100, 1},
387 {0x00000001, 1},
388 {0x23010456, 1},
389 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700390
Randall Spanglere9213a72013-01-24 11:19:55 -0800391 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
392 BuildTestGptData(gpt);
393 h1->revision = cases[i].value_to_test;
394 h2->revision = cases[i].value_to_test;
395 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700396
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800397 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800398 cases[i].expect_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800399 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800400 cases[i].expect_rv);
401 }
402 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700403}
404
Randall Spanglere9213a72013-01-24 11:19:55 -0800405static int SizeTest(void)
406{
407 GptData *gpt = GetEmptyGptData();
408 GptHeader *h1 = (GptHeader *)gpt->primary_header;
409 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
410 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700411
Randall Spanglere9213a72013-01-24 11:19:55 -0800412 struct {
413 uint32_t value_to_test;
414 int expect_rv;
415 } cases[] = {
416 {91, 1},
417 {92, 0},
418 {93, 0},
419 {511, 0},
420 {512, 0},
421 {513, 1},
422 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700423
Randall Spanglere9213a72013-01-24 11:19:55 -0800424 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
425 BuildTestGptData(gpt);
426 h1->size = cases[i].value_to_test;
427 h2->size = cases[i].value_to_test;
428 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700429
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800430 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800431 cases[i].expect_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800432 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800433 cases[i].expect_rv);
434 }
435 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700436}
437
Randall Spanglere9213a72013-01-24 11:19:55 -0800438/* Test if CRC is checked. */
439static int CrcFieldTest(void)
440{
441 GptData *gpt = GetEmptyGptData();
442 GptHeader *h1 = (GptHeader *)gpt->primary_header;
443 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700444
Randall Spanglere9213a72013-01-24 11:19:55 -0800445 BuildTestGptData(gpt);
446 /* Modify a field that the header verification doesn't care about */
447 h1->entries_crc32++;
448 h2->entries_crc32++;
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800449 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
450 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800451 /* Refresh the CRC; should pass now */
452 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800453 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
454 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700455
Randall Spanglere9213a72013-01-24 11:19:55 -0800456 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700457}
458
Randall Spanglere9213a72013-01-24 11:19:55 -0800459/* Test if reserved fields are checked. We'll try non-zero values to test. */
460static int ReservedFieldsTest(void)
461{
462 GptData *gpt = GetEmptyGptData();
463 GptHeader *h1 = (GptHeader *)gpt->primary_header;
464 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700465
Randall Spanglere9213a72013-01-24 11:19:55 -0800466 BuildTestGptData(gpt);
467 h1->reserved_zero ^= 0x12345678; /* whatever random */
468 h2->reserved_zero ^= 0x12345678; /* whatever random */
469 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800470 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
471 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700472
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700473#ifdef PADDING_CHECKED
Randall Spanglere9213a72013-01-24 11:19:55 -0800474 /* TODO: padding check is currently disabled */
475 BuildTestGptData(gpt);
476 h1->padding[12] ^= 0x34; /* whatever random */
477 h2->padding[56] ^= 0x78; /* whatever random */
478 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800479 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
480 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700481#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700482
Randall Spanglere9213a72013-01-24 11:19:55 -0800483 return TEST_OK;
484}
485
486/*
487 * Technically, any size which is 2^N where N > 6 should work, but our
488 * library only supports one size.
489 */
490static int SizeOfPartitionEntryTest(void) {
491 GptData *gpt = GetEmptyGptData();
492 GptHeader *h1 = (GptHeader *)gpt->primary_header;
493 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
494 int i;
495
496 struct {
497 uint32_t value_to_test;
498 int expect_rv;
499 } cases[] = {
500 {127, 1},
501 {128, 0},
502 {129, 1},
503 {256, 1},
504 {512, 1},
505 };
506
507 /* Check size of entryes */
508 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
509 BuildTestGptData(gpt);
510 h1->size_of_entry = cases[i].value_to_test;
511 h2->size_of_entry = cases[i].value_to_test;
512 h1->number_of_entries = TOTAL_ENTRIES_SIZE /
513 cases[i].value_to_test;
514 h2->number_of_entries = TOTAL_ENTRIES_SIZE /
515 cases[i].value_to_test;
516 RefreshCrc32(gpt);
517
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800518 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800519 cases[i].expect_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800520 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800521 cases[i].expect_rv);
522 }
523
524 return TEST_OK;
525}
526
527/*
528 * Technically, any size which is 2^N where N > 6 should work, but our library
529 * only supports one size.
530 */
531static int NumberOfPartitionEntriesTest(void)
532{
533 GptData *gpt = GetEmptyGptData();
534 GptHeader *h1 = (GptHeader *)gpt->primary_header;
535 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
536
537 BuildTestGptData(gpt);
538 h1->number_of_entries--;
539 h2->number_of_entries /= 2;
Nam T. Nguyen32004012014-12-12 09:38:35 -0800540 /* Because we halved h2 entries, its entries_lba is going to change. */
541 h2->entries_lba = h2->my_lba - CalculateEntriesSectors(h2);
Randall Spanglere9213a72013-01-24 11:19:55 -0800542 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800543 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
544 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700545 /* But it's okay to have less if the GPT structs are stored elsewhere. */
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800546 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
547 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Randall Spanglere9213a72013-01-24 11:19:55 -0800548
549 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700550}
551
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700552
Randall Spanglere9213a72013-01-24 11:19:55 -0800553/* Test if myLBA field is checked (1 for primary, last for secondary). */
554static int MyLbaTest(void)
555{
556 GptData *gpt = GetEmptyGptData();
557 GptHeader *h1 = (GptHeader *)gpt->primary_header;
558 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700559
Randall Spanglere9213a72013-01-24 11:19:55 -0800560 /* myLBA depends on primary vs secondary flag */
561 BuildTestGptData(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800562 EXPECT(1 == CheckHeader(h1, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
563 EXPECT(1 == CheckHeader(h2, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700564
Randall Spanglere9213a72013-01-24 11:19:55 -0800565 BuildTestGptData(gpt);
566 h1->my_lba--;
567 h2->my_lba--;
568 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800569 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
570 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700571
Randall Spanglere9213a72013-01-24 11:19:55 -0800572 BuildTestGptData(gpt);
573 h1->my_lba = 2;
574 h2->my_lba--;
575 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800576 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
577 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700578
Randall Spanglere9213a72013-01-24 11:19:55 -0800579 /* We should ignore the alternate_lba field entirely */
580 BuildTestGptData(gpt);
581 h1->alternate_lba++;
582 h2->alternate_lba++;
583 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800584 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
585 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800586
587 BuildTestGptData(gpt);
588 h1->alternate_lba--;
589 h2->alternate_lba--;
590 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800591 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
592 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800593
594 BuildTestGptData(gpt);
595 h1->entries_lba++;
596 h2->entries_lba++;
597 RefreshCrc32(gpt);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700598 /*
599 * We support a padding between primary GPT header and its entries. So
600 * this still passes.
601 */
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800602 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700603 /*
604 * But the secondary table should fail because it would overlap the
605 * header, which is now lying after its entry array.
606 */
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800607 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800608
609 BuildTestGptData(gpt);
610 h1->entries_lba--;
611 h2->entries_lba--;
612 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800613 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
614 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800615
616 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700617}
618
Randall Spanglere9213a72013-01-24 11:19:55 -0800619/* Test if FirstUsableLBA and LastUsableLBA are checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700620 * FirstUsableLBA must be after the end of the primary GPT table array.
621 * LastUsableLBA must be before the start of the secondary GPT table array.
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700622 * FirstUsableLBA <= LastUsableLBA.
623 * Also see CheckHeaderOffDevice() test. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800624static int FirstUsableLbaAndLastUsableLbaTest(void)
625{
626 GptData *gpt = GetEmptyGptData();
627 GptHeader *h1 = (GptHeader *)gpt->primary_header;
628 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
629 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700630
Randall Spanglere9213a72013-01-24 11:19:55 -0800631 struct {
632 uint64_t primary_entries_lba;
633 uint64_t primary_first_usable_lba;
634 uint64_t primary_last_usable_lba;
635 uint64_t secondary_first_usable_lba;
636 uint64_t secondary_last_usable_lba;
637 uint64_t secondary_entries_lba;
638 int primary_rv;
639 int secondary_rv;
640 } cases[] = {
641 {2, 34, 433, 34, 433, 434, 0, 0},
642 {2, 34, 432, 34, 430, 434, 0, 0},
643 {2, 33, 433, 33, 433, 434, 1, 1},
644 {2, 34, 434, 34, 433, 434, 1, 0},
645 {2, 34, 433, 34, 434, 434, 0, 1},
646 {2, 35, 433, 35, 433, 434, 0, 0},
647 {2, 433, 433, 433, 433, 434, 0, 0},
648 {2, 434, 433, 434, 434, 434, 1, 1},
649 {2, 433, 34, 34, 433, 434, 1, 0},
650 {2, 34, 433, 433, 34, 434, 0, 1},
651 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700652
Randall Spanglere9213a72013-01-24 11:19:55 -0800653 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
654 BuildTestGptData(gpt);
655 h1->entries_lba = cases[i].primary_entries_lba;
656 h1->first_usable_lba = cases[i].primary_first_usable_lba;
657 h1->last_usable_lba = cases[i].primary_last_usable_lba;
658 h2->entries_lba = cases[i].secondary_entries_lba;
659 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
660 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
661 RefreshCrc32(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700662
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800663 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800664 cases[i].primary_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800665 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800666 cases[i].secondary_rv);
667 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700668
Randall Spanglere9213a72013-01-24 11:19:55 -0800669 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700670}
671
Randall Spanglere9213a72013-01-24 11:19:55 -0800672/*
673 * Test if PartitionEntryArrayCRC32 is checked. PartitionEntryArrayCRC32 must
674 * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700675 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800676static int EntriesCrcTest(void)
677{
678 GptData *gpt = GetEmptyGptData();
679 GptHeader *h1 = (GptHeader *)gpt->primary_header;
680 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
681 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700682
Randall Spanglere9213a72013-01-24 11:19:55 -0800683 /* Modify first byte of primary entries, and expect the CRC is wrong. */
684 BuildTestGptData(gpt);
685 EXPECT(0 == CheckEntries(e1, h1));
686 EXPECT(0 == CheckEntries(e2, h1));
687 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
688 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
689 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
690 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700691
Randall Spanglere9213a72013-01-24 11:19:55 -0800692 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700693}
694
Randall Spanglere9213a72013-01-24 11:19:55 -0800695/*
696 * Test if partition geometry is checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700697 * All active (non-zero PartitionTypeGUID) partition entries should have:
698 * entry.StartingLBA >= header.FirstUsableLBA
699 * entry.EndingLBA <= header.LastUsableLBA
700 * entry.StartingLBA <= entry.EndingLBA
701 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800702static int ValidEntryTest(void)
703{
704 GptData *gpt = GetEmptyGptData();
705 GptHeader *h1 = (GptHeader *)gpt->primary_header;
706 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700707
Randall Spanglere9213a72013-01-24 11:19:55 -0800708 /* error case: entry.StartingLBA < header.FirstUsableLBA */
709 BuildTestGptData(gpt);
710 e1[0].starting_lba = h1->first_usable_lba - 1;
711 RefreshCrc32(gpt);
712 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700713
Randall Spanglere9213a72013-01-24 11:19:55 -0800714 /* error case: entry.EndingLBA > header.LastUsableLBA */
715 BuildTestGptData(gpt);
716 e1[2].ending_lba = h1->last_usable_lba + 1;
717 RefreshCrc32(gpt);
718 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700719
Randall Spanglere9213a72013-01-24 11:19:55 -0800720 /* error case: entry.StartingLBA > entry.EndingLBA */
721 BuildTestGptData(gpt);
722 e1[3].starting_lba = e1[3].ending_lba + 1;
723 RefreshCrc32(gpt);
724 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700725
Randall Spanglere9213a72013-01-24 11:19:55 -0800726 /* case: non active entry should be ignored. */
727 BuildTestGptData(gpt);
728 Memset(&e1[1].type, 0, sizeof(e1[1].type));
729 e1[1].starting_lba = e1[1].ending_lba + 1;
730 RefreshCrc32(gpt);
731 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700732
Randall Spanglere9213a72013-01-24 11:19:55 -0800733 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700734}
735
Randall Spanglere9213a72013-01-24 11:19:55 -0800736/* Test if overlapped partition tables can be detected. */
737static int OverlappedPartitionTest(void) {
738 GptData *gpt = GetEmptyGptData();
739 GptHeader *h = (GptHeader *)gpt->primary_header;
740 GptEntry *e = (GptEntry *)gpt->primary_entries;
741 int i, j;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700742
Randall Spanglere9213a72013-01-24 11:19:55 -0800743 struct {
744 int overlapped;
745 struct {
746 int active;
747 uint64_t starting_lba;
748 uint64_t ending_lba;
749 } entries[16]; /* enough for testing. */
750 } cases[] = {
751 {GPT_SUCCESS, {{0, 100, 199}}},
752 {GPT_SUCCESS, {{1, 100, 199}}},
753 {GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
754 {GPT_ERROR_START_LBA_OVERLAP,
755 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
756 {GPT_ERROR_END_LBA_OVERLAP,
757 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
758 {GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
759 {GPT_ERROR_END_LBA_OVERLAP,
760 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
761 {GPT_ERROR_START_LBA_OVERLAP,
762 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
763 {GPT_ERROR_START_LBA_OVERLAP,
764 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
765 {GPT_ERROR_END_LBA_OVERLAP,
766 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
767 {GPT_ERROR_START_LBA_OVERLAP,
768 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
769 {GPT_SUCCESS,
770 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
771 {GPT_ERROR_START_LBA_OVERLAP,
772 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
773 {GPT_ERROR_START_LBA_OVERLAP,
774 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
775 {GPT_SUCCESS,
776 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
777 {GPT_ERROR_END_LBA_OVERLAP,
778 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
779 {GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
780 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
781 {GPT_ERROR_START_LBA_OVERLAP,
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}, {1, 199, 199}}},
785 {GPT_SUCCESS,
786 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
787 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
788 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
789 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700790
Randall Spanglere9213a72013-01-24 11:19:55 -0800791 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
792 BuildTestGptData(gpt);
793 ZeroEntries(gpt);
794 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
795 if (!cases[i].entries[j].starting_lba)
796 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700797
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700798 if (cases[i].entries[j].active) {
Randall Spanglere9213a72013-01-24 11:19:55 -0800799 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700800 }
Randall Spanglere9213a72013-01-24 11:19:55 -0800801 SetGuid(&e[j].unique, j);
802 e[j].starting_lba = cases[i].entries[j].starting_lba;
803 e[j].ending_lba = cases[i].entries[j].ending_lba;
804 }
805 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700806
Randall Spanglere9213a72013-01-24 11:19:55 -0800807 EXPECT(cases[i].overlapped == CheckEntries(e, h));
808 }
809 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700810}
811
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700812/* Test both sanity checking and repair. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800813static int SanityCheckTest(void)
814{
815 GptData *gpt = GetEmptyGptData();
816 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler0bda13f2013-01-24 12:25:26 -0800817 GptEntry *e1 = (GptEntry *)gpt->primary_entries;
818 uint8_t *tempptr;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700819
Randall Spanglere9213a72013-01-24 11:19:55 -0800820 /* Unmodified test data is completely sane */
821 BuildTestGptData(gpt);
822 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
823 EXPECT(MASK_BOTH == gpt->valid_headers);
824 EXPECT(MASK_BOTH == gpt->valid_entries);
825 /* Repair doesn't damage it */
826 GptRepair(gpt);
827 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
828 EXPECT(MASK_BOTH == gpt->valid_headers);
829 EXPECT(MASK_BOTH == gpt->valid_entries);
830 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700831
Randall Spangler0bda13f2013-01-24 12:25:26 -0800832 /* Invalid sector size should fail */
833 BuildTestGptData(gpt);
834 gpt->sector_bytes = 1024;
835 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
836
Randall Spanglere9213a72013-01-24 11:19:55 -0800837 /* Modify headers */
838 BuildTestGptData(gpt);
839 gpt->primary_header[0]++;
840 gpt->secondary_header[0]++;
841 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
842 EXPECT(0 == gpt->valid_headers);
843 EXPECT(0 == gpt->valid_entries);
844 /* Repair can't fix completely busted headers */
845 GptRepair(gpt);
846 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
847 EXPECT(0 == gpt->valid_headers);
848 EXPECT(0 == gpt->valid_entries);
849 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700850
Randall Spanglere9213a72013-01-24 11:19:55 -0800851 BuildTestGptData(gpt);
852 gpt->primary_header[0]++;
853 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
854 EXPECT(MASK_SECONDARY == gpt->valid_headers);
855 EXPECT(MASK_BOTH == gpt->valid_entries);
856 GptRepair(gpt);
857 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
858 EXPECT(MASK_BOTH == gpt->valid_headers);
859 EXPECT(MASK_BOTH == gpt->valid_entries);
860 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700861
Randall Spanglere9213a72013-01-24 11:19:55 -0800862 BuildTestGptData(gpt);
863 gpt->secondary_header[0]++;
864 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
865 EXPECT(MASK_PRIMARY == gpt->valid_headers);
866 EXPECT(MASK_BOTH == gpt->valid_entries);
867 GptRepair(gpt);
868 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
869 EXPECT(MASK_BOTH == gpt->valid_headers);
870 EXPECT(MASK_BOTH == gpt->valid_entries);
871 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700872
Randall Spanglere9213a72013-01-24 11:19:55 -0800873 /*
874 * Modify header1 and update its CRC. Since header2 is now different
875 * than header1, it'll be the one considered invalid.
876 */
877 BuildTestGptData(gpt);
878 h1->size++;
879 RefreshCrc32(gpt);
880 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
881 EXPECT(MASK_PRIMARY == gpt->valid_headers);
882 EXPECT(MASK_BOTH == gpt->valid_entries);
883 GptRepair(gpt);
884 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
885 EXPECT(MASK_BOTH == gpt->valid_headers);
886 EXPECT(MASK_BOTH == gpt->valid_entries);
887 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700888
Randall Spanglere9213a72013-01-24 11:19:55 -0800889 /* Modify entries */
890 BuildTestGptData(gpt);
891 gpt->primary_entries[0]++;
892 gpt->secondary_entries[0]++;
893 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
894 EXPECT(MASK_BOTH == gpt->valid_headers);
895 EXPECT(MASK_NONE == gpt->valid_entries);
896 /* Repair can't fix both copies of entries being bad, either. */
897 GptRepair(gpt);
898 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
899 EXPECT(MASK_BOTH == gpt->valid_headers);
900 EXPECT(MASK_NONE == gpt->valid_entries);
901 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700902
Randall Spanglere9213a72013-01-24 11:19:55 -0800903 BuildTestGptData(gpt);
904 gpt->primary_entries[0]++;
905 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
906 EXPECT(MASK_BOTH == gpt->valid_headers);
907 EXPECT(MASK_SECONDARY == gpt->valid_entries);
908 GptRepair(gpt);
909 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
910 EXPECT(MASK_BOTH == gpt->valid_headers);
911 EXPECT(MASK_BOTH == gpt->valid_entries);
912 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700913
Randall Spanglere9213a72013-01-24 11:19:55 -0800914 BuildTestGptData(gpt);
915 gpt->secondary_entries[0]++;
916 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
917 EXPECT(MASK_BOTH == gpt->valid_headers);
918 EXPECT(MASK_PRIMARY == gpt->valid_entries);
919 GptRepair(gpt);
920 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
921 EXPECT(MASK_BOTH == gpt->valid_headers);
922 EXPECT(MASK_BOTH == gpt->valid_entries);
923 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700924
Randall Spangler0bda13f2013-01-24 12:25:26 -0800925 /*
926 * Modify entries and recompute CRCs, then make both primary and
927 * secondary entry pointers use the secondary data. The primary
928 * header will have the wrong entries CRC, so we should fall back
929 * to the secondary header.
930 */
931 BuildTestGptData(gpt);
932 e1->starting_lba++;
933 RefreshCrc32(gpt);
934 tempptr = gpt->primary_entries;
935 gpt->primary_entries = gpt->secondary_entries;
936 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
937 EXPECT(MASK_SECONDARY == gpt->valid_headers);
938 EXPECT(MASK_BOTH == gpt->valid_entries);
939 gpt->primary_entries = tempptr;
940
Randall Spanglere9213a72013-01-24 11:19:55 -0800941 /* Modify both header and entries */
942 BuildTestGptData(gpt);
943 gpt->primary_header[0]++;
944 gpt->primary_entries[0]++;
945 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
946 EXPECT(MASK_SECONDARY == gpt->valid_headers);
947 EXPECT(MASK_SECONDARY == gpt->valid_entries);
948 GptRepair(gpt);
949 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
950 EXPECT(MASK_BOTH == gpt->valid_headers);
951 EXPECT(MASK_BOTH == gpt->valid_entries);
952 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700953
Randall Spanglere9213a72013-01-24 11:19:55 -0800954 BuildTestGptData(gpt);
955 gpt->secondary_header[0]++;
956 gpt->secondary_entries[0]++;
957 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
958 EXPECT(MASK_PRIMARY == gpt->valid_headers);
959 EXPECT(MASK_PRIMARY == gpt->valid_entries);
960 GptRepair(gpt);
961 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
962 EXPECT(MASK_BOTH == gpt->valid_headers);
963 EXPECT(MASK_BOTH == gpt->valid_entries);
964 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700965
Randall Spanglere9213a72013-01-24 11:19:55 -0800966 /* Test cross-correction (h1+e2, h2+e1) */
967 BuildTestGptData(gpt);
968 gpt->primary_header[0]++;
969 gpt->secondary_entries[0]++;
970 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
971 EXPECT(MASK_SECONDARY == gpt->valid_headers);
972 EXPECT(MASK_PRIMARY == gpt->valid_entries);
973 GptRepair(gpt);
974 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
975 EXPECT(MASK_BOTH == gpt->valid_headers);
976 EXPECT(MASK_BOTH == gpt->valid_entries);
977 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700978
Randall Spanglere9213a72013-01-24 11:19:55 -0800979 BuildTestGptData(gpt);
980 gpt->secondary_header[0]++;
981 gpt->primary_entries[0]++;
982 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
983 EXPECT(MASK_PRIMARY == gpt->valid_headers);
984 EXPECT(MASK_SECONDARY == gpt->valid_entries);
985 GptRepair(gpt);
986 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
987 EXPECT(MASK_BOTH == gpt->valid_headers);
988 EXPECT(MASK_BOTH == gpt->valid_entries);
989 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700990
Randall Spanglere9213a72013-01-24 11:19:55 -0800991 /*
992 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different. This
993 * simulates a partial update of the drive.
994 */
995 BuildTestGptData(gpt);
996 gpt->secondary_entries[0]++;
997 RefreshCrc32(gpt);
998 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
999 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1000 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1001 GptRepair(gpt);
1002 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1003 EXPECT(MASK_BOTH == gpt->valid_headers);
1004 EXPECT(MASK_BOTH == gpt->valid_entries);
1005 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001006
Nam T. Nguyen5ce83252014-10-30 15:09:43 -07001007 /* Test unloaded entry array. */
1008 gpt = GetEmptyGptData();
1009 BuildTestGptData(gpt);
1010 gpt->primary_entries = NULL;
1011 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1012 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1013 gpt = GetEmptyGptData();
1014 BuildTestGptData(gpt);
1015 gpt->secondary_entries = NULL;
1016 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1017 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1018
1019 /* Test unloaded header. */
1020 gpt = GetEmptyGptData();
1021 BuildTestGptData(gpt);
1022 gpt->primary_header = NULL;
1023 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1024 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1025 gpt = GetEmptyGptData();
1026 BuildTestGptData(gpt);
1027 gpt->secondary_header = NULL;
1028 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1029 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1030
Randall Spanglere9213a72013-01-24 11:19:55 -08001031 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001032}
1033
Randall Spanglere9213a72013-01-24 11:19:55 -08001034static int EntryAttributeGetSetTest(void)
1035{
1036 GptData *gpt = GetEmptyGptData();
1037 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001038
Randall Spanglere9213a72013-01-24 11:19:55 -08001039 e->attrs.whole = 0x0000000000000000ULL;
1040 SetEntrySuccessful(e, 1);
1041 EXPECT(0x0100000000000000ULL == e->attrs.whole);
1042 EXPECT(1 == GetEntrySuccessful(e));
1043 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1044 SetEntrySuccessful(e, 0);
1045 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1046 EXPECT(0 == GetEntrySuccessful(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001047
Randall Spanglere9213a72013-01-24 11:19:55 -08001048 e->attrs.whole = 0x0000000000000000ULL;
1049 SetEntryTries(e, 15);
1050 EXPECT(15 == GetEntryTries(e));
1051 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1052 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1053 SetEntryTries(e, 0);
1054 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1055 EXPECT(0 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001056
Randall Spanglere9213a72013-01-24 11:19:55 -08001057 e->attrs.whole = 0x0000000000000000ULL;
1058 SetEntryPriority(e, 15);
1059 EXPECT(0x000F000000000000ULL == e->attrs.whole);
1060 EXPECT(15 == GetEntryPriority(e));
1061 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1062 SetEntryPriority(e, 0);
1063 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1064 EXPECT(0 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001065
Randall Spanglere9213a72013-01-24 11:19:55 -08001066 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1067 EXPECT(1 == GetEntrySuccessful(e));
1068 EXPECT(15 == GetEntryPriority(e));
1069 EXPECT(15 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001070
Randall Spanglere9213a72013-01-24 11:19:55 -08001071 e->attrs.whole = 0x0123000000000000ULL;
1072 EXPECT(1 == GetEntrySuccessful(e));
1073 EXPECT(2 == GetEntryTries(e));
1074 EXPECT(3 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001075
Randall Spanglere9213a72013-01-24 11:19:55 -08001076 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001077}
1078
Randall Spanglere9213a72013-01-24 11:19:55 -08001079static int EntryTypeTest(void)
1080{
1081 GptData *gpt = GetEmptyGptData();
1082 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001083
Randall Spanglere9213a72013-01-24 11:19:55 -08001084 Memcpy(&e->type, &guid_zero, sizeof(Guid));
1085 EXPECT(1 == IsUnusedEntry(e));
1086 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001087
Randall Spanglere9213a72013-01-24 11:19:55 -08001088 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1089 EXPECT(0 == IsUnusedEntry(e));
1090 EXPECT(1 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001091
Randall Spanglere9213a72013-01-24 11:19:55 -08001092 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1093 EXPECT(0 == IsUnusedEntry(e));
1094 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001095
Randall Spanglere9213a72013-01-24 11:19:55 -08001096 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001097}
1098
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001099/* Make an entry unused by clearing its type. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001100static void FreeEntry(GptEntry *e)
1101{
1102 Memset(&e->type, 0, sizeof(Guid));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001103}
1104
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001105/* Set up an entry. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001106static void FillEntry(GptEntry *e, int is_kernel,
1107 int priority, int successful, int tries)
1108{
1109 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1110 SetEntryPriority(e, priority);
1111 SetEntrySuccessful(e, successful);
1112 SetEntryTries(e, tries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001113}
1114
Randall Spanglere9213a72013-01-24 11:19:55 -08001115/*
1116 * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001117 * any usable kernel entry.
1118 */
Randall Spanglere9213a72013-01-24 11:19:55 -08001119static int NoValidKernelEntryTest(void)
1120{
1121 GptData *gpt = GetEmptyGptData();
1122 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001123
Randall Spanglere9213a72013-01-24 11:19:55 -08001124 BuildTestGptData(gpt);
1125 SetEntryPriority(e1 + KERNEL_A, 0);
1126 FreeEntry(e1 + KERNEL_B);
1127 RefreshCrc32(gpt);
1128 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1129 GptNextKernelEntry(gpt, NULL, NULL));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001130
Randall Spanglere9213a72013-01-24 11:19:55 -08001131 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001132}
1133
Randall Spanglere9213a72013-01-24 11:19:55 -08001134static int GetNextNormalTest(void)
1135{
1136 GptData *gpt = GetEmptyGptData();
1137 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1138 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001139
Randall Spanglere9213a72013-01-24 11:19:55 -08001140 /* Normal case - both kernels successful */
1141 BuildTestGptData(gpt);
1142 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1143 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1144 RefreshCrc32(gpt);
1145 GptInit(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001146
Randall Spanglere9213a72013-01-24 11:19:55 -08001147 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1148 EXPECT(KERNEL_A == gpt->current_kernel);
1149 EXPECT(34 == start);
1150 EXPECT(100 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001151
Randall Spanglere9213a72013-01-24 11:19:55 -08001152 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1153 EXPECT(KERNEL_B == gpt->current_kernel);
1154 EXPECT(134 == start);
1155 EXPECT(99 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001156
Randall Spanglere9213a72013-01-24 11:19:55 -08001157 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1158 GptNextKernelEntry(gpt, &start, &size));
1159 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001160
Randall Spanglere9213a72013-01-24 11:19:55 -08001161 /* Call as many times as you want; you won't get another kernel... */
1162 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1163 GptNextKernelEntry(gpt, &start, &size));
1164 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001165
Randall Spanglere9213a72013-01-24 11:19:55 -08001166 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001167}
1168
Randall Spanglere9213a72013-01-24 11:19:55 -08001169static int GetNextPrioTest(void)
1170{
1171 GptData *gpt = GetEmptyGptData();
1172 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1173 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001174
Randall Spanglere9213a72013-01-24 11:19:55 -08001175 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1176 BuildTestGptData(gpt);
1177 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1178 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1179 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1180 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1181 RefreshCrc32(gpt);
1182 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001183
Randall Spanglere9213a72013-01-24 11:19:55 -08001184 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1185 EXPECT(KERNEL_B == gpt->current_kernel);
1186 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1187 EXPECT(KERNEL_Y == gpt->current_kernel);
1188 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1189 EXPECT(KERNEL_A == gpt->current_kernel);
1190 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1191 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001192
Randall Spanglere9213a72013-01-24 11:19:55 -08001193 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001194}
1195
Randall Spanglere9213a72013-01-24 11:19:55 -08001196static int GetNextTriesTest(void)
1197{
1198 GptData *gpt = GetEmptyGptData();
1199 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1200 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001201
Randall Spanglere9213a72013-01-24 11:19:55 -08001202 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1203 BuildTestGptData(gpt);
1204 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1205 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1206 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1207 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1208 RefreshCrc32(gpt);
1209 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001210
Randall Spanglere9213a72013-01-24 11:19:55 -08001211 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1212 EXPECT(KERNEL_X == gpt->current_kernel);
1213 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1214 EXPECT(KERNEL_A == gpt->current_kernel);
1215 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1216 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001217
Randall Spanglere9213a72013-01-24 11:19:55 -08001218 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001219}
1220
Randall Spanglere9213a72013-01-24 11:19:55 -08001221static int GptUpdateTest(void)
1222{
1223 GptData *gpt = GetEmptyGptData();
1224 GptEntry *e = (GptEntry *)(gpt->primary_entries);
1225 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1226 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001227
Randall Spanglere9213a72013-01-24 11:19:55 -08001228 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1229 BuildTestGptData(gpt);
1230 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1231 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1232 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1233 RefreshCrc32(gpt);
1234 GptInit(gpt);
1235 gpt->modified = 0; /* Nothing modified yet */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001236
Randall Spanglere9213a72013-01-24 11:19:55 -08001237 /* Successful kernel */
1238 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1239 EXPECT(KERNEL_A == gpt->current_kernel);
1240 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1241 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1242 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1243 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1244 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1245 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1246 /* Trying successful kernel changes nothing */
1247 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1248 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1249 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1250 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1251 EXPECT(0 == gpt->modified);
1252 /* Marking it bad also does not update it. */
1253 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1254 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1255 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1256 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1257 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001258
Randall Spanglere9213a72013-01-24 11:19:55 -08001259 /* Kernel with tries */
1260 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1261 EXPECT(KERNEL_B == gpt->current_kernel);
1262 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1263 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1264 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1265 /* Marking it bad clears it */
1266 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1267 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1268 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1269 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1270 /* Which affects both copies of the partition entries */
1271 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1272 EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1273 EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1274 /* And that's caused the GPT to need updating */
1275 EXPECT(0x0F == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001276
Randall Spanglere9213a72013-01-24 11:19:55 -08001277 /* Another kernel with tries */
1278 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1279 EXPECT(KERNEL_X == gpt->current_kernel);
1280 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1281 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1282 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1283 /* Trying it uses up a try */
1284 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1285 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1286 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1287 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1288 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1289 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1290 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1291 /* Trying it again marks it inactive */
1292 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1293 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1294 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1295 EXPECT(0 == GetEntryTries(e + KERNEL_X));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001296
Randall Spangler0bda13f2013-01-24 12:25:26 -08001297 /* Can't update if entry isn't a kernel, or there isn't an entry */
1298 Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
1299 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1300 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1301 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1302 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1303 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1304
1305
Randall Spanglere9213a72013-01-24 11:19:55 -08001306 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001307}
1308
Randall Spanglere9213a72013-01-24 11:19:55 -08001309/*
1310 * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1311 * GPT_ERROR_INVALID_UPDATE_TYPE.
1312 */
1313static int UpdateInvalidKernelTypeTest(void)
1314{
1315 GptData *gpt = GetEmptyGptData();
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001316
Randall Spanglere9213a72013-01-24 11:19:55 -08001317 BuildTestGptData(gpt);
1318 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1319 gpt->current_kernel = 0;
1320 /* any invalid update_type value */
1321 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1322 GptUpdateKernelEntry(gpt, 99));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001323
Randall Spanglere9213a72013-01-24 11:19:55 -08001324 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001325}
1326
Randall Spanglere9213a72013-01-24 11:19:55 -08001327/* Test duplicate UniqueGuids can be detected. */
1328static int DuplicateUniqueGuidTest(void)
1329{
1330 GptData *gpt = GetEmptyGptData();
1331 GptHeader *h = (GptHeader *)gpt->primary_header;
1332 GptEntry *e = (GptEntry *)gpt->primary_entries;
1333 int i, j;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001334
Randall Spanglere9213a72013-01-24 11:19:55 -08001335 struct {
1336 int duplicate;
1337 struct {
1338 uint64_t starting_lba;
1339 uint64_t ending_lba;
1340 uint32_t type_guid;
1341 uint32_t unique_guid;
1342 } entries[16]; /* enough for testing. */
1343 } cases[] = {
1344 {GPT_SUCCESS, {{100, 109, 1, 1},
1345 {110, 119, 2, 2},
1346 {120, 129, 3, 3},
1347 {130, 139, 4, 4},
1348 }},
1349 {GPT_SUCCESS, {{100, 109, 1, 1},
1350 {110, 119, 1, 2},
1351 {120, 129, 2, 3},
1352 {130, 139, 2, 4},
1353 }},
1354 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1355 {110, 119, 2, 2},
1356 {120, 129, 3, 1},
1357 {130, 139, 4, 4},
1358 }},
1359 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1360 {110, 119, 1, 2},
1361 {120, 129, 2, 3},
1362 {130, 139, 2, 2},
1363 }},
1364 };
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001365
Randall Spanglere9213a72013-01-24 11:19:55 -08001366 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1367 BuildTestGptData(gpt);
1368 ZeroEntries(gpt);
1369 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1370 if (!cases[i].entries[j].starting_lba)
1371 break;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001372
Randall Spanglere9213a72013-01-24 11:19:55 -08001373 e[j].starting_lba = cases[i].entries[j].starting_lba;
1374 e[j].ending_lba = cases[i].entries[j].ending_lba;
1375 SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1376 SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1377 }
1378 RefreshCrc32(gpt);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001379
Randall Spanglere9213a72013-01-24 11:19:55 -08001380 EXPECT(cases[i].duplicate == CheckEntries(e, h));
1381 }
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001382
Randall Spanglere9213a72013-01-24 11:19:55 -08001383 return TEST_OK;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001384}
1385
Randall Spangler0bda13f2013-01-24 12:25:26 -08001386/* Test getting the current kernel GUID */
1387static int GetKernelGuidTest(void)
1388{
1389 GptData *gpt = GetEmptyGptData();
1390 GptEntry *e = (GptEntry *)gpt->primary_entries;
1391 Guid g;
1392
1393 BuildTestGptData(gpt);
1394 gpt->current_kernel = 0;
1395 GetCurrentKernelUniqueGuid(gpt, &g);
1396 EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
1397 gpt->current_kernel = 1;
1398 GetCurrentKernelUniqueGuid(gpt, &g);
1399 EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
1400
1401 return TEST_OK;
1402}
1403
1404/* Test getting GPT error text strings */
1405static int ErrorTextTest(void)
1406{
1407 int i;
1408
1409 /* Known errors are not unknown */
1410 for (i = 0; i < GPT_ERROR_COUNT; i++) {
1411 EXPECT(GptErrorText(i));
1412 EXPECT(strcmp(GptErrorText(i), "Unknown"));
1413 }
1414
1415 /* But other error values are */
1416 EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
1417
1418 return TEST_OK;
1419}
1420
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001421static int CheckHeaderOffDevice()
1422{
1423 GptData* gpt = GetEmptyGptData();
1424 BuildTestGptData(gpt);
1425
1426 GptHeader* primary_header = (GptHeader*)gpt->primary_header;
1427 primary_header->first_usable_lba = 0;
1428 RefreshCrc32(gpt);
1429 // GPT is stored on the same device so first usable lba should not
1430 // start at 0.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001431 EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1432 gpt->gpt_drive_sectors, 0));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001433 // But off device, it is okay to accept this GPT header.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001434 EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1435 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001436
1437 BuildTestGptData(gpt);
1438 primary_header->number_of_entries = 100;
1439 RefreshCrc32(gpt);
1440 // Normally, number of entries is 128. So this should fail.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001441 EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1442 gpt->gpt_drive_sectors, 0));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001443 // But off device, it is okay.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001444 EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1445 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001446
1447 primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1448 RefreshCrc32(gpt);
1449 // However, too few entries is not good.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001450 EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1451 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001452
1453 // Repeat for secondary header.
1454 BuildTestGptData(gpt);
1455 GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
1456 secondary_header->first_usable_lba = 0;
1457 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001458 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1459 gpt->gpt_drive_sectors, 0));
1460 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1461 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001462
1463 BuildTestGptData(gpt);
1464 secondary_header->number_of_entries = 100;
Nam T. Nguyen32004012014-12-12 09:38:35 -08001465 /* Because we change number of entries, we need to also update entrie_lba. */
1466 secondary_header->entries_lba = secondary_header->my_lba -
1467 CalculateEntriesSectors(secondary_header);
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001468 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001469 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1470 gpt->gpt_drive_sectors, 0));
1471 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1472 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001473
1474 secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1475 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001476 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1477 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001478
1479 return TEST_OK;
1480}
1481
Randall Spanglere9213a72013-01-24 11:19:55 -08001482int main(int argc, char *argv[])
1483{
1484 int i;
1485 int error_count = 0;
1486 struct {
1487 char *name;
1488 test_func fp;
1489 int retval;
1490 } test_cases[] = {
1491 { TEST_CASE(StructSizeTest), },
1492 { TEST_CASE(TestBuildTestGptData), },
1493 { TEST_CASE(ParameterTests), },
1494 { TEST_CASE(HeaderCrcTest), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001495 { TEST_CASE(HeaderSameTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001496 { TEST_CASE(SignatureTest), },
1497 { TEST_CASE(RevisionTest), },
1498 { TEST_CASE(SizeTest), },
1499 { TEST_CASE(CrcFieldTest), },
1500 { TEST_CASE(ReservedFieldsTest), },
1501 { TEST_CASE(SizeOfPartitionEntryTest), },
1502 { TEST_CASE(NumberOfPartitionEntriesTest), },
1503 { TEST_CASE(MyLbaTest), },
1504 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1505 { TEST_CASE(EntriesCrcTest), },
1506 { TEST_CASE(ValidEntryTest), },
1507 { TEST_CASE(OverlappedPartitionTest), },
1508 { TEST_CASE(SanityCheckTest), },
1509 { TEST_CASE(NoValidKernelEntryTest), },
1510 { TEST_CASE(EntryAttributeGetSetTest), },
1511 { TEST_CASE(EntryTypeTest), },
1512 { TEST_CASE(GetNextNormalTest), },
1513 { TEST_CASE(GetNextPrioTest), },
1514 { TEST_CASE(GetNextTriesTest), },
1515 { TEST_CASE(GptUpdateTest), },
1516 { TEST_CASE(UpdateInvalidKernelTypeTest), },
1517 { TEST_CASE(DuplicateUniqueGuidTest), },
1518 { TEST_CASE(TestCrc32TestVectors), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001519 { TEST_CASE(GetKernelGuidTest), },
1520 { TEST_CASE(ErrorTextTest), },
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001521 { TEST_CASE(CheckHeaderOffDevice), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001522 };
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001523
Randall Spanglere9213a72013-01-24 11:19:55 -08001524 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1525 printf("Running %s() ...\n", test_cases[i].name);
1526 test_cases[i].retval = test_cases[i].fp();
1527 if (test_cases[i].retval) {
1528 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1529 ++error_count;
1530 } else {
1531 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1532 }
1533 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001534
Randall Spanglere9213a72013-01-24 11:19:55 -08001535 if (error_count) {
1536 printf("\n------------------------------------------------\n");
1537 printf(COL_RED "The following %d test cases are failed:\n"
1538 COL_STOP, error_count);
1539 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1540 if (test_cases[i].retval)
1541 printf(" %s()\n", test_cases[i].name);
1542 }
1543 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001544
Randall Spanglere9213a72013-01-24 11:19:55 -08001545 return error_count ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001546}