blob: f016b212fb5fa1529ef08e19932df23d3f965ca8 [file] [log] [blame]
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07006#include <string.h>
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07007
Louis Yung-Chieh Lo0dce41c2010-05-17 22:45:30 -07008#include "cgptlib.h"
9#include "cgptlib_internal.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070010#include "cgptlib_test.h"
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070011#include "crc32.h"
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +080012#include "crc32_test.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070013#include "gpt.h"
14#include "utility.h"
15
16/* Testing partition layout (sector_bytes=512)
17 *
18 * LBA Size Usage
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070019 * ---------------------------------------------------------
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070020 * 0 1 PMBR
21 * 1 1 primary partition header
22 * 2 32 primary partition entries (128B * 128)
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070023 * 34 100 kernel A (index: 0)
24 * 134 100 root A (index: 1)
25 * 234 100 root B (index: 2)
26 * 334 100 kernel B (index: 3)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070027 * 434 32 secondary partition entries
28 * 466 1 secondary partition header
29 * 467
30 */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070031#define KERNEL_A 0
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070032#define KERNEL_B 1
33#define ROOTFS_A 2
34#define ROOTFS_B 3
35#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
36#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070037
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070038#define DEFAULT_SECTOR_SIZE 512
39#define MAX_SECTOR_SIZE 4096
40#define DEFAULT_DRIVE_SECTORS 467
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070041#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070042
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070043static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
44static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
45static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
46
47
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070048/* Given a GptData pointer, first re-calculate entries CRC32 value,
49 * then reset header CRC32 value to 0, and calculate header CRC32 value.
50 * Both primary and secondary are updated. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070051static void RefreshCrc32(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070052 GptHeader *header, *header2;
53 GptEntry *entries, *entries2;
54
55 header = (GptHeader*)gpt->primary_header;
56 entries = (GptEntry*)gpt->primary_entries;
57 header2 = (GptHeader*)gpt->secondary_header;
58 entries2 = (GptEntry*)gpt->secondary_entries;
59
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070060 header->entries_crc32 =
61 Crc32((uint8_t*)entries,
62 header->number_of_entries * header->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070063 header->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070064 header->header_crc32 = Crc32((uint8_t*)header, header->size);
65 header2->entries_crc32 =
66 Crc32((uint8_t*)entries2,
67 header2->number_of_entries * header2->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070068 header2->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070069 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size);
70}
71
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070072
73static void ZeroHeaders(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070074 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
75 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
76}
77
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070078
79static void ZeroEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070080 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
81 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
82}
83
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070084
85static void ZeroHeadersEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070086 ZeroHeaders(gpt);
87 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070088}
89
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070090
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070091/* Returns a pointer to a static GptData instance (no free is required).
92 * All fields are zero except 4 pointers linking to header and entries.
93 * All content of headers and entries are zero. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070094static GptData* GetEmptyGptData() {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070095 static GptData gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070096 static uint8_t primary_header[MAX_SECTOR_SIZE];
97 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
98 static uint8_t secondary_header[MAX_SECTOR_SIZE];
99 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
100
101 Memset(&gpt, 0, sizeof(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700102 gpt.primary_header = primary_header;
103 gpt.primary_entries = primary_entries;
104 gpt.secondary_header = secondary_header;
105 gpt.secondary_entries = secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700106 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700107
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700108 /* Initialize GptData internal states. */
109 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
110
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700111 return &gpt;
112}
113
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700114
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700115/* Fills in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700116 * file. Before calling this function, primary/secondary header/entries must
117 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
118 * This function returns a good (valid) copy of GPT layout described in top of
119 * this file. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700120static void BuildTestGptData(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700121 GptHeader *header, *header2;
122 GptEntry *entries, *entries2;
123 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700124 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700125
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700126 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700127 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700128 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lo418ad3b2010-05-27 11:21:17 +0800129 gpt->valid_headers = MASK_BOTH;
130 gpt->valid_entries = MASK_BOTH;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700131 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700132
133 /* build primary */
134 header = (GptHeader*)gpt->primary_header;
135 entries = (GptEntry*)gpt->primary_entries;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700136 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
137 sizeof(GPT_HEADER_SIGNATURE));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700138 header->revision = GPT_HEADER_REVISION;
Bill Richardsonf1372d92010-06-11 09:15:55 -0700139 header->size = sizeof(GptHeader);
140 header->reserved_zero = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700141 header->my_lba = 1;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700142 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700143 header->first_usable_lba = 34;
144 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
145 header->entries_lba = 2;
146 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */
147 header->size_of_entry = 128; /* bytes */
148 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
149 entries[0].starting_lba = 34;
150 entries[0].ending_lba = 133;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700151 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700152 entries[1].starting_lba = 134;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700153 entries[1].ending_lba = 232;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700154 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700155 entries[2].starting_lba = 234;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700156 entries[2].ending_lba = 331;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700157 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
158 entries[3].starting_lba = 334;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700159 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700160
161 /* build secondary */
162 header2 = (GptHeader*)gpt->secondary_header;
163 entries2 = (GptEntry*)gpt->secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700164 Memcpy(header2, header, sizeof(GptHeader));
165 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700166 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700167 header2->alternate_lba = 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700168 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
169
170 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700171}
172
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700173
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700174/* Tests if the default structure returned by BuildTestGptData() is good. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700175static int TestBuildTestGptData() {
176 GptData* gpt;
177
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700178 gpt = GetEmptyGptData();
179 BuildTestGptData(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700180 EXPECT(GPT_SUCCESS == GptInit(gpt));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700181 return TEST_OK;
182}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700183
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700184
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700185/* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
186 * Currently we only support 512 bytes per sector.
187 * In the future, we may support other sizes.
188 * A too small drive_sectors should be rejected by GptInit(). */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700189static int ParameterTests() {
190 GptData* gpt;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700191 struct {
192 uint32_t sector_bytes;
193 uint64_t drive_sectors;
194 int expected_retval;
195 } cases[] = {
196 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
197 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
198 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
199 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
200 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2,
201 GPT_SUCCESS},
202 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
203 };
204 int i;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700205
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700206 gpt = GetEmptyGptData();
207 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
208 BuildTestGptData(gpt);
209 gpt->sector_bytes = cases[i].sector_bytes;
210 gpt->drive_sectors = cases[i].drive_sectors;
211 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700212 }
213
214 return TEST_OK;
215}
216
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700217
218/* Tests if header CRC in two copies are calculated. */
219static int HeaderCrcTest() {
220 GptData* gpt = GetEmptyGptData();
221 GptHeader* h1 = (GptHeader*)gpt->primary_header;
222
223 BuildTestGptData(gpt);
224 EXPECT(HeaderCrc(h1) == h1->header_crc32);
225
226 /* CRC covers first byte of header */
227 BuildTestGptData(gpt);
228 gpt->primary_header[0] ^= 0xa5;
229 EXPECT(HeaderCrc(h1) != h1->header_crc32);
230
231 /* CRC covers last byte of header */
232 BuildTestGptData(gpt);
233 gpt->primary_header[h1->size - 1] ^= 0x5a;
234 EXPECT(HeaderCrc(h1) != h1->header_crc32);
235
236 /* CRC only covers header */
237 BuildTestGptData(gpt);
238 gpt->primary_header[h1->size] ^= 0x5a;
239 EXPECT(HeaderCrc(h1) == h1->header_crc32);
240
241 return TEST_OK;
242}
243
244
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700245/* Tests if signature ("EFI PART") is checked. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700246static int SignatureTest() {
247 GptData* gpt = GetEmptyGptData();
248 GptHeader* h1 = (GptHeader*)gpt->primary_header;
249 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700250 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700251
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700252 for (i = 0; i < 8; ++i) {
253 BuildTestGptData(gpt);
254 h1->signature[i] ^= 0xff;
255 h2->signature[i] ^= 0xff;
256 RefreshCrc32(gpt);
257 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
258 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700259 }
260
261 return TEST_OK;
262}
263
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700264
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700265/* The revision we currently support is GPT_HEADER_REVISION.
266 * If the revision in header is not that, we expect the header is invalid. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700267static int RevisionTest() {
268 GptData* gpt = GetEmptyGptData();
269 GptHeader* h1 = (GptHeader*)gpt->primary_header;
270 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
271 int i;
272
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700273 struct {
274 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700275 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700276 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700277 {0x01000000, 1},
278 {0x00010000, 0}, /* GPT_HEADER_REVISION */
279 {0x00000100, 1},
280 {0x00000001, 1},
281 {0x23010456, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700282 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700283
284 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700285 BuildTestGptData(gpt);
286 h1->revision = cases[i].value_to_test;
287 h2->revision = cases[i].value_to_test;
288 RefreshCrc32(gpt);
289
290 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
291 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700292 }
293 return TEST_OK;
294}
295
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700296
297static int SizeTest() {
298 GptData* gpt = GetEmptyGptData();
299 GptHeader* h1 = (GptHeader*)gpt->primary_header;
300 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
301 int i;
302
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700303 struct {
304 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700305 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700306 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700307 {91, 1},
308 {92, 0},
309 {93, 0},
310 {511, 0},
311 {512, 0},
312 {513, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700313 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700314
315 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700316 BuildTestGptData(gpt);
317 h1->size = cases[i].value_to_test;
318 h2->size = cases[i].value_to_test;
319 RefreshCrc32(gpt);
320
321 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
322 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700323 }
324 return TEST_OK;
325}
326
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700327
328/* Tests if CRC is checked. */
329static int CrcFieldTest() {
330 GptData* gpt = GetEmptyGptData();
331 GptHeader* h1 = (GptHeader*)gpt->primary_header;
332 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
333
334 BuildTestGptData(gpt);
335 /* Modify a field that the header verification doesn't care about */
336 h1->entries_crc32++;
337 h2->entries_crc32++;
338 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
339 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
340 /* Refresh the CRC; should pass now */
341 RefreshCrc32(gpt);
342 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
343 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
344
345 return TEST_OK;
346}
347
348
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700349/* Tests if reserved fields are checked.
350 * We'll try non-zero values to test. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700351static int ReservedFieldsTest() {
352 GptData* gpt = GetEmptyGptData();
353 GptHeader* h1 = (GptHeader*)gpt->primary_header;
354 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700355
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700356 BuildTestGptData(gpt);
Bill Richardsonf1372d92010-06-11 09:15:55 -0700357 h1->reserved_zero ^= 0x12345678; /* whatever random */
358 h2->reserved_zero ^= 0x12345678; /* whatever random */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700359 RefreshCrc32(gpt);
360 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
361 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700362
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700363#ifdef PADDING_CHECKED
364 /* TODO: padding check is currently disabled */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700365 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700366 h1->padding[12] ^= 0x34; /* whatever random */
367 h2->padding[56] ^= 0x78; /* whatever random */
368 RefreshCrc32(gpt);
369 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
370 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
371#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700372
373 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700374}
375
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700376
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700377/* Technically, any size which is 2^N where N > 6 should work, but our
378 * library only supports one size. */
379static int SizeOfPartitionEntryTest() {
380 GptData* gpt = GetEmptyGptData();
381 GptHeader* h1 = (GptHeader*)gpt->primary_header;
382 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
383 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700384
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700385 struct {
386 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700387 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700388 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700389 {127, 1},
390 {128, 0},
391 {129, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700392 {256, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700393 {512, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700394 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700395
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700396 /* Check size of entryes */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700397 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700398 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700399 h1->size_of_entry = cases[i].value_to_test;
400 h2->size_of_entry = cases[i].value_to_test;
401 h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
402 h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
403 RefreshCrc32(gpt);
404
405 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
406 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700407 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700408
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700409 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700410}
411
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700412
413/* Technically, any size which is 2^N where N > 6 should work, but our
414 * library only supports one size. */
415static int NumberOfPartitionEntriesTest() {
416 GptData* gpt = GetEmptyGptData();
417 GptHeader* h1 = (GptHeader*)gpt->primary_header;
418 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
419
420 BuildTestGptData(gpt);
421 h1->number_of_entries--;
422 h2->number_of_entries /= 2;
423 RefreshCrc32(gpt);
424 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
425 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
426
427 return TEST_OK;
428}
429
430
431/* Tests if myLBA field is checked (1 for primary, last for secondary). */
432static int MyLbaTest() {
433 GptData* gpt = GetEmptyGptData();
434 GptHeader* h1 = (GptHeader*)gpt->primary_header;
435 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
436
437 /* myLBA depends on primary vs secondary flag */
438 BuildTestGptData(gpt);
439 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
440 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
441
442 BuildTestGptData(gpt);
443 h1->my_lba--;
444 h2->my_lba--;
445 RefreshCrc32(gpt);
446 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
447 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
448
449 BuildTestGptData(gpt);
450 h1->my_lba = 2;
451 h2->my_lba--;
452 RefreshCrc32(gpt);
453 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
454 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
455
Bill Richardson31066a42010-06-03 15:20:19 -0700456 /* We should ignore the alternate_lba field entirely */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700457 BuildTestGptData(gpt);
458 h1->alternate_lba++;
459 h2->alternate_lba++;
460 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700461 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
462 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700463
464 BuildTestGptData(gpt);
465 h1->alternate_lba--;
466 h2->alternate_lba--;
467 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700468 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
469 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700470
471 BuildTestGptData(gpt);
472 h1->entries_lba++;
473 h2->entries_lba++;
474 RefreshCrc32(gpt);
475 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
476 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
477
478 BuildTestGptData(gpt);
479 h1->entries_lba--;
480 h2->entries_lba--;
481 RefreshCrc32(gpt);
482 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
483 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
484
485 return TEST_OK;
486}
487
488
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700489/* Tests if FirstUsableLBA and LastUsableLBA are checked.
490 * FirstUsableLBA must be after the end of the primary GPT table array.
491 * LastUsableLBA must be before the start of the secondary GPT table array.
492 * FirstUsableLBA <= LastUsableLBA. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700493static int FirstUsableLbaAndLastUsableLbaTest() {
494 GptData* gpt = GetEmptyGptData();
495 GptHeader* h1 = (GptHeader*)gpt->primary_header;
496 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700497 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700498
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700499 struct {
500 uint64_t primary_entries_lba;
501 uint64_t primary_first_usable_lba;
502 uint64_t primary_last_usable_lba;
503 uint64_t secondary_first_usable_lba;
504 uint64_t secondary_last_usable_lba;
505 uint64_t secondary_entries_lba;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700506 int primary_rv;
507 int secondary_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700508 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700509 {2, 34, 433, 34, 433, 434, 0, 0},
510 {2, 34, 432, 34, 430, 434, 0, 0},
511 {2, 33, 433, 33, 433, 434, 1, 1},
512 {2, 34, 434, 34, 433, 434, 1, 0},
513 {2, 34, 433, 34, 434, 434, 0, 1},
514 {2, 35, 433, 35, 433, 434, 0, 0},
515 {2, 433, 433, 433, 433, 434, 0, 0},
516 {2, 434, 433, 434, 434, 434, 1, 1},
517 {2, 433, 34, 34, 433, 434, 1, 0},
518 {2, 34, 433, 433, 34, 434, 0, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700519 };
520
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700521 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
522 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700523 h1->entries_lba = cases[i].primary_entries_lba;
524 h1->first_usable_lba = cases[i].primary_first_usable_lba;
525 h1->last_usable_lba = cases[i].primary_last_usable_lba;
526 h2->entries_lba = cases[i].secondary_entries_lba;
527 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
528 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
529 RefreshCrc32(gpt);
530
531 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].primary_rv);
532 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].secondary_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700533 }
534
535 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700536}
537
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700538
539/* Tests if PartitionEntryArrayCRC32 is checked.
540 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
541 * NumberOfPartitionEntries bytes.
542 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700543static int EntriesCrcTest() {
544 GptData* gpt = GetEmptyGptData();
545 GptHeader* h1 = (GptHeader*)gpt->primary_header;
546 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
547 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700548
549 /* Modify the first byte of primary entries, and expect the CRC is wrong. */
550 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700551 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
552 EXPECT(0 == CheckEntries(e2, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700553 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700554 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700555 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
556 EXPECT(1 == CheckEntries(e2, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700557
558 return TEST_OK;
559}
560
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700561
562/* Tests if partition geometry is checked.
563 * All active (non-zero PartitionTypeGUID) partition entries should have:
564 * entry.StartingLBA >= header.FirstUsableLBA
565 * entry.EndingLBA <= header.LastUsableLBA
566 * entry.StartingLBA <= entry.EndingLBA
567 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700568static int ValidEntryTest() {
569 GptData* gpt = GetEmptyGptData();
570 GptHeader* h1 = (GptHeader*)gpt->primary_header;
571 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700572
573 /* error case: entry.StartingLBA < header.FirstUsableLBA */
574 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700575 e1[0].starting_lba = h1->first_usable_lba - 1;
576 RefreshCrc32(gpt);
577 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700578
579 /* error case: entry.EndingLBA > header.LastUsableLBA */
580 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700581 e1[2].ending_lba = h1->last_usable_lba + 1;
582 RefreshCrc32(gpt);
583 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700584
585 /* error case: entry.StartingLBA > entry.EndingLBA */
586 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700587 e1[3].starting_lba = e1[3].ending_lba + 1;
588 RefreshCrc32(gpt);
589 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700590
591 /* case: non active entry should be ignored. */
592 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700593 Memset(&e1[1].type, 0, sizeof(e1[1].type));
594 e1[1].starting_lba = e1[1].ending_lba + 1;
595 RefreshCrc32(gpt);
596 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700597
598 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700599}
600
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700601
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700602/* Tests if overlapped partition tables can be detected. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700603static int OverlappedPartitionTest() {
604 GptData* gpt = GetEmptyGptData();
605 GptHeader* h = (GptHeader*)gpt->primary_header;
606 GptEntry* e = (GptEntry*)gpt->primary_entries;
607 int i, j;
608
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700609 struct {
610 int overlapped;
611 struct {
612 int active;
613 uint64_t starting_lba;
614 uint64_t ending_lba;
615 } entries[16]; /* enough for testing. */
616 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700617 {0, {{0, 100, 199}}},
618 {0, {{1, 100, 199}}},
619 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
620 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
621 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
622 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
623 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
624 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
625 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
626 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
627 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
628 {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
629 {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
630 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
631 {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
632 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
633 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
634 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700635 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
636 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700637 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700638 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
639 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700640 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700641 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700642
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700643
644 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700645 BuildTestGptData(gpt);
646 ZeroEntries(gpt);
647 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
648 if (!cases[i].entries[j].starting_lba)
649 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700650
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700651 if (cases[i].entries[j].active)
652 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
653 e[j].starting_lba = cases[i].entries[j].starting_lba;
654 e[j].ending_lba = cases[i].entries[j].ending_lba;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700655 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700656 RefreshCrc32(gpt);
657
658 EXPECT(cases[i].overlapped == CheckEntries(e, h, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700659 }
660 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700661}
662
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700663
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700664/* Test both sanity checking and repair. */
665static int SanityCheckTest() {
666 GptData* gpt = GetEmptyGptData();
667 GptHeader* h1 = (GptHeader*)gpt->primary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700668
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700669 /* Unmodified test data is completely sane */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700670 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700671 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
672 EXPECT(MASK_BOTH == gpt->valid_headers);
673 EXPECT(MASK_BOTH == gpt->valid_entries);
674 /* Repair doesn't damage it */
675 GptRepair(gpt);
676 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
677 EXPECT(MASK_BOTH == gpt->valid_headers);
678 EXPECT(MASK_BOTH == gpt->valid_entries);
679 EXPECT(0 == gpt->modified);
680
681 /* Modify headers */
682 BuildTestGptData(gpt);
683 gpt->primary_header[0]++;
684 gpt->secondary_header[0]++;
685 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
686 EXPECT(0 == gpt->valid_headers);
687 EXPECT(0 == gpt->valid_entries);
688 /* Repair can't fix completely busted headers */
689 GptRepair(gpt);
690 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
691 EXPECT(0 == gpt->valid_headers);
692 EXPECT(0 == gpt->valid_entries);
693 EXPECT(0 == gpt->modified);
694
695 BuildTestGptData(gpt);
696 gpt->primary_header[0]++;
697 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
698 EXPECT(MASK_SECONDARY == gpt->valid_headers);
699 EXPECT(MASK_BOTH == gpt->valid_entries);
700 GptRepair(gpt);
701 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
702 EXPECT(MASK_BOTH == gpt->valid_headers);
703 EXPECT(MASK_BOTH == gpt->valid_entries);
704 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
705
706 BuildTestGptData(gpt);
707 gpt->secondary_header[0]++;
708 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
709 EXPECT(MASK_PRIMARY == gpt->valid_headers);
710 EXPECT(MASK_BOTH == gpt->valid_entries);
711 GptRepair(gpt);
712 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
713 EXPECT(MASK_BOTH == gpt->valid_headers);
714 EXPECT(MASK_BOTH == gpt->valid_entries);
715 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
716
717 /* Modify header1 and update its CRC. Since header2 is now different than
718 * header1, it'll be the one considered invalid. */
719 BuildTestGptData(gpt);
720 h1->size++;
721 RefreshCrc32(gpt);
722 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
723 EXPECT(MASK_PRIMARY == gpt->valid_headers);
724 EXPECT(MASK_BOTH == gpt->valid_entries);
725 GptRepair(gpt);
726 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
727 EXPECT(MASK_BOTH == gpt->valid_headers);
728 EXPECT(MASK_BOTH == gpt->valid_entries);
729 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
730
731 /* Modify entries */
732 BuildTestGptData(gpt);
733 gpt->primary_entries[0]++;
734 gpt->secondary_entries[0]++;
735 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
736 EXPECT(MASK_BOTH == gpt->valid_headers);
737 EXPECT(MASK_NONE == gpt->valid_entries);
738 /* Repair can't fix both copies of entries being bad, either. */
739 GptRepair(gpt);
740 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
741 EXPECT(MASK_BOTH == gpt->valid_headers);
742 EXPECT(MASK_NONE == gpt->valid_entries);
743 EXPECT(0 == gpt->modified);
744
745 BuildTestGptData(gpt);
746 gpt->primary_entries[0]++;
747 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
748 EXPECT(MASK_BOTH == gpt->valid_headers);
749 EXPECT(MASK_SECONDARY == gpt->valid_entries);
750 GptRepair(gpt);
751 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
752 EXPECT(MASK_BOTH == gpt->valid_headers);
753 EXPECT(MASK_BOTH == gpt->valid_entries);
754 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
755
756 BuildTestGptData(gpt);
757 gpt->secondary_entries[0]++;
758 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
759 EXPECT(MASK_BOTH == gpt->valid_headers);
760 EXPECT(MASK_PRIMARY == gpt->valid_entries);
761 GptRepair(gpt);
762 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
763 EXPECT(MASK_BOTH == gpt->valid_headers);
764 EXPECT(MASK_BOTH == gpt->valid_entries);
765 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
766
767 /* Test cross-correction (h1+e2, h2+e1) */
768 BuildTestGptData(gpt);
769 gpt->primary_header[0]++;
770 gpt->secondary_entries[0]++;
771 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
772 EXPECT(MASK_SECONDARY == 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_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
779
780 BuildTestGptData(gpt);
781 gpt->secondary_header[0]++;
782 gpt->primary_entries[0]++;
783 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
784 EXPECT(MASK_PRIMARY == gpt->valid_headers);
785 EXPECT(MASK_SECONDARY == gpt->valid_entries);
786 GptRepair(gpt);
787 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
788 EXPECT(MASK_BOTH == gpt->valid_headers);
789 EXPECT(MASK_BOTH == gpt->valid_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700790 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700791
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700792 /* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.
793 * This simulates a partial update of the drive. */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700794 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700795 gpt->secondary_entries[0]++;
796 RefreshCrc32(gpt);
797 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
798 EXPECT(MASK_PRIMARY == gpt->valid_headers);
799 EXPECT(MASK_PRIMARY == gpt->valid_entries);
800 GptRepair(gpt);
801 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
802 EXPECT(MASK_BOTH == gpt->valid_headers);
803 EXPECT(MASK_BOTH == gpt->valid_entries);
804 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700805
806 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700807}
808
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700809
810static int EntryAttributeGetSetTest() {
811 GptData* gpt = GetEmptyGptData();
812 GptEntry* e = (GptEntry*)(gpt->primary_entries);
813
Colin Chowafdd0582010-06-02 18:20:59 -0700814 e->attributes = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700815 SetEntrySuccessful(e, 1);
Colin Chowafdd0582010-06-02 18:20:59 -0700816 EXPECT(0x0100000000000000LLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700817 EXPECT(1 == GetEntrySuccessful(e));
Colin Chowafdd0582010-06-02 18:20:59 -0700818 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700819 SetEntrySuccessful(e, 0);
Colin Chowafdd0582010-06-02 18:20:59 -0700820 EXPECT(0xFEFFFFFFFFFFFFFFLLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700821 EXPECT(0 == GetEntrySuccessful(e));
822
Colin Chowafdd0582010-06-02 18:20:59 -0700823 e->attributes = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700824 SetEntryTries(e, 15);
825 EXPECT(15 == GetEntryTries(e));
Colin Chowafdd0582010-06-02 18:20:59 -0700826 EXPECT(0x00F0000000000000LLU == e->attributes);
827 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700828 SetEntryTries(e, 0);
Colin Chowafdd0582010-06-02 18:20:59 -0700829 EXPECT(0xFF0FFFFFFFFFFFFFLLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700830 EXPECT(0 == GetEntryTries(e));
831
Colin Chowafdd0582010-06-02 18:20:59 -0700832 e->attributes = 0x0000000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700833 SetEntryPriority(e, 15);
Colin Chowafdd0582010-06-02 18:20:59 -0700834 EXPECT(0x000F000000000000LLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700835 EXPECT(15 == GetEntryPriority(e));
Colin Chowafdd0582010-06-02 18:20:59 -0700836 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700837 SetEntryPriority(e, 0);
Colin Chowafdd0582010-06-02 18:20:59 -0700838 EXPECT(0xFFF0FFFFFFFFFFFFLLU == e->attributes);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700839 EXPECT(0 == GetEntryPriority(e));
840
Colin Chowafdd0582010-06-02 18:20:59 -0700841 e->attributes = 0xFFFFFFFFFFFFFFFFLLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700842 EXPECT(1 == GetEntrySuccessful(e));
843 EXPECT(15 == GetEntryPriority(e));
844 EXPECT(15 == GetEntryTries(e));
845
Colin Chowafdd0582010-06-02 18:20:59 -0700846 e->attributes = 0x0123000000000000LLU;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700847 EXPECT(1 == GetEntrySuccessful(e));
848 EXPECT(2 == GetEntryTries(e));
849 EXPECT(3 == GetEntryPriority(e));
850
851 return TEST_OK;
852}
853
854
855static int EntryTypeTest() {
856 GptData* gpt = GetEmptyGptData();
857 GptEntry* e = (GptEntry*)(gpt->primary_entries);
858
859 Memcpy(&e->type, &guid_zero, sizeof(Guid));
860 EXPECT(1 == IsUnusedEntry(e));
861 EXPECT(0 == IsKernelEntry(e));
862
863 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
864 EXPECT(0 == IsUnusedEntry(e));
865 EXPECT(1 == IsKernelEntry(e));
866
867 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
868 EXPECT(0 == IsUnusedEntry(e));
869 EXPECT(0 == IsKernelEntry(e));
870
871 return TEST_OK;
872}
873
874
875/* Make an entry unused by clearing its type. */
876static void FreeEntry(GptEntry* e) {
877 Memset(&e->type, 0, sizeof(Guid));
878}
879
880
881/* Set up an entry. */
882static void FillEntry(GptEntry* e, int is_kernel,
883 int priority, int successful, int tries) {
884 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
885 SetEntryPriority(e, priority);
886 SetEntrySuccessful(e, successful);
887 SetEntryTries(e, tries);
888}
889
890
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700891/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
892 * any usable kernel entry.
893 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700894static int NoValidKernelEntryTest() {
895 GptData* gpt = GetEmptyGptData();
896 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700897
898 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700899 SetEntryPriority(e1 + KERNEL_A, 0);
900 FreeEntry(e1 + KERNEL_B);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700901 RefreshCrc32(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700902 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
903
904 return TEST_OK;
905}
906
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700907
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700908static int GetNextNormalTest() {
909 GptData* gpt = GetEmptyGptData();
910 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
911 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700912
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700913 /* Normal case - both kernels successful */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700914 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700915 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
916 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
917 RefreshCrc32(gpt);
918 GptInit(gpt);
919
920 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
921 EXPECT(KERNEL_A == gpt->current_kernel);
922 EXPECT(34 == start);
923 EXPECT(100 == size);
924
925 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
926 EXPECT(KERNEL_B == gpt->current_kernel);
927 EXPECT(134 == start);
928 EXPECT(99 == size);
929
930 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
931 EXPECT(-1 == gpt->current_kernel);
932
933 /* Call as many times as you want; you won't get another kernel... */
934 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
935 EXPECT(-1 == gpt->current_kernel);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700936
937 return TEST_OK;
938}
939
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700940
941static int GetNextPrioTest() {
942 GptData* gpt = GetEmptyGptData();
943 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
944 uint64_t start, size;
945
946 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
947 BuildTestGptData(gpt);
948 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
949 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
950 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
951 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
952 RefreshCrc32(gpt);
953 GptInit(gpt);
954
955 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
956 EXPECT(KERNEL_B == gpt->current_kernel);
957 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
958 EXPECT(KERNEL_Y == gpt->current_kernel);
959 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
960 EXPECT(KERNEL_A == gpt->current_kernel);
961 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
962
963 return TEST_OK;
964}
965
966
967static int GetNextTriesTest() {
968 GptData* gpt = GetEmptyGptData();
969 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
970 uint64_t start, size;
971
972 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
973 BuildTestGptData(gpt);
974 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
975 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
976 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
977 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
978 RefreshCrc32(gpt);
979 GptInit(gpt);
980
981 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
982 EXPECT(KERNEL_X == gpt->current_kernel);
983 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
984 EXPECT(KERNEL_A == gpt->current_kernel);
985 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
986
987 return TEST_OK;
988}
989
990
991static int GptUpdateTest() {
992 GptData* gpt = GetEmptyGptData();
993 GptEntry* e = (GptEntry*)(gpt->primary_entries);
994 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
995 uint64_t start, size;
996
997 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
998 BuildTestGptData(gpt);
999 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1000 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1001 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1002 RefreshCrc32(gpt);
1003 GptInit(gpt);
1004 gpt->modified = 0; /* Nothing modified yet */
1005
1006 /* Successful kernel */
1007 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1008 EXPECT(KERNEL_A == gpt->current_kernel);
1009 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1010 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1011 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1012 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1013 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1014 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1015 /* Trying successful kernel changes nothing */
1016 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1017 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1018 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1019 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1020 EXPECT(0 == gpt->modified);
1021 /* Marking it bad does, though */
1022 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1023 EXPECT(0 == GetEntrySuccessful(e + KERNEL_A));
1024 EXPECT(0 == GetEntryPriority(e + KERNEL_A));
1025 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1026 /* Which affects both copies of the partition entries */
1027 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_A));
1028 EXPECT(0 == GetEntryPriority(e2 + KERNEL_A));
1029 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1030 /* And that's caused the GPT to need updating */
1031 EXPECT(0x0F == gpt->modified);
1032
1033 /* Kernel with tries */
1034 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1035 EXPECT(KERNEL_B == gpt->current_kernel);
1036 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1037 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1038 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1039 /* Marking it bad clears it */
1040 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1041 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1042 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1043 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1044
1045 /* Another kernel with tries */
1046 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1047 EXPECT(KERNEL_X == gpt->current_kernel);
1048 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1049 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1050 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1051 /* Trying it uses up a try */
1052 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1053 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1054 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1055 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1056 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1057 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1058 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1059 /* Trying it again marks it inactive */
1060 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1061 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1062 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1063 EXPECT(0 == GetEntryTries(e + KERNEL_X));
1064
1065 return TEST_OK;
1066}
1067
1068
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001069/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
1070 * GPT_ERROR_INVALID_UPDATE_TYPE. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001071static int UpdateInvalidKernelTypeTest() {
1072 GptData* gpt = GetEmptyGptData();
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001073
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001074 BuildTestGptData(gpt);
1075 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1076 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1077 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
1078
1079 return TEST_OK;
1080}
1081
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001082
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001083int main(int argc, char *argv[]) {
1084 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001085 int error_count = 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001086 struct {
1087 char *name;
1088 test_func fp;
1089 int retval;
1090 } test_cases[] = {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001091 { TEST_CASE(TestBuildTestGptData), },
1092 { TEST_CASE(ParameterTests), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001093 { TEST_CASE(HeaderCrcTest), },
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07001094 { TEST_CASE(SignatureTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001095 { TEST_CASE(RevisionTest), },
1096 { TEST_CASE(SizeTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001097 { TEST_CASE(CrcFieldTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001098 { TEST_CASE(ReservedFieldsTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001099 { TEST_CASE(SizeOfPartitionEntryTest), },
1100 { TEST_CASE(NumberOfPartitionEntriesTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001101 { TEST_CASE(MyLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001102 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001103 { TEST_CASE(EntriesCrcTest), },
1104 { TEST_CASE(ValidEntryTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001105 { TEST_CASE(OverlappedPartitionTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001106 { TEST_CASE(SanityCheckTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001107 { TEST_CASE(NoValidKernelEntryTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001108 { TEST_CASE(EntryAttributeGetSetTest), },
1109 { TEST_CASE(EntryTypeTest), },
1110 { TEST_CASE(GetNextNormalTest), },
1111 { TEST_CASE(GetNextPrioTest), },
1112 { TEST_CASE(GetNextTriesTest), },
1113 { TEST_CASE(GptUpdateTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001114 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +08001115 { TEST_CASE(TestCrc32TestVectors), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001116 };
1117
1118 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1119 printf("Running %s() ...\n", test_cases[i].name);
1120 test_cases[i].retval = test_cases[i].fp();
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001121 if (test_cases[i].retval) {
1122 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1123 ++error_count;
1124 } else {
1125 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1126 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001127 }
1128
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001129 if (error_count) {
1130 printf("\n--------------------------------------------------\n");
1131 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP,
1132 error_count);
1133 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1134 if (test_cases[i].retval)
1135 printf(" %s()\n", test_cases[i].name);
1136 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001137 }
1138
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001139 return (error_count) ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001140}