blob: 1ab5342afe00bbb25e7d4d80545debb7bfe2a7ba [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;
139 header->size = sizeof(GptHeader) - sizeof(header->padding);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700140 header->reserved = 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;
160 Memset(header->padding, 0, sizeof(header->padding));
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
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700175/* Tests if the default structure returned by BuildTestGptData() is good. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700176static int TestBuildTestGptData() {
177 GptData* gpt;
178
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700179 gpt = GetEmptyGptData();
180 BuildTestGptData(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700181 EXPECT(GPT_SUCCESS == GptInit(gpt));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700182 return TEST_OK;
183}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700184
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700185
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700186/* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
187 * Currently we only support 512 bytes per sector.
188 * In the future, we may support other sizes.
189 * A too small drive_sectors should be rejected by GptInit(). */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700190static int ParameterTests() {
191 GptData* gpt;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700192 struct {
193 uint32_t sector_bytes;
194 uint64_t drive_sectors;
195 int expected_retval;
196 } cases[] = {
197 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
198 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
199 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
200 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
201 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2,
202 GPT_SUCCESS},
203 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
204 };
205 int i;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700206
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700207 gpt = GetEmptyGptData();
208 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
209 BuildTestGptData(gpt);
210 gpt->sector_bytes = cases[i].sector_bytes;
211 gpt->drive_sectors = cases[i].drive_sectors;
212 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700213 }
214
215 return TEST_OK;
216}
217
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700218
219/* Tests if header CRC in two copies are calculated. */
220static int HeaderCrcTest() {
221 GptData* gpt = GetEmptyGptData();
222 GptHeader* h1 = (GptHeader*)gpt->primary_header;
223
224 BuildTestGptData(gpt);
225 EXPECT(HeaderCrc(h1) == h1->header_crc32);
226
227 /* CRC covers first byte of header */
228 BuildTestGptData(gpt);
229 gpt->primary_header[0] ^= 0xa5;
230 EXPECT(HeaderCrc(h1) != h1->header_crc32);
231
232 /* CRC covers last byte of header */
233 BuildTestGptData(gpt);
234 gpt->primary_header[h1->size - 1] ^= 0x5a;
235 EXPECT(HeaderCrc(h1) != h1->header_crc32);
236
237 /* CRC only covers header */
238 BuildTestGptData(gpt);
239 gpt->primary_header[h1->size] ^= 0x5a;
240 EXPECT(HeaderCrc(h1) == h1->header_crc32);
241
242 return TEST_OK;
243}
244
245
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700246/* Tests if signature ("EFI PART") is checked. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700247static int SignatureTest() {
248 GptData* gpt = GetEmptyGptData();
249 GptHeader* h1 = (GptHeader*)gpt->primary_header;
250 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700251 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700252
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700253 for (i = 0; i < 8; ++i) {
254 BuildTestGptData(gpt);
255 h1->signature[i] ^= 0xff;
256 h2->signature[i] ^= 0xff;
257 RefreshCrc32(gpt);
258 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
259 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700260 }
261
262 return TEST_OK;
263}
264
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700265
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700266/* The revision we currently support is GPT_HEADER_REVISION.
267 * If the revision in header is not that, we expect the header is invalid. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700268static int RevisionTest() {
269 GptData* gpt = GetEmptyGptData();
270 GptHeader* h1 = (GptHeader*)gpt->primary_header;
271 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
272 int i;
273
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700274 struct {
275 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700276 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700277 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700278 {0x01000000, 1},
279 {0x00010000, 0}, /* GPT_HEADER_REVISION */
280 {0x00000100, 1},
281 {0x00000001, 1},
282 {0x23010456, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700283 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700284
285 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700286 BuildTestGptData(gpt);
287 h1->revision = cases[i].value_to_test;
288 h2->revision = cases[i].value_to_test;
289 RefreshCrc32(gpt);
290
291 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
292 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700293 }
294 return TEST_OK;
295}
296
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700297
298static int SizeTest() {
299 GptData* gpt = GetEmptyGptData();
300 GptHeader* h1 = (GptHeader*)gpt->primary_header;
301 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
302 int i;
303
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700304 struct {
305 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700306 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700307 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700308 {91, 1},
309 {92, 0},
310 {93, 0},
311 {511, 0},
312 {512, 0},
313 {513, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700314 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700315
316 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700317 BuildTestGptData(gpt);
318 h1->size = cases[i].value_to_test;
319 h2->size = cases[i].value_to_test;
320 RefreshCrc32(gpt);
321
322 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
323 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700324 }
325 return TEST_OK;
326}
327
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700328
329/* Tests if CRC is checked. */
330static int CrcFieldTest() {
331 GptData* gpt = GetEmptyGptData();
332 GptHeader* h1 = (GptHeader*)gpt->primary_header;
333 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
334
335 BuildTestGptData(gpt);
336 /* Modify a field that the header verification doesn't care about */
337 h1->entries_crc32++;
338 h2->entries_crc32++;
339 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
340 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
341 /* Refresh the CRC; should pass now */
342 RefreshCrc32(gpt);
343 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
344 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
345
346 return TEST_OK;
347}
348
349
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700350/* Tests if reserved fields are checked.
351 * We'll try non-zero values to test. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700352static int ReservedFieldsTest() {
353 GptData* gpt = GetEmptyGptData();
354 GptHeader* h1 = (GptHeader*)gpt->primary_header;
355 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700356
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700357 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700358 h1->reserved ^= 0x12345678; /* whatever random */
359 h2->reserved ^= 0x12345678; /* whatever random */
360 RefreshCrc32(gpt);
361 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
362 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700363
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700364#ifdef PADDING_CHECKED
365 /* TODO: padding check is currently disabled */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700366 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700367 h1->padding[12] ^= 0x34; /* whatever random */
368 h2->padding[56] ^= 0x78; /* whatever random */
369 RefreshCrc32(gpt);
370 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
371 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
372#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700373
374 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700375}
376
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700377
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700378/* Technically, any size which is 2^N where N > 6 should work, but our
379 * library only supports one size. */
380static int SizeOfPartitionEntryTest() {
381 GptData* gpt = GetEmptyGptData();
382 GptHeader* h1 = (GptHeader*)gpt->primary_header;
383 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
384 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700385
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700386 struct {
387 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700388 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700389 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700390 {127, 1},
391 {128, 0},
392 {129, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700393 {256, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700394 {512, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700395 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700396
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700397 /* Check size of entryes */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700398 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700399 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700400 h1->size_of_entry = cases[i].value_to_test;
401 h2->size_of_entry = cases[i].value_to_test;
402 h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
403 h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
404 RefreshCrc32(gpt);
405
406 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
407 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700408 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700409
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700410 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700411}
412
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700413
414/* Technically, any size which is 2^N where N > 6 should work, but our
415 * library only supports one size. */
416static int NumberOfPartitionEntriesTest() {
417 GptData* gpt = GetEmptyGptData();
418 GptHeader* h1 = (GptHeader*)gpt->primary_header;
419 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
420
421 BuildTestGptData(gpt);
422 h1->number_of_entries--;
423 h2->number_of_entries /= 2;
424 RefreshCrc32(gpt);
425 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
426 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
427
428 return TEST_OK;
429}
430
431
432/* Tests if myLBA field is checked (1 for primary, last for secondary). */
433static int MyLbaTest() {
434 GptData* gpt = GetEmptyGptData();
435 GptHeader* h1 = (GptHeader*)gpt->primary_header;
436 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
437
438 /* myLBA depends on primary vs secondary flag */
439 BuildTestGptData(gpt);
440 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
441 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
442
443 BuildTestGptData(gpt);
444 h1->my_lba--;
445 h2->my_lba--;
446 RefreshCrc32(gpt);
447 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
448 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
449
450 BuildTestGptData(gpt);
451 h1->my_lba = 2;
452 h2->my_lba--;
453 RefreshCrc32(gpt);
454 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
455 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
456
Bill Richardson31066a42010-06-03 15:20:19 -0700457 /* We should ignore the alternate_lba field entirely */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700458 BuildTestGptData(gpt);
459 h1->alternate_lba++;
460 h2->alternate_lba++;
461 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700462 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
463 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700464
465 BuildTestGptData(gpt);
466 h1->alternate_lba--;
467 h2->alternate_lba--;
468 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700469 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
470 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700471
472 BuildTestGptData(gpt);
473 h1->entries_lba++;
474 h2->entries_lba++;
475 RefreshCrc32(gpt);
476 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
477 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
478
479 BuildTestGptData(gpt);
480 h1->entries_lba--;
481 h2->entries_lba--;
482 RefreshCrc32(gpt);
483 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
484 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
485
486 return TEST_OK;
487}
488
489
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700490/* Tests if FirstUsableLBA and LastUsableLBA are checked.
491 * FirstUsableLBA must be after the end of the primary GPT table array.
492 * LastUsableLBA must be before the start of the secondary GPT table array.
493 * FirstUsableLBA <= LastUsableLBA. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700494static int FirstUsableLbaAndLastUsableLbaTest() {
495 GptData* gpt = GetEmptyGptData();
496 GptHeader* h1 = (GptHeader*)gpt->primary_header;
497 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700498 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700499
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700500 struct {
501 uint64_t primary_entries_lba;
502 uint64_t primary_first_usable_lba;
503 uint64_t primary_last_usable_lba;
504 uint64_t secondary_first_usable_lba;
505 uint64_t secondary_last_usable_lba;
506 uint64_t secondary_entries_lba;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700507 int primary_rv;
508 int secondary_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700509 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700510 {2, 34, 433, 34, 433, 434, 0, 0},
511 {2, 34, 432, 34, 430, 434, 0, 0},
512 {2, 33, 433, 33, 433, 434, 1, 1},
513 {2, 34, 434, 34, 433, 434, 1, 0},
514 {2, 34, 433, 34, 434, 434, 0, 1},
515 {2, 35, 433, 35, 433, 434, 0, 0},
516 {2, 433, 433, 433, 433, 434, 0, 0},
517 {2, 434, 433, 434, 434, 434, 1, 1},
518 {2, 433, 34, 34, 433, 434, 1, 0},
519 {2, 34, 433, 433, 34, 434, 0, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700520 };
521
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700522 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
523 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700524 h1->entries_lba = cases[i].primary_entries_lba;
525 h1->first_usable_lba = cases[i].primary_first_usable_lba;
526 h1->last_usable_lba = cases[i].primary_last_usable_lba;
527 h2->entries_lba = cases[i].secondary_entries_lba;
528 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
529 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
530 RefreshCrc32(gpt);
531
532 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].primary_rv);
533 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].secondary_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700534 }
535
536 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700537}
538
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700539
540/* Tests if PartitionEntryArrayCRC32 is checked.
541 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
542 * NumberOfPartitionEntries bytes.
543 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700544static int EntriesCrcTest() {
545 GptData* gpt = GetEmptyGptData();
546 GptHeader* h1 = (GptHeader*)gpt->primary_header;
547 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
548 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700549
550 /* Modify the first byte of primary entries, and expect the CRC is wrong. */
551 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700552 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
553 EXPECT(0 == CheckEntries(e2, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700554 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700555 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700556 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
557 EXPECT(1 == CheckEntries(e2, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700558
559 return TEST_OK;
560}
561
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700562
563/* Tests if partition geometry is checked.
564 * All active (non-zero PartitionTypeGUID) partition entries should have:
565 * entry.StartingLBA >= header.FirstUsableLBA
566 * entry.EndingLBA <= header.LastUsableLBA
567 * entry.StartingLBA <= entry.EndingLBA
568 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700569static int ValidEntryTest() {
570 GptData* gpt = GetEmptyGptData();
571 GptHeader* h1 = (GptHeader*)gpt->primary_header;
572 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700573
574 /* error case: entry.StartingLBA < header.FirstUsableLBA */
575 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700576 e1[0].starting_lba = h1->first_usable_lba - 1;
577 RefreshCrc32(gpt);
578 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700579
580 /* error case: entry.EndingLBA > header.LastUsableLBA */
581 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700582 e1[2].ending_lba = h1->last_usable_lba + 1;
583 RefreshCrc32(gpt);
584 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700585
586 /* error case: entry.StartingLBA > entry.EndingLBA */
587 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700588 e1[3].starting_lba = e1[3].ending_lba + 1;
589 RefreshCrc32(gpt);
590 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700591
592 /* case: non active entry should be ignored. */
593 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700594 Memset(&e1[1].type, 0, sizeof(e1[1].type));
595 e1[1].starting_lba = e1[1].ending_lba + 1;
596 RefreshCrc32(gpt);
597 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700598
599 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700600}
601
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700602
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700603/* Tests if overlapped partition tables can be detected. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700604static int OverlappedPartitionTest() {
605 GptData* gpt = GetEmptyGptData();
606 GptHeader* h = (GptHeader*)gpt->primary_header;
607 GptEntry* e = (GptEntry*)gpt->primary_entries;
608 int i, j;
609
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700610 struct {
611 int overlapped;
612 struct {
613 int active;
614 uint64_t starting_lba;
615 uint64_t ending_lba;
616 } entries[16]; /* enough for testing. */
617 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700618 {0, {{0, 100, 199}}},
619 {0, {{1, 100, 199}}},
620 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
621 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
622 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
623 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
624 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
625 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
626 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
627 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
628 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
629 {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
630 {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
631 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
632 {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
633 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
634 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
635 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700636 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
637 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700638 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700639 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
640 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700641 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700642 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700643
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700644
645 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700646 BuildTestGptData(gpt);
647 ZeroEntries(gpt);
648 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
649 if (!cases[i].entries[j].starting_lba)
650 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700651
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700652 if (cases[i].entries[j].active)
653 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
654 e[j].starting_lba = cases[i].entries[j].starting_lba;
655 e[j].ending_lba = cases[i].entries[j].ending_lba;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700656 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700657 RefreshCrc32(gpt);
658
659 EXPECT(cases[i].overlapped == CheckEntries(e, h, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700660 }
661 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700662}
663
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700664
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700665/* Test both sanity checking and repair. */
666static int SanityCheckTest() {
667 GptData* gpt = GetEmptyGptData();
668 GptHeader* h1 = (GptHeader*)gpt->primary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700669
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700670 /* Unmodified test data is completely sane */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700671 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700672 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
673 EXPECT(MASK_BOTH == gpt->valid_headers);
674 EXPECT(MASK_BOTH == gpt->valid_entries);
675 /* Repair doesn't damage it */
676 GptRepair(gpt);
677 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
678 EXPECT(MASK_BOTH == gpt->valid_headers);
679 EXPECT(MASK_BOTH == gpt->valid_entries);
680 EXPECT(0 == gpt->modified);
681
682 /* Modify headers */
683 BuildTestGptData(gpt);
684 gpt->primary_header[0]++;
685 gpt->secondary_header[0]++;
686 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
687 EXPECT(0 == gpt->valid_headers);
688 EXPECT(0 == gpt->valid_entries);
689 /* Repair can't fix completely busted headers */
690 GptRepair(gpt);
691 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
692 EXPECT(0 == gpt->valid_headers);
693 EXPECT(0 == gpt->valid_entries);
694 EXPECT(0 == gpt->modified);
695
696 BuildTestGptData(gpt);
697 gpt->primary_header[0]++;
698 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
699 EXPECT(MASK_SECONDARY == gpt->valid_headers);
700 EXPECT(MASK_BOTH == gpt->valid_entries);
701 GptRepair(gpt);
702 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
703 EXPECT(MASK_BOTH == gpt->valid_headers);
704 EXPECT(MASK_BOTH == gpt->valid_entries);
705 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
706
707 BuildTestGptData(gpt);
708 gpt->secondary_header[0]++;
709 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
710 EXPECT(MASK_PRIMARY == 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_HEADER2 == gpt->modified);
717
718 /* Modify header1 and update its CRC. Since header2 is now different than
719 * header1, it'll be the one considered invalid. */
720 BuildTestGptData(gpt);
721 h1->size++;
722 RefreshCrc32(gpt);
723 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
724 EXPECT(MASK_PRIMARY == gpt->valid_headers);
725 EXPECT(MASK_BOTH == gpt->valid_entries);
726 GptRepair(gpt);
727 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
728 EXPECT(MASK_BOTH == gpt->valid_headers);
729 EXPECT(MASK_BOTH == gpt->valid_entries);
730 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
731
732 /* Modify entries */
733 BuildTestGptData(gpt);
734 gpt->primary_entries[0]++;
735 gpt->secondary_entries[0]++;
736 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
737 EXPECT(MASK_BOTH == gpt->valid_headers);
738 EXPECT(MASK_NONE == gpt->valid_entries);
739 /* Repair can't fix both copies of entries being bad, either. */
740 GptRepair(gpt);
741 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
742 EXPECT(MASK_BOTH == gpt->valid_headers);
743 EXPECT(MASK_NONE == gpt->valid_entries);
744 EXPECT(0 == gpt->modified);
745
746 BuildTestGptData(gpt);
747 gpt->primary_entries[0]++;
748 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
749 EXPECT(MASK_BOTH == gpt->valid_headers);
750 EXPECT(MASK_SECONDARY == gpt->valid_entries);
751 GptRepair(gpt);
752 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
753 EXPECT(MASK_BOTH == gpt->valid_headers);
754 EXPECT(MASK_BOTH == gpt->valid_entries);
755 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
756
757 BuildTestGptData(gpt);
758 gpt->secondary_entries[0]++;
759 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
760 EXPECT(MASK_BOTH == gpt->valid_headers);
761 EXPECT(MASK_PRIMARY == 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_ENTRIES2 == gpt->modified);
767
768 /* Test cross-correction (h1+e2, h2+e1) */
769 BuildTestGptData(gpt);
770 gpt->primary_header[0]++;
771 gpt->secondary_entries[0]++;
772 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
773 EXPECT(MASK_SECONDARY == gpt->valid_headers);
774 EXPECT(MASK_PRIMARY == gpt->valid_entries);
775 GptRepair(gpt);
776 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
777 EXPECT(MASK_BOTH == gpt->valid_headers);
778 EXPECT(MASK_BOTH == gpt->valid_entries);
779 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
780
781 BuildTestGptData(gpt);
782 gpt->secondary_header[0]++;
783 gpt->primary_entries[0]++;
784 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
785 EXPECT(MASK_PRIMARY == gpt->valid_headers);
786 EXPECT(MASK_SECONDARY == 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);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700791 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700792
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700793 /* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.
794 * This simulates a partial update of the drive. */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700795 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700796 gpt->secondary_entries[0]++;
797 RefreshCrc32(gpt);
798 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
799 EXPECT(MASK_PRIMARY == gpt->valid_headers);
800 EXPECT(MASK_PRIMARY == gpt->valid_entries);
801 GptRepair(gpt);
802 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
803 EXPECT(MASK_BOTH == gpt->valid_headers);
804 EXPECT(MASK_BOTH == gpt->valid_entries);
805 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700806
807 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700808}
809
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700810
811static int EntryAttributeGetSetTest() {
812 GptData* gpt = GetEmptyGptData();
813 GptEntry* e = (GptEntry*)(gpt->primary_entries);
814
Colin Chowafdd0582010-06-02 18:20:59 -0700815 e->attributes = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700816 SetEntrySuccessful(e, 1);
Colin Chowafdd0582010-06-02 18:20:59 -0700817 EXPECT(0x0100000000000000LLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700818 EXPECT(1 == GetEntrySuccessful(e));
Colin Chowafdd0582010-06-02 18:20:59 -0700819 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700820 SetEntrySuccessful(e, 0);
Colin Chowafdd0582010-06-02 18:20:59 -0700821 EXPECT(0xFEFFFFFFFFFFFFFFLLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700822 EXPECT(0 == GetEntrySuccessful(e));
823
Colin Chowafdd0582010-06-02 18:20:59 -0700824 e->attributes = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700825 SetEntryTries(e, 15);
826 EXPECT(15 == GetEntryTries(e));
Colin Chowafdd0582010-06-02 18:20:59 -0700827 EXPECT(0x00F0000000000000LLU == e->attributes);
828 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700829 SetEntryTries(e, 0);
Colin Chowafdd0582010-06-02 18:20:59 -0700830 EXPECT(0xFF0FFFFFFFFFFFFFLLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700831 EXPECT(0 == GetEntryTries(e));
832
Colin Chowafdd0582010-06-02 18:20:59 -0700833 e->attributes = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700834 SetEntryPriority(e, 15);
Colin Chowafdd0582010-06-02 18:20:59 -0700835 EXPECT(0x000F000000000000LLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700836 EXPECT(15 == GetEntryPriority(e));
Colin Chowafdd0582010-06-02 18:20:59 -0700837 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700838 SetEntryPriority(e, 0);
Colin Chowafdd0582010-06-02 18:20:59 -0700839 EXPECT(0xFFF0FFFFFFFFFFFFLLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700840 EXPECT(0 == GetEntryPriority(e));
841
Colin Chowafdd0582010-06-02 18:20:59 -0700842 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700843 EXPECT(1 == GetEntrySuccessful(e));
844 EXPECT(15 == GetEntryPriority(e));
845 EXPECT(15 == GetEntryTries(e));
846
Colin Chowafdd0582010-06-02 18:20:59 -0700847 e->attributes = 0x0123000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700848 EXPECT(1 == GetEntrySuccessful(e));
849 EXPECT(2 == GetEntryTries(e));
850 EXPECT(3 == GetEntryPriority(e));
851
852 return TEST_OK;
853}
854
855
856static int EntryTypeTest() {
857 GptData* gpt = GetEmptyGptData();
858 GptEntry* e = (GptEntry*)(gpt->primary_entries);
859
860 Memcpy(&e->type, &guid_zero, sizeof(Guid));
861 EXPECT(1 == IsUnusedEntry(e));
862 EXPECT(0 == IsKernelEntry(e));
863
864 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
865 EXPECT(0 == IsUnusedEntry(e));
866 EXPECT(1 == IsKernelEntry(e));
867
868 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
869 EXPECT(0 == IsUnusedEntry(e));
870 EXPECT(0 == IsKernelEntry(e));
871
872 return TEST_OK;
873}
874
875
876/* Make an entry unused by clearing its type. */
877static void FreeEntry(GptEntry* e) {
878 Memset(&e->type, 0, sizeof(Guid));
879}
880
881
882/* Set up an entry. */
883static void FillEntry(GptEntry* e, int is_kernel,
884 int priority, int successful, int tries) {
885 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
886 SetEntryPriority(e, priority);
887 SetEntrySuccessful(e, successful);
888 SetEntryTries(e, tries);
889}
890
891
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700892/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
893 * any usable kernel entry.
894 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700895static int NoValidKernelEntryTest() {
896 GptData* gpt = GetEmptyGptData();
897 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700898
899 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700900 SetEntryPriority(e1 + KERNEL_A, 0);
901 FreeEntry(e1 + KERNEL_B);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700902 RefreshCrc32(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700903 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
904
905 return TEST_OK;
906}
907
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700908
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700909static int GetNextNormalTest() {
910 GptData* gpt = GetEmptyGptData();
911 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
912 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700913
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700914 /* Normal case - both kernels successful */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700915 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700916 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
917 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
918 RefreshCrc32(gpt);
919 GptInit(gpt);
920
921 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
922 EXPECT(KERNEL_A == gpt->current_kernel);
923 EXPECT(34 == start);
924 EXPECT(100 == size);
925
926 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
927 EXPECT(KERNEL_B == gpt->current_kernel);
928 EXPECT(134 == start);
929 EXPECT(99 == size);
930
931 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
932 EXPECT(-1 == gpt->current_kernel);
933
934 /* Call as many times as you want; you won't get another kernel... */
935 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
936 EXPECT(-1 == gpt->current_kernel);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700937
938 return TEST_OK;
939}
940
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700941
942static int GetNextPrioTest() {
943 GptData* gpt = GetEmptyGptData();
944 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
945 uint64_t start, size;
946
947 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
948 BuildTestGptData(gpt);
949 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
950 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
951 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
952 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
953 RefreshCrc32(gpt);
954 GptInit(gpt);
955
956 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
957 EXPECT(KERNEL_B == gpt->current_kernel);
958 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
959 EXPECT(KERNEL_Y == gpt->current_kernel);
960 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
961 EXPECT(KERNEL_A == gpt->current_kernel);
962 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
963
964 return TEST_OK;
965}
966
967
968static int GetNextTriesTest() {
969 GptData* gpt = GetEmptyGptData();
970 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
971 uint64_t start, size;
972
973 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
974 BuildTestGptData(gpt);
975 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
976 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
977 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
978 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
979 RefreshCrc32(gpt);
980 GptInit(gpt);
981
982 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
983 EXPECT(KERNEL_X == gpt->current_kernel);
984 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
985 EXPECT(KERNEL_A == gpt->current_kernel);
986 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
987
988 return TEST_OK;
989}
990
991
992static int GptUpdateTest() {
993 GptData* gpt = GetEmptyGptData();
994 GptEntry* e = (GptEntry*)(gpt->primary_entries);
995 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
996 uint64_t start, size;
997
998 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
999 BuildTestGptData(gpt);
1000 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1001 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1002 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1003 RefreshCrc32(gpt);
1004 GptInit(gpt);
1005 gpt->modified = 0; /* Nothing modified yet */
1006
1007 /* Successful kernel */
1008 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1009 EXPECT(KERNEL_A == gpt->current_kernel);
1010 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1011 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1012 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1013 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1014 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1015 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1016 /* Trying successful kernel changes nothing */
1017 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1018 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1019 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1020 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1021 EXPECT(0 == gpt->modified);
1022 /* Marking it bad does, though */
1023 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1024 EXPECT(0 == GetEntrySuccessful(e + KERNEL_A));
1025 EXPECT(0 == GetEntryPriority(e + KERNEL_A));
1026 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1027 /* Which affects both copies of the partition entries */
1028 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_A));
1029 EXPECT(0 == GetEntryPriority(e2 + KERNEL_A));
1030 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1031 /* And that's caused the GPT to need updating */
1032 EXPECT(0x0F == gpt->modified);
1033
1034 /* Kernel with tries */
1035 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1036 EXPECT(KERNEL_B == gpt->current_kernel);
1037 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1038 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1039 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1040 /* Marking it bad clears it */
1041 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1042 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1043 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1044 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1045
1046 /* Another kernel with tries */
1047 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1048 EXPECT(KERNEL_X == gpt->current_kernel);
1049 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1050 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1051 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1052 /* Trying it uses up a try */
1053 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1054 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1055 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1056 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1057 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1058 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1059 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1060 /* Trying it again marks it inactive */
1061 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1062 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1063 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1064 EXPECT(0 == GetEntryTries(e + KERNEL_X));
1065
1066 return TEST_OK;
1067}
1068
1069
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001070/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
1071 * GPT_ERROR_INVALID_UPDATE_TYPE. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001072static int UpdateInvalidKernelTypeTest() {
1073 GptData* gpt = GetEmptyGptData();
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001074
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001075 BuildTestGptData(gpt);
1076 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1077 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1078 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
1079
1080 return TEST_OK;
1081}
1082
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001083
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001084int main(int argc, char *argv[]) {
1085 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001086 int error_count = 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001087 struct {
1088 char *name;
1089 test_func fp;
1090 int retval;
1091 } test_cases[] = {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001092 { TEST_CASE(TestBuildTestGptData), },
1093 { TEST_CASE(ParameterTests), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001094 { TEST_CASE(HeaderCrcTest), },
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07001095 { TEST_CASE(SignatureTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001096 { TEST_CASE(RevisionTest), },
1097 { TEST_CASE(SizeTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001098 { TEST_CASE(CrcFieldTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001099 { TEST_CASE(ReservedFieldsTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001100 { TEST_CASE(SizeOfPartitionEntryTest), },
1101 { TEST_CASE(NumberOfPartitionEntriesTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001102 { TEST_CASE(MyLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001103 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001104 { TEST_CASE(EntriesCrcTest), },
1105 { TEST_CASE(ValidEntryTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001106 { TEST_CASE(OverlappedPartitionTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001107 { TEST_CASE(SanityCheckTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001108 { TEST_CASE(NoValidKernelEntryTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001109 { TEST_CASE(EntryAttributeGetSetTest), },
1110 { TEST_CASE(EntryTypeTest), },
1111 { TEST_CASE(GetNextNormalTest), },
1112 { TEST_CASE(GetNextPrioTest), },
1113 { TEST_CASE(GetNextTriesTest), },
1114 { TEST_CASE(GptUpdateTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001115 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +08001116 { TEST_CASE(TestCrc32TestVectors), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001117 };
1118
1119 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1120 printf("Running %s() ...\n", test_cases[i].name);
1121 test_cases[i].retval = test_cases[i].fp();
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001122 if (test_cases[i].retval) {
1123 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1124 ++error_count;
1125 } else {
1126 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1127 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001128 }
1129
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001130 if (error_count) {
1131 printf("\n--------------------------------------------------\n");
1132 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP,
1133 error_count);
1134 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1135 if (test_cases[i].retval)
1136 printf(" %s()\n", test_cases[i].name);
1137 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001138 }
1139
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001140 return (error_count) ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001141}