blob: 5b0b9b47515fefceb4a58e399ec8d3834035b180 [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"
vbendeb3ecaf772010-06-24 16:19:53 -070014#include "test_common.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070015#include "utility.h"
16
17/* Testing partition layout (sector_bytes=512)
18 *
19 * LBA Size Usage
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070020 * ---------------------------------------------------------
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070021 * 0 1 PMBR
22 * 1 1 primary partition header
23 * 2 32 primary partition entries (128B * 128)
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070024 * 34 100 kernel A (index: 0)
25 * 134 100 root A (index: 1)
26 * 234 100 root B (index: 2)
27 * 334 100 kernel B (index: 3)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070028 * 434 32 secondary partition entries
29 * 466 1 secondary partition header
30 * 467
31 */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070032#define KERNEL_A 0
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070033#define KERNEL_B 1
34#define ROOTFS_A 2
35#define ROOTFS_B 3
36#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
37#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070038
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070039#define DEFAULT_SECTOR_SIZE 512
40#define MAX_SECTOR_SIZE 4096
41#define DEFAULT_DRIVE_SECTORS 467
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070042#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070043
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070044static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
45static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
46static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
47
48
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070049/* Given a GptData pointer, first re-calculate entries CRC32 value,
50 * then reset header CRC32 value to 0, and calculate header CRC32 value.
51 * Both primary and secondary are updated. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070052static void RefreshCrc32(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070053 GptHeader *header, *header2;
54 GptEntry *entries, *entries2;
55
56 header = (GptHeader*)gpt->primary_header;
57 entries = (GptEntry*)gpt->primary_entries;
58 header2 = (GptHeader*)gpt->secondary_header;
59 entries2 = (GptEntry*)gpt->secondary_entries;
60
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070061 header->entries_crc32 =
62 Crc32((uint8_t*)entries,
63 header->number_of_entries * header->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070064 header->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070065 header->header_crc32 = Crc32((uint8_t*)header, header->size);
66 header2->entries_crc32 =
67 Crc32((uint8_t*)entries2,
68 header2->number_of_entries * header2->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070069 header2->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070070 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size);
71}
72
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070073
74static void ZeroHeaders(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070075 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
76 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
77}
78
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070079
80static void ZeroEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070081 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
82 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
83}
84
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070085
86static void ZeroHeadersEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070087 ZeroHeaders(gpt);
88 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070089}
90
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070091
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070092/* Returns a pointer to a static GptData instance (no free is required).
93 * All fields are zero except 4 pointers linking to header and entries.
94 * All content of headers and entries are zero. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070095static GptData* GetEmptyGptData() {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070096 static GptData gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070097 static uint8_t primary_header[MAX_SECTOR_SIZE];
98 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
99 static uint8_t secondary_header[MAX_SECTOR_SIZE];
100 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
101
102 Memset(&gpt, 0, sizeof(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700103 gpt.primary_header = primary_header;
104 gpt.primary_entries = primary_entries;
105 gpt.secondary_header = secondary_header;
106 gpt.secondary_entries = secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700107 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700108
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700109 /* Initialize GptData internal states. */
110 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
111
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700112 return &gpt;
113}
114
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700115
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700116/* Fills in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700117 * file. Before calling this function, primary/secondary header/entries must
118 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
119 * This function returns a good (valid) copy of GPT layout described in top of
120 * this file. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700121static void BuildTestGptData(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700122 GptHeader *header, *header2;
123 GptEntry *entries, *entries2;
124 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700125 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700126
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700127 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700128 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700129 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lo418ad3b2010-05-27 11:21:17 +0800130 gpt->valid_headers = MASK_BOTH;
131 gpt->valid_entries = MASK_BOTH;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700132 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700133
134 /* build primary */
135 header = (GptHeader*)gpt->primary_header;
136 entries = (GptEntry*)gpt->primary_entries;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700137 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
138 sizeof(GPT_HEADER_SIGNATURE));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700139 header->revision = GPT_HEADER_REVISION;
Bill Richardsonf1372d92010-06-11 09:15:55 -0700140 header->size = sizeof(GptHeader);
141 header->reserved_zero = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700142 header->my_lba = 1;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700143 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700144 header->first_usable_lba = 34;
145 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
146 header->entries_lba = 2;
147 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */
148 header->size_of_entry = 128; /* bytes */
149 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
150 entries[0].starting_lba = 34;
151 entries[0].ending_lba = 133;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700152 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700153 entries[1].starting_lba = 134;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700154 entries[1].ending_lba = 232;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700155 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700156 entries[2].starting_lba = 234;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700157 entries[2].ending_lba = 331;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700158 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
159 entries[3].starting_lba = 334;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700160 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700161
162 /* build secondary */
163 header2 = (GptHeader*)gpt->secondary_header;
164 entries2 = (GptEntry*)gpt->secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700165 Memcpy(header2, header, sizeof(GptHeader));
166 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700167 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700168 header2->alternate_lba = 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700169 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
170
171 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700172}
173
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700174
Randall Spangler81d09962010-06-23 10:15:38 -0700175/* Tests if the structures are the expected size; if this fails,
176 * struct packing is not working properly. */
177static int StructSizeTest() {
178
179 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
180 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
181 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
182
183 return TEST_OK;
184}
185
186
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700187/* Tests if the default structure returned by BuildTestGptData() is good. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700188static int TestBuildTestGptData() {
189 GptData* gpt;
190
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700191 gpt = GetEmptyGptData();
192 BuildTestGptData(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700193 EXPECT(GPT_SUCCESS == GptInit(gpt));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700194 return TEST_OK;
195}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700196
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700197
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700198/* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
199 * Currently we only support 512 bytes per sector.
200 * In the future, we may support other sizes.
201 * A too small drive_sectors should be rejected by GptInit(). */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700202static int ParameterTests() {
203 GptData* gpt;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700204 struct {
205 uint32_t sector_bytes;
206 uint64_t drive_sectors;
207 int expected_retval;
208 } cases[] = {
209 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
210 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
211 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
212 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
213 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2,
214 GPT_SUCCESS},
215 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
216 };
217 int i;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700218
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700219 gpt = GetEmptyGptData();
220 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
221 BuildTestGptData(gpt);
222 gpt->sector_bytes = cases[i].sector_bytes;
223 gpt->drive_sectors = cases[i].drive_sectors;
224 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700225 }
226
227 return TEST_OK;
228}
229
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700230
231/* Tests if header CRC in two copies are calculated. */
232static int HeaderCrcTest() {
233 GptData* gpt = GetEmptyGptData();
234 GptHeader* h1 = (GptHeader*)gpt->primary_header;
235
236 BuildTestGptData(gpt);
237 EXPECT(HeaderCrc(h1) == h1->header_crc32);
238
239 /* CRC covers first byte of header */
240 BuildTestGptData(gpt);
241 gpt->primary_header[0] ^= 0xa5;
242 EXPECT(HeaderCrc(h1) != h1->header_crc32);
243
244 /* CRC covers last byte of header */
245 BuildTestGptData(gpt);
246 gpt->primary_header[h1->size - 1] ^= 0x5a;
247 EXPECT(HeaderCrc(h1) != h1->header_crc32);
248
249 /* CRC only covers header */
250 BuildTestGptData(gpt);
251 gpt->primary_header[h1->size] ^= 0x5a;
252 EXPECT(HeaderCrc(h1) == h1->header_crc32);
253
254 return TEST_OK;
255}
256
257
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700258/* Tests if signature ("EFI PART") is checked. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700259static int SignatureTest() {
260 GptData* gpt = GetEmptyGptData();
261 GptHeader* h1 = (GptHeader*)gpt->primary_header;
262 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700263 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700264
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700265 for (i = 0; i < 8; ++i) {
266 BuildTestGptData(gpt);
267 h1->signature[i] ^= 0xff;
268 h2->signature[i] ^= 0xff;
269 RefreshCrc32(gpt);
270 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
271 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700272 }
273
274 return TEST_OK;
275}
276
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700277
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700278/* The revision we currently support is GPT_HEADER_REVISION.
279 * If the revision in header is not that, we expect the header is invalid. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700280static int RevisionTest() {
281 GptData* gpt = GetEmptyGptData();
282 GptHeader* h1 = (GptHeader*)gpt->primary_header;
283 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
284 int i;
285
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700286 struct {
287 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700288 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700289 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700290 {0x01000000, 1},
291 {0x00010000, 0}, /* GPT_HEADER_REVISION */
292 {0x00000100, 1},
293 {0x00000001, 1},
294 {0x23010456, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700295 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700296
297 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700298 BuildTestGptData(gpt);
299 h1->revision = cases[i].value_to_test;
300 h2->revision = cases[i].value_to_test;
301 RefreshCrc32(gpt);
302
303 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
304 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700305 }
306 return TEST_OK;
307}
308
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700309
310static int SizeTest() {
311 GptData* gpt = GetEmptyGptData();
312 GptHeader* h1 = (GptHeader*)gpt->primary_header;
313 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
314 int i;
315
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700316 struct {
317 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700318 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700319 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700320 {91, 1},
321 {92, 0},
322 {93, 0},
323 {511, 0},
324 {512, 0},
325 {513, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700326 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700327
328 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700329 BuildTestGptData(gpt);
330 h1->size = cases[i].value_to_test;
331 h2->size = cases[i].value_to_test;
332 RefreshCrc32(gpt);
333
334 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
335 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700336 }
337 return TEST_OK;
338}
339
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700340
341/* Tests if CRC is checked. */
342static int CrcFieldTest() {
343 GptData* gpt = GetEmptyGptData();
344 GptHeader* h1 = (GptHeader*)gpt->primary_header;
345 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
346
347 BuildTestGptData(gpt);
348 /* Modify a field that the header verification doesn't care about */
349 h1->entries_crc32++;
350 h2->entries_crc32++;
351 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
352 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
353 /* Refresh the CRC; should pass now */
354 RefreshCrc32(gpt);
355 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
356 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
357
358 return TEST_OK;
359}
360
361
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700362/* Tests if reserved fields are checked.
363 * We'll try non-zero values to test. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700364static int ReservedFieldsTest() {
365 GptData* gpt = GetEmptyGptData();
366 GptHeader* h1 = (GptHeader*)gpt->primary_header;
367 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700368
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700369 BuildTestGptData(gpt);
Bill Richardsonf1372d92010-06-11 09:15:55 -0700370 h1->reserved_zero ^= 0x12345678; /* whatever random */
371 h2->reserved_zero ^= 0x12345678; /* whatever random */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700372 RefreshCrc32(gpt);
373 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
374 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700375
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700376#ifdef PADDING_CHECKED
377 /* TODO: padding check is currently disabled */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700378 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700379 h1->padding[12] ^= 0x34; /* whatever random */
380 h2->padding[56] ^= 0x78; /* whatever random */
381 RefreshCrc32(gpt);
382 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
383 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
384#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700385
386 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700387}
388
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700389
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700390/* Technically, any size which is 2^N where N > 6 should work, but our
391 * library only supports one size. */
392static int SizeOfPartitionEntryTest() {
393 GptData* gpt = GetEmptyGptData();
394 GptHeader* h1 = (GptHeader*)gpt->primary_header;
395 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
396 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700397
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700398 struct {
399 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700400 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700401 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700402 {127, 1},
403 {128, 0},
404 {129, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700405 {256, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700406 {512, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700407 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700408
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700409 /* Check size of entryes */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700410 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700411 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700412 h1->size_of_entry = cases[i].value_to_test;
413 h2->size_of_entry = cases[i].value_to_test;
414 h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
415 h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
416 RefreshCrc32(gpt);
417
418 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
419 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700420 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700421
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700422 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700423}
424
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700425
426/* Technically, any size which is 2^N where N > 6 should work, but our
427 * library only supports one size. */
428static int NumberOfPartitionEntriesTest() {
429 GptData* gpt = GetEmptyGptData();
430 GptHeader* h1 = (GptHeader*)gpt->primary_header;
431 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
432
433 BuildTestGptData(gpt);
434 h1->number_of_entries--;
435 h2->number_of_entries /= 2;
436 RefreshCrc32(gpt);
437 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
438 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
439
440 return TEST_OK;
441}
442
443
444/* Tests if myLBA field is checked (1 for primary, last for secondary). */
445static int MyLbaTest() {
446 GptData* gpt = GetEmptyGptData();
447 GptHeader* h1 = (GptHeader*)gpt->primary_header;
448 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
449
450 /* myLBA depends on primary vs secondary flag */
451 BuildTestGptData(gpt);
452 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
453 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
454
455 BuildTestGptData(gpt);
456 h1->my_lba--;
457 h2->my_lba--;
458 RefreshCrc32(gpt);
459 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
460 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
461
462 BuildTestGptData(gpt);
463 h1->my_lba = 2;
464 h2->my_lba--;
465 RefreshCrc32(gpt);
466 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
467 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
468
Bill Richardson31066a42010-06-03 15:20:19 -0700469 /* We should ignore the alternate_lba field entirely */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700470 BuildTestGptData(gpt);
471 h1->alternate_lba++;
472 h2->alternate_lba++;
473 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700474 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
475 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700476
477 BuildTestGptData(gpt);
478 h1->alternate_lba--;
479 h2->alternate_lba--;
480 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700481 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
482 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700483
484 BuildTestGptData(gpt);
485 h1->entries_lba++;
486 h2->entries_lba++;
487 RefreshCrc32(gpt);
488 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
489 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
490
491 BuildTestGptData(gpt);
492 h1->entries_lba--;
493 h2->entries_lba--;
494 RefreshCrc32(gpt);
495 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
496 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
497
498 return TEST_OK;
499}
500
501
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700502/* Tests if FirstUsableLBA and LastUsableLBA are checked.
503 * FirstUsableLBA must be after the end of the primary GPT table array.
504 * LastUsableLBA must be before the start of the secondary GPT table array.
505 * FirstUsableLBA <= LastUsableLBA. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700506static int FirstUsableLbaAndLastUsableLbaTest() {
507 GptData* gpt = GetEmptyGptData();
508 GptHeader* h1 = (GptHeader*)gpt->primary_header;
509 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700510 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700511
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700512 struct {
513 uint64_t primary_entries_lba;
514 uint64_t primary_first_usable_lba;
515 uint64_t primary_last_usable_lba;
516 uint64_t secondary_first_usable_lba;
517 uint64_t secondary_last_usable_lba;
518 uint64_t secondary_entries_lba;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700519 int primary_rv;
520 int secondary_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700521 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700522 {2, 34, 433, 34, 433, 434, 0, 0},
523 {2, 34, 432, 34, 430, 434, 0, 0},
524 {2, 33, 433, 33, 433, 434, 1, 1},
525 {2, 34, 434, 34, 433, 434, 1, 0},
526 {2, 34, 433, 34, 434, 434, 0, 1},
527 {2, 35, 433, 35, 433, 434, 0, 0},
528 {2, 433, 433, 433, 433, 434, 0, 0},
529 {2, 434, 433, 434, 434, 434, 1, 1},
530 {2, 433, 34, 34, 433, 434, 1, 0},
531 {2, 34, 433, 433, 34, 434, 0, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700532 };
533
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700534 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
535 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700536 h1->entries_lba = cases[i].primary_entries_lba;
537 h1->first_usable_lba = cases[i].primary_first_usable_lba;
538 h1->last_usable_lba = cases[i].primary_last_usable_lba;
539 h2->entries_lba = cases[i].secondary_entries_lba;
540 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
541 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
542 RefreshCrc32(gpt);
543
544 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].primary_rv);
545 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].secondary_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700546 }
547
548 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700549}
550
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700551
552/* Tests if PartitionEntryArrayCRC32 is checked.
553 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
554 * NumberOfPartitionEntries bytes.
555 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700556static int EntriesCrcTest() {
557 GptData* gpt = GetEmptyGptData();
558 GptHeader* h1 = (GptHeader*)gpt->primary_header;
559 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
560 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700561
562 /* Modify the first byte of primary entries, and expect the CRC is wrong. */
563 BuildTestGptData(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700564 EXPECT(0 == CheckEntries(e1, h1));
565 EXPECT(0 == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700566 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700567 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
vbendeb3ecaf772010-06-24 16:19:53 -0700568 EXPECT(1 == CheckEntries(e1, h1));
569 EXPECT(1 == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700570
571 return TEST_OK;
572}
573
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700574
575/* Tests if partition geometry is checked.
576 * All active (non-zero PartitionTypeGUID) partition entries should have:
577 * entry.StartingLBA >= header.FirstUsableLBA
578 * entry.EndingLBA <= header.LastUsableLBA
579 * entry.StartingLBA <= entry.EndingLBA
580 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700581static int ValidEntryTest() {
582 GptData* gpt = GetEmptyGptData();
583 GptHeader* h1 = (GptHeader*)gpt->primary_header;
584 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700585
586 /* error case: entry.StartingLBA < header.FirstUsableLBA */
587 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700588 e1[0].starting_lba = h1->first_usable_lba - 1;
589 RefreshCrc32(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700590 EXPECT(1 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700591
592 /* error case: entry.EndingLBA > header.LastUsableLBA */
593 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700594 e1[2].ending_lba = h1->last_usable_lba + 1;
595 RefreshCrc32(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700596 EXPECT(1 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700597
598 /* error case: entry.StartingLBA > entry.EndingLBA */
599 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700600 e1[3].starting_lba = e1[3].ending_lba + 1;
601 RefreshCrc32(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700602 EXPECT(1 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700603
604 /* case: non active entry should be ignored. */
605 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700606 Memset(&e1[1].type, 0, sizeof(e1[1].type));
607 e1[1].starting_lba = e1[1].ending_lba + 1;
608 RefreshCrc32(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700609 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700610
611 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700612}
613
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700614
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700615/* Tests if overlapped partition tables can be detected. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700616static int OverlappedPartitionTest() {
617 GptData* gpt = GetEmptyGptData();
618 GptHeader* h = (GptHeader*)gpt->primary_header;
619 GptEntry* e = (GptEntry*)gpt->primary_entries;
620 int i, j;
621
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700622 struct {
623 int overlapped;
624 struct {
625 int active;
626 uint64_t starting_lba;
627 uint64_t ending_lba;
628 } entries[16]; /* enough for testing. */
629 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700630 {0, {{0, 100, 199}}},
631 {0, {{1, 100, 199}}},
632 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
633 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
634 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
635 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
636 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
637 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
638 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
639 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
640 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
641 {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
642 {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
643 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
644 {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
645 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
646 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
647 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700648 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
649 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700650 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700651 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
652 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700653 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700654 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700655
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700656
657 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700658 BuildTestGptData(gpt);
659 ZeroEntries(gpt);
660 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
661 if (!cases[i].entries[j].starting_lba)
662 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700663
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700664 if (cases[i].entries[j].active)
665 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
666 e[j].starting_lba = cases[i].entries[j].starting_lba;
667 e[j].ending_lba = cases[i].entries[j].ending_lba;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700668 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700669 RefreshCrc32(gpt);
670
vbendeb3ecaf772010-06-24 16:19:53 -0700671 EXPECT(cases[i].overlapped == CheckEntries(e, h));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700672 }
673 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700674}
675
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700676
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700677/* Test both sanity checking and repair. */
678static int SanityCheckTest() {
679 GptData* gpt = GetEmptyGptData();
680 GptHeader* h1 = (GptHeader*)gpt->primary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700681
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700682 /* Unmodified test data is completely sane */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700683 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700684 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
685 EXPECT(MASK_BOTH == gpt->valid_headers);
686 EXPECT(MASK_BOTH == gpt->valid_entries);
687 /* Repair doesn't damage it */
688 GptRepair(gpt);
689 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
690 EXPECT(MASK_BOTH == gpt->valid_headers);
691 EXPECT(MASK_BOTH == gpt->valid_entries);
692 EXPECT(0 == gpt->modified);
693
694 /* Modify headers */
695 BuildTestGptData(gpt);
696 gpt->primary_header[0]++;
697 gpt->secondary_header[0]++;
698 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
699 EXPECT(0 == gpt->valid_headers);
700 EXPECT(0 == gpt->valid_entries);
701 /* Repair can't fix completely busted headers */
702 GptRepair(gpt);
703 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
704 EXPECT(0 == gpt->valid_headers);
705 EXPECT(0 == gpt->valid_entries);
706 EXPECT(0 == gpt->modified);
707
708 BuildTestGptData(gpt);
709 gpt->primary_header[0]++;
710 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
711 EXPECT(MASK_SECONDARY == gpt->valid_headers);
712 EXPECT(MASK_BOTH == gpt->valid_entries);
713 GptRepair(gpt);
714 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
715 EXPECT(MASK_BOTH == gpt->valid_headers);
716 EXPECT(MASK_BOTH == gpt->valid_entries);
717 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
718
719 BuildTestGptData(gpt);
720 gpt->secondary_header[0]++;
721 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
722 EXPECT(MASK_PRIMARY == gpt->valid_headers);
723 EXPECT(MASK_BOTH == gpt->valid_entries);
724 GptRepair(gpt);
725 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
726 EXPECT(MASK_BOTH == gpt->valid_headers);
727 EXPECT(MASK_BOTH == gpt->valid_entries);
728 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
729
730 /* Modify header1 and update its CRC. Since header2 is now different than
731 * header1, it'll be the one considered invalid. */
732 BuildTestGptData(gpt);
733 h1->size++;
734 RefreshCrc32(gpt);
735 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
736 EXPECT(MASK_PRIMARY == gpt->valid_headers);
737 EXPECT(MASK_BOTH == gpt->valid_entries);
738 GptRepair(gpt);
739 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
740 EXPECT(MASK_BOTH == gpt->valid_headers);
741 EXPECT(MASK_BOTH == gpt->valid_entries);
742 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
743
744 /* Modify entries */
745 BuildTestGptData(gpt);
746 gpt->primary_entries[0]++;
747 gpt->secondary_entries[0]++;
748 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
749 EXPECT(MASK_BOTH == gpt->valid_headers);
750 EXPECT(MASK_NONE == gpt->valid_entries);
751 /* Repair can't fix both copies of entries being bad, either. */
752 GptRepair(gpt);
753 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
754 EXPECT(MASK_BOTH == gpt->valid_headers);
755 EXPECT(MASK_NONE == gpt->valid_entries);
756 EXPECT(0 == gpt->modified);
757
758 BuildTestGptData(gpt);
759 gpt->primary_entries[0]++;
760 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
761 EXPECT(MASK_BOTH == gpt->valid_headers);
762 EXPECT(MASK_SECONDARY == gpt->valid_entries);
763 GptRepair(gpt);
764 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
765 EXPECT(MASK_BOTH == gpt->valid_headers);
766 EXPECT(MASK_BOTH == gpt->valid_entries);
767 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
768
769 BuildTestGptData(gpt);
770 gpt->secondary_entries[0]++;
771 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
772 EXPECT(MASK_BOTH == gpt->valid_headers);
773 EXPECT(MASK_PRIMARY == gpt->valid_entries);
774 GptRepair(gpt);
775 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
776 EXPECT(MASK_BOTH == gpt->valid_headers);
777 EXPECT(MASK_BOTH == gpt->valid_entries);
778 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
779
780 /* Test cross-correction (h1+e2, h2+e1) */
781 BuildTestGptData(gpt);
782 gpt->primary_header[0]++;
783 gpt->secondary_entries[0]++;
784 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
785 EXPECT(MASK_SECONDARY == gpt->valid_headers);
786 EXPECT(MASK_PRIMARY == gpt->valid_entries);
787 GptRepair(gpt);
788 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
789 EXPECT(MASK_BOTH == gpt->valid_headers);
790 EXPECT(MASK_BOTH == gpt->valid_entries);
791 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
792
793 BuildTestGptData(gpt);
794 gpt->secondary_header[0]++;
795 gpt->primary_entries[0]++;
796 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
797 EXPECT(MASK_PRIMARY == gpt->valid_headers);
798 EXPECT(MASK_SECONDARY == gpt->valid_entries);
799 GptRepair(gpt);
800 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
801 EXPECT(MASK_BOTH == gpt->valid_headers);
802 EXPECT(MASK_BOTH == gpt->valid_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700803 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700804
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700805 /* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.
806 * This simulates a partial update of the drive. */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700807 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700808 gpt->secondary_entries[0]++;
809 RefreshCrc32(gpt);
810 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
811 EXPECT(MASK_PRIMARY == gpt->valid_headers);
812 EXPECT(MASK_PRIMARY == gpt->valid_entries);
813 GptRepair(gpt);
814 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
815 EXPECT(MASK_BOTH == gpt->valid_headers);
816 EXPECT(MASK_BOTH == gpt->valid_entries);
817 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700818
819 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700820}
821
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700822
823static int EntryAttributeGetSetTest() {
824 GptData* gpt = GetEmptyGptData();
825 GptEntry* e = (GptEntry*)(gpt->primary_entries);
826
vbendeb3ecaf772010-06-24 16:19:53 -0700827 e->attrs.whole = 0x0000000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700828 SetEntrySuccessful(e, 1);
vbendeb3ecaf772010-06-24 16:19:53 -0700829 EXPECT(0x0100000000000000ULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700830 EXPECT(1 == GetEntrySuccessful(e));
vbendeb3ecaf772010-06-24 16:19:53 -0700831 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700832 SetEntrySuccessful(e, 0);
vbendeb3ecaf772010-06-24 16:19:53 -0700833 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700834 EXPECT(0 == GetEntrySuccessful(e));
835
vbendeb3ecaf772010-06-24 16:19:53 -0700836 e->attrs.whole = 0x0000000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700837 SetEntryTries(e, 15);
838 EXPECT(15 == GetEntryTries(e));
vbendeb3ecaf772010-06-24 16:19:53 -0700839 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
840 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700841 SetEntryTries(e, 0);
vbendeb3ecaf772010-06-24 16:19:53 -0700842 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700843 EXPECT(0 == GetEntryTries(e));
844
vbendeb3ecaf772010-06-24 16:19:53 -0700845 e->attrs.whole = 0x0000000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700846 SetEntryPriority(e, 15);
vbendeb3ecaf772010-06-24 16:19:53 -0700847 EXPECT(0x000F000000000000ULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700848 EXPECT(15 == GetEntryPriority(e));
vbendeb3ecaf772010-06-24 16:19:53 -0700849 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700850 SetEntryPriority(e, 0);
vbendeb3ecaf772010-06-24 16:19:53 -0700851 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700852 EXPECT(0 == GetEntryPriority(e));
853
vbendeb3ecaf772010-06-24 16:19:53 -0700854 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700855 EXPECT(1 == GetEntrySuccessful(e));
856 EXPECT(15 == GetEntryPriority(e));
857 EXPECT(15 == GetEntryTries(e));
858
vbendeb3ecaf772010-06-24 16:19:53 -0700859 e->attrs.whole = 0x0123000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700860 EXPECT(1 == GetEntrySuccessful(e));
861 EXPECT(2 == GetEntryTries(e));
862 EXPECT(3 == GetEntryPriority(e));
863
864 return TEST_OK;
865}
866
867
868static int EntryTypeTest() {
869 GptData* gpt = GetEmptyGptData();
870 GptEntry* e = (GptEntry*)(gpt->primary_entries);
871
872 Memcpy(&e->type, &guid_zero, sizeof(Guid));
873 EXPECT(1 == IsUnusedEntry(e));
874 EXPECT(0 == IsKernelEntry(e));
875
876 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
877 EXPECT(0 == IsUnusedEntry(e));
878 EXPECT(1 == IsKernelEntry(e));
879
880 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
881 EXPECT(0 == IsUnusedEntry(e));
882 EXPECT(0 == IsKernelEntry(e));
883
884 return TEST_OK;
885}
886
887
888/* Make an entry unused by clearing its type. */
889static void FreeEntry(GptEntry* e) {
890 Memset(&e->type, 0, sizeof(Guid));
891}
892
893
894/* Set up an entry. */
895static void FillEntry(GptEntry* e, int is_kernel,
896 int priority, int successful, int tries) {
897 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
898 SetEntryPriority(e, priority);
899 SetEntrySuccessful(e, successful);
900 SetEntryTries(e, tries);
901}
902
903
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700904/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
905 * any usable kernel entry.
906 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700907static int NoValidKernelEntryTest() {
908 GptData* gpt = GetEmptyGptData();
909 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700910
911 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700912 SetEntryPriority(e1 + KERNEL_A, 0);
913 FreeEntry(e1 + KERNEL_B);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700914 RefreshCrc32(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700915 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
916
917 return TEST_OK;
918}
919
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700920
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700921static int GetNextNormalTest() {
922 GptData* gpt = GetEmptyGptData();
923 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
924 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700925
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700926 /* Normal case - both kernels successful */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700927 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700928 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
929 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
930 RefreshCrc32(gpt);
931 GptInit(gpt);
932
933 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
934 EXPECT(KERNEL_A == gpt->current_kernel);
935 EXPECT(34 == start);
936 EXPECT(100 == size);
937
938 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
939 EXPECT(KERNEL_B == gpt->current_kernel);
940 EXPECT(134 == start);
941 EXPECT(99 == size);
942
943 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
944 EXPECT(-1 == gpt->current_kernel);
945
946 /* Call as many times as you want; you won't get another kernel... */
947 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
948 EXPECT(-1 == gpt->current_kernel);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700949
950 return TEST_OK;
951}
952
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700953
954static int GetNextPrioTest() {
955 GptData* gpt = GetEmptyGptData();
956 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
957 uint64_t start, size;
958
959 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
960 BuildTestGptData(gpt);
961 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
962 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
963 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
964 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
965 RefreshCrc32(gpt);
966 GptInit(gpt);
967
968 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
969 EXPECT(KERNEL_B == gpt->current_kernel);
970 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
971 EXPECT(KERNEL_Y == gpt->current_kernel);
972 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
973 EXPECT(KERNEL_A == gpt->current_kernel);
974 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
975
976 return TEST_OK;
977}
978
979
980static int GetNextTriesTest() {
981 GptData* gpt = GetEmptyGptData();
982 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
983 uint64_t start, size;
984
985 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
986 BuildTestGptData(gpt);
987 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
988 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
989 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
990 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
991 RefreshCrc32(gpt);
992 GptInit(gpt);
993
994 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
995 EXPECT(KERNEL_X == gpt->current_kernel);
996 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
997 EXPECT(KERNEL_A == gpt->current_kernel);
998 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
999
1000 return TEST_OK;
1001}
1002
1003
1004static int GptUpdateTest() {
1005 GptData* gpt = GetEmptyGptData();
1006 GptEntry* e = (GptEntry*)(gpt->primary_entries);
1007 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
1008 uint64_t start, size;
1009
1010 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1011 BuildTestGptData(gpt);
1012 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1013 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1014 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1015 RefreshCrc32(gpt);
1016 GptInit(gpt);
1017 gpt->modified = 0; /* Nothing modified yet */
1018
1019 /* Successful kernel */
1020 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1021 EXPECT(KERNEL_A == gpt->current_kernel);
1022 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1023 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1024 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1025 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1026 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1027 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1028 /* Trying successful kernel changes nothing */
1029 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1030 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1031 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1032 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1033 EXPECT(0 == gpt->modified);
1034 /* Marking it bad does, though */
1035 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1036 EXPECT(0 == GetEntrySuccessful(e + KERNEL_A));
1037 EXPECT(0 == GetEntryPriority(e + KERNEL_A));
1038 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1039 /* Which affects both copies of the partition entries */
1040 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_A));
1041 EXPECT(0 == GetEntryPriority(e2 + KERNEL_A));
1042 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1043 /* And that's caused the GPT to need updating */
1044 EXPECT(0x0F == gpt->modified);
1045
1046 /* Kernel with tries */
1047 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1048 EXPECT(KERNEL_B == gpt->current_kernel);
1049 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1050 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1051 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1052 /* Marking it bad clears it */
1053 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1054 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1055 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1056 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1057
1058 /* Another kernel with tries */
1059 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1060 EXPECT(KERNEL_X == gpt->current_kernel);
1061 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1062 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1063 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1064 /* Trying it uses up a try */
1065 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1066 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1067 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1068 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1069 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1070 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1071 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1072 /* Trying it again marks it inactive */
1073 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1074 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1075 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1076 EXPECT(0 == GetEntryTries(e + KERNEL_X));
1077
1078 return TEST_OK;
1079}
1080
1081
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001082/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
1083 * GPT_ERROR_INVALID_UPDATE_TYPE. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001084static int UpdateInvalidKernelTypeTest() {
1085 GptData* gpt = GetEmptyGptData();
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001086
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001087 BuildTestGptData(gpt);
1088 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1089 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1090 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
1091
1092 return TEST_OK;
1093}
1094
vbendeb3ecaf772010-06-24 16:19:53 -07001095/* disable MSVC warnings on unused arguments */
1096__pragma(warning (disable: 4100))
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001097
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001098int main(int argc, char *argv[]) {
1099 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001100 int error_count = 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001101 struct {
1102 char *name;
1103 test_func fp;
1104 int retval;
1105 } test_cases[] = {
Randall Spangler81d09962010-06-23 10:15:38 -07001106 { TEST_CASE(StructSizeTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001107 { TEST_CASE(TestBuildTestGptData), },
1108 { TEST_CASE(ParameterTests), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001109 { TEST_CASE(HeaderCrcTest), },
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07001110 { TEST_CASE(SignatureTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001111 { TEST_CASE(RevisionTest), },
1112 { TEST_CASE(SizeTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001113 { TEST_CASE(CrcFieldTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001114 { TEST_CASE(ReservedFieldsTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001115 { TEST_CASE(SizeOfPartitionEntryTest), },
1116 { TEST_CASE(NumberOfPartitionEntriesTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001117 { TEST_CASE(MyLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001118 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001119 { TEST_CASE(EntriesCrcTest), },
1120 { TEST_CASE(ValidEntryTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001121 { TEST_CASE(OverlappedPartitionTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001122 { TEST_CASE(SanityCheckTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001123 { TEST_CASE(NoValidKernelEntryTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001124 { TEST_CASE(EntryAttributeGetSetTest), },
1125 { TEST_CASE(EntryTypeTest), },
1126 { TEST_CASE(GetNextNormalTest), },
1127 { TEST_CASE(GetNextPrioTest), },
1128 { TEST_CASE(GetNextTriesTest), },
1129 { TEST_CASE(GptUpdateTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001130 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +08001131 { TEST_CASE(TestCrc32TestVectors), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001132 };
1133
1134 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1135 printf("Running %s() ...\n", test_cases[i].name);
1136 test_cases[i].retval = test_cases[i].fp();
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001137 if (test_cases[i].retval) {
1138 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1139 ++error_count;
1140 } else {
1141 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1142 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001143 }
1144
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001145 if (error_count) {
1146 printf("\n--------------------------------------------------\n");
1147 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP,
1148 error_count);
1149 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1150 if (test_cases[i].retval)
1151 printf(" %s()\n", test_cases[i].name);
1152 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001153 }
1154
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001155 return (error_count) ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001156}