blob: 13244a5654758c61722d2a7b2c06dcab7710b8d2 [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
Dan Ehrenbergf3f7fca2015-01-02 14:39:38 -080045#define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 16384 */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070046#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070047
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070048static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
49static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
50static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
51
Albert Chaulk534723a2013-03-20 14:46:50 -070052// cgpt_common.c requires these be defined if linked in.
53const char *progname = "CGPT-TEST";
54const char *command = "TEST";
55
Randall Spanglere9213a72013-01-24 11:19:55 -080056/*
57 * Copy a random-for-this-program-only Guid into the dest. The num parameter
Bill Richardsonaa8eda42010-08-27 09:31:26 -070058 * completely determines the Guid.
59 */
Randall Spanglere9213a72013-01-24 11:19:55 -080060static void SetGuid(void *dest, uint32_t num)
61{
62 Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,
63 {0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
64 Memcpy(dest, &g, sizeof(Guid));
Bill Richardsonaa8eda42010-08-27 09:31:26 -070065}
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070066
Randall Spanglere9213a72013-01-24 11:19:55 -080067/*
68 * Given a GptData pointer, first re-calculate entries CRC32 value, then reset
69 * header CRC32 value to 0, and calculate header CRC32 value. Both primary and
70 * secondary are updated.
71 */
72static void RefreshCrc32(GptData *gpt)
73{
74 GptHeader *header, *header2;
75 GptEntry *entries, *entries2;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070076
Randall Spanglere9213a72013-01-24 11:19:55 -080077 header = (GptHeader *)gpt->primary_header;
78 entries = (GptEntry *)gpt->primary_entries;
79 header2 = (GptHeader *)gpt->secondary_header;
80 entries2 = (GptEntry *)gpt->secondary_entries;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070081
Randall Spanglere9213a72013-01-24 11:19:55 -080082 header->entries_crc32 =
83 Crc32((uint8_t *)entries,
84 header->number_of_entries * header->size_of_entry);
85 header->header_crc32 = 0;
86 header->header_crc32 = Crc32((uint8_t *)header, header->size);
87 header2->entries_crc32 =
88 Crc32((uint8_t *)entries2,
89 header2->number_of_entries * header2->size_of_entry);
90 header2->header_crc32 = 0;
91 header2->header_crc32 = Crc32((uint8_t *)header2, header2->size);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070092}
93
Randall Spanglere9213a72013-01-24 11:19:55 -080094static void ZeroHeaders(GptData *gpt)
95{
96 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
97 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070098}
99
Randall Spanglere9213a72013-01-24 11:19:55 -0800100static void ZeroEntries(GptData *gpt)
101{
102 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
103 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700104}
105
Randall Spanglere9213a72013-01-24 11:19:55 -0800106static void ZeroHeadersEntries(GptData *gpt)
107{
108 ZeroHeaders(gpt);
109 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700110}
111
Randall Spanglere9213a72013-01-24 11:19:55 -0800112/*
113 * Return a pointer to a static GptData instance (no free is required).
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700114 * All fields are zero except 4 pointers linking to header and entries.
Randall Spanglere9213a72013-01-24 11:19:55 -0800115 * All content of headers and entries are zero.
116 */
117static GptData *GetEmptyGptData(void)
118{
119 static GptData gpt;
120 static uint8_t primary_header[MAX_SECTOR_SIZE];
121 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
122 static uint8_t secondary_header[MAX_SECTOR_SIZE];
123 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700124
Randall Spanglere9213a72013-01-24 11:19:55 -0800125 Memset(&gpt, 0, sizeof(gpt));
126 gpt.primary_header = primary_header;
127 gpt.primary_entries = primary_entries;
128 gpt.secondary_header = secondary_header;
129 gpt.secondary_entries = secondary_entries;
130 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700131
Randall Spanglere9213a72013-01-24 11:19:55 -0800132 /* Initialize GptData internal states. */
133 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700134
Randall Spanglere9213a72013-01-24 11:19:55 -0800135 return &gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700136}
137
Randall Spanglere9213a72013-01-24 11:19:55 -0800138/*
139 * Fill in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700140 * file. Before calling this function, primary/secondary header/entries must
141 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
142 * This function returns a good (valid) copy of GPT layout described in top of
Randall Spanglere9213a72013-01-24 11:19:55 -0800143 * this file.
144 */
145static void BuildTestGptData(GptData *gpt)
146{
147 GptHeader *header, *header2;
148 GptEntry *entries, *entries2;
149 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
150 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700151
Randall Spanglere9213a72013-01-24 11:19:55 -0800152 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800153 gpt->streaming_drive_sectors =
154 gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
Randall Spanglere9213a72013-01-24 11:19:55 -0800155 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
156 gpt->valid_headers = MASK_BOTH;
157 gpt->valid_entries = MASK_BOTH;
158 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700159
Randall Spanglere9213a72013-01-24 11:19:55 -0800160 /* Build primary */
161 header = (GptHeader *)gpt->primary_header;
162 entries = (GptEntry *)gpt->primary_entries;
163 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
164 sizeof(GPT_HEADER_SIGNATURE));
165 header->revision = GPT_HEADER_REVISION;
166 header->size = sizeof(GptHeader);
167 header->reserved_zero = 0;
168 header->my_lba = 1;
169 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
170 header->first_usable_lba = 34;
171 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
172 header->entries_lba = 2;
173 /* 512B / 128B * 32sectors = 128 entries */
174 header->number_of_entries = 128;
175 header->size_of_entry = 128; /* bytes */
176 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
177 SetGuid(&entries[0].unique, 0);
178 entries[0].starting_lba = 34;
179 entries[0].ending_lba = 133;
180 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
181 SetGuid(&entries[1].unique, 1);
182 entries[1].starting_lba = 134;
183 entries[1].ending_lba = 232;
184 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
185 SetGuid(&entries[2].unique, 2);
186 entries[2].starting_lba = 234;
187 entries[2].ending_lba = 331;
188 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
189 SetGuid(&entries[3].unique, 3);
190 entries[3].starting_lba = 334;
191 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700192
Randall Spanglere9213a72013-01-24 11:19:55 -0800193 /* Build secondary */
194 header2 = (GptHeader *)gpt->secondary_header;
195 entries2 = (GptEntry *)gpt->secondary_entries;
196 Memcpy(header2, header, sizeof(GptHeader));
197 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
198 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
199 header2->alternate_lba = 1;
200 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700201
Randall Spanglere9213a72013-01-24 11:19:55 -0800202 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700203}
204
Randall Spanglere9213a72013-01-24 11:19:55 -0800205/*
206 * Test if the structures are the expected size; if this fails, struct packing
207 * is not working properly.
208 */
209static int StructSizeTest(void)
210{
Randall Spangler81d09962010-06-23 10:15:38 -0700211
Randall Spanglere9213a72013-01-24 11:19:55 -0800212 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
213 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
214 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
215 return TEST_OK;
Randall Spangler81d09962010-06-23 10:15:38 -0700216}
217
218
Randall Spanglere9213a72013-01-24 11:19:55 -0800219/* Test if the default structure returned by BuildTestGptData() is good. */
220static int TestBuildTestGptData(void)
221{
222 GptData *gpt;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700223
Randall Spanglere9213a72013-01-24 11:19:55 -0800224 gpt = GetEmptyGptData();
225 BuildTestGptData(gpt);
226 EXPECT(GPT_SUCCESS == GptInit(gpt));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800227 gpt->sector_bytes = 0;
228 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
Randall Spanglere9213a72013-01-24 11:19:55 -0800229 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700230}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700231
Randall Spanglere9213a72013-01-24 11:19:55 -0800232/*
233 * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
234 * Currently we only support 512 bytes per sector. In the future, we may
235 * support other sizes. A too small drive_sectors should be rejected by
236 * GptInit().
237 */
238static int ParameterTests(void)
239{
240 GptData *gpt;
241 struct {
242 uint32_t sector_bytes;
243 uint64_t drive_sectors;
244 int expected_retval;
245 } cases[] = {
246 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
247 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
248 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
Dan Ehrenbergf3f7fca2015-01-02 14:39:38 -0800249 {512, 10, GPT_ERROR_INVALID_SECTOR_NUMBER},
Nam T. Nguyen88458d92014-08-28 10:58:47 -0700250 {512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
Nam T. Nguyen32004012014-12-12 09:38:35 -0800251 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
Randall Spanglere9213a72013-01-24 11:19:55 -0800252 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
253 };
254 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700255
Randall Spanglere9213a72013-01-24 11:19:55 -0800256 gpt = GetEmptyGptData();
257 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
258 BuildTestGptData(gpt);
259 gpt->sector_bytes = cases[i].sector_bytes;
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800260 gpt->streaming_drive_sectors =
261 gpt->gpt_drive_sectors = cases[i].drive_sectors;
Randall Spanglere9213a72013-01-24 11:19:55 -0800262 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
263 }
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700264
Randall Spanglere9213a72013-01-24 11:19:55 -0800265 return TEST_OK;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700266}
267
Randall Spanglere9213a72013-01-24 11:19:55 -0800268/* Test if header CRC in two copies are calculated. */
269static int HeaderCrcTest(void)
270{
271 GptData *gpt = GetEmptyGptData();
272 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700273
Randall Spanglere9213a72013-01-24 11:19:55 -0800274 BuildTestGptData(gpt);
275 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700276
Randall Spanglere9213a72013-01-24 11:19:55 -0800277 /* CRC covers first byte of header */
278 BuildTestGptData(gpt);
279 gpt->primary_header[0] ^= 0xa5;
280 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700281
Randall Spanglere9213a72013-01-24 11:19:55 -0800282 /* CRC covers last byte of header */
283 BuildTestGptData(gpt);
284 gpt->primary_header[h1->size - 1] ^= 0x5a;
285 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700286
Randall Spanglere9213a72013-01-24 11:19:55 -0800287 /* CRC only covers header */
288 BuildTestGptData(gpt);
289 gpt->primary_header[h1->size] ^= 0x5a;
290 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700291
Randall Spanglere9213a72013-01-24 11:19:55 -0800292 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700293}
294
Randall Spangler0bda13f2013-01-24 12:25:26 -0800295/* Test if header-same comparison works. */
296static int HeaderSameTest(void)
297{
298 GptData *gpt = GetEmptyGptData();
299 GptHeader *h1 = (GptHeader *)gpt->primary_header;
300 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
301 GptHeader h3;
302
303 EXPECT(0 == HeaderFieldsSame(h1, h2));
304
305 Memcpy(&h3, h2, sizeof(h3));
306 h3.signature[0] ^= 0xba;
307 EXPECT(1 == HeaderFieldsSame(h1, &h3));
308
309 Memcpy(&h3, h2, sizeof(h3));
310 h3.revision++;
311 EXPECT(1 == HeaderFieldsSame(h1, &h3));
312
313 Memcpy(&h3, h2, sizeof(h3));
314 h3.size++;
315 EXPECT(1 == HeaderFieldsSame(h1, &h3));
316
317 Memcpy(&h3, h2, sizeof(h3));
318 h3.reserved_zero++;
319 EXPECT(1 == HeaderFieldsSame(h1, &h3));
320
321 Memcpy(&h3, h2, sizeof(h3));
322 h3.first_usable_lba++;
323 EXPECT(1 == HeaderFieldsSame(h1, &h3));
324
325 Memcpy(&h3, h2, sizeof(h3));
326 h3.last_usable_lba++;
327 EXPECT(1 == HeaderFieldsSame(h1, &h3));
328
329 Memcpy(&h3, h2, sizeof(h3));
330 h3.disk_uuid.u.raw[0] ^= 0xba;
331 EXPECT(1 == HeaderFieldsSame(h1, &h3));
332
333 Memcpy(&h3, h2, sizeof(h3));
334 h3.number_of_entries++;
335 EXPECT(1 == HeaderFieldsSame(h1, &h3));
336
337 Memcpy(&h3, h2, sizeof(h3));
338 h3.size_of_entry++;
339 EXPECT(1 == HeaderFieldsSame(h1, &h3));
340
341 Memcpy(&h3, h2, sizeof(h3));
342 h3.entries_crc32++;
343 EXPECT(1 == HeaderFieldsSame(h1, &h3));
344
345 return TEST_OK;
346}
347
Randall Spanglere9213a72013-01-24 11:19:55 -0800348/* Test if signature ("EFI PART") is checked. */
349static int SignatureTest(void)
350{
351 GptData *gpt = GetEmptyGptData();
352 GptHeader *h1 = (GptHeader *)gpt->primary_header;
353 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
354 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700355
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800356 EXPECT(1 == CheckHeader(NULL, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800357
Randall Spanglere9213a72013-01-24 11:19:55 -0800358 for (i = 0; i < 8; ++i) {
359 BuildTestGptData(gpt);
360 h1->signature[i] ^= 0xff;
361 h2->signature[i] ^= 0xff;
362 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800363 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
364 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800365 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700366
Randall Spanglere9213a72013-01-24 11:19:55 -0800367 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700368}
369
Randall Spanglere9213a72013-01-24 11:19:55 -0800370/*
371 * The revision we currently support is GPT_HEADER_REVISION. If the revision
372 * in header is not that, we expect the header is invalid.
373 */
374static int RevisionTest(void)
375{
376 GptData *gpt = GetEmptyGptData();
377 GptHeader *h1 = (GptHeader *)gpt->primary_header;
378 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
379 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700380
Randall Spanglere9213a72013-01-24 11:19:55 -0800381 struct {
382 uint32_t value_to_test;
383 int expect_rv;
384 } cases[] = {
385 {0x01000000, 1},
386 {0x00010000, 0}, /* GPT_HEADER_REVISION */
387 {0x00000100, 1},
388 {0x00000001, 1},
389 {0x23010456, 1},
390 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700391
Randall Spanglere9213a72013-01-24 11:19:55 -0800392 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
393 BuildTestGptData(gpt);
394 h1->revision = cases[i].value_to_test;
395 h2->revision = cases[i].value_to_test;
396 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700397
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800398 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800399 cases[i].expect_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800400 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800401 cases[i].expect_rv);
402 }
403 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700404}
405
Randall Spanglere9213a72013-01-24 11:19:55 -0800406static int SizeTest(void)
407{
408 GptData *gpt = GetEmptyGptData();
409 GptHeader *h1 = (GptHeader *)gpt->primary_header;
410 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
411 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700412
Randall Spanglere9213a72013-01-24 11:19:55 -0800413 struct {
414 uint32_t value_to_test;
415 int expect_rv;
416 } cases[] = {
417 {91, 1},
418 {92, 0},
419 {93, 0},
420 {511, 0},
421 {512, 0},
422 {513, 1},
423 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700424
Randall Spanglere9213a72013-01-24 11:19:55 -0800425 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
426 BuildTestGptData(gpt);
427 h1->size = cases[i].value_to_test;
428 h2->size = cases[i].value_to_test;
429 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700430
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800431 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800432 cases[i].expect_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800433 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800434 cases[i].expect_rv);
435 }
436 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700437}
438
Randall Spanglere9213a72013-01-24 11:19:55 -0800439/* Test if CRC is checked. */
440static int CrcFieldTest(void)
441{
442 GptData *gpt = GetEmptyGptData();
443 GptHeader *h1 = (GptHeader *)gpt->primary_header;
444 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700445
Randall Spanglere9213a72013-01-24 11:19:55 -0800446 BuildTestGptData(gpt);
447 /* Modify a field that the header verification doesn't care about */
448 h1->entries_crc32++;
449 h2->entries_crc32++;
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800450 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
451 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800452 /* Refresh the CRC; should pass now */
453 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800454 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
455 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700456
Randall Spanglere9213a72013-01-24 11:19:55 -0800457 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700458}
459
Randall Spanglere9213a72013-01-24 11:19:55 -0800460/* Test if reserved fields are checked. We'll try non-zero values to test. */
461static int ReservedFieldsTest(void)
462{
463 GptData *gpt = GetEmptyGptData();
464 GptHeader *h1 = (GptHeader *)gpt->primary_header;
465 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700466
Randall Spanglere9213a72013-01-24 11:19:55 -0800467 BuildTestGptData(gpt);
468 h1->reserved_zero ^= 0x12345678; /* whatever random */
469 h2->reserved_zero ^= 0x12345678; /* whatever random */
470 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800471 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
472 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700473
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700474#ifdef PADDING_CHECKED
Randall Spanglere9213a72013-01-24 11:19:55 -0800475 /* TODO: padding check is currently disabled */
476 BuildTestGptData(gpt);
477 h1->padding[12] ^= 0x34; /* whatever random */
478 h2->padding[56] ^= 0x78; /* whatever random */
479 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800480 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
481 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700482#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700483
Randall Spanglere9213a72013-01-24 11:19:55 -0800484 return TEST_OK;
485}
486
487/*
488 * Technically, any size which is 2^N where N > 6 should work, but our
489 * library only supports one size.
490 */
491static int SizeOfPartitionEntryTest(void) {
492 GptData *gpt = GetEmptyGptData();
493 GptHeader *h1 = (GptHeader *)gpt->primary_header;
494 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
495 int i;
496
497 struct {
498 uint32_t value_to_test;
499 int expect_rv;
500 } cases[] = {
501 {127, 1},
502 {128, 0},
503 {129, 1},
504 {256, 1},
505 {512, 1},
506 };
507
508 /* Check size of entryes */
509 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
510 BuildTestGptData(gpt);
511 h1->size_of_entry = cases[i].value_to_test;
512 h2->size_of_entry = cases[i].value_to_test;
513 h1->number_of_entries = TOTAL_ENTRIES_SIZE /
514 cases[i].value_to_test;
515 h2->number_of_entries = TOTAL_ENTRIES_SIZE /
516 cases[i].value_to_test;
517 RefreshCrc32(gpt);
518
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800519 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800520 cases[i].expect_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800521 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800522 cases[i].expect_rv);
523 }
524
525 return TEST_OK;
526}
527
528/*
529 * Technically, any size which is 2^N where N > 6 should work, but our library
530 * only supports one size.
531 */
532static int NumberOfPartitionEntriesTest(void)
533{
534 GptData *gpt = GetEmptyGptData();
535 GptHeader *h1 = (GptHeader *)gpt->primary_header;
536 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
537
538 BuildTestGptData(gpt);
539 h1->number_of_entries--;
540 h2->number_of_entries /= 2;
Nam T. Nguyen32004012014-12-12 09:38:35 -0800541 /* Because we halved h2 entries, its entries_lba is going to change. */
542 h2->entries_lba = h2->my_lba - CalculateEntriesSectors(h2);
Randall Spanglere9213a72013-01-24 11:19:55 -0800543 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800544 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
545 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700546 /* But it's okay to have less if the GPT structs are stored elsewhere. */
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800547 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
548 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Randall Spanglere9213a72013-01-24 11:19:55 -0800549
550 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700551}
552
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700553
Randall Spanglere9213a72013-01-24 11:19:55 -0800554/* Test if myLBA field is checked (1 for primary, last for secondary). */
555static int MyLbaTest(void)
556{
557 GptData *gpt = GetEmptyGptData();
558 GptHeader *h1 = (GptHeader *)gpt->primary_header;
559 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700560
Randall Spanglere9213a72013-01-24 11:19:55 -0800561 /* myLBA depends on primary vs secondary flag */
562 BuildTestGptData(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800563 EXPECT(1 == CheckHeader(h1, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
564 EXPECT(1 == CheckHeader(h2, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700565
Randall Spanglere9213a72013-01-24 11:19:55 -0800566 BuildTestGptData(gpt);
567 h1->my_lba--;
568 h2->my_lba--;
569 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800570 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
571 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700572
Randall Spanglere9213a72013-01-24 11:19:55 -0800573 BuildTestGptData(gpt);
574 h1->my_lba = 2;
575 h2->my_lba--;
576 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800577 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
578 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700579
Randall Spanglere9213a72013-01-24 11:19:55 -0800580 /* We should ignore the alternate_lba field entirely */
581 BuildTestGptData(gpt);
582 h1->alternate_lba++;
583 h2->alternate_lba++;
584 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800585 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
586 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800587
588 BuildTestGptData(gpt);
589 h1->alternate_lba--;
590 h2->alternate_lba--;
591 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800592 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
593 EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800594
595 BuildTestGptData(gpt);
596 h1->entries_lba++;
597 h2->entries_lba++;
598 RefreshCrc32(gpt);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700599 /*
600 * We support a padding between primary GPT header and its entries. So
601 * this still passes.
602 */
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800603 EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700604 /*
605 * But the secondary table should fail because it would overlap the
606 * header, which is now lying after its entry array.
607 */
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800608 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800609
610 BuildTestGptData(gpt);
611 h1->entries_lba--;
612 h2->entries_lba--;
613 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800614 EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
615 EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
Randall Spanglere9213a72013-01-24 11:19:55 -0800616
617 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700618}
619
Randall Spanglere9213a72013-01-24 11:19:55 -0800620/* Test if FirstUsableLBA and LastUsableLBA are checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700621 * FirstUsableLBA must be after the end of the primary GPT table array.
622 * LastUsableLBA must be before the start of the secondary GPT table array.
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700623 * FirstUsableLBA <= LastUsableLBA.
624 * Also see CheckHeaderOffDevice() test. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800625static int FirstUsableLbaAndLastUsableLbaTest(void)
626{
627 GptData *gpt = GetEmptyGptData();
628 GptHeader *h1 = (GptHeader *)gpt->primary_header;
629 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
630 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700631
Randall Spanglere9213a72013-01-24 11:19:55 -0800632 struct {
633 uint64_t primary_entries_lba;
634 uint64_t primary_first_usable_lba;
635 uint64_t primary_last_usable_lba;
636 uint64_t secondary_first_usable_lba;
637 uint64_t secondary_last_usable_lba;
638 uint64_t secondary_entries_lba;
639 int primary_rv;
640 int secondary_rv;
641 } cases[] = {
642 {2, 34, 433, 34, 433, 434, 0, 0},
643 {2, 34, 432, 34, 430, 434, 0, 0},
644 {2, 33, 433, 33, 433, 434, 1, 1},
645 {2, 34, 434, 34, 433, 434, 1, 0},
646 {2, 34, 433, 34, 434, 434, 0, 1},
647 {2, 35, 433, 35, 433, 434, 0, 0},
648 {2, 433, 433, 433, 433, 434, 0, 0},
649 {2, 434, 433, 434, 434, 434, 1, 1},
650 {2, 433, 34, 34, 433, 434, 1, 0},
651 {2, 34, 433, 433, 34, 434, 0, 1},
652 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700653
Randall Spanglere9213a72013-01-24 11:19:55 -0800654 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
655 BuildTestGptData(gpt);
656 h1->entries_lba = cases[i].primary_entries_lba;
657 h1->first_usable_lba = cases[i].primary_first_usable_lba;
658 h1->last_usable_lba = cases[i].primary_last_usable_lba;
659 h2->entries_lba = cases[i].secondary_entries_lba;
660 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
661 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
662 RefreshCrc32(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700663
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800664 EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800665 cases[i].primary_rv);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -0800666 EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800667 cases[i].secondary_rv);
668 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700669
Randall Spanglere9213a72013-01-24 11:19:55 -0800670 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700671}
672
Randall Spanglere9213a72013-01-24 11:19:55 -0800673/*
674 * Test if PartitionEntryArrayCRC32 is checked. PartitionEntryArrayCRC32 must
675 * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700676 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800677static int EntriesCrcTest(void)
678{
679 GptData *gpt = GetEmptyGptData();
680 GptHeader *h1 = (GptHeader *)gpt->primary_header;
681 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
682 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700683
Randall Spanglere9213a72013-01-24 11:19:55 -0800684 /* Modify first byte of primary entries, and expect the CRC is wrong. */
685 BuildTestGptData(gpt);
686 EXPECT(0 == CheckEntries(e1, h1));
687 EXPECT(0 == CheckEntries(e2, h1));
688 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
689 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
690 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
691 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700692
Randall Spanglere9213a72013-01-24 11:19:55 -0800693 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700694}
695
Randall Spanglere9213a72013-01-24 11:19:55 -0800696/*
697 * Test if partition geometry is checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700698 * All active (non-zero PartitionTypeGUID) partition entries should have:
699 * entry.StartingLBA >= header.FirstUsableLBA
700 * entry.EndingLBA <= header.LastUsableLBA
701 * entry.StartingLBA <= entry.EndingLBA
702 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800703static int ValidEntryTest(void)
704{
705 GptData *gpt = GetEmptyGptData();
706 GptHeader *h1 = (GptHeader *)gpt->primary_header;
707 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700708
Randall Spanglere9213a72013-01-24 11:19:55 -0800709 /* error case: entry.StartingLBA < header.FirstUsableLBA */
710 BuildTestGptData(gpt);
711 e1[0].starting_lba = h1->first_usable_lba - 1;
712 RefreshCrc32(gpt);
713 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700714
Randall Spanglere9213a72013-01-24 11:19:55 -0800715 /* error case: entry.EndingLBA > header.LastUsableLBA */
716 BuildTestGptData(gpt);
717 e1[2].ending_lba = h1->last_usable_lba + 1;
718 RefreshCrc32(gpt);
719 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700720
Randall Spanglere9213a72013-01-24 11:19:55 -0800721 /* error case: entry.StartingLBA > entry.EndingLBA */
722 BuildTestGptData(gpt);
723 e1[3].starting_lba = e1[3].ending_lba + 1;
724 RefreshCrc32(gpt);
725 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700726
Randall Spanglere9213a72013-01-24 11:19:55 -0800727 /* case: non active entry should be ignored. */
728 BuildTestGptData(gpt);
729 Memset(&e1[1].type, 0, sizeof(e1[1].type));
730 e1[1].starting_lba = e1[1].ending_lba + 1;
731 RefreshCrc32(gpt);
732 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700733
Randall Spanglere9213a72013-01-24 11:19:55 -0800734 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700735}
736
Randall Spanglere9213a72013-01-24 11:19:55 -0800737/* Test if overlapped partition tables can be detected. */
738static int OverlappedPartitionTest(void) {
739 GptData *gpt = GetEmptyGptData();
740 GptHeader *h = (GptHeader *)gpt->primary_header;
741 GptEntry *e = (GptEntry *)gpt->primary_entries;
742 int i, j;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700743
Randall Spanglere9213a72013-01-24 11:19:55 -0800744 struct {
745 int overlapped;
746 struct {
747 int active;
748 uint64_t starting_lba;
749 uint64_t ending_lba;
750 } entries[16]; /* enough for testing. */
751 } cases[] = {
752 {GPT_SUCCESS, {{0, 100, 199}}},
753 {GPT_SUCCESS, {{1, 100, 199}}},
754 {GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
755 {GPT_ERROR_START_LBA_OVERLAP,
756 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
757 {GPT_ERROR_END_LBA_OVERLAP,
758 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
759 {GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
760 {GPT_ERROR_END_LBA_OVERLAP,
761 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
762 {GPT_ERROR_START_LBA_OVERLAP,
763 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
764 {GPT_ERROR_START_LBA_OVERLAP,
765 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
766 {GPT_ERROR_END_LBA_OVERLAP,
767 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
768 {GPT_ERROR_START_LBA_OVERLAP,
769 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
770 {GPT_SUCCESS,
771 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
772 {GPT_ERROR_START_LBA_OVERLAP,
773 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
774 {GPT_ERROR_START_LBA_OVERLAP,
775 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
776 {GPT_SUCCESS,
777 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
778 {GPT_ERROR_END_LBA_OVERLAP,
779 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
780 {GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
781 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
782 {GPT_ERROR_START_LBA_OVERLAP,
783 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
784 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
785 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
786 {GPT_SUCCESS,
787 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
788 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
789 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
790 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700791
Randall Spanglere9213a72013-01-24 11:19:55 -0800792 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
793 BuildTestGptData(gpt);
794 ZeroEntries(gpt);
795 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
796 if (!cases[i].entries[j].starting_lba)
797 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700798
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700799 if (cases[i].entries[j].active) {
Randall Spanglere9213a72013-01-24 11:19:55 -0800800 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700801 }
Randall Spanglere9213a72013-01-24 11:19:55 -0800802 SetGuid(&e[j].unique, j);
803 e[j].starting_lba = cases[i].entries[j].starting_lba;
804 e[j].ending_lba = cases[i].entries[j].ending_lba;
805 }
806 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700807
Randall Spanglere9213a72013-01-24 11:19:55 -0800808 EXPECT(cases[i].overlapped == CheckEntries(e, h));
809 }
810 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700811}
812
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700813/* Test both sanity checking and repair. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800814static int SanityCheckTest(void)
815{
816 GptData *gpt = GetEmptyGptData();
817 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler0bda13f2013-01-24 12:25:26 -0800818 GptEntry *e1 = (GptEntry *)gpt->primary_entries;
819 uint8_t *tempptr;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700820
Randall Spanglere9213a72013-01-24 11:19:55 -0800821 /* Unmodified test data is completely sane */
822 BuildTestGptData(gpt);
823 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
824 EXPECT(MASK_BOTH == gpt->valid_headers);
825 EXPECT(MASK_BOTH == gpt->valid_entries);
826 /* Repair doesn't damage it */
827 GptRepair(gpt);
828 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
829 EXPECT(MASK_BOTH == gpt->valid_headers);
830 EXPECT(MASK_BOTH == gpt->valid_entries);
831 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700832
Randall Spangler0bda13f2013-01-24 12:25:26 -0800833 /* Invalid sector size should fail */
834 BuildTestGptData(gpt);
835 gpt->sector_bytes = 1024;
836 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
837
Randall Spanglere9213a72013-01-24 11:19:55 -0800838 /* Modify headers */
839 BuildTestGptData(gpt);
840 gpt->primary_header[0]++;
841 gpt->secondary_header[0]++;
842 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
843 EXPECT(0 == gpt->valid_headers);
844 EXPECT(0 == gpt->valid_entries);
845 /* Repair can't fix completely busted headers */
846 GptRepair(gpt);
847 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
848 EXPECT(0 == gpt->valid_headers);
849 EXPECT(0 == gpt->valid_entries);
850 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700851
Randall Spanglere9213a72013-01-24 11:19:55 -0800852 BuildTestGptData(gpt);
853 gpt->primary_header[0]++;
854 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
855 EXPECT(MASK_SECONDARY == gpt->valid_headers);
856 EXPECT(MASK_BOTH == gpt->valid_entries);
857 GptRepair(gpt);
858 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
859 EXPECT(MASK_BOTH == gpt->valid_headers);
860 EXPECT(MASK_BOTH == gpt->valid_entries);
861 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700862
Randall Spanglere9213a72013-01-24 11:19:55 -0800863 BuildTestGptData(gpt);
864 gpt->secondary_header[0]++;
865 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
866 EXPECT(MASK_PRIMARY == gpt->valid_headers);
867 EXPECT(MASK_BOTH == gpt->valid_entries);
868 GptRepair(gpt);
869 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
870 EXPECT(MASK_BOTH == gpt->valid_headers);
871 EXPECT(MASK_BOTH == gpt->valid_entries);
872 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700873
Randall Spanglere9213a72013-01-24 11:19:55 -0800874 /*
875 * Modify header1 and update its CRC. Since header2 is now different
876 * than header1, it'll be the one considered invalid.
877 */
878 BuildTestGptData(gpt);
879 h1->size++;
880 RefreshCrc32(gpt);
881 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
882 EXPECT(MASK_PRIMARY == gpt->valid_headers);
883 EXPECT(MASK_BOTH == gpt->valid_entries);
884 GptRepair(gpt);
885 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
886 EXPECT(MASK_BOTH == gpt->valid_headers);
887 EXPECT(MASK_BOTH == gpt->valid_entries);
888 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700889
Randall Spanglere9213a72013-01-24 11:19:55 -0800890 /* Modify entries */
891 BuildTestGptData(gpt);
892 gpt->primary_entries[0]++;
893 gpt->secondary_entries[0]++;
894 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
895 EXPECT(MASK_BOTH == gpt->valid_headers);
896 EXPECT(MASK_NONE == gpt->valid_entries);
897 /* Repair can't fix both copies of entries being bad, either. */
898 GptRepair(gpt);
899 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
900 EXPECT(MASK_BOTH == gpt->valid_headers);
901 EXPECT(MASK_NONE == gpt->valid_entries);
902 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700903
Randall Spanglere9213a72013-01-24 11:19:55 -0800904 BuildTestGptData(gpt);
905 gpt->primary_entries[0]++;
906 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
907 EXPECT(MASK_BOTH == gpt->valid_headers);
908 EXPECT(MASK_SECONDARY == gpt->valid_entries);
909 GptRepair(gpt);
910 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
911 EXPECT(MASK_BOTH == gpt->valid_headers);
912 EXPECT(MASK_BOTH == gpt->valid_entries);
913 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700914
Randall Spanglere9213a72013-01-24 11:19:55 -0800915 BuildTestGptData(gpt);
916 gpt->secondary_entries[0]++;
917 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
918 EXPECT(MASK_BOTH == gpt->valid_headers);
919 EXPECT(MASK_PRIMARY == gpt->valid_entries);
920 GptRepair(gpt);
921 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
922 EXPECT(MASK_BOTH == gpt->valid_headers);
923 EXPECT(MASK_BOTH == gpt->valid_entries);
924 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700925
Randall Spangler0bda13f2013-01-24 12:25:26 -0800926 /*
927 * Modify entries and recompute CRCs, then make both primary and
928 * secondary entry pointers use the secondary data. The primary
929 * header will have the wrong entries CRC, so we should fall back
930 * to the secondary header.
931 */
932 BuildTestGptData(gpt);
933 e1->starting_lba++;
934 RefreshCrc32(gpt);
935 tempptr = gpt->primary_entries;
936 gpt->primary_entries = gpt->secondary_entries;
937 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
938 EXPECT(MASK_SECONDARY == gpt->valid_headers);
939 EXPECT(MASK_BOTH == gpt->valid_entries);
940 gpt->primary_entries = tempptr;
941
Randall Spanglere9213a72013-01-24 11:19:55 -0800942 /* Modify both header and entries */
943 BuildTestGptData(gpt);
944 gpt->primary_header[0]++;
945 gpt->primary_entries[0]++;
946 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
947 EXPECT(MASK_SECONDARY == gpt->valid_headers);
948 EXPECT(MASK_SECONDARY == gpt->valid_entries);
949 GptRepair(gpt);
950 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
951 EXPECT(MASK_BOTH == gpt->valid_headers);
952 EXPECT(MASK_BOTH == gpt->valid_entries);
953 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700954
Randall Spanglere9213a72013-01-24 11:19:55 -0800955 BuildTestGptData(gpt);
956 gpt->secondary_header[0]++;
957 gpt->secondary_entries[0]++;
958 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
959 EXPECT(MASK_PRIMARY == gpt->valid_headers);
960 EXPECT(MASK_PRIMARY == gpt->valid_entries);
961 GptRepair(gpt);
962 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
963 EXPECT(MASK_BOTH == gpt->valid_headers);
964 EXPECT(MASK_BOTH == gpt->valid_entries);
965 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700966
Randall Spanglere9213a72013-01-24 11:19:55 -0800967 /* Test cross-correction (h1+e2, h2+e1) */
968 BuildTestGptData(gpt);
969 gpt->primary_header[0]++;
970 gpt->secondary_entries[0]++;
971 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
972 EXPECT(MASK_SECONDARY == gpt->valid_headers);
973 EXPECT(MASK_PRIMARY == gpt->valid_entries);
974 GptRepair(gpt);
975 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
976 EXPECT(MASK_BOTH == gpt->valid_headers);
977 EXPECT(MASK_BOTH == gpt->valid_entries);
978 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700979
Randall Spanglere9213a72013-01-24 11:19:55 -0800980 BuildTestGptData(gpt);
981 gpt->secondary_header[0]++;
982 gpt->primary_entries[0]++;
983 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
984 EXPECT(MASK_PRIMARY == gpt->valid_headers);
985 EXPECT(MASK_SECONDARY == gpt->valid_entries);
986 GptRepair(gpt);
987 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
988 EXPECT(MASK_BOTH == gpt->valid_headers);
989 EXPECT(MASK_BOTH == gpt->valid_entries);
990 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700991
Randall Spanglere9213a72013-01-24 11:19:55 -0800992 /*
993 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different. This
994 * simulates a partial update of the drive.
995 */
996 BuildTestGptData(gpt);
997 gpt->secondary_entries[0]++;
998 RefreshCrc32(gpt);
999 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1000 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1001 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1002 GptRepair(gpt);
1003 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1004 EXPECT(MASK_BOTH == gpt->valid_headers);
1005 EXPECT(MASK_BOTH == gpt->valid_entries);
1006 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001007
Nam T. Nguyen5ce83252014-10-30 15:09:43 -07001008 /* Test unloaded entry array. */
1009 gpt = GetEmptyGptData();
1010 BuildTestGptData(gpt);
1011 gpt->primary_entries = NULL;
1012 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1013 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1014 gpt = GetEmptyGptData();
1015 BuildTestGptData(gpt);
1016 gpt->secondary_entries = NULL;
1017 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1018 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1019
1020 /* Test unloaded header. */
1021 gpt = GetEmptyGptData();
1022 BuildTestGptData(gpt);
1023 gpt->primary_header = NULL;
1024 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1025 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1026 gpt = GetEmptyGptData();
1027 BuildTestGptData(gpt);
1028 gpt->secondary_header = NULL;
1029 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1030 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1031
Randall Spanglere9213a72013-01-24 11:19:55 -08001032 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001033}
1034
Randall Spanglere9213a72013-01-24 11:19:55 -08001035static int EntryAttributeGetSetTest(void)
1036{
1037 GptData *gpt = GetEmptyGptData();
1038 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001039
Randall Spanglere9213a72013-01-24 11:19:55 -08001040 e->attrs.whole = 0x0000000000000000ULL;
1041 SetEntrySuccessful(e, 1);
1042 EXPECT(0x0100000000000000ULL == e->attrs.whole);
1043 EXPECT(1 == GetEntrySuccessful(e));
1044 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1045 SetEntrySuccessful(e, 0);
1046 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1047 EXPECT(0 == GetEntrySuccessful(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001048
Randall Spanglere9213a72013-01-24 11:19:55 -08001049 e->attrs.whole = 0x0000000000000000ULL;
1050 SetEntryTries(e, 15);
1051 EXPECT(15 == GetEntryTries(e));
1052 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1053 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1054 SetEntryTries(e, 0);
1055 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1056 EXPECT(0 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001057
Randall Spanglere9213a72013-01-24 11:19:55 -08001058 e->attrs.whole = 0x0000000000000000ULL;
1059 SetEntryPriority(e, 15);
1060 EXPECT(0x000F000000000000ULL == e->attrs.whole);
1061 EXPECT(15 == GetEntryPriority(e));
1062 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1063 SetEntryPriority(e, 0);
1064 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1065 EXPECT(0 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001066
Randall Spanglere9213a72013-01-24 11:19:55 -08001067 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1068 EXPECT(1 == GetEntrySuccessful(e));
1069 EXPECT(15 == GetEntryPriority(e));
1070 EXPECT(15 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001071
Randall Spanglere9213a72013-01-24 11:19:55 -08001072 e->attrs.whole = 0x0123000000000000ULL;
1073 EXPECT(1 == GetEntrySuccessful(e));
1074 EXPECT(2 == GetEntryTries(e));
1075 EXPECT(3 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001076
Randall Spanglere9213a72013-01-24 11:19:55 -08001077 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001078}
1079
Randall Spanglere9213a72013-01-24 11:19:55 -08001080static int EntryTypeTest(void)
1081{
1082 GptData *gpt = GetEmptyGptData();
1083 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001084
Randall Spanglere9213a72013-01-24 11:19:55 -08001085 Memcpy(&e->type, &guid_zero, sizeof(Guid));
1086 EXPECT(1 == IsUnusedEntry(e));
1087 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001088
Randall Spanglere9213a72013-01-24 11:19:55 -08001089 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1090 EXPECT(0 == IsUnusedEntry(e));
1091 EXPECT(1 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001092
Randall Spanglere9213a72013-01-24 11:19:55 -08001093 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1094 EXPECT(0 == IsUnusedEntry(e));
1095 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001096
Randall Spanglere9213a72013-01-24 11:19:55 -08001097 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001098}
1099
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001100/* Make an entry unused by clearing its type. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001101static void FreeEntry(GptEntry *e)
1102{
1103 Memset(&e->type, 0, sizeof(Guid));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001104}
1105
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001106/* Set up an entry. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001107static void FillEntry(GptEntry *e, int is_kernel,
1108 int priority, int successful, int tries)
1109{
1110 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1111 SetEntryPriority(e, priority);
1112 SetEntrySuccessful(e, successful);
1113 SetEntryTries(e, tries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001114}
1115
Randall Spanglere9213a72013-01-24 11:19:55 -08001116/*
1117 * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001118 * any usable kernel entry.
1119 */
Randall Spanglere9213a72013-01-24 11:19:55 -08001120static int NoValidKernelEntryTest(void)
1121{
1122 GptData *gpt = GetEmptyGptData();
1123 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001124
Randall Spanglere9213a72013-01-24 11:19:55 -08001125 BuildTestGptData(gpt);
1126 SetEntryPriority(e1 + KERNEL_A, 0);
1127 FreeEntry(e1 + KERNEL_B);
1128 RefreshCrc32(gpt);
1129 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1130 GptNextKernelEntry(gpt, NULL, NULL));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001131
Randall Spanglere9213a72013-01-24 11:19:55 -08001132 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001133}
1134
Randall Spanglere9213a72013-01-24 11:19:55 -08001135static int GetNextNormalTest(void)
1136{
1137 GptData *gpt = GetEmptyGptData();
1138 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1139 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001140
Randall Spanglere9213a72013-01-24 11:19:55 -08001141 /* Normal case - both kernels successful */
1142 BuildTestGptData(gpt);
1143 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1144 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1145 RefreshCrc32(gpt);
1146 GptInit(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001147
Randall Spanglere9213a72013-01-24 11:19:55 -08001148 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1149 EXPECT(KERNEL_A == gpt->current_kernel);
1150 EXPECT(34 == start);
1151 EXPECT(100 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001152
Randall Spanglere9213a72013-01-24 11:19:55 -08001153 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1154 EXPECT(KERNEL_B == gpt->current_kernel);
1155 EXPECT(134 == start);
1156 EXPECT(99 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001157
Randall Spanglere9213a72013-01-24 11:19:55 -08001158 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 /* Call as many times as you want; you won't get another kernel... */
1163 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1164 GptNextKernelEntry(gpt, &start, &size));
1165 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001166
Randall Spanglere9213a72013-01-24 11:19:55 -08001167 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001168}
1169
Randall Spanglere9213a72013-01-24 11:19:55 -08001170static int GetNextPrioTest(void)
1171{
1172 GptData *gpt = GetEmptyGptData();
1173 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1174 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001175
Randall Spanglere9213a72013-01-24 11:19:55 -08001176 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1177 BuildTestGptData(gpt);
1178 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1179 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1180 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1181 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1182 RefreshCrc32(gpt);
1183 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001184
Randall Spanglere9213a72013-01-24 11:19:55 -08001185 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1186 EXPECT(KERNEL_B == gpt->current_kernel);
1187 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1188 EXPECT(KERNEL_Y == gpt->current_kernel);
1189 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1190 EXPECT(KERNEL_A == gpt->current_kernel);
1191 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1192 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001193
Randall Spanglere9213a72013-01-24 11:19:55 -08001194 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001195}
1196
Randall Spanglere9213a72013-01-24 11:19:55 -08001197static int GetNextTriesTest(void)
1198{
1199 GptData *gpt = GetEmptyGptData();
1200 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1201 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001202
Randall Spanglere9213a72013-01-24 11:19:55 -08001203 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1204 BuildTestGptData(gpt);
1205 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1206 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1207 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1208 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1209 RefreshCrc32(gpt);
1210 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001211
Randall Spanglere9213a72013-01-24 11:19:55 -08001212 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1213 EXPECT(KERNEL_X == gpt->current_kernel);
1214 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1215 EXPECT(KERNEL_A == gpt->current_kernel);
1216 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1217 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001218
Randall Spanglere9213a72013-01-24 11:19:55 -08001219 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001220}
1221
Randall Spanglere9213a72013-01-24 11:19:55 -08001222static int GptUpdateTest(void)
1223{
1224 GptData *gpt = GetEmptyGptData();
1225 GptEntry *e = (GptEntry *)(gpt->primary_entries);
1226 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1227 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001228
Randall Spanglere9213a72013-01-24 11:19:55 -08001229 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1230 BuildTestGptData(gpt);
1231 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1232 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1233 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1234 RefreshCrc32(gpt);
1235 GptInit(gpt);
1236 gpt->modified = 0; /* Nothing modified yet */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001237
Randall Spanglere9213a72013-01-24 11:19:55 -08001238 /* Successful kernel */
1239 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1240 EXPECT(KERNEL_A == gpt->current_kernel);
1241 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1242 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1243 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1244 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1245 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1246 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1247 /* Trying successful kernel changes nothing */
1248 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1249 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1250 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1251 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1252 EXPECT(0 == gpt->modified);
1253 /* Marking it bad also does not update it. */
1254 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1255 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1256 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1257 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1258 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001259
Randall Spanglere9213a72013-01-24 11:19:55 -08001260 /* Kernel with tries */
1261 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1262 EXPECT(KERNEL_B == gpt->current_kernel);
1263 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1264 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1265 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1266 /* Marking it bad clears it */
1267 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1268 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1269 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1270 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1271 /* Which affects both copies of the partition entries */
1272 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1273 EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1274 EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1275 /* And that's caused the GPT to need updating */
1276 EXPECT(0x0F == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001277
Randall Spanglere9213a72013-01-24 11:19:55 -08001278 /* Another kernel with tries */
1279 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1280 EXPECT(KERNEL_X == gpt->current_kernel);
1281 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1282 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1283 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1284 /* Trying it uses up a try */
1285 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1286 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1287 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1288 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1289 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1290 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1291 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1292 /* Trying it again marks it inactive */
1293 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1294 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1295 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1296 EXPECT(0 == GetEntryTries(e + KERNEL_X));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001297
Randall Spangler0bda13f2013-01-24 12:25:26 -08001298 /* Can't update if entry isn't a kernel, or there isn't an entry */
1299 Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
1300 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1301 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1302 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1303 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1304 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1305
1306
Randall Spanglere9213a72013-01-24 11:19:55 -08001307 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001308}
1309
Randall Spanglere9213a72013-01-24 11:19:55 -08001310/*
1311 * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1312 * GPT_ERROR_INVALID_UPDATE_TYPE.
1313 */
1314static int UpdateInvalidKernelTypeTest(void)
1315{
1316 GptData *gpt = GetEmptyGptData();
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001317
Randall Spanglere9213a72013-01-24 11:19:55 -08001318 BuildTestGptData(gpt);
1319 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1320 gpt->current_kernel = 0;
1321 /* any invalid update_type value */
1322 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1323 GptUpdateKernelEntry(gpt, 99));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001324
Randall Spanglere9213a72013-01-24 11:19:55 -08001325 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001326}
1327
Randall Spanglere9213a72013-01-24 11:19:55 -08001328/* Test duplicate UniqueGuids can be detected. */
1329static int DuplicateUniqueGuidTest(void)
1330{
1331 GptData *gpt = GetEmptyGptData();
1332 GptHeader *h = (GptHeader *)gpt->primary_header;
1333 GptEntry *e = (GptEntry *)gpt->primary_entries;
1334 int i, j;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001335
Randall Spanglere9213a72013-01-24 11:19:55 -08001336 struct {
1337 int duplicate;
1338 struct {
1339 uint64_t starting_lba;
1340 uint64_t ending_lba;
1341 uint32_t type_guid;
1342 uint32_t unique_guid;
1343 } entries[16]; /* enough for testing. */
1344 } cases[] = {
1345 {GPT_SUCCESS, {{100, 109, 1, 1},
1346 {110, 119, 2, 2},
1347 {120, 129, 3, 3},
1348 {130, 139, 4, 4},
1349 }},
1350 {GPT_SUCCESS, {{100, 109, 1, 1},
1351 {110, 119, 1, 2},
1352 {120, 129, 2, 3},
1353 {130, 139, 2, 4},
1354 }},
1355 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1356 {110, 119, 2, 2},
1357 {120, 129, 3, 1},
1358 {130, 139, 4, 4},
1359 }},
1360 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1361 {110, 119, 1, 2},
1362 {120, 129, 2, 3},
1363 {130, 139, 2, 2},
1364 }},
1365 };
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001366
Randall Spanglere9213a72013-01-24 11:19:55 -08001367 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1368 BuildTestGptData(gpt);
1369 ZeroEntries(gpt);
1370 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1371 if (!cases[i].entries[j].starting_lba)
1372 break;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001373
Randall Spanglere9213a72013-01-24 11:19:55 -08001374 e[j].starting_lba = cases[i].entries[j].starting_lba;
1375 e[j].ending_lba = cases[i].entries[j].ending_lba;
1376 SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1377 SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1378 }
1379 RefreshCrc32(gpt);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001380
Randall Spanglere9213a72013-01-24 11:19:55 -08001381 EXPECT(cases[i].duplicate == CheckEntries(e, h));
1382 }
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001383
Randall Spanglere9213a72013-01-24 11:19:55 -08001384 return TEST_OK;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001385}
1386
Randall Spangler0bda13f2013-01-24 12:25:26 -08001387/* Test getting the current kernel GUID */
1388static int GetKernelGuidTest(void)
1389{
1390 GptData *gpt = GetEmptyGptData();
1391 GptEntry *e = (GptEntry *)gpt->primary_entries;
1392 Guid g;
1393
1394 BuildTestGptData(gpt);
1395 gpt->current_kernel = 0;
1396 GetCurrentKernelUniqueGuid(gpt, &g);
1397 EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
1398 gpt->current_kernel = 1;
1399 GetCurrentKernelUniqueGuid(gpt, &g);
1400 EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
1401
1402 return TEST_OK;
1403}
1404
1405/* Test getting GPT error text strings */
1406static int ErrorTextTest(void)
1407{
1408 int i;
1409
1410 /* Known errors are not unknown */
1411 for (i = 0; i < GPT_ERROR_COUNT; i++) {
1412 EXPECT(GptErrorText(i));
1413 EXPECT(strcmp(GptErrorText(i), "Unknown"));
1414 }
1415
1416 /* But other error values are */
1417 EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
1418
1419 return TEST_OK;
1420}
1421
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001422static int CheckHeaderOffDevice()
1423{
1424 GptData* gpt = GetEmptyGptData();
1425 BuildTestGptData(gpt);
1426
1427 GptHeader* primary_header = (GptHeader*)gpt->primary_header;
1428 primary_header->first_usable_lba = 0;
1429 RefreshCrc32(gpt);
1430 // GPT is stored on the same device so first usable lba should not
1431 // start at 0.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001432 EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1433 gpt->gpt_drive_sectors, 0));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001434 // But off device, it is okay to accept this GPT header.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001435 EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1436 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001437
1438 BuildTestGptData(gpt);
1439 primary_header->number_of_entries = 100;
1440 RefreshCrc32(gpt);
1441 // Normally, number of entries is 128. So this should fail.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001442 EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1443 gpt->gpt_drive_sectors, 0));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001444 // But off device, it is okay.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001445 EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1446 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001447
1448 primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1449 RefreshCrc32(gpt);
1450 // However, too few entries is not good.
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001451 EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1452 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001453
1454 // Repeat for secondary header.
1455 BuildTestGptData(gpt);
1456 GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
1457 secondary_header->first_usable_lba = 0;
1458 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001459 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1460 gpt->gpt_drive_sectors, 0));
1461 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1462 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001463
1464 BuildTestGptData(gpt);
1465 secondary_header->number_of_entries = 100;
Nam T. Nguyen32004012014-12-12 09:38:35 -08001466 /* Because we change number of entries, we need to also update entrie_lba. */
1467 secondary_header->entries_lba = secondary_header->my_lba -
1468 CalculateEntriesSectors(secondary_header);
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001469 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001470 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1471 gpt->gpt_drive_sectors, 0));
1472 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1473 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001474
1475 secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
1476 RefreshCrc32(gpt);
Dan Ehrenbergb3d38f52014-12-09 13:42:15 -08001477 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1478 gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001479
1480 return TEST_OK;
1481}
1482
Randall Spanglere9213a72013-01-24 11:19:55 -08001483int main(int argc, char *argv[])
1484{
1485 int i;
1486 int error_count = 0;
1487 struct {
1488 char *name;
1489 test_func fp;
1490 int retval;
1491 } test_cases[] = {
1492 { TEST_CASE(StructSizeTest), },
1493 { TEST_CASE(TestBuildTestGptData), },
1494 { TEST_CASE(ParameterTests), },
1495 { TEST_CASE(HeaderCrcTest), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001496 { TEST_CASE(HeaderSameTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001497 { TEST_CASE(SignatureTest), },
1498 { TEST_CASE(RevisionTest), },
1499 { TEST_CASE(SizeTest), },
1500 { TEST_CASE(CrcFieldTest), },
1501 { TEST_CASE(ReservedFieldsTest), },
1502 { TEST_CASE(SizeOfPartitionEntryTest), },
1503 { TEST_CASE(NumberOfPartitionEntriesTest), },
1504 { TEST_CASE(MyLbaTest), },
1505 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1506 { TEST_CASE(EntriesCrcTest), },
1507 { TEST_CASE(ValidEntryTest), },
1508 { TEST_CASE(OverlappedPartitionTest), },
1509 { TEST_CASE(SanityCheckTest), },
1510 { TEST_CASE(NoValidKernelEntryTest), },
1511 { TEST_CASE(EntryAttributeGetSetTest), },
1512 { TEST_CASE(EntryTypeTest), },
1513 { TEST_CASE(GetNextNormalTest), },
1514 { TEST_CASE(GetNextPrioTest), },
1515 { TEST_CASE(GetNextTriesTest), },
1516 { TEST_CASE(GptUpdateTest), },
1517 { TEST_CASE(UpdateInvalidKernelTypeTest), },
1518 { TEST_CASE(DuplicateUniqueGuidTest), },
1519 { TEST_CASE(TestCrc32TestVectors), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001520 { TEST_CASE(GetKernelGuidTest), },
1521 { TEST_CASE(ErrorTextTest), },
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001522 { TEST_CASE(CheckHeaderOffDevice), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001523 };
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001524
Randall Spanglere9213a72013-01-24 11:19:55 -08001525 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1526 printf("Running %s() ...\n", test_cases[i].name);
1527 test_cases[i].retval = test_cases[i].fp();
1528 if (test_cases[i].retval) {
1529 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1530 ++error_count;
1531 } else {
1532 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1533 }
1534 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001535
Randall Spanglere9213a72013-01-24 11:19:55 -08001536 if (error_count) {
1537 printf("\n------------------------------------------------\n");
1538 printf(COL_RED "The following %d test cases are failed:\n"
1539 COL_STOP, error_count);
1540 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1541 if (test_cases[i].retval)
1542 printf(" %s()\n", test_cases[i].name);
1543 }
1544 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001545
Randall Spanglere9213a72013-01-24 11:19:55 -08001546 return error_count ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001547}