blob: 3402ac8563be3270da3fa1aa9d35a70885f8d776 [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_internal.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07009#include "cgptlib_test.h"
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070010#include "crc32.h"
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +080011#include "crc32_test.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070012#include "gpt.h"
vbendeb3ecaf772010-06-24 16:19:53 -070013#include "test_common.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070014#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
Bill Richardsonaa8eda42010-08-27 09:31:26 -070047/* Copy a random-for-this-program-only Guid into the dest. The num parameter
48 * completely determines the Guid.
49 */
50static void SetGuid(void *dest, uint32_t num) {
51 Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,{0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
52 Memcpy(dest, &g, sizeof(Guid));
53}
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070054
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070055/* Given a GptData pointer, first re-calculate entries CRC32 value,
56 * then reset header CRC32 value to 0, and calculate header CRC32 value.
57 * Both primary and secondary are updated. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070058static void RefreshCrc32(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070059 GptHeader *header, *header2;
60 GptEntry *entries, *entries2;
61
62 header = (GptHeader*)gpt->primary_header;
63 entries = (GptEntry*)gpt->primary_entries;
64 header2 = (GptHeader*)gpt->secondary_header;
65 entries2 = (GptEntry*)gpt->secondary_entries;
66
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070067 header->entries_crc32 =
68 Crc32((uint8_t*)entries,
69 header->number_of_entries * header->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070070 header->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070071 header->header_crc32 = Crc32((uint8_t*)header, header->size);
72 header2->entries_crc32 =
73 Crc32((uint8_t*)entries2,
74 header2->number_of_entries * header2->size_of_entry);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070075 header2->header_crc32 = 0;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070076 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size);
77}
78
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070079
80static void ZeroHeaders(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070081 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
82 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
83}
84
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070085
86static void ZeroEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070087 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
88 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
89}
90
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070091
92static void ZeroHeadersEntries(GptData* gpt) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070093 ZeroHeaders(gpt);
94 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070095}
96
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070097
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070098/* Returns a pointer to a static GptData instance (no free is required).
99 * All fields are zero except 4 pointers linking to header and entries.
100 * All content of headers and entries are zero. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700101static GptData* GetEmptyGptData() {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700102 static GptData gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700103 static uint8_t primary_header[MAX_SECTOR_SIZE];
104 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
105 static uint8_t secondary_header[MAX_SECTOR_SIZE];
106 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
107
108 Memset(&gpt, 0, sizeof(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700109 gpt.primary_header = primary_header;
110 gpt.primary_entries = primary_entries;
111 gpt.secondary_header = secondary_header;
112 gpt.secondary_entries = secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700113 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700114
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700115 /* Initialize GptData internal states. */
116 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
117
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700118 return &gpt;
119}
120
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700121
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700122/* Fills in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700123 * file. Before calling this function, primary/secondary header/entries must
124 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
125 * This function returns a good (valid) copy of GPT layout described in top of
126 * this file. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700127static void BuildTestGptData(GptData* gpt) {
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700128 GptHeader *header, *header2;
129 GptEntry *entries, *entries2;
130 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700131 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700132
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700133 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700134 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700135 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lo418ad3b2010-05-27 11:21:17 +0800136 gpt->valid_headers = MASK_BOTH;
137 gpt->valid_entries = MASK_BOTH;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700138 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700139
140 /* build primary */
141 header = (GptHeader*)gpt->primary_header;
142 entries = (GptEntry*)gpt->primary_entries;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700143 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
144 sizeof(GPT_HEADER_SIGNATURE));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700145 header->revision = GPT_HEADER_REVISION;
Bill Richardsonf1372d92010-06-11 09:15:55 -0700146 header->size = sizeof(GptHeader);
147 header->reserved_zero = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700148 header->my_lba = 1;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700149 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700150 header->first_usable_lba = 34;
151 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
152 header->entries_lba = 2;
153 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */
154 header->size_of_entry = 128; /* bytes */
155 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700156 SetGuid(&entries[0].unique, 0);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700157 entries[0].starting_lba = 34;
158 entries[0].ending_lba = 133;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700159 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700160 SetGuid(&entries[1].unique, 1);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700161 entries[1].starting_lba = 134;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700162 entries[1].ending_lba = 232;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700163 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700164 SetGuid(&entries[2].unique, 2);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700165 entries[2].starting_lba = 234;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700166 entries[2].ending_lba = 331;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700167 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700168 SetGuid(&entries[3].unique, 3);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700169 entries[3].starting_lba = 334;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700170 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700171
172 /* build secondary */
173 header2 = (GptHeader*)gpt->secondary_header;
174 entries2 = (GptEntry*)gpt->secondary_entries;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700175 Memcpy(header2, header, sizeof(GptHeader));
176 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700177 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700178 header2->alternate_lba = 1;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700179 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
180
181 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700182}
183
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700184
Randall Spangler81d09962010-06-23 10:15:38 -0700185/* Tests if the structures are the expected size; if this fails,
186 * struct packing is not working properly. */
187static int StructSizeTest() {
188
189 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
190 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
191 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
192
193 return TEST_OK;
194}
195
196
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700197/* Tests if the default structure returned by BuildTestGptData() is good. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700198static int TestBuildTestGptData() {
199 GptData* gpt;
200
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700201 gpt = GetEmptyGptData();
202 BuildTestGptData(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700203 EXPECT(GPT_SUCCESS == GptInit(gpt));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700204 return TEST_OK;
205}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700206
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700207
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700208/* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
209 * Currently we only support 512 bytes per sector.
210 * In the future, we may support other sizes.
211 * A too small drive_sectors should be rejected by GptInit(). */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700212static int ParameterTests() {
213 GptData* gpt;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700214 struct {
215 uint32_t sector_bytes;
216 uint64_t drive_sectors;
217 int expected_retval;
218 } cases[] = {
219 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
220 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
221 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
222 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
223 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2,
224 GPT_SUCCESS},
225 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
226 };
227 int i;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700228
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700229 gpt = GetEmptyGptData();
230 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
231 BuildTestGptData(gpt);
232 gpt->sector_bytes = cases[i].sector_bytes;
233 gpt->drive_sectors = cases[i].drive_sectors;
234 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700235 }
236
237 return TEST_OK;
238}
239
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700240
241/* Tests if header CRC in two copies are calculated. */
242static int HeaderCrcTest() {
243 GptData* gpt = GetEmptyGptData();
244 GptHeader* h1 = (GptHeader*)gpt->primary_header;
245
246 BuildTestGptData(gpt);
247 EXPECT(HeaderCrc(h1) == h1->header_crc32);
248
249 /* CRC covers first byte of header */
250 BuildTestGptData(gpt);
251 gpt->primary_header[0] ^= 0xa5;
252 EXPECT(HeaderCrc(h1) != h1->header_crc32);
253
254 /* CRC covers last byte of header */
255 BuildTestGptData(gpt);
256 gpt->primary_header[h1->size - 1] ^= 0x5a;
257 EXPECT(HeaderCrc(h1) != h1->header_crc32);
258
259 /* CRC only covers header */
260 BuildTestGptData(gpt);
261 gpt->primary_header[h1->size] ^= 0x5a;
262 EXPECT(HeaderCrc(h1) == h1->header_crc32);
263
264 return TEST_OK;
265}
266
267
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700268/* Tests if signature ("EFI PART") is checked. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700269static int SignatureTest() {
270 GptData* gpt = GetEmptyGptData();
271 GptHeader* h1 = (GptHeader*)gpt->primary_header;
272 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700273 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700274
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700275 for (i = 0; i < 8; ++i) {
276 BuildTestGptData(gpt);
277 h1->signature[i] ^= 0xff;
278 h2->signature[i] ^= 0xff;
279 RefreshCrc32(gpt);
280 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
281 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700282 }
283
284 return TEST_OK;
285}
286
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700287
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700288/* The revision we currently support is GPT_HEADER_REVISION.
289 * If the revision in header is not that, we expect the header is invalid. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700290static int RevisionTest() {
291 GptData* gpt = GetEmptyGptData();
292 GptHeader* h1 = (GptHeader*)gpt->primary_header;
293 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
294 int i;
295
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700296 struct {
297 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700298 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700299 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700300 {0x01000000, 1},
301 {0x00010000, 0}, /* GPT_HEADER_REVISION */
302 {0x00000100, 1},
303 {0x00000001, 1},
304 {0x23010456, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700305 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700306
307 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700308 BuildTestGptData(gpt);
309 h1->revision = cases[i].value_to_test;
310 h2->revision = cases[i].value_to_test;
311 RefreshCrc32(gpt);
312
313 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
314 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700315 }
316 return TEST_OK;
317}
318
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700319
320static int SizeTest() {
321 GptData* gpt = GetEmptyGptData();
322 GptHeader* h1 = (GptHeader*)gpt->primary_header;
323 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
324 int i;
325
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700326 struct {
327 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700328 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700329 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700330 {91, 1},
331 {92, 0},
332 {93, 0},
333 {511, 0},
334 {512, 0},
335 {513, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700336 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700337
338 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700339 BuildTestGptData(gpt);
340 h1->size = cases[i].value_to_test;
341 h2->size = cases[i].value_to_test;
342 RefreshCrc32(gpt);
343
344 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
345 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700346 }
347 return TEST_OK;
348}
349
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700350
351/* Tests if CRC is checked. */
352static int CrcFieldTest() {
353 GptData* gpt = GetEmptyGptData();
354 GptHeader* h1 = (GptHeader*)gpt->primary_header;
355 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
356
357 BuildTestGptData(gpt);
358 /* Modify a field that the header verification doesn't care about */
359 h1->entries_crc32++;
360 h2->entries_crc32++;
361 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
362 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
363 /* Refresh the CRC; should pass now */
364 RefreshCrc32(gpt);
365 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
366 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
367
368 return TEST_OK;
369}
370
371
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700372/* Tests if reserved fields are checked.
373 * We'll try non-zero values to test. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700374static int ReservedFieldsTest() {
375 GptData* gpt = GetEmptyGptData();
376 GptHeader* h1 = (GptHeader*)gpt->primary_header;
377 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700378
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700379 BuildTestGptData(gpt);
Bill Richardsonf1372d92010-06-11 09:15:55 -0700380 h1->reserved_zero ^= 0x12345678; /* whatever random */
381 h2->reserved_zero ^= 0x12345678; /* whatever random */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700382 RefreshCrc32(gpt);
383 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
384 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700385
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700386#ifdef PADDING_CHECKED
387 /* TODO: padding check is currently disabled */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700388 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700389 h1->padding[12] ^= 0x34; /* whatever random */
390 h2->padding[56] ^= 0x78; /* whatever random */
391 RefreshCrc32(gpt);
392 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
393 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
394#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700395
396 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700397}
398
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700399
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700400/* Technically, any size which is 2^N where N > 6 should work, but our
401 * library only supports one size. */
402static int SizeOfPartitionEntryTest() {
403 GptData* gpt = GetEmptyGptData();
404 GptHeader* h1 = (GptHeader*)gpt->primary_header;
405 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
406 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700407
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700408 struct {
409 uint32_t value_to_test;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700410 int expect_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700411 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700412 {127, 1},
413 {128, 0},
414 {129, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700415 {256, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700416 {512, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700417 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700418
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700419 /* Check size of entryes */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700420 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700421 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700422 h1->size_of_entry = cases[i].value_to_test;
423 h2->size_of_entry = cases[i].value_to_test;
424 h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
425 h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
426 RefreshCrc32(gpt);
427
428 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
429 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700430 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700431
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700432 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700433}
434
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700435
436/* Technically, any size which is 2^N where N > 6 should work, but our
437 * library only supports one size. */
438static int NumberOfPartitionEntriesTest() {
439 GptData* gpt = GetEmptyGptData();
440 GptHeader* h1 = (GptHeader*)gpt->primary_header;
441 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
442
443 BuildTestGptData(gpt);
444 h1->number_of_entries--;
445 h2->number_of_entries /= 2;
446 RefreshCrc32(gpt);
447 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
448 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
449
450 return TEST_OK;
451}
452
453
454/* Tests if myLBA field is checked (1 for primary, last for secondary). */
455static int MyLbaTest() {
456 GptData* gpt = GetEmptyGptData();
457 GptHeader* h1 = (GptHeader*)gpt->primary_header;
458 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
459
460 /* myLBA depends on primary vs secondary flag */
461 BuildTestGptData(gpt);
462 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
463 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
464
465 BuildTestGptData(gpt);
466 h1->my_lba--;
467 h2->my_lba--;
468 RefreshCrc32(gpt);
469 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
470 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
471
472 BuildTestGptData(gpt);
473 h1->my_lba = 2;
474 h2->my_lba--;
475 RefreshCrc32(gpt);
476 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
477 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
478
Bill Richardson31066a42010-06-03 15:20:19 -0700479 /* We should ignore the alternate_lba field entirely */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700480 BuildTestGptData(gpt);
481 h1->alternate_lba++;
482 h2->alternate_lba++;
483 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700484 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
485 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700486
487 BuildTestGptData(gpt);
488 h1->alternate_lba--;
489 h2->alternate_lba--;
490 RefreshCrc32(gpt);
Bill Richardson31066a42010-06-03 15:20:19 -0700491 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
492 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700493
494 BuildTestGptData(gpt);
495 h1->entries_lba++;
496 h2->entries_lba++;
497 RefreshCrc32(gpt);
498 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
499 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
500
501 BuildTestGptData(gpt);
502 h1->entries_lba--;
503 h2->entries_lba--;
504 RefreshCrc32(gpt);
505 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
506 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
507
508 return TEST_OK;
509}
510
511
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700512/* Tests if FirstUsableLBA and LastUsableLBA are checked.
513 * FirstUsableLBA must be after the end of the primary GPT table array.
514 * LastUsableLBA must be before the start of the secondary GPT table array.
515 * FirstUsableLBA <= LastUsableLBA. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700516static int FirstUsableLbaAndLastUsableLbaTest() {
517 GptData* gpt = GetEmptyGptData();
518 GptHeader* h1 = (GptHeader*)gpt->primary_header;
519 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700520 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700521
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700522 struct {
523 uint64_t primary_entries_lba;
524 uint64_t primary_first_usable_lba;
525 uint64_t primary_last_usable_lba;
526 uint64_t secondary_first_usable_lba;
527 uint64_t secondary_last_usable_lba;
528 uint64_t secondary_entries_lba;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700529 int primary_rv;
530 int secondary_rv;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700531 } cases[] = {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700532 {2, 34, 433, 34, 433, 434, 0, 0},
533 {2, 34, 432, 34, 430, 434, 0, 0},
534 {2, 33, 433, 33, 433, 434, 1, 1},
535 {2, 34, 434, 34, 433, 434, 1, 0},
536 {2, 34, 433, 34, 434, 434, 0, 1},
537 {2, 35, 433, 35, 433, 434, 0, 0},
538 {2, 433, 433, 433, 433, 434, 0, 0},
539 {2, 434, 433, 434, 434, 434, 1, 1},
540 {2, 433, 34, 34, 433, 434, 1, 0},
541 {2, 34, 433, 433, 34, 434, 0, 1},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700542 };
543
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700544 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
545 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700546 h1->entries_lba = cases[i].primary_entries_lba;
547 h1->first_usable_lba = cases[i].primary_first_usable_lba;
548 h1->last_usable_lba = cases[i].primary_last_usable_lba;
549 h2->entries_lba = cases[i].secondary_entries_lba;
550 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
551 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
552 RefreshCrc32(gpt);
553
554 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].primary_rv);
555 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].secondary_rv);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700556 }
557
558 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700559}
560
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700561
562/* Tests if PartitionEntryArrayCRC32 is checked.
563 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
564 * NumberOfPartitionEntries bytes.
565 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700566static int EntriesCrcTest() {
567 GptData* gpt = GetEmptyGptData();
568 GptHeader* h1 = (GptHeader*)gpt->primary_header;
569 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
570 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700571
572 /* Modify the first byte of primary entries, and expect the CRC is wrong. */
573 BuildTestGptData(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700574 EXPECT(0 == CheckEntries(e1, h1));
575 EXPECT(0 == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700576 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700577 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
Vadim Bendebury65d3c272012-09-24 17:41:18 -0700578 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
579 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700580
581 return TEST_OK;
582}
583
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700584
585/* Tests if partition geometry is checked.
586 * All active (non-zero PartitionTypeGUID) partition entries should have:
587 * entry.StartingLBA >= header.FirstUsableLBA
588 * entry.EndingLBA <= header.LastUsableLBA
589 * entry.StartingLBA <= entry.EndingLBA
590 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700591static int ValidEntryTest() {
592 GptData* gpt = GetEmptyGptData();
593 GptHeader* h1 = (GptHeader*)gpt->primary_header;
594 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700595
596 /* error case: entry.StartingLBA < header.FirstUsableLBA */
597 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700598 e1[0].starting_lba = h1->first_usable_lba - 1;
599 RefreshCrc32(gpt);
Vadim Bendebury65d3c272012-09-24 17:41:18 -0700600 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700601
602 /* error case: entry.EndingLBA > header.LastUsableLBA */
603 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700604 e1[2].ending_lba = h1->last_usable_lba + 1;
605 RefreshCrc32(gpt);
Vadim Bendebury65d3c272012-09-24 17:41:18 -0700606 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700607
608 /* error case: entry.StartingLBA > entry.EndingLBA */
609 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700610 e1[3].starting_lba = e1[3].ending_lba + 1;
611 RefreshCrc32(gpt);
Vadim Bendebury65d3c272012-09-24 17:41:18 -0700612 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700613
614 /* case: non active entry should be ignored. */
615 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700616 Memset(&e1[1].type, 0, sizeof(e1[1].type));
617 e1[1].starting_lba = e1[1].ending_lba + 1;
618 RefreshCrc32(gpt);
vbendeb3ecaf772010-06-24 16:19:53 -0700619 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700620
621 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700622}
623
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700624
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700625/* Tests if overlapped partition tables can be detected. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700626static int OverlappedPartitionTest() {
627 GptData* gpt = GetEmptyGptData();
628 GptHeader* h = (GptHeader*)gpt->primary_header;
629 GptEntry* e = (GptEntry*)gpt->primary_entries;
630 int i, j;
631
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700632 struct {
633 int overlapped;
634 struct {
635 int active;
636 uint64_t starting_lba;
637 uint64_t ending_lba;
638 } entries[16]; /* enough for testing. */
639 } cases[] = {
Vadim Bendebury65d3c272012-09-24 17:41:18 -0700640 {GPT_SUCCESS, {{0, 100, 199}}},
641 {GPT_SUCCESS, {{1, 100, 199}}},
642 {GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
643 {GPT_ERROR_START_LBA_OVERLAP,
644 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
645 {GPT_ERROR_END_LBA_OVERLAP, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
646 {GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
647 {GPT_ERROR_END_LBA_OVERLAP, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
648 {GPT_ERROR_START_LBA_OVERLAP, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
649 {GPT_ERROR_START_LBA_OVERLAP, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
650 {GPT_ERROR_END_LBA_OVERLAP, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
651 {GPT_ERROR_START_LBA_OVERLAP,
652 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
653 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
654 {GPT_ERROR_START_LBA_OVERLAP,
655 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
656 {GPT_ERROR_START_LBA_OVERLAP,
657 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
658 {GPT_SUCCESS, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
659 {GPT_ERROR_END_LBA_OVERLAP,
660 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
661 {GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
662 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
663 {GPT_ERROR_START_LBA_OVERLAP,
664 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
665 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
666 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
667 {GPT_SUCCESS, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
668 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
669 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700670 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700671
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700672
673 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700674 BuildTestGptData(gpt);
675 ZeroEntries(gpt);
676 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
677 if (!cases[i].entries[j].starting_lba)
678 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700679
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700680 if (cases[i].entries[j].active)
681 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700682 SetGuid(&e[j].unique, j);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700683 e[j].starting_lba = cases[i].entries[j].starting_lba;
684 e[j].ending_lba = cases[i].entries[j].ending_lba;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700685 }
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700686 RefreshCrc32(gpt);
687
vbendeb3ecaf772010-06-24 16:19:53 -0700688 EXPECT(cases[i].overlapped == CheckEntries(e, h));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700689 }
690 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700691}
692
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700693
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700694/* Test both sanity checking and repair. */
695static int SanityCheckTest() {
696 GptData* gpt = GetEmptyGptData();
697 GptHeader* h1 = (GptHeader*)gpt->primary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700698
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700699 /* Unmodified test data is completely sane */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700700 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700701 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
702 EXPECT(MASK_BOTH == gpt->valid_headers);
703 EXPECT(MASK_BOTH == gpt->valid_entries);
704 /* Repair doesn't damage it */
705 GptRepair(gpt);
706 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
707 EXPECT(MASK_BOTH == gpt->valid_headers);
708 EXPECT(MASK_BOTH == gpt->valid_entries);
709 EXPECT(0 == gpt->modified);
710
711 /* Modify headers */
712 BuildTestGptData(gpt);
713 gpt->primary_header[0]++;
714 gpt->secondary_header[0]++;
715 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
716 EXPECT(0 == gpt->valid_headers);
717 EXPECT(0 == gpt->valid_entries);
718 /* Repair can't fix completely busted headers */
719 GptRepair(gpt);
720 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
721 EXPECT(0 == gpt->valid_headers);
722 EXPECT(0 == gpt->valid_entries);
723 EXPECT(0 == gpt->modified);
724
725 BuildTestGptData(gpt);
726 gpt->primary_header[0]++;
727 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
728 EXPECT(MASK_SECONDARY == gpt->valid_headers);
729 EXPECT(MASK_BOTH == gpt->valid_entries);
730 GptRepair(gpt);
731 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
732 EXPECT(MASK_BOTH == gpt->valid_headers);
733 EXPECT(MASK_BOTH == gpt->valid_entries);
734 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
735
736 BuildTestGptData(gpt);
737 gpt->secondary_header[0]++;
738 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
739 EXPECT(MASK_PRIMARY == gpt->valid_headers);
740 EXPECT(MASK_BOTH == gpt->valid_entries);
741 GptRepair(gpt);
742 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
743 EXPECT(MASK_BOTH == gpt->valid_headers);
744 EXPECT(MASK_BOTH == gpt->valid_entries);
745 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
746
747 /* Modify header1 and update its CRC. Since header2 is now different than
748 * header1, it'll be the one considered invalid. */
749 BuildTestGptData(gpt);
750 h1->size++;
751 RefreshCrc32(gpt);
752 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
753 EXPECT(MASK_PRIMARY == gpt->valid_headers);
754 EXPECT(MASK_BOTH == gpt->valid_entries);
755 GptRepair(gpt);
756 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
757 EXPECT(MASK_BOTH == gpt->valid_headers);
758 EXPECT(MASK_BOTH == gpt->valid_entries);
759 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
760
761 /* Modify entries */
762 BuildTestGptData(gpt);
763 gpt->primary_entries[0]++;
764 gpt->secondary_entries[0]++;
765 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
766 EXPECT(MASK_BOTH == gpt->valid_headers);
767 EXPECT(MASK_NONE == gpt->valid_entries);
768 /* Repair can't fix both copies of entries being bad, either. */
769 GptRepair(gpt);
770 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
771 EXPECT(MASK_BOTH == gpt->valid_headers);
772 EXPECT(MASK_NONE == gpt->valid_entries);
773 EXPECT(0 == gpt->modified);
774
775 BuildTestGptData(gpt);
776 gpt->primary_entries[0]++;
777 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
778 EXPECT(MASK_BOTH == gpt->valid_headers);
779 EXPECT(MASK_SECONDARY == gpt->valid_entries);
780 GptRepair(gpt);
781 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
782 EXPECT(MASK_BOTH == gpt->valid_headers);
783 EXPECT(MASK_BOTH == gpt->valid_entries);
784 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
785
786 BuildTestGptData(gpt);
787 gpt->secondary_entries[0]++;
788 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
789 EXPECT(MASK_BOTH == gpt->valid_headers);
790 EXPECT(MASK_PRIMARY == gpt->valid_entries);
791 GptRepair(gpt);
792 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
793 EXPECT(MASK_BOTH == gpt->valid_headers);
794 EXPECT(MASK_BOTH == gpt->valid_entries);
795 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
796
Bill Richardsonaa8eda42010-08-27 09:31:26 -0700797 /* Modify both header and entries */
798 BuildTestGptData(gpt);
799 gpt->primary_header[0]++;
800 gpt->primary_entries[0]++;
801 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
802 EXPECT(MASK_SECONDARY == gpt->valid_headers);
803 EXPECT(MASK_SECONDARY == gpt->valid_entries);
804 GptRepair(gpt);
805 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
806 EXPECT(MASK_BOTH == gpt->valid_headers);
807 EXPECT(MASK_BOTH == gpt->valid_entries);
808 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
809
810 BuildTestGptData(gpt);
811 gpt->secondary_header[0]++;
812 gpt->secondary_entries[0]++;
813 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
814 EXPECT(MASK_PRIMARY == gpt->valid_headers);
815 EXPECT(MASK_PRIMARY == gpt->valid_entries);
816 GptRepair(gpt);
817 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
818 EXPECT(MASK_BOTH == gpt->valid_headers);
819 EXPECT(MASK_BOTH == gpt->valid_entries);
820 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
821
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700822 /* Test cross-correction (h1+e2, h2+e1) */
823 BuildTestGptData(gpt);
824 gpt->primary_header[0]++;
825 gpt->secondary_entries[0]++;
826 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
827 EXPECT(MASK_SECONDARY == gpt->valid_headers);
828 EXPECT(MASK_PRIMARY == gpt->valid_entries);
829 GptRepair(gpt);
830 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
831 EXPECT(MASK_BOTH == gpt->valid_headers);
832 EXPECT(MASK_BOTH == gpt->valid_entries);
833 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
834
835 BuildTestGptData(gpt);
836 gpt->secondary_header[0]++;
837 gpt->primary_entries[0]++;
838 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
839 EXPECT(MASK_PRIMARY == gpt->valid_headers);
840 EXPECT(MASK_SECONDARY == gpt->valid_entries);
841 GptRepair(gpt);
842 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
843 EXPECT(MASK_BOTH == gpt->valid_headers);
844 EXPECT(MASK_BOTH == gpt->valid_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700845 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700846
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700847 /* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.
848 * This simulates a partial update of the drive. */
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700849 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700850 gpt->secondary_entries[0]++;
851 RefreshCrc32(gpt);
852 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
853 EXPECT(MASK_PRIMARY == gpt->valid_headers);
854 EXPECT(MASK_PRIMARY == gpt->valid_entries);
855 GptRepair(gpt);
856 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
857 EXPECT(MASK_BOTH == gpt->valid_headers);
858 EXPECT(MASK_BOTH == gpt->valid_entries);
859 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700860
861 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700862}
863
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700864
865static int EntryAttributeGetSetTest() {
866 GptData* gpt = GetEmptyGptData();
867 GptEntry* e = (GptEntry*)(gpt->primary_entries);
868
vbendeb3ecaf772010-06-24 16:19:53 -0700869 e->attrs.whole = 0x0000000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700870 SetEntrySuccessful(e, 1);
vbendeb3ecaf772010-06-24 16:19:53 -0700871 EXPECT(0x0100000000000000ULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700872 EXPECT(1 == GetEntrySuccessful(e));
vbendeb3ecaf772010-06-24 16:19:53 -0700873 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700874 SetEntrySuccessful(e, 0);
vbendeb3ecaf772010-06-24 16:19:53 -0700875 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700876 EXPECT(0 == GetEntrySuccessful(e));
877
vbendeb3ecaf772010-06-24 16:19:53 -0700878 e->attrs.whole = 0x0000000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700879 SetEntryTries(e, 15);
880 EXPECT(15 == GetEntryTries(e));
vbendeb3ecaf772010-06-24 16:19:53 -0700881 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
882 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700883 SetEntryTries(e, 0);
vbendeb3ecaf772010-06-24 16:19:53 -0700884 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700885 EXPECT(0 == GetEntryTries(e));
886
vbendeb3ecaf772010-06-24 16:19:53 -0700887 e->attrs.whole = 0x0000000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700888 SetEntryPriority(e, 15);
vbendeb3ecaf772010-06-24 16:19:53 -0700889 EXPECT(0x000F000000000000ULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700890 EXPECT(15 == GetEntryPriority(e));
vbendeb3ecaf772010-06-24 16:19:53 -0700891 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700892 SetEntryPriority(e, 0);
vbendeb3ecaf772010-06-24 16:19:53 -0700893 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700894 EXPECT(0 == GetEntryPriority(e));
895
vbendeb3ecaf772010-06-24 16:19:53 -0700896 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700897 EXPECT(1 == GetEntrySuccessful(e));
898 EXPECT(15 == GetEntryPriority(e));
899 EXPECT(15 == GetEntryTries(e));
900
vbendeb3ecaf772010-06-24 16:19:53 -0700901 e->attrs.whole = 0x0123000000000000ULL;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700902 EXPECT(1 == GetEntrySuccessful(e));
903 EXPECT(2 == GetEntryTries(e));
904 EXPECT(3 == GetEntryPriority(e));
905
906 return TEST_OK;
907}
908
909
910static int EntryTypeTest() {
911 GptData* gpt = GetEmptyGptData();
912 GptEntry* e = (GptEntry*)(gpt->primary_entries);
913
914 Memcpy(&e->type, &guid_zero, sizeof(Guid));
915 EXPECT(1 == IsUnusedEntry(e));
916 EXPECT(0 == IsKernelEntry(e));
917
918 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
919 EXPECT(0 == IsUnusedEntry(e));
920 EXPECT(1 == IsKernelEntry(e));
921
922 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
923 EXPECT(0 == IsUnusedEntry(e));
924 EXPECT(0 == IsKernelEntry(e));
925
926 return TEST_OK;
927}
928
929
930/* Make an entry unused by clearing its type. */
931static void FreeEntry(GptEntry* e) {
932 Memset(&e->type, 0, sizeof(Guid));
933}
934
935
936/* Set up an entry. */
937static void FillEntry(GptEntry* e, int is_kernel,
938 int priority, int successful, int tries) {
939 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
940 SetEntryPriority(e, priority);
941 SetEntrySuccessful(e, successful);
942 SetEntryTries(e, tries);
943}
944
945
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700946/* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
947 * any usable kernel entry.
948 */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700949static int NoValidKernelEntryTest() {
950 GptData* gpt = GetEmptyGptData();
951 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700952
953 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700954 SetEntryPriority(e1 + KERNEL_A, 0);
955 FreeEntry(e1 + KERNEL_B);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700956 RefreshCrc32(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700957 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
958
959 return TEST_OK;
960}
961
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700962
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700963static int GetNextNormalTest() {
964 GptData* gpt = GetEmptyGptData();
965 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
966 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700967
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700968 /* Normal case - both kernels successful */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700969 BuildTestGptData(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700970 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
971 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
972 RefreshCrc32(gpt);
973 GptInit(gpt);
974
975 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
976 EXPECT(KERNEL_A == gpt->current_kernel);
977 EXPECT(34 == start);
978 EXPECT(100 == size);
979
980 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
981 EXPECT(KERNEL_B == gpt->current_kernel);
982 EXPECT(134 == start);
983 EXPECT(99 == size);
984
985 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
986 EXPECT(-1 == gpt->current_kernel);
987
988 /* Call as many times as you want; you won't get another kernel... */
989 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
990 EXPECT(-1 == gpt->current_kernel);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700991
992 return TEST_OK;
993}
994
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700995
996static int GetNextPrioTest() {
997 GptData* gpt = GetEmptyGptData();
998 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
999 uint64_t start, size;
1000
1001 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1002 BuildTestGptData(gpt);
1003 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1004 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1005 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1006 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1007 RefreshCrc32(gpt);
1008 GptInit(gpt);
1009
1010 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1011 EXPECT(KERNEL_B == gpt->current_kernel);
1012 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1013 EXPECT(KERNEL_Y == gpt->current_kernel);
1014 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1015 EXPECT(KERNEL_A == gpt->current_kernel);
1016 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
1017
1018 return TEST_OK;
1019}
1020
1021
1022static int GetNextTriesTest() {
1023 GptData* gpt = GetEmptyGptData();
1024 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
1025 uint64_t start, size;
1026
1027 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1028 BuildTestGptData(gpt);
1029 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1030 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1031 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1032 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1033 RefreshCrc32(gpt);
1034 GptInit(gpt);
1035
1036 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1037 EXPECT(KERNEL_X == gpt->current_kernel);
1038 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1039 EXPECT(KERNEL_A == gpt->current_kernel);
1040 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
1041
1042 return TEST_OK;
1043}
1044
1045
1046static int GptUpdateTest() {
1047 GptData* gpt = GetEmptyGptData();
1048 GptEntry* e = (GptEntry*)(gpt->primary_entries);
1049 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
1050 uint64_t start, size;
1051
1052 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1053 BuildTestGptData(gpt);
1054 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1055 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1056 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1057 RefreshCrc32(gpt);
1058 GptInit(gpt);
1059 gpt->modified = 0; /* Nothing modified yet */
1060
1061 /* Successful kernel */
1062 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1063 EXPECT(KERNEL_A == gpt->current_kernel);
1064 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1065 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1066 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1067 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1068 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1069 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1070 /* Trying successful kernel changes nothing */
1071 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1072 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1073 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1074 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1075 EXPECT(0 == gpt->modified);
Randall Spangler2c21fe62010-09-07 10:30:50 -07001076 /* Marking it bad also does not update it. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001077 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
Randall Spangler2c21fe62010-09-07 10:30:50 -07001078 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1079 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001080 EXPECT(0 == GetEntryTries(e + KERNEL_A));
Randall Spangler2c21fe62010-09-07 10:30:50 -07001081 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001082
1083 /* Kernel with tries */
1084 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1085 EXPECT(KERNEL_B == gpt->current_kernel);
1086 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1087 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1088 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1089 /* Marking it bad clears it */
1090 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1091 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1092 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1093 EXPECT(0 == GetEntryTries(e + KERNEL_B));
Randall Spangler2c21fe62010-09-07 10:30:50 -07001094 /* Which affects both copies of the partition entries */
1095 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1096 EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1097 EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1098 /* And that's caused the GPT to need updating */
1099 EXPECT(0x0F == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001100
1101 /* Another kernel with tries */
1102 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1103 EXPECT(KERNEL_X == gpt->current_kernel);
1104 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1105 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1106 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1107 /* Trying it uses up a try */
1108 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1109 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1110 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1111 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1112 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1113 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1114 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1115 /* Trying it again marks it inactive */
1116 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1117 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1118 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1119 EXPECT(0 == GetEntryTries(e + KERNEL_X));
1120
1121 return TEST_OK;
1122}
1123
1124
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001125/* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
1126 * GPT_ERROR_INVALID_UPDATE_TYPE. */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001127static int UpdateInvalidKernelTypeTest() {
1128 GptData* gpt = GetEmptyGptData();
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001129
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001130 BuildTestGptData(gpt);
1131 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1132 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1133 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
1134
1135 return TEST_OK;
1136}
1137
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001138
1139/* Tests duplicate UniqueGuids can be detected. */
1140static int DuplicateUniqueGuidTest() {
1141 GptData* gpt = GetEmptyGptData();
1142 GptHeader* h = (GptHeader*)gpt->primary_header;
1143 GptEntry* e = (GptEntry*)gpt->primary_entries;
1144 int i, j;
1145
1146 struct {
1147 int duplicate;
1148 struct {
1149 uint64_t starting_lba;
1150 uint64_t ending_lba;
1151 uint32_t type_guid;
1152 uint32_t unique_guid;
1153 } entries[16]; /* enough for testing. */
1154 } cases[] = {
Vadim Bendebury65d3c272012-09-24 17:41:18 -07001155 {GPT_SUCCESS, {{100, 109, 1, 1},
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001156 {110, 119, 2, 2},
1157 {120, 129, 3, 3},
1158 {130, 139, 4, 4},
1159 }},
Vadim Bendebury65d3c272012-09-24 17:41:18 -07001160 {GPT_SUCCESS, {{100, 109, 1, 1},
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001161 {110, 119, 1, 2},
1162 {120, 129, 2, 3},
1163 {130, 139, 2, 4},
1164 }},
Vadim Bendebury65d3c272012-09-24 17:41:18 -07001165 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001166 {110, 119, 2, 2},
1167 {120, 129, 3, 1},
1168 {130, 139, 4, 4},
1169 }},
Vadim Bendebury65d3c272012-09-24 17:41:18 -07001170 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001171 {110, 119, 1, 2},
1172 {120, 129, 2, 3},
1173 {130, 139, 2, 2},
1174 }},
1175 };
1176
1177 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1178 BuildTestGptData(gpt);
1179 ZeroEntries(gpt);
1180 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1181 if (!cases[i].entries[j].starting_lba)
1182 break;
1183
1184 e[j].starting_lba = cases[i].entries[j].starting_lba;
1185 e[j].ending_lba = cases[i].entries[j].ending_lba;
1186 SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1187 SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1188 }
1189 RefreshCrc32(gpt);
1190
1191 EXPECT(cases[i].duplicate == CheckEntries(e, h));
1192 }
1193 return TEST_OK;
1194}
1195
1196
1197
vbendeb3ecaf772010-06-24 16:19:53 -07001198/* disable MSVC warnings on unused arguments */
1199__pragma(warning (disable: 4100))
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001200
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001201int main(int argc, char *argv[]) {
1202 int i;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001203 int error_count = 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001204 struct {
1205 char *name;
1206 test_func fp;
1207 int retval;
1208 } test_cases[] = {
Randall Spangler81d09962010-06-23 10:15:38 -07001209 { TEST_CASE(StructSizeTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001210 { TEST_CASE(TestBuildTestGptData), },
1211 { TEST_CASE(ParameterTests), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001212 { TEST_CASE(HeaderCrcTest), },
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07001213 { TEST_CASE(SignatureTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001214 { TEST_CASE(RevisionTest), },
1215 { TEST_CASE(SizeTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001216 { TEST_CASE(CrcFieldTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001217 { TEST_CASE(ReservedFieldsTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001218 { TEST_CASE(SizeOfPartitionEntryTest), },
1219 { TEST_CASE(NumberOfPartitionEntriesTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001220 { TEST_CASE(MyLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001221 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001222 { TEST_CASE(EntriesCrcTest), },
1223 { TEST_CASE(ValidEntryTest), },
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001224 { TEST_CASE(OverlappedPartitionTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001225 { TEST_CASE(SanityCheckTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001226 { TEST_CASE(NoValidKernelEntryTest), },
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001227 { TEST_CASE(EntryAttributeGetSetTest), },
1228 { TEST_CASE(EntryTypeTest), },
1229 { TEST_CASE(GetNextNormalTest), },
1230 { TEST_CASE(GetNextPrioTest), },
1231 { TEST_CASE(GetNextTriesTest), },
1232 { TEST_CASE(GptUpdateTest), },
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001233 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001234 { TEST_CASE(DuplicateUniqueGuidTest), },
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +08001235 { TEST_CASE(TestCrc32TestVectors), },
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001236 };
1237
1238 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1239 printf("Running %s() ...\n", test_cases[i].name);
1240 test_cases[i].retval = test_cases[i].fp();
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001241 if (test_cases[i].retval) {
1242 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1243 ++error_count;
1244 } else {
1245 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1246 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001247 }
1248
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001249 if (error_count) {
1250 printf("\n--------------------------------------------------\n");
1251 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP,
1252 error_count);
1253 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1254 if (test_cases[i].retval)
1255 printf(" %s()\n", test_cases[i].name);
1256 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001257 }
1258
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001259 return (error_count) ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001260}