blob: 29f91d871fa408cc668e396178a6dfb6a21446e7 [file] [log] [blame]
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07006#include <string.h>
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07007
Louis Yung-Chieh Lo0dce41c2010-05-17 22:45:30 -07008#include "cgptlib.h"
9#include "cgptlib_internal.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070010#include "cgptlib_test.h"
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070011#include "crc32.h"
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +080012#include "crc32_test.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070013#include "gpt.h"
14#include "utility.h"
15
16/* Testing partition layout (sector_bytes=512)
17 *
18 * LBA Size Usage
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070019 * ---------------------------------------------------------
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070020 * 0 1 PMBR
21 * 1 1 primary partition header
22 * 2 32 primary partition entries (128B * 128)
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070023 * 34 100 kernel A (index: 0)
24 * 134 100 root A (index: 1)
25 * 234 100 root B (index: 2)
26 * 334 100 kernel B (index: 3)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070027 * 434 32 secondary partition entries
28 * 466 1 secondary partition header
29 * 467
30 */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070031#define KERNEL_A 0
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070032#define KERNEL_B 1
33#define ROOTFS_A 2
34#define ROOTFS_B 3
35#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
36#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070037
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070038#define DEFAULT_SECTOR_SIZE 512
39#define MAX_SECTOR_SIZE 4096
40#define DEFAULT_DRIVE_SECTORS 467
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070041#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070042
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070043static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
44static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
45static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
46
47
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070048/* Given a GptData pointer, first re-calculate entries CRC32 value,
49 * then reset header CRC32 value to 0, and calculate header CRC32 value.
50 * Both primary and secondary are updated. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070051static void RefreshCrc32(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070052 GptHeader *header, *header2;
53 GptEntry *entries, *entries2;
54
55 header = (GptHeader*)gpt->primary_header;
56 entries = (GptEntry*)gpt->primary_entries;
57 header2 = (GptHeader*)gpt->secondary_header;
58 entries2 = (GptEntry*)gpt->secondary_entries;
59
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070060 header->entries_crc32 =
61 Crc32((uint8_t*)entries,
62 header->number_of_entries * header->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070063 header->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070064 header->header_crc32 = Crc32((uint8_t*)header, header->size);
65 header2->entries_crc32 =
66 Crc32((uint8_t*)entries2,
67 header2->number_of_entries * header2->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070068 header2->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070069 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size);
70}
71
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070072
73static void ZeroHeaders(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070074 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
75 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
76}
77
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070078
79static void ZeroEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070080 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
81 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
82}
83
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070084
85static void ZeroHeadersEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070086 ZeroHeaders(gpt);
87 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070088}
89
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070090
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070091/* Returns a pointer to a static GptData instance (no free is required).
92 * All fields are zero except 4 pointers linking to header and entries.
93 * All content of headers and entries are zero. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070094static GptData* GetEmptyGptData() {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070095 static GptData gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070096 static uint8_t primary_header[MAX_SECTOR_SIZE];
97 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
98 static uint8_t secondary_header[MAX_SECTOR_SIZE];
99 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
100
101 Memset(&gpt, 0, sizeof(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700102 gpt.primary_header = primary_header;
103 gpt.primary_entries = primary_entries;
104 gpt.secondary_header = secondary_header;
105 gpt.secondary_entries = secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700106 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700107
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700108 /* Initialize GptData internal states. */
109 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
110
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700111 return &gpt;
112}
113
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700114
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700115/* Fills in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700116 * file. Before calling this function, primary/secondary header/entries must
117 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
118 * This function returns a good (valid) copy of GPT layout described in top of
119 * this file. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700120static void BuildTestGptData(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700121 GptHeader *header, *header2;
122 GptEntry *entries, *entries2;
123 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700124 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700125
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700126 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700127 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700128 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lo418ad3b2010-05-27 11:21:17 +0800129 gpt->valid_headers = MASK_BOTH;
130 gpt->valid_entries = MASK_BOTH;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700131 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700132
133 /* build primary */
134 header = (GptHeader*)gpt->primary_header;
135 entries = (GptEntry*)gpt->primary_entries;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700136 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
137 sizeof(GPT_HEADER_SIGNATURE));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700138 header->revision = GPT_HEADER_REVISION;
Bill Richardsonf1372d92010-06-11 09:15:55 -0700139 header->size = sizeof(GptHeader);
140 header->reserved_zero = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700141 header->my_lba = 1;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700142 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700143 header->first_usable_lba = 34;
144 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
145 header->entries_lba = 2;
146 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */
147 header->size_of_entry = 128; /* bytes */
148 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
149 entries[0].starting_lba = 34;
150 entries[0].ending_lba = 133;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700151 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700152 entries[1].starting_lba = 134;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700153 entries[1].ending_lba = 232;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700154 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700155 entries[2].starting_lba = 234;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700156 entries[2].ending_lba = 331;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700157 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
158 entries[3].starting_lba = 334;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700159 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700160
161 /* build secondary */
162 header2 = (GptHeader*)gpt->secondary_header;
163 entries2 = (GptEntry*)gpt->secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700164 Memcpy(header2, header, sizeof(GptHeader));
165 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700166 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700167 header2->alternate_lba = 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700168 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
169
170 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700171}
172
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700173
Randall Spangler81d09962010-06-23 10:15:38 -0700174/* Tests if the structures are the expected size; if this fails,
175 * struct packing is not working properly. */
176static int StructSizeTest() {
177
178 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
179 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
180 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
181
182 return TEST_OK;
183}
184
185
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700186/* Tests if the default structure returned by BuildTestGptData() is good. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700187static int TestBuildTestGptData() {
188 GptData* gpt;
189
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700190 gpt = GetEmptyGptData();
191 BuildTestGptData(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700192 EXPECT(GPT_SUCCESS == GptInit(gpt));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700193 return TEST_OK;
194}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700195
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700196
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700197/* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
198 * Currently we only support 512 bytes per sector.
199 * In the future, we may support other sizes.
200 * A too small drive_sectors should be rejected by GptInit(). */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700201static int ParameterTests() {
202 GptData* gpt;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700203 struct {
204 uint32_t sector_bytes;
205 uint64_t drive_sectors;
206 int expected_retval;
207 } cases[] = {
208 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
209 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
210 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
211 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
212 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2,
213 GPT_SUCCESS},
214 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
215 };
216 int i;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700217
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700218 gpt = GetEmptyGptData();
219 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
220 BuildTestGptData(gpt);
221 gpt->sector_bytes = cases[i].sector_bytes;
222 gpt->drive_sectors = cases[i].drive_sectors;
223 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700224 }
225
226 return TEST_OK;
227}
228
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700229
230/* Tests if header CRC in two copies are calculated. */
231static int HeaderCrcTest() {
232 GptData* gpt = GetEmptyGptData();
233 GptHeader* h1 = (GptHeader*)gpt->primary_header;
234
235 BuildTestGptData(gpt);
236 EXPECT(HeaderCrc(h1) == h1->header_crc32);
237
238 /* CRC covers first byte of header */
239 BuildTestGptData(gpt);
240 gpt->primary_header[0] ^= 0xa5;
241 EXPECT(HeaderCrc(h1) != h1->header_crc32);
242
243 /* CRC covers last byte of header */
244 BuildTestGptData(gpt);
245 gpt->primary_header[h1->size - 1] ^= 0x5a;
246 EXPECT(HeaderCrc(h1) != h1->header_crc32);
247
248 /* CRC only covers header */
249 BuildTestGptData(gpt);
250 gpt->primary_header[h1->size] ^= 0x5a;
251 EXPECT(HeaderCrc(h1) == h1->header_crc32);
252
253 return TEST_OK;
254}
255
256
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700257/* Tests if signature ("EFI PART") is checked. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700258static int SignatureTest() {
259 GptData* gpt = GetEmptyGptData();
260 GptHeader* h1 = (GptHeader*)gpt->primary_header;
261 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700262 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700263
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700264 for (i = 0; i < 8; ++i) {
265 BuildTestGptData(gpt);
266 h1->signature[i] ^= 0xff;
267 h2->signature[i] ^= 0xff;
268 RefreshCrc32(gpt);
269 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
270 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700271 }
272
273 return TEST_OK;
274}
275
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700276
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700277/* The revision we currently support is GPT_HEADER_REVISION.
278 * If the revision in header is not that, we expect the header is invalid. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700279static int RevisionTest() {
280 GptData* gpt = GetEmptyGptData();
281 GptHeader* h1 = (GptHeader*)gpt->primary_header;
282 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
283 int i;
284
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700285 struct {
286 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700287 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700288 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700289 {0x01000000, 1},
290 {0x00010000, 0}, /* GPT_HEADER_REVISION */
291 {0x00000100, 1},
292 {0x00000001, 1},
293 {0x23010456, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700294 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700295
296 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700297 BuildTestGptData(gpt);
298 h1->revision = cases[i].value_to_test;
299 h2->revision = cases[i].value_to_test;
300 RefreshCrc32(gpt);
301
302 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
303 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700304 }
305 return TEST_OK;
306}
307
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700308
309static int SizeTest() {
310 GptData* gpt = GetEmptyGptData();
311 GptHeader* h1 = (GptHeader*)gpt->primary_header;
312 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
313 int i;
314
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700315 struct {
316 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700317 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700318 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700319 {91, 1},
320 {92, 0},
321 {93, 0},
322 {511, 0},
323 {512, 0},
324 {513, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700325 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700326
327 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700328 BuildTestGptData(gpt);
329 h1->size = cases[i].value_to_test;
330 h2->size = cases[i].value_to_test;
331 RefreshCrc32(gpt);
332
333 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
334 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700335 }
336 return TEST_OK;
337}
338
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700339
340/* Tests if CRC is checked. */
341static int CrcFieldTest() {
342 GptData* gpt = GetEmptyGptData();
343 GptHeader* h1 = (GptHeader*)gpt->primary_header;
344 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
345
346 BuildTestGptData(gpt);
347 /* Modify a field that the header verification doesn't care about */
348 h1->entries_crc32++;
349 h2->entries_crc32++;
350 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
351 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
352 /* Refresh the CRC; should pass now */
353 RefreshCrc32(gpt);
354 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
355 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
356
357 return TEST_OK;
358}
359
360
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700361/* Tests if reserved fields are checked.
362 * We'll try non-zero values to test. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700363static int ReservedFieldsTest() {
364 GptData* gpt = GetEmptyGptData();
365 GptHeader* h1 = (GptHeader*)gpt->primary_header;
366 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700367
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700368 BuildTestGptData(gpt);
Bill Richardsonf1372d92010-06-11 09:15:55 -0700369 h1->reserved_zero ^= 0x12345678; /* whatever random */
370 h2->reserved_zero ^= 0x12345678; /* whatever random */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700371 RefreshCrc32(gpt);
372 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
373 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700374
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700375#ifdef PADDING_CHECKED
376 /* TODO: padding check is currently disabled */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700377 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700378 h1->padding[12] ^= 0x34; /* whatever random */
379 h2->padding[56] ^= 0x78; /* whatever random */
380 RefreshCrc32(gpt);
381 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
382 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
383#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700384
385 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700386}
387
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700388
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700389/* Technically, any size which is 2^N where N > 6 should work, but our
390 * library only supports one size. */
391static int SizeOfPartitionEntryTest() {
392 GptData* gpt = GetEmptyGptData();
393 GptHeader* h1 = (GptHeader*)gpt->primary_header;
394 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
395 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700396
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700397 struct {
398 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700399 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700400 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700401 {127, 1},
402 {128, 0},
403 {129, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700404 {256, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700405 {512, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700406 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700407
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700408 /* Check size of entryes */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700409 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700410 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700411 h1->size_of_entry = cases[i].value_to_test;
412 h2->size_of_entry = cases[i].value_to_test;
413 h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
414 h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
415 RefreshCrc32(gpt);
416
417 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
418 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700419 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700420
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700421 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700422}
423
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700424
425/* Technically, any size which is 2^N where N > 6 should work, but our
426 * library only supports one size. */
427static int NumberOfPartitionEntriesTest() {
428 GptData* gpt = GetEmptyGptData();
429 GptHeader* h1 = (GptHeader*)gpt->primary_header;
430 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
431
432 BuildTestGptData(gpt);
433 h1->number_of_entries--;
434 h2->number_of_entries /= 2;
435 RefreshCrc32(gpt);
436 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
437 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
438
439 return TEST_OK;
440}
441
442
443/* Tests if myLBA field is checked (1 for primary, last for secondary). */
444static int MyLbaTest() {
445 GptData* gpt = GetEmptyGptData();
446 GptHeader* h1 = (GptHeader*)gpt->primary_header;
447 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
448
449 /* myLBA depends on primary vs secondary flag */
450 BuildTestGptData(gpt);
451 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
452 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
453
454 BuildTestGptData(gpt);
455 h1->my_lba--;
456 h2->my_lba--;
457 RefreshCrc32(gpt);
458 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
459 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
460
461 BuildTestGptData(gpt);
462 h1->my_lba = 2;
463 h2->my_lba--;
464 RefreshCrc32(gpt);
465 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
466 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
467
Bill Richardson31066a42010-06-03 15:20:19 -0700468 /* We should ignore the alternate_lba field entirely */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700469 BuildTestGptData(gpt);
470 h1->alternate_lba++;
471 h2->alternate_lba++;
472 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700473 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
474 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700475
476 BuildTestGptData(gpt);
477 h1->alternate_lba--;
478 h2->alternate_lba--;
479 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700480 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
481 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700482
483 BuildTestGptData(gpt);
484 h1->entries_lba++;
485 h2->entries_lba++;
486 RefreshCrc32(gpt);
487 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
488 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
489
490 BuildTestGptData(gpt);
491 h1->entries_lba--;
492 h2->entries_lba--;
493 RefreshCrc32(gpt);
494 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
495 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
496
497 return TEST_OK;
498}
499
500
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700501/* Tests if FirstUsableLBA and LastUsableLBA are checked.
502 * FirstUsableLBA must be after the end of the primary GPT table array.
503 * LastUsableLBA must be before the start of the secondary GPT table array.
504 * FirstUsableLBA <= LastUsableLBA. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700505static int FirstUsableLbaAndLastUsableLbaTest() {
506 GptData* gpt = GetEmptyGptData();
507 GptHeader* h1 = (GptHeader*)gpt->primary_header;
508 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700509 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700510
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700511 struct {
512 uint64_t primary_entries_lba;
513 uint64_t primary_first_usable_lba;
514 uint64_t primary_last_usable_lba;
515 uint64_t secondary_first_usable_lba;
516 uint64_t secondary_last_usable_lba;
517 uint64_t secondary_entries_lba;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700518 int primary_rv;
519 int secondary_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700520 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700521 {2, 34, 433, 34, 433, 434, 0, 0},
522 {2, 34, 432, 34, 430, 434, 0, 0},
523 {2, 33, 433, 33, 433, 434, 1, 1},
524 {2, 34, 434, 34, 433, 434, 1, 0},
525 {2, 34, 433, 34, 434, 434, 0, 1},
526 {2, 35, 433, 35, 433, 434, 0, 0},
527 {2, 433, 433, 433, 433, 434, 0, 0},
528 {2, 434, 433, 434, 434, 434, 1, 1},
529 {2, 433, 34, 34, 433, 434, 1, 0},
530 {2, 34, 433, 433, 34, 434, 0, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700531 };
532
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700533 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
534 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700535 h1->entries_lba = cases[i].primary_entries_lba;
536 h1->first_usable_lba = cases[i].primary_first_usable_lba;
537 h1->last_usable_lba = cases[i].primary_last_usable_lba;
538 h2->entries_lba = cases[i].secondary_entries_lba;
539 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
540 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
541 RefreshCrc32(gpt);
542
543 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].primary_rv);
544 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].secondary_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700545 }
546
547 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700548}
549
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700550
551/* Tests if PartitionEntryArrayCRC32 is checked.
552 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
553 * NumberOfPartitionEntries bytes.
554 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700555static int EntriesCrcTest() {
556 GptData* gpt = GetEmptyGptData();
557 GptHeader* h1 = (GptHeader*)gpt->primary_header;
558 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
559 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700560
561 /* Modify the first byte of primary entries, and expect the CRC is wrong. */
562 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700563 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
564 EXPECT(0 == CheckEntries(e2, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700565 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700566 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700567 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
568 EXPECT(1 == CheckEntries(e2, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700569
570 return TEST_OK;
571}
572
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700573
574/* Tests if partition geometry is checked.
575 * All active (non-zero PartitionTypeGUID) partition entries should have:
576 * entry.StartingLBA >= header.FirstUsableLBA
577 * entry.EndingLBA <= header.LastUsableLBA
578 * entry.StartingLBA <= entry.EndingLBA
579 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700580static int ValidEntryTest() {
581 GptData* gpt = GetEmptyGptData();
582 GptHeader* h1 = (GptHeader*)gpt->primary_header;
583 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700584
585 /* error case: entry.StartingLBA < header.FirstUsableLBA */
586 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700587 e1[0].starting_lba = h1->first_usable_lba - 1;
588 RefreshCrc32(gpt);
589 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700590
591 /* error case: entry.EndingLBA > header.LastUsableLBA */
592 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700593 e1[2].ending_lba = h1->last_usable_lba + 1;
594 RefreshCrc32(gpt);
595 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700596
597 /* error case: entry.StartingLBA > entry.EndingLBA */
598 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700599 e1[3].starting_lba = e1[3].ending_lba + 1;
600 RefreshCrc32(gpt);
601 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700602
603 /* case: non active entry should be ignored. */
604 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700605 Memset(&e1[1].type, 0, sizeof(e1[1].type));
606 e1[1].starting_lba = e1[1].ending_lba + 1;
607 RefreshCrc32(gpt);
608 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700609
610 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700611}
612
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700613
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700614/* Tests if overlapped partition tables can be detected. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700615static int OverlappedPartitionTest() {
616 GptData* gpt = GetEmptyGptData();
617 GptHeader* h = (GptHeader*)gpt->primary_header;
618 GptEntry* e = (GptEntry*)gpt->primary_entries;
619 int i, j;
620
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700621 struct {
622 int overlapped;
623 struct {
624 int active;
625 uint64_t starting_lba;
626 uint64_t ending_lba;
627 } entries[16]; /* enough for testing. */
628 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700629 {0, {{0, 100, 199}}},
630 {0, {{1, 100, 199}}},
631 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
632 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
633 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
634 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
635 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
636 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
637 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
638 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
639 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
640 {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
641 {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
642 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
643 {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
644 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
645 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
646 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700647 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
648 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700649 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700650 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
651 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700652 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700653 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700654
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700655
656 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700657 BuildTestGptData(gpt);
658 ZeroEntries(gpt);
659 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
660 if (!cases[i].entries[j].starting_lba)
661 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700662
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700663 if (cases[i].entries[j].active)
664 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
665 e[j].starting_lba = cases[i].entries[j].starting_lba;
666 e[j].ending_lba = cases[i].entries[j].ending_lba;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700667 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700668 RefreshCrc32(gpt);
669
670 EXPECT(cases[i].overlapped == CheckEntries(e, h, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700671 }
672 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700673}
674
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700675
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700676/* Test both sanity checking and repair. */
677static int SanityCheckTest() {
678 GptData* gpt = GetEmptyGptData();
679 GptHeader* h1 = (GptHeader*)gpt->primary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700680
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700681 /* Unmodified test data is completely sane */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700682 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700683 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
684 EXPECT(MASK_BOTH == gpt->valid_headers);
685 EXPECT(MASK_BOTH == gpt->valid_entries);
686 /* Repair doesn't damage it */
687 GptRepair(gpt);
688 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
689 EXPECT(MASK_BOTH == gpt->valid_headers);
690 EXPECT(MASK_BOTH == gpt->valid_entries);
691 EXPECT(0 == gpt->modified);
692
693 /* Modify headers */
694 BuildTestGptData(gpt);
695 gpt->primary_header[0]++;
696 gpt->secondary_header[0]++;
697 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
698 EXPECT(0 == gpt->valid_headers);
699 EXPECT(0 == gpt->valid_entries);
700 /* Repair can't fix completely busted headers */
701 GptRepair(gpt);
702 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
703 EXPECT(0 == gpt->valid_headers);
704 EXPECT(0 == gpt->valid_entries);
705 EXPECT(0 == gpt->modified);
706
707 BuildTestGptData(gpt);
708 gpt->primary_header[0]++;
709 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
710 EXPECT(MASK_SECONDARY == gpt->valid_headers);
711 EXPECT(MASK_BOTH == gpt->valid_entries);
712 GptRepair(gpt);
713 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
714 EXPECT(MASK_BOTH == gpt->valid_headers);
715 EXPECT(MASK_BOTH == gpt->valid_entries);
716 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
717
718 BuildTestGptData(gpt);
719 gpt->secondary_header[0]++;
720 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
721 EXPECT(MASK_PRIMARY == gpt->valid_headers);
722 EXPECT(MASK_BOTH == gpt->valid_entries);
723 GptRepair(gpt);
724 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
725 EXPECT(MASK_BOTH == gpt->valid_headers);
726 EXPECT(MASK_BOTH == gpt->valid_entries);
727 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
728
729 /* Modify header1 and update its CRC. Since header2 is now different than
730 * header1, it'll be the one considered invalid. */
731 BuildTestGptData(gpt);
732 h1->size++;
733 RefreshCrc32(gpt);
734 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
735 EXPECT(MASK_PRIMARY == gpt->valid_headers);
736 EXPECT(MASK_BOTH == gpt->valid_entries);
737 GptRepair(gpt);
738 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
739 EXPECT(MASK_BOTH == gpt->valid_headers);
740 EXPECT(MASK_BOTH == gpt->valid_entries);
741 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
742
743 /* Modify entries */
744 BuildTestGptData(gpt);
745 gpt->primary_entries[0]++;
746 gpt->secondary_entries[0]++;
747 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
748 EXPECT(MASK_BOTH == gpt->valid_headers);
749 EXPECT(MASK_NONE == gpt->valid_entries);
750 /* Repair can't fix both copies of entries being bad, either. */
751 GptRepair(gpt);
752 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
753 EXPECT(MASK_BOTH == gpt->valid_headers);
754 EXPECT(MASK_NONE == gpt->valid_entries);
755 EXPECT(0 == gpt->modified);
756
757 BuildTestGptData(gpt);
758 gpt->primary_entries[0]++;
759 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
760 EXPECT(MASK_BOTH == gpt->valid_headers);
761 EXPECT(MASK_SECONDARY == gpt->valid_entries);
762 GptRepair(gpt);
763 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
764 EXPECT(MASK_BOTH == gpt->valid_headers);
765 EXPECT(MASK_BOTH == gpt->valid_entries);
766 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
767
768 BuildTestGptData(gpt);
769 gpt->secondary_entries[0]++;
770 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
771 EXPECT(MASK_BOTH == gpt->valid_headers);
772 EXPECT(MASK_PRIMARY == gpt->valid_entries);
773 GptRepair(gpt);
774 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
775 EXPECT(MASK_BOTH == gpt->valid_headers);
776 EXPECT(MASK_BOTH == gpt->valid_entries);
777 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
778
779 /* Test cross-correction (h1+e2, h2+e1) */
780 BuildTestGptData(gpt);
781 gpt->primary_header[0]++;
782 gpt->secondary_entries[0]++;
783 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
784 EXPECT(MASK_SECONDARY == gpt->valid_headers);
785 EXPECT(MASK_PRIMARY == gpt->valid_entries);
786 GptRepair(gpt);
787 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
788 EXPECT(MASK_BOTH == gpt->valid_headers);
789 EXPECT(MASK_BOTH == gpt->valid_entries);
790 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
791
792 BuildTestGptData(gpt);
793 gpt->secondary_header[0]++;
794 gpt->primary_entries[0]++;
795 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
796 EXPECT(MASK_PRIMARY == gpt->valid_headers);
797 EXPECT(MASK_SECONDARY == gpt->valid_entries);
798 GptRepair(gpt);
799 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
800 EXPECT(MASK_BOTH == gpt->valid_headers);
801 EXPECT(MASK_BOTH == gpt->valid_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700802 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700803
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700804 /* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.
805 * This simulates a partial update of the drive. */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700806 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700807 gpt->secondary_entries[0]++;
808 RefreshCrc32(gpt);
809 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
810 EXPECT(MASK_PRIMARY == gpt->valid_headers);
811 EXPECT(MASK_PRIMARY == gpt->valid_entries);
812 GptRepair(gpt);
813 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
814 EXPECT(MASK_BOTH == gpt->valid_headers);
815 EXPECT(MASK_BOTH == gpt->valid_entries);
816 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700817
818 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700819}
820
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700821
822static int EntryAttributeGetSetTest() {
823 GptData* gpt = GetEmptyGptData();
824 GptEntry* e = (GptEntry*)(gpt->primary_entries);
825
vbendebf7a45cc2010-06-21 08:44:16 -0700826 e->attrs.whole = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700827 SetEntrySuccessful(e, 1);
vbendebf7a45cc2010-06-21 08:44:16 -0700828 EXPECT(0x0100000000000000LLU == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700829 EXPECT(1 == GetEntrySuccessful(e));
vbendebf7a45cc2010-06-21 08:44:16 -0700830 e->attrs.whole = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700831 SetEntrySuccessful(e, 0);
vbendebf7a45cc2010-06-21 08:44:16 -0700832 EXPECT(0xFEFFFFFFFFFFFFFFLLU == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700833 EXPECT(0 == GetEntrySuccessful(e));
834
vbendebf7a45cc2010-06-21 08:44:16 -0700835 e->attrs.whole = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700836 SetEntryTries(e, 15);
837 EXPECT(15 == GetEntryTries(e));
vbendebf7a45cc2010-06-21 08:44:16 -0700838 EXPECT(0x00F0000000000000LLU == e->attrs.whole);
839 e->attrs.whole = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700840 SetEntryTries(e, 0);
vbendebf7a45cc2010-06-21 08:44:16 -0700841 EXPECT(0xFF0FFFFFFFFFFFFFLLU == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700842 EXPECT(0 == GetEntryTries(e));
843
vbendebf7a45cc2010-06-21 08:44:16 -0700844 e->attrs.whole = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700845 SetEntryPriority(e, 15);
vbendebf7a45cc2010-06-21 08:44:16 -0700846 EXPECT(0x000F000000000000LLU == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700847 EXPECT(15 == GetEntryPriority(e));
vbendebf7a45cc2010-06-21 08:44:16 -0700848 e->attrs.whole = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700849 SetEntryPriority(e, 0);
vbendebf7a45cc2010-06-21 08:44:16 -0700850 EXPECT(0xFFF0FFFFFFFFFFFFLLU == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700851 EXPECT(0 == GetEntryPriority(e));
852
vbendebf7a45cc2010-06-21 08:44:16 -0700853 e->attrs.whole = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700854 EXPECT(1 == GetEntrySuccessful(e));
855 EXPECT(15 == GetEntryPriority(e));
856 EXPECT(15 == GetEntryTries(e));
857
vbendebf7a45cc2010-06-21 08:44:16 -0700858 e->attrs.whole = 0x0123000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700859 EXPECT(1 == GetEntrySuccessful(e));
860 EXPECT(2 == GetEntryTries(e));
861 EXPECT(3 == GetEntryPriority(e));
862
863 return TEST_OK;
864}
865
866
867static int EntryTypeTest() {
868 GptData* gpt = GetEmptyGptData();
869 GptEntry* e = (GptEntry*)(gpt->primary_entries);
870
871 Memcpy(&e->type, &guid_zero, sizeof(Guid));
872 EXPECT(1 == IsUnusedEntry(e));
873 EXPECT(0 == IsKernelEntry(e));
874
875 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
876 EXPECT(0 == IsUnusedEntry(e));
877 EXPECT(1 == IsKernelEntry(e));
878
879 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
880 EXPECT(0 == IsUnusedEntry(e));
881 EXPECT(0 == IsKernelEntry(e));
882
883 return TEST_OK;
884}
885
886
887/* Make an entry unused by clearing its type. */
888static void FreeEntry(GptEntry* e) {
889 Memset(&e->type, 0, sizeof(Guid));
890}
891
892
893/* Set up an entry. */
894static void FillEntry(GptEntry* e, int is_kernel,
895 int priority, int successful, int tries) {
896 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
897 SetEntryPriority(e, priority);
898 SetEntrySuccessful(e, successful);
899 SetEntryTries(e, tries);
900}
901
902
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700903/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
904 * any usable kernel entry.
905 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700906static int NoValidKernelEntryTest() {
907 GptData* gpt = GetEmptyGptData();
908 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700909
910 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700911 SetEntryPriority(e1 + KERNEL_A, 0);
912 FreeEntry(e1 + KERNEL_B);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700913 RefreshCrc32(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700914 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
915
916 return TEST_OK;
917}
918
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700919
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700920static int GetNextNormalTest() {
921 GptData* gpt = GetEmptyGptData();
922 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
923 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700924
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700925 /* Normal case - both kernels successful */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700926 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700927 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
928 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
929 RefreshCrc32(gpt);
930 GptInit(gpt);
931
932 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
933 EXPECT(KERNEL_A == gpt->current_kernel);
934 EXPECT(34 == start);
935 EXPECT(100 == size);
936
937 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
938 EXPECT(KERNEL_B == gpt->current_kernel);
939 EXPECT(134 == start);
940 EXPECT(99 == size);
941
942 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
943 EXPECT(-1 == gpt->current_kernel);
944
945 /* Call as many times as you want; you won't get another kernel... */
946 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
947 EXPECT(-1 == gpt->current_kernel);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700948
949 return TEST_OK;
950}
951
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700952
953static int GetNextPrioTest() {
954 GptData* gpt = GetEmptyGptData();
955 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
956 uint64_t start, size;
957
958 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
959 BuildTestGptData(gpt);
960 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
961 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
962 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
963 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
964 RefreshCrc32(gpt);
965 GptInit(gpt);
966
967 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
968 EXPECT(KERNEL_B == gpt->current_kernel);
969 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
970 EXPECT(KERNEL_Y == gpt->current_kernel);
971 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
972 EXPECT(KERNEL_A == gpt->current_kernel);
973 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
974
975 return TEST_OK;
976}
977
978
979static int GetNextTriesTest() {
980 GptData* gpt = GetEmptyGptData();
981 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
982 uint64_t start, size;
983
984 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
985 BuildTestGptData(gpt);
986 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
987 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
988 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
989 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
990 RefreshCrc32(gpt);
991 GptInit(gpt);
992
993 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
994 EXPECT(KERNEL_X == gpt->current_kernel);
995 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
996 EXPECT(KERNEL_A == gpt->current_kernel);
997 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
998
999 return TEST_OK;
1000}
1001
1002
1003static int GptUpdateTest() {
1004 GptData* gpt = GetEmptyGptData();
1005 GptEntry* e = (GptEntry*)(gpt->primary_entries);
1006 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
1007 uint64_t start, size;
1008
1009 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1010 BuildTestGptData(gpt);
1011 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1012 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1013 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1014 RefreshCrc32(gpt);
1015 GptInit(gpt);
1016 gpt->modified = 0; /* Nothing modified yet */
1017
1018 /* Successful kernel */
1019 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1020 EXPECT(KERNEL_A == gpt->current_kernel);
1021 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1022 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1023 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1024 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1025 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1026 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1027 /* Trying successful kernel changes nothing */
1028 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1029 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1030 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1031 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1032 EXPECT(0 == gpt->modified);
1033 /* Marking it bad does, though */
1034 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1035 EXPECT(0 == GetEntrySuccessful(e + KERNEL_A));
1036 EXPECT(0 == GetEntryPriority(e + KERNEL_A));
1037 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1038 /* Which affects both copies of the partition entries */
1039 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_A));
1040 EXPECT(0 == GetEntryPriority(e2 + KERNEL_A));
1041 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1042 /* And that's caused the GPT to need updating */
1043 EXPECT(0x0F == gpt->modified);
1044
1045 /* Kernel with tries */
1046 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1047 EXPECT(KERNEL_B == gpt->current_kernel);
1048 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1049 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1050 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1051 /* Marking it bad clears it */
1052 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1053 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1054 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1055 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1056
1057 /* Another kernel with tries */
1058 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1059 EXPECT(KERNEL_X == gpt->current_kernel);
1060 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1061 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1062 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1063 /* Trying it uses up a try */
1064 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1065 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1066 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1067 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1068 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1069 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1070 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1071 /* Trying it again marks it inactive */
1072 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1073 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1074 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1075 EXPECT(0 == GetEntryTries(e + KERNEL_X));
1076
1077 return TEST_OK;
1078}
1079
1080
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001081/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
1082 * GPT_ERROR_INVALID_UPDATE_TYPE. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001083static int UpdateInvalidKernelTypeTest() {
1084 GptData* gpt = GetEmptyGptData();
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001085
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001086 BuildTestGptData(gpt);
1087 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1088 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1089 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
1090
1091 return TEST_OK;
1092}
1093
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001094
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001095int main(int argc, char *argv[]) {
1096 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001097 int error_count = 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001098 struct {
1099 char *name;
1100 test_func fp;
1101 int retval;
1102 } test_cases[] = {
Randall Spangler81d09962010-06-23 10:15:38 -07001103 { TEST_CASE(StructSizeTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001104 { TEST_CASE(TestBuildTestGptData), },
1105 { TEST_CASE(ParameterTests), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001106 { TEST_CASE(HeaderCrcTest), },
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07001107 { TEST_CASE(SignatureTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001108 { TEST_CASE(RevisionTest), },
1109 { TEST_CASE(SizeTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001110 { TEST_CASE(CrcFieldTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001111 { TEST_CASE(ReservedFieldsTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001112 { TEST_CASE(SizeOfPartitionEntryTest), },
1113 { TEST_CASE(NumberOfPartitionEntriesTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001114 { TEST_CASE(MyLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001115 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001116 { TEST_CASE(EntriesCrcTest), },
1117 { TEST_CASE(ValidEntryTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001118 { TEST_CASE(OverlappedPartitionTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001119 { TEST_CASE(SanityCheckTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001120 { TEST_CASE(NoValidKernelEntryTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001121 { TEST_CASE(EntryAttributeGetSetTest), },
1122 { TEST_CASE(EntryTypeTest), },
1123 { TEST_CASE(GetNextNormalTest), },
1124 { TEST_CASE(GetNextPrioTest), },
1125 { TEST_CASE(GetNextTriesTest), },
1126 { TEST_CASE(GptUpdateTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001127 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +08001128 { TEST_CASE(TestCrc32TestVectors), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001129 };
1130
1131 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1132 printf("Running %s() ...\n", test_cases[i].name);
1133 test_cases[i].retval = test_cases[i].fp();
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001134 if (test_cases[i].retval) {
1135 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1136 ++error_count;
1137 } else {
1138 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1139 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001140 }
1141
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001142 if (error_count) {
1143 printf("\n--------------------------------------------------\n");
1144 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP,
1145 error_count);
1146 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1147 if (test_cases[i].retval)
1148 printf(" %s()\n", test_cases[i].name);
1149 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001150 }
1151
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001152 return (error_count) ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001153}