Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(639)

Side by Side Diff: src/platform/vboot_reference/tests/cgptlib_test.c

Issue 2438005: Much rearranging of cgptlib. Passes all its (new) unit tests. (Closed) Base URL: ssh://gitrw.chromium.org/chromiumos
Patch Set: Pre commit Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* 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 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 */ 4 */
5 5
6 #include "cgptlib_test.h"
7 #include <string.h> 6 #include <string.h>
7
8 #include "cgptlib.h" 8 #include "cgptlib.h"
9 #include "cgptlib_internal.h" 9 #include "cgptlib_internal.h"
10 #include "cgptlib_test.h"
10 #include "crc32.h" 11 #include "crc32.h"
11 #include "crc32_test.h" 12 #include "crc32_test.h"
12 #include "gpt.h" 13 #include "gpt.h"
13 #include "quick_sort_test.h"
14 #include "utility.h" 14 #include "utility.h"
15 15
16 /* Testing partition layout (sector_bytes=512) 16 /* Testing partition layout (sector_bytes=512)
17 * 17 *
18 * LBA Size Usage 18 * LBA Size Usage
19 * --------------------------------------------------------- 19 * ---------------------------------------------------------
20 * 0 1 PMBR 20 * 0 1 PMBR
21 * 1 1 primary partition header 21 * 1 1 primary partition header
22 * 2 32 primary partition entries (128B * 128) 22 * 2 32 primary partition entries (128B * 128)
23 * 34 100 kernel A (index: 0) 23 * 34 100 kernel A (index: 0)
24 * 134 100 root A (index: 1) 24 * 134 100 root A (index: 1)
25 * 234 100 root B (index: 2) 25 * 234 100 root B (index: 2)
26 * 334 100 kernel B (index: 3) 26 * 334 100 kernel B (index: 3)
27 * 434 32 secondary partition entries 27 * 434 32 secondary partition entries
28 * 466 1 secondary partition header 28 * 466 1 secondary partition header
29 * 467 29 * 467
30 */ 30 */
31 #define KERNEL_A 0 31 #define KERNEL_A 0
32 #define ROOTFS_A 1 32 #define KERNEL_B 1
33 #define ROOTFS_B 2 33 #define ROOTFS_A 2
34 #define KERNEL_B 3 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 */
35 37
36 #define DEFAULT_SECTOR_SIZE 512 38 #define DEFAULT_SECTOR_SIZE 512
37 #define MAX_SECTOR_SIZE 4096 39 #define MAX_SECTOR_SIZE 4096
38 #define DEFAULT_DRIVE_SECTORS 467 40 #define DEFAULT_DRIVE_SECTORS 467
39 #define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */ 41 #define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
40 42
43 static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
44 static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
45 static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
46
47
41 /* Given a GptData pointer, first re-calculate entries CRC32 value, 48 /* Given a GptData pointer, first re-calculate entries CRC32 value,
42 * then reset header CRC32 value to 0, and calculate header CRC32 value. 49 * then reset header CRC32 value to 0, and calculate header CRC32 value.
43 * Both primary and secondary are updated. */ 50 * Both primary and secondary are updated. */
44 void RefreshCrc32(GptData *gpt) { 51 static void RefreshCrc32(GptData* gpt) {
45 GptHeader *header, *header2; 52 GptHeader *header, *header2;
46 GptEntry *entries, *entries2; 53 GptEntry *entries, *entries2;
47 54
48 header = (GptHeader*)gpt->primary_header; 55 header = (GptHeader*)gpt->primary_header;
49 entries = (GptEntry*)gpt->primary_entries; 56 entries = (GptEntry*)gpt->primary_entries;
50 header2 = (GptHeader*)gpt->secondary_header; 57 header2 = (GptHeader*)gpt->secondary_header;
51 entries2 = (GptEntry*)gpt->secondary_entries; 58 entries2 = (GptEntry*)gpt->secondary_entries;
52 59
53 header->entries_crc32 = 60 header->entries_crc32 =
54 Crc32((uint8_t*)entries, 61 Crc32((uint8_t*)entries,
55 header->number_of_entries * header->size_of_entry); 62 header->number_of_entries * header->size_of_entry);
56 header->header_crc32 = 0; 63 header->header_crc32 = 0;
57 header->header_crc32 = Crc32((uint8_t*)header, header->size); 64 header->header_crc32 = Crc32((uint8_t*)header, header->size);
58 header2->entries_crc32 = 65 header2->entries_crc32 =
59 Crc32((uint8_t*)entries2, 66 Crc32((uint8_t*)entries2,
60 header2->number_of_entries * header2->size_of_entry); 67 header2->number_of_entries * header2->size_of_entry);
61 header2->header_crc32 = 0; 68 header2->header_crc32 = 0;
62 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size); 69 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size);
63 } 70 }
64 71
65 void ZeroHeaders(GptData* gpt) { 72
73 static void ZeroHeaders(GptData* gpt) {
66 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE); 74 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
67 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE); 75 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
68 } 76 }
69 77
70 void ZeroEntries(GptData* gpt) { 78
79 static void ZeroEntries(GptData* gpt) {
71 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE); 80 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
72 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE); 81 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
73 } 82 }
74 83
75 void ZeroHeadersEntries(GptData* gpt) { 84
85 static void ZeroHeadersEntries(GptData* gpt) {
76 ZeroHeaders(gpt); 86 ZeroHeaders(gpt);
77 ZeroEntries(gpt); 87 ZeroEntries(gpt);
78 } 88 }
79 89
90
80 /* Returns a pointer to a static GptData instance (no free is required). 91 /* Returns a pointer to a static GptData instance (no free is required).
81 * All fields are zero except 4 pointers linking to header and entries. 92 * All fields are zero except 4 pointers linking to header and entries.
82 * All content of headers and entries are zero. */ 93 * All content of headers and entries are zero. */
83 GptData* GetEmptyGptData() { 94 static GptData* GetEmptyGptData() {
84 static GptData gpt; 95 static GptData gpt;
85 static uint8_t primary_header[MAX_SECTOR_SIZE]; 96 static uint8_t primary_header[MAX_SECTOR_SIZE];
86 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE]; 97 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
87 static uint8_t secondary_header[MAX_SECTOR_SIZE]; 98 static uint8_t secondary_header[MAX_SECTOR_SIZE];
88 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE]; 99 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
89 100
90 Memset(&gpt, 0, sizeof(gpt)); 101 Memset(&gpt, 0, sizeof(gpt));
91 gpt.primary_header = primary_header; 102 gpt.primary_header = primary_header;
92 gpt.primary_entries = primary_entries; 103 gpt.primary_entries = primary_entries;
93 gpt.secondary_header = secondary_header; 104 gpt.secondary_header = secondary_header;
94 gpt.secondary_entries = secondary_entries; 105 gpt.secondary_entries = secondary_entries;
95 ZeroHeadersEntries(&gpt); 106 ZeroHeadersEntries(&gpt);
96 107
97 /* Initialize GptData internal states. */ 108 /* Initialize GptData internal states. */
98 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND; 109 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
99 110
100 return &gpt; 111 return &gpt;
101 } 112 }
102 113
114
103 /* Fills in most of fields and creates the layout described in the top of this 115 /* Fills in most of fields and creates the layout described in the top of this
104 * file. Before calling this function, primary/secondary header/entries must 116 * file. Before calling this function, primary/secondary header/entries must
105 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData(). 117 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
106 * This function returns a good (valid) copy of GPT layout described in top of 118 * This function returns a good (valid) copy of GPT layout described in top of
107 * this file. */ 119 * this file. */
108 void BuildTestGptData(GptData *gpt) { 120 static void BuildTestGptData(GptData* gpt) {
109 GptHeader *header, *header2; 121 GptHeader *header, *header2;
110 GptEntry *entries, *entries2; 122 GptEntry *entries, *entries2;
111 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; 123 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
112 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS; 124 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
113 125
114 gpt->sector_bytes = DEFAULT_SECTOR_SIZE; 126 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
115 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS; 127 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS;
116 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND; 128 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
117 gpt->valid_headers = MASK_BOTH; 129 gpt->valid_headers = MASK_BOTH;
118 gpt->valid_entries = MASK_BOTH; 130 gpt->valid_entries = MASK_BOTH;
131 gpt->modified = 0;
119 132
120 /* build primary */ 133 /* build primary */
121 header = (GptHeader*)gpt->primary_header; 134 header = (GptHeader*)gpt->primary_header;
122 entries = (GptEntry*)gpt->primary_entries; 135 entries = (GptEntry*)gpt->primary_entries;
123 Memcpy(header->signature, GPT_HEADER_SIGNATURE, sizeof(GPT_HEADER_SIGNATURE)); 136 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
137 sizeof(GPT_HEADER_SIGNATURE));
124 header->revision = GPT_HEADER_REVISION; 138 header->revision = GPT_HEADER_REVISION;
125 header->size = sizeof(GptHeader) - sizeof(header->padding); 139 header->size = sizeof(GptHeader) - sizeof(header->padding);
126 header->reserved = 0; 140 header->reserved = 0;
127 header->my_lba = 1; 141 header->my_lba = 1;
142 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
128 header->first_usable_lba = 34; 143 header->first_usable_lba = 34;
129 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */ 144 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
130 header->entries_lba = 2; 145 header->entries_lba = 2;
131 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */ 146 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */
132 header->size_of_entry = 128; /* bytes */ 147 header->size_of_entry = 128; /* bytes */
133 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel)); 148 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
134 entries[0].starting_lba = 34; 149 entries[0].starting_lba = 34;
135 entries[0].ending_lba = 133; 150 entries[0].ending_lba = 133;
136 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs)); 151 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
137 entries[1].starting_lba = 134; 152 entries[1].starting_lba = 134;
138 entries[1].ending_lba = 233; 153 entries[1].ending_lba = 232;
139 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs)); 154 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
140 entries[2].starting_lba = 234; 155 entries[2].starting_lba = 234;
141 entries[2].ending_lba = 333; 156 entries[2].ending_lba = 331;
142 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel)); 157 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
143 entries[3].starting_lba = 334; 158 entries[3].starting_lba = 334;
144 entries[3].ending_lba = 433; 159 entries[3].ending_lba = 430;
145 header->padding = 0; 160 Memset(header->padding, 0, sizeof(header->padding));
146 161
147 /* build secondary */ 162 /* build secondary */
148 header2 = (GptHeader*)gpt->secondary_header; 163 header2 = (GptHeader*)gpt->secondary_header;
149 entries2 = (GptEntry*)gpt->secondary_entries; 164 entries2 = (GptEntry*)gpt->secondary_entries;
150 Memcpy(header2, header, sizeof(GptHeader)); 165 Memcpy(header2, header, sizeof(GptHeader));
151 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE); 166 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
152 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */ 167 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
168 header2->alternate_lba = 1;
153 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */ 169 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
154 170
155 RefreshCrc32(gpt); 171 RefreshCrc32(gpt);
156 } 172 }
157 173
158 /* Dumps memory starting from [vp] with [len] bytes.
159 * Prints [memo] if not NULL. Example output:
160 *
161 * 00 01 02 03 04 05 06 07 - 08 09 0a 0b 0c 0d 0e 0f
162 * 10 11 12 13 14 15 16 17 - 18 19 1a 1b 1c 1d 1e 1f
163 * ...
164 */
165 static void Dump(void *vp, int len, char* memo) {
166 uint8_t *start = vp;
167 int i;
168 if (memo) printf("--[%s]----------\n", memo);
169 for (i = 0; i < len; ++i) {
170 printf("%02x%s", start[i],
171 (!(~i & 15) ? "\n" :
172 !(~i & 7) ? " - ": " "));
173 }
174 if (i&15) printf("\n");
175 }
176
177 /* More formatted dump with GptData. */
178 void DumpGptData(GptData *gpt) {
179 printf("DumpGptData(%p)...\n", gpt);
180 Dump(gpt, sizeof(gpt), NULL);
181 Dump(gpt->primary_header, sizeof(GptHeader), "Primary header");
182 Dump(gpt->primary_entries, sizeof(GptEntry) * 8, "Primary entries");
183 Dump(gpt->secondary_header, sizeof(GptHeader), "Secondary header");
184 Dump(gpt->secondary_entries, sizeof(GptEntry) * 8,
185 "Secondary entries");
186 }
187 174
188 /* Tests if the default structure returned by BuildTestGptData() is good. */ 175 /* Tests if the default structure returned by BuildTestGptData() is good. */
189 int TestBuildTestGptData() { 176 static int TestBuildTestGptData() {
190 GptData *gpt; 177 GptData* gpt;
178
191 gpt = GetEmptyGptData(); 179 gpt = GetEmptyGptData();
192 BuildTestGptData(gpt); 180 BuildTestGptData(gpt);
193 EXPECT(GPT_SUCCESS == GptInit(gpt)); 181 EXPECT(GPT_SUCCESS == GptInit(gpt));
194 return TEST_OK; 182 return TEST_OK;
195 } 183 }
196 184
185
197 /* Tests if wrong sector_bytes or drive_sectors is detected by GptInit(). 186 /* Tests if wrong sector_bytes or drive_sectors is detected by GptInit().
198 * Currently we only support 512 bytes per sector. 187 * Currently we only support 512 bytes per sector.
199 * In the future, we may support other sizes. 188 * In the future, we may support other sizes.
200 * A too small drive_sectors should be rejected by GptInit(). */ 189 * A too small drive_sectors should be rejected by GptInit(). */
201 int ParameterTests() { 190 static int ParameterTests() {
202 GptData *gpt; 191 GptData* gpt;
203 struct { 192 struct {
204 uint32_t sector_bytes; 193 uint32_t sector_bytes;
205 uint64_t drive_sectors; 194 uint64_t drive_sectors;
206 int expected_retval; 195 int expected_retval;
207 } cases[] = { 196 } cases[] = {
208 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS}, 197 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
209 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE}, 198 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
210 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER}, 199 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
211 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER}, 200 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
212 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2, 201 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2,
213 GPT_SUCCESS}, 202 GPT_SUCCESS},
214 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE}, 203 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
215 }; 204 };
216 int i; 205 int i;
217 206
218 gpt = GetEmptyGptData(); 207 gpt = GetEmptyGptData();
219 for (i = 0; i < ARRAY_SIZE(cases); ++i) { 208 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
220 BuildTestGptData(gpt); 209 BuildTestGptData(gpt);
221 gpt->sector_bytes = cases[i].sector_bytes; 210 gpt->sector_bytes = cases[i].sector_bytes;
222 gpt->drive_sectors = cases[i].drive_sectors; 211 gpt->drive_sectors = cases[i].drive_sectors;
223 EXPECT(cases[i].expected_retval == CheckParameters(gpt)); 212 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
224 } 213 }
225 214
226 return TEST_OK; 215 return TEST_OK;
227 } 216 }
228 217
218
219 /* Tests if header CRC in two copies are calculated. */
220 static int HeaderCrcTest() {
221 GptData* gpt = GetEmptyGptData();
222 GptHeader* h1 = (GptHeader*)gpt->primary_header;
223
224 BuildTestGptData(gpt);
225 EXPECT(HeaderCrc(h1) == h1->header_crc32);
226
227 /* CRC covers first byte of header */
228 BuildTestGptData(gpt);
229 gpt->primary_header[0] ^= 0xa5;
230 EXPECT(HeaderCrc(h1) != h1->header_crc32);
231
232 /* CRC covers last byte of header */
233 BuildTestGptData(gpt);
234 gpt->primary_header[h1->size - 1] ^= 0x5a;
235 EXPECT(HeaderCrc(h1) != h1->header_crc32);
236
237 /* CRC only covers header */
238 BuildTestGptData(gpt);
239 gpt->primary_header[h1->size] ^= 0x5a;
240 EXPECT(HeaderCrc(h1) == h1->header_crc32);
241
242 return TEST_OK;
243 }
244
245
229 /* Tests if signature ("EFI PART") is checked. */ 246 /* Tests if signature ("EFI PART") is checked. */
230 int SignatureTest() { 247 static int SignatureTest() {
231 int i; 248 GptData* gpt = GetEmptyGptData();
232 GptData *gpt; 249 GptHeader* h1 = (GptHeader*)gpt->primary_header;
233 int test_mask; 250 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
234 GptHeader *headers[2]; 251 int i;
235 252
236 gpt = GetEmptyGptData(); 253 for (i = 0; i < 8; ++i) {
237 headers[PRIMARY] = (GptHeader*)gpt->primary_header; 254 BuildTestGptData(gpt);
238 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; 255 h1->signature[i] ^= 0xff;
239 256 h2->signature[i] ^= 0xff;
240 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { 257 RefreshCrc32(gpt);
241 for (i = 0; i < 8; ++i) { 258 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
242 BuildTestGptData(gpt); 259 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
243 if (test_mask & MASK_PRIMARY) 260 }
244 headers[PRIMARY]->signature[i] ^= 0xff; 261
245 if (test_mask & MASK_SECONDARY) 262 return TEST_OK;
246 headers[SECONDARY]->signature[i] ^= 0xff; 263 }
247 EXPECT((MASK_BOTH ^ test_mask) == CheckHeaderSignature(gpt)); 264
248 }
249 }
250
251 return TEST_OK;
252 }
253 265
254 /* The revision we currently support is GPT_HEADER_REVISION. 266 /* The revision we currently support is GPT_HEADER_REVISION.
255 * If the revision in header is not that, we expect the header is invalid. */ 267 * If the revision in header is not that, we expect the header is invalid. */
256 int RevisionTest() { 268 static int RevisionTest() {
257 GptData *gpt; 269 GptData* gpt = GetEmptyGptData();
270 GptHeader* h1 = (GptHeader*)gpt->primary_header;
271 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
272 int i;
273
258 struct { 274 struct {
259 uint32_t value_to_test; 275 uint32_t value_to_test;
260 int is_valid_value; 276 int expect_rv;
261 } cases[] = { 277 } cases[] = {
262 {0x01000000, 0}, 278 {0x01000000, 1},
263 {0x00010000, 1}, /* GPT_HEADER_REVISION */ 279 {0x00010000, 0}, /* GPT_HEADER_REVISION */
264 {0x00000100, 0}, 280 {0x00000100, 1},
265 {0x00000001, 0}, 281 {0x00000001, 1},
266 {0x23010456, 0}, 282 {0x23010456, 1},
267 }; 283 };
268 int i;
269 int test_mask;
270 GptHeader *headers[2];
271 uint32_t valid_headers;
272
273 gpt = GetEmptyGptData();
274 headers[PRIMARY] = (GptHeader*)gpt->primary_header;
275 headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
276 284
277 for (i = 0; i < ARRAY_SIZE(cases); ++i) { 285 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
278 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { 286 BuildTestGptData(gpt);
279 BuildTestGptData(gpt); 287 h1->revision = cases[i].value_to_test;
280 if (test_mask & MASK_PRIMARY) 288 h2->revision = cases[i].value_to_test;
281 headers[PRIMARY]->revision = cases[i].value_to_test; 289 RefreshCrc32(gpt);
282 if (test_mask & MASK_SECONDARY) 290
283 headers[SECONDARY]->revision = cases[i].value_to_test; 291 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
284 valid_headers = CheckRevision(gpt); 292 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
285 if (cases[i].is_valid_value) 293 }
286 EXPECT(MASK_BOTH == valid_headers); 294 return TEST_OK;
287 else 295 }
288 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); 296
289 } 297
290 } 298 static int SizeTest() {
291 return TEST_OK; 299 GptData* gpt = GetEmptyGptData();
292 } 300 GptHeader* h1 = (GptHeader*)gpt->primary_header;
293 301 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
294 int SizeTest() { 302 int i;
295 GptData *gpt; 303
296 struct { 304 struct {
297 uint32_t value_to_test; 305 uint32_t value_to_test;
298 int is_valid_value; 306 int expect_rv;
299 } cases[] = { 307 } cases[] = {
300 {91, 0}, 308 {91, 1},
301 {92, 1}, 309 {92, 0},
302 {93, 1}, 310 {93, 0},
303 {511, 1}, 311 {511, 0},
304 {512, 1}, 312 {512, 0},
305 {513, 0}, 313 {513, 1},
306 }; 314 };
307 int i;
308 int test_mask;
309 GptHeader *headers[2];
310 uint32_t valid_headers;
311
312 gpt = GetEmptyGptData();
313 headers[PRIMARY] = (GptHeader*)gpt->primary_header;
314 headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
315 315
316 for (i = 0; i < ARRAY_SIZE(cases); ++i) { 316 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
317 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { 317 BuildTestGptData(gpt);
318 BuildTestGptData(gpt); 318 h1->size = cases[i].value_to_test;
319 if (test_mask & MASK_PRIMARY) 319 h2->size = cases[i].value_to_test;
320 headers[PRIMARY]->size = cases[i].value_to_test; 320 RefreshCrc32(gpt);
321 if (test_mask & MASK_SECONDARY) 321
322 headers[SECONDARY]->size = cases[i].value_to_test; 322 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
323 valid_headers = CheckSize(gpt); 323 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
324 if (cases[i].is_valid_value) 324 }
325 EXPECT(MASK_BOTH == valid_headers); 325 return TEST_OK;
326 else 326 }
327 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); 327
328 } 328
329 } 329 /* Tests if CRC is checked. */
330 return TEST_OK; 330 static int CrcFieldTest() {
331 } 331 GptData* gpt = GetEmptyGptData();
332 GptHeader* h1 = (GptHeader*)gpt->primary_header;
333 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
334
335 BuildTestGptData(gpt);
336 /* Modify a field that the header verification doesn't care about */
337 h1->entries_crc32++;
338 h2->entries_crc32++;
339 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
340 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
341 /* Refresh the CRC; should pass now */
342 RefreshCrc32(gpt);
343 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
344 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
345
346 return TEST_OK;
347 }
348
332 349
333 /* Tests if reserved fields are checked. 350 /* Tests if reserved fields are checked.
334 * We'll try non-zero values to test. */ 351 * We'll try non-zero values to test. */
335 int ReservedFieldsTest() { 352 static int ReservedFieldsTest() {
336 GptData *gpt; 353 GptData* gpt = GetEmptyGptData();
337 GptHeader *primary_header, *secondary_header; 354 GptHeader* h1 = (GptHeader*)gpt->primary_header;
338 355 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
339 gpt = GetEmptyGptData(); 356
340 primary_header = (GptHeader*)gpt->primary_header; 357 BuildTestGptData(gpt);
341 secondary_header = (GptHeader*)gpt->secondary_header; 358 h1->reserved ^= 0x12345678; /* whatever random */
342 359 h2->reserved ^= 0x12345678; /* whatever random */
343 /* expect secondary is still valid. */ 360 RefreshCrc32(gpt);
344 BuildTestGptData(gpt); 361 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
345 primary_header->reserved ^= 0x12345678; /* whatever random */ 362 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
346 EXPECT(MASK_SECONDARY == CheckReservedFields(gpt)); 363
347 364 #ifdef PADDING_CHECKED
348 /* expect secondary is still valid. */ 365 /* TODO: padding check is currently disabled */
349 BuildTestGptData(gpt); 366 BuildTestGptData(gpt);
350 primary_header->padding ^= 0x12345678; /* whatever random */ 367 h1->padding[12] ^= 0x34; /* whatever random */
351 EXPECT(MASK_SECONDARY == CheckReservedFields(gpt)); 368 h2->padding[56] ^= 0x78; /* whatever random */
352 369 RefreshCrc32(gpt);
353 /* expect primary is still valid. */ 370 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
354 BuildTestGptData(gpt); 371 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
355 secondary_header->reserved ^= 0x12345678; /* whatever random */ 372 #endif
356 EXPECT(MASK_PRIMARY == CheckReservedFields(gpt)); 373
357 374 return TEST_OK;
358 /* expect primary is still valid. */ 375 }
359 BuildTestGptData(gpt); 376
360 secondary_header->padding ^= 0x12345678; /* whatever random */ 377
361 EXPECT(MASK_PRIMARY == CheckReservedFields(gpt)); 378 /* Technically, any size which is 2^N where N > 6 should work, but our
362 379 * library only supports one size. */
363 return TEST_OK; 380 static int SizeOfPartitionEntryTest() {
364 } 381 GptData* gpt = GetEmptyGptData();
382 GptHeader* h1 = (GptHeader*)gpt->primary_header;
383 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
384 int i;
385
386 struct {
387 uint32_t value_to_test;
388 int expect_rv;
389 } cases[] = {
390 {127, 1},
391 {128, 0},
392 {129, 1},
393 {256, 1},
394 {512, 1},
395 };
396
397 /* Check size of entryes */
398 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
399 BuildTestGptData(gpt);
400 h1->size_of_entry = cases[i].value_to_test;
401 h2->size_of_entry = cases[i].value_to_test;
402 h1->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
403 h2->number_of_entries = TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
404 RefreshCrc32(gpt);
405
406 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) == cases[i].expect_rv);
407 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) == cases[i].expect_rv);
408 }
409
410 return TEST_OK;
411 }
412
413
414 /* Technically, any size which is 2^N where N > 6 should work, but our
415 * library only supports one size. */
416 static int NumberOfPartitionEntriesTest() {
417 GptData* gpt = GetEmptyGptData();
418 GptHeader* h1 = (GptHeader*)gpt->primary_header;
419 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
420
421 BuildTestGptData(gpt);
422 h1->number_of_entries--;
423 h2->number_of_entries /= 2;
424 RefreshCrc32(gpt);
425 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
426 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
427
428 return TEST_OK;
429 }
430
365 431
366 /* Tests if myLBA field is checked (1 for primary, last for secondary). */ 432 /* Tests if myLBA field is checked (1 for primary, last for secondary). */
367 int MyLbaTest() { 433 static int MyLbaTest() {
368 GptData *gpt; 434 GptData* gpt = GetEmptyGptData();
369 int test_mask; 435 GptHeader* h1 = (GptHeader*)gpt->primary_header;
370 GptHeader *headers[2]; 436 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
371 uint32_t valid_headers; 437
372 438 /* myLBA depends on primary vs secondary flag */
373 gpt = GetEmptyGptData(); 439 BuildTestGptData(gpt);
374 headers[PRIMARY] = (GptHeader*)gpt->primary_header; 440 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
375 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; 441 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
376 442
377 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { 443 BuildTestGptData(gpt);
378 BuildTestGptData(gpt); 444 h1->my_lba--;
379 if (test_mask & MASK_PRIMARY) 445 h2->my_lba--;
380 ++headers[PRIMARY]->my_lba; 446 RefreshCrc32(gpt);
381 if (test_mask & MASK_SECONDARY) 447 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
382 --headers[SECONDARY]->my_lba; 448 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
383 valid_headers = CheckMyLba(gpt); 449
384 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); 450 BuildTestGptData(gpt);
385 } 451 h1->my_lba = 2;
386 return TEST_OK; 452 h2->my_lba--;
387 } 453 RefreshCrc32(gpt);
388 454 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
389 /* Tests if SizeOfPartitionEntry is checked. SizeOfPartitionEntry must be 455 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
390 * between 128 and 512, and a multiple of 8. */ 456
391 int SizeOfPartitionEntryTest() { 457 BuildTestGptData(gpt);
392 GptData *gpt; 458 h1->alternate_lba++;
393 struct { 459 h2->alternate_lba++;
394 uint32_t value_to_test; 460 RefreshCrc32(gpt);
395 int is_valid_value; 461 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
396 } cases[] = { 462 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
397 {127, 0}, 463
398 {128, 1}, 464 BuildTestGptData(gpt);
399 {129, 0}, 465 h1->alternate_lba--;
400 {130, 0}, 466 h2->alternate_lba--;
401 {131, 0}, 467 RefreshCrc32(gpt);
402 {132, 0}, 468 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
403 {133, 0}, 469 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
404 {134, 0}, 470
405 {135, 0}, 471 BuildTestGptData(gpt);
406 {136, 1}, 472 h1->entries_lba++;
407 {144, 1}, 473 h2->entries_lba++;
408 {160, 1}, 474 RefreshCrc32(gpt);
409 {192, 1}, 475 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
410 {256, 1}, 476 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
411 {384, 1}, 477
412 {504, 1}, 478 BuildTestGptData(gpt);
413 {512, 1}, 479 h1->entries_lba--;
414 {513, 0}, 480 h2->entries_lba--;
415 {520, 0}, 481 RefreshCrc32(gpt);
416 }; 482 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
417 int i; 483 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
418 int test_mask; 484
419 GptHeader *headers[2]; 485 return TEST_OK;
420 uint32_t valid_headers; 486 }
421 487
422 gpt = GetEmptyGptData();
423 headers[PRIMARY] = (GptHeader*)gpt->primary_header;
424 headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
425
426 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
427 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
428 BuildTestGptData(gpt);
429 if (test_mask & MASK_PRIMARY) {
430 headers[PRIMARY]->size_of_entry = cases[i].value_to_test;
431 headers[PRIMARY]->number_of_entries =
432 TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
433 }
434 if (test_mask & MASK_SECONDARY) {
435 headers[SECONDARY]->size_of_entry = cases[i].value_to_test;
436 headers[SECONDARY]->number_of_entries =
437 TOTAL_ENTRIES_SIZE / cases[i].value_to_test;
438 }
439 valid_headers = CheckSizeOfPartitionEntry(gpt);
440 if (cases[i].is_valid_value)
441 EXPECT(MASK_BOTH == valid_headers);
442 else
443 EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
444 }
445 }
446 return TEST_OK;
447 }
448
449 /* Tests if NumberOfPartitionEntries is checes. NumberOfPartitionEntries must
450 * be between 32 and 512, and SizeOfPartitionEntry * NumberOfPartitionEntries
451 * must be 16384. */
452 int NumberOfPartitionEntriesTest() {
453 GptData *gpt;
454 struct {
455 uint32_t size_of_entry;
456 uint32_t number_of_entries;
457 int is_valid_value;
458 } cases[] = {
459 {111, 147, 0},
460 {111, 149, 0},
461 {128, 32, 0},
462 {128, 64, 0},
463 {128, 127, 0},
464 {128, 128, 1},
465 {128, 129, 0},
466 {128, 256, 0},
467 {256, 32, 0},
468 {256, 64, 1},
469 {256, 128, 0},
470 {256, 256, 0},
471 {512, 32, 1},
472 {512, 64, 0},
473 {512, 128, 0},
474 {512, 256, 0},
475 {1024, 128, 0},
476 };
477 int i;
478 int test_mask;
479 GptHeader *headers[2];
480 uint32_t valid_headers;
481
482 gpt = GetEmptyGptData();
483 headers[PRIMARY] = (GptHeader*)gpt->primary_header;
484 headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
485
486 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
487 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
488 BuildTestGptData(gpt);
489 if (test_mask & MASK_PRIMARY) {
490 headers[PRIMARY]->size_of_entry = cases[i].size_of_entry;
491 headers[PRIMARY]->number_of_entries = cases[i].number_of_entries;
492 }
493 if (test_mask & MASK_SECONDARY) {
494 headers[SECONDARY]->size_of_entry = cases[i].size_of_entry;
495 headers[SECONDARY]->number_of_entries = cases[i].number_of_entries;
496 }
497 valid_headers = CheckNumberOfEntries(gpt);
498 if (cases[i].is_valid_value)
499 EXPECT(MASK_BOTH == valid_headers);
500 else
501 EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
502 }
503 }
504 return TEST_OK;
505 }
506
507 /* Tests if PartitionEntryLBA in primary/secondary headers is checked. */
508 int PartitionEntryLbaTest() {
509 GptData *gpt;
510 int test_mask;
511 GptHeader *headers[2];
512 uint32_t valid_headers;
513
514 gpt = GetEmptyGptData();
515 headers[PRIMARY] = (GptHeader*)gpt->primary_header;
516 headers[SECONDARY] = (GptHeader*)gpt->secondary_header;
517
518 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) {
519 BuildTestGptData(gpt);
520 if (test_mask & MASK_PRIMARY)
521 headers[PRIMARY]->entries_lba = 0;
522 if (test_mask & MASK_SECONDARY)
523 headers[SECONDARY]->entries_lba = DEFAULT_DRIVE_SECTORS - 31 - 1;
524 valid_headers = CheckEntriesLba(gpt);
525 EXPECT((MASK_BOTH ^ test_mask) == valid_headers);
526 }
527 return TEST_OK;
528 }
529 488
530 /* Tests if FirstUsableLBA and LastUsableLBA are checked. 489 /* Tests if FirstUsableLBA and LastUsableLBA are checked.
531 * FirstUsableLBA must be after the end of the primary GPT table array. 490 * FirstUsableLBA must be after the end of the primary GPT table array.
532 * LastUsableLBA must be before the start of the secondary GPT table array. 491 * LastUsableLBA must be before the start of the secondary GPT table array.
533 * FirstUsableLBA <= LastUsableLBA. */ 492 * FirstUsableLBA <= LastUsableLBA. */
534 int FirstUsableLbaAndLastUsableLbaTest() { 493 static int FirstUsableLbaAndLastUsableLbaTest() {
535 GptData *gpt; 494 GptData* gpt = GetEmptyGptData();
536 GptHeader *primary_header, *secondary_header; 495 GptHeader* h1 = (GptHeader*)gpt->primary_header;
537 uint32_t valid_headers; 496 GptHeader* h2 = (GptHeader*)gpt->secondary_header;
538 int i; 497 int i;
498
539 struct { 499 struct {
540 uint64_t primary_entries_lba; 500 uint64_t primary_entries_lba;
541 uint64_t primary_first_usable_lba; 501 uint64_t primary_first_usable_lba;
542 uint64_t primary_last_usable_lba; 502 uint64_t primary_last_usable_lba;
543 uint64_t secondary_first_usable_lba; 503 uint64_t secondary_first_usable_lba;
544 uint64_t secondary_last_usable_lba; 504 uint64_t secondary_last_usable_lba;
545 uint64_t secondary_entries_lba; 505 uint64_t secondary_entries_lba;
546 int expected_masks; 506 int primary_rv;
507 int secondary_rv;
547 } cases[] = { 508 } cases[] = {
548 {2, 34, 433, 34, 433, 434, MASK_BOTH}, 509 {2, 34, 433, 34, 433, 434, 0, 0},
549 {2, 34, 432, 34, 430, 434, MASK_BOTH}, 510 {2, 34, 432, 34, 430, 434, 0, 0},
550 {2, 33, 433, 33, 433, 434, MASK_NONE}, 511 {2, 33, 433, 33, 433, 434, 1, 1},
551 {3, 34, 433, 35, 433, 434, MASK_SECONDARY}, 512 {2, 34, 434, 34, 433, 434, 1, 0},
552 {3, 35, 433, 33, 433, 434, MASK_PRIMARY}, 513 {2, 34, 433, 34, 434, 434, 0, 1},
553 {2, 34, 434, 34, 433, 434, MASK_SECONDARY}, 514 {2, 35, 433, 35, 433, 434, 0, 0},
554 {2, 34, 433, 34, 434, 434, MASK_PRIMARY}, 515 {2, 433, 433, 433, 433, 434, 0, 0},
555 {2, 35, 433, 35, 433, 434, MASK_BOTH}, 516 {2, 434, 433, 434, 434, 434, 1, 1},
556 {2, 433, 433, 433, 433, 434, MASK_BOTH}, 517 {2, 433, 34, 34, 433, 434, 1, 0},
557 {2, 434, 433, 434, 434, 434, MASK_NONE}, 518 {2, 34, 433, 433, 34, 434, 0, 1},
558 {2, 433, 34, 34, 433, 434, MASK_SECONDARY},
559 {2, 34, 433, 433, 34, 434, MASK_PRIMARY},
560 }; 519 };
561 520
562 gpt = GetEmptyGptData();
563 primary_header = (GptHeader*)gpt->primary_header;
564 secondary_header = (GptHeader*)gpt->secondary_header;
565
566 for (i = 0; i < ARRAY_SIZE(cases); ++i) { 521 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
567 BuildTestGptData(gpt); 522 BuildTestGptData(gpt);
568 primary_header->entries_lba = cases[i].primary_entries_lba; 523 h1->entries_lba = cases[i].primary_entries_lba;
569 primary_header->first_usable_lba = cases[i].primary_first_usable_lba; 524 h1->first_usable_lba = cases[i].primary_first_usable_lba;
570 primary_header->last_usable_lba = cases[i].primary_last_usable_lba; 525 h1->last_usable_lba = cases[i].primary_last_usable_lba;
571 secondary_header->entries_lba = cases[i].secondary_entries_lba; 526 h2->entries_lba = cases[i].secondary_entries_lba;
572 secondary_header->first_usable_lba = cases[i].secondary_first_usable_lba; 527 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
573 secondary_header->last_usable_lba = cases[i].secondary_last_usable_lba; 528 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
574 valid_headers = CheckValidUsableLbas(gpt); 529 RefreshCrc32(gpt);
575 EXPECT(cases[i].expected_masks == valid_headers); 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);
576 } 533 }
577 534
578 return TEST_OK; 535 return TEST_OK;
579 } 536 }
580 537
581 /* Tests if header CRC in two copies are calculated. */
582 int HeaderCrcTest() {
583 GptData *gpt;
584 GptHeader *primary_header, *secondary_header;
585
586 gpt = GetEmptyGptData();
587 primary_header = (GptHeader*)gpt->primary_header;
588 secondary_header = (GptHeader*)gpt->secondary_header;
589
590 /* Modify the first byte of primary header, and expect the CRC is wrong. */
591 BuildTestGptData(gpt);
592 gpt->primary_header[0] ^= 0xa5; /* just XOR a non-zero value */
593 EXPECT(MASK_SECONDARY == CheckHeaderCrc(gpt));
594
595 /* Modify the last byte of secondary header, and expect the CRC is wrong. */
596 BuildTestGptData(gpt);
597 gpt->secondary_header[secondary_header->size-1] ^= 0x5a;
598 EXPECT(MASK_PRIMARY == CheckHeaderCrc(gpt));
599
600 /* Modify out of CRC range, expect CRC is still right. */
601 BuildTestGptData(gpt);
602 gpt->primary_header[primary_header->size] ^= 0x87;
603 EXPECT(MASK_BOTH == CheckHeaderCrc(gpt));
604
605 /* Very long header (actually invalid header). Expect will be ignored. */
606 primary_header->size = 0x12345678;
607 secondary_header->size = 0x87654321;
608 gpt->valid_headers = MASK_NONE;
609 EXPECT(MASK_NONE == CheckHeaderCrc(gpt));
610
611 return TEST_OK;
612 }
613 538
614 /* Tests if PartitionEntryArrayCRC32 is checked. 539 /* Tests if PartitionEntryArrayCRC32 is checked.
615 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry * 540 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry *
616 * NumberOfPartitionEntries bytes. 541 * NumberOfPartitionEntries bytes.
617 */ 542 */
618 int EntriesCrcTest() { 543 static int EntriesCrcTest() {
619 GptData *gpt; 544 GptData* gpt = GetEmptyGptData();
620 545 GptHeader* h1 = (GptHeader*)gpt->primary_header;
621 gpt = GetEmptyGptData(); 546 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
547 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
622 548
623 /* Modify the first byte of primary entries, and expect the CRC is wrong. */ 549 /* Modify the first byte of primary entries, and expect the CRC is wrong. */
624 BuildTestGptData(gpt); 550 BuildTestGptData(gpt);
551 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
552 EXPECT(0 == CheckEntries(e2, h1, gpt->drive_sectors));
625 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */ 553 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
626 EXPECT(MASK_SECONDARY == CheckEntriesCrc(gpt));
627
628 /* Modify the last byte of secondary entries, and expect the CRC is wrong. */
629 BuildTestGptData(gpt);
630 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a; 554 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
631 EXPECT(MASK_PRIMARY == CheckEntriesCrc(gpt)); 555 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
556 EXPECT(1 == CheckEntries(e2, h1, gpt->drive_sectors));
632 557
633 return TEST_OK; 558 return TEST_OK;
634 } 559 }
635 560
636 /* Tests if GptInit() handles non-identical partition entries well.
637 * Two copies of partition table entries must be identical. If not, we trust the
638 * primary table entries, and mark secondary as modified. */
639 int IdenticalEntriesTest() {
640 GptData *gpt;
641
642 gpt = GetEmptyGptData();
643
644 /* Tests RepairEntries() first. */
645 BuildTestGptData(gpt);
646 EXPECT(0 == RepairEntries(gpt, MASK_BOTH));
647 gpt->secondary_entries[0] ^= 0xa5; /* XOR any number */
648 EXPECT(GPT_MODIFIED_ENTRIES2 == RepairEntries(gpt, MASK_BOTH));
649 EXPECT(GPT_MODIFIED_ENTRIES2 == RepairEntries(gpt, MASK_PRIMARY));
650 EXPECT(GPT_MODIFIED_ENTRIES1 == RepairEntries(gpt, MASK_SECONDARY));
651 EXPECT(0 == RepairEntries(gpt, MASK_NONE));
652
653 /* The first byte is different. We expect secondary entries is marked as
654 * modified. */
655 BuildTestGptData(gpt);
656 gpt->primary_entries[0] ^= 0xff;
657 RefreshCrc32(gpt);
658 EXPECT(GPT_SUCCESS == GptInit(gpt));
659 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
660 EXPECT(0 == Memcmp(gpt->primary_entries, gpt->secondary_entries,
661 TOTAL_ENTRIES_SIZE));
662
663 /* The last byte is different, but the primary entries CRC is bad.
664 * We expect primary entries is marked as modified. */
665 BuildTestGptData(gpt);
666 gpt->primary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0xff;
667 EXPECT(GPT_SUCCESS == GptInit(gpt));
668 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
669 EXPECT(0 == Memcmp(gpt->primary_entries, gpt->secondary_entries,
670 TOTAL_ENTRIES_SIZE));
671
672 return TEST_OK;
673 }
674
675 /* Tests if GptInit() handles synonymous headers well.
676 * Note that two partition headers are NOT bit-swise identical.
677 * For exmaple, my_lba must be different (pointing to respective self).
678 * So in normal case, they are synonymous, not identical.
679 * If not synonymous, we trust the primary partition header, and
680 * overwrite secondary, then mark secondary as modified.*/
681 int SynonymousHeaderTest() {
682 GptData *gpt;
683 GptHeader *primary_header, *secondary_header;
684
685 gpt = GetEmptyGptData();
686 primary_header = (GptHeader*)gpt->primary_header;
687 secondary_header = (GptHeader*)gpt->secondary_header;
688
689 /* Tests RepairHeader() for synonymous cases first. */
690 BuildTestGptData(gpt);
691 EXPECT(0 == RepairHeader(gpt, MASK_BOTH));
692 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_PRIMARY));
693 EXPECT(GPT_MODIFIED_HEADER1 == RepairHeader(gpt, MASK_SECONDARY));
694 EXPECT(0 == RepairHeader(gpt, MASK_NONE));
695 /* Then tests non-synonymous cases. */
696 BuildTestGptData(gpt);
697 ++secondary_header->first_usable_lba; /* chnage any bit */
698 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
699 EXPECT(primary_header->first_usable_lba ==
700 secondary_header->first_usable_lba);
701 /* ---- */
702 BuildTestGptData(gpt);
703 --secondary_header->last_usable_lba;
704 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
705 EXPECT(primary_header->last_usable_lba == secondary_header->last_usable_lba);
706 /* ---- */
707 BuildTestGptData(gpt);
708 ++secondary_header->number_of_entries;
709 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
710 EXPECT(primary_header->number_of_entries ==
711 secondary_header->number_of_entries);
712 /* ---- */
713 BuildTestGptData(gpt);
714 --secondary_header->size_of_entry;
715 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
716 EXPECT(primary_header->size_of_entry ==
717 secondary_header->size_of_entry);
718 /* ---- */
719 BuildTestGptData(gpt);
720 secondary_header->disk_uuid.u.raw[0] ^= 0x56;
721 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH));
722 EXPECT(0 == Memcmp(&primary_header->disk_uuid,
723 &secondary_header->disk_uuid, sizeof(Guid)));
724
725 /* Consider header repairing in GptInit(). */
726 BuildTestGptData(gpt);
727 ++secondary_header->first_usable_lba;
728 RefreshCrc32(gpt);
729 EXPECT(GPT_SUCCESS == GptInit(gpt));
730 EXPECT((gpt->modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_HEADER2)) ==
731 GPT_MODIFIED_HEADER2);
732 EXPECT(primary_header->first_usable_lba ==
733 secondary_header->first_usable_lba);
734
735 return TEST_OK;
736 }
737 561
738 /* Tests if partition geometry is checked. 562 /* Tests if partition geometry is checked.
739 * All active (non-zero PartitionTypeGUID) partition entries should have: 563 * All active (non-zero PartitionTypeGUID) partition entries should have:
740 * entry.StartingLBA >= header.FirstUsableLBA 564 * entry.StartingLBA >= header.FirstUsableLBA
741 * entry.EndingLBA <= header.LastUsableLBA 565 * entry.EndingLBA <= header.LastUsableLBA
742 * entry.StartingLBA <= entry.EndingLBA 566 * entry.StartingLBA <= entry.EndingLBA
743 */ 567 */
744 int ValidEntryTest() { 568 static int ValidEntryTest() {
745 GptData *gpt; 569 GptData* gpt = GetEmptyGptData();
746 GptHeader *primary_header, *secondary_header; 570 GptHeader* h1 = (GptHeader*)gpt->primary_header;
747 GptEntry *primary_entries, *secondary_entries; 571 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
748
749 gpt = GetEmptyGptData();
750 primary_header = (GptHeader*)gpt->primary_header;
751 secondary_header = (GptHeader*)gpt->secondary_header;
752 primary_entries = (GptEntry*)gpt->primary_entries;
753 secondary_entries = (GptEntry*)gpt->secondary_entries;
754 572
755 /* error case: entry.StartingLBA < header.FirstUsableLBA */ 573 /* error case: entry.StartingLBA < header.FirstUsableLBA */
756 BuildTestGptData(gpt); 574 BuildTestGptData(gpt);
757 primary_entries[0].starting_lba = primary_header->first_usable_lba - 1; 575 e1[0].starting_lba = h1->first_usable_lba - 1;
758 EXPECT(MASK_SECONDARY == CheckValidEntries(gpt)); 576 RefreshCrc32(gpt);
759 secondary_entries[1].starting_lba = secondary_header->first_usable_lba - 1; 577 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
760 EXPECT(MASK_NONE == CheckValidEntries(gpt));
761 578
762 /* error case: entry.EndingLBA > header.LastUsableLBA */ 579 /* error case: entry.EndingLBA > header.LastUsableLBA */
763 BuildTestGptData(gpt); 580 BuildTestGptData(gpt);
764 primary_entries[2].ending_lba = primary_header->last_usable_lba + 1; 581 e1[2].ending_lba = h1->last_usable_lba + 1;
765 EXPECT(MASK_SECONDARY == CheckValidEntries(gpt)); 582 RefreshCrc32(gpt);
766 secondary_entries[3].ending_lba = secondary_header->last_usable_lba + 1; 583 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
767 EXPECT(MASK_NONE == CheckValidEntries(gpt));
768 584
769 /* error case: entry.StartingLBA > entry.EndingLBA */ 585 /* error case: entry.StartingLBA > entry.EndingLBA */
770 BuildTestGptData(gpt); 586 BuildTestGptData(gpt);
771 primary_entries[3].starting_lba = primary_entries[3].ending_lba + 1; 587 e1[3].starting_lba = e1[3].ending_lba + 1;
772 EXPECT(MASK_SECONDARY == CheckValidEntries(gpt)); 588 RefreshCrc32(gpt);
773 secondary_entries[1].starting_lba = secondary_entries[1].ending_lba + 1; 589 EXPECT(1 == CheckEntries(e1, h1, gpt->drive_sectors));
774 EXPECT(MASK_NONE == CheckValidEntries(gpt));
775 590
776 /* case: non active entry should be ignored. */ 591 /* case: non active entry should be ignored. */
777 BuildTestGptData(gpt); 592 BuildTestGptData(gpt);
778 Memset(&primary_entries[1].type, 0, sizeof(primary_entries[1].type)); 593 Memset(&e1[1].type, 0, sizeof(e1[1].type));
779 primary_entries[1].starting_lba = primary_entries[1].ending_lba + 1; 594 e1[1].starting_lba = e1[1].ending_lba + 1;
780 EXPECT(MASK_BOTH == CheckValidEntries(gpt)); 595 RefreshCrc32(gpt);
781 Memset(&secondary_entries[2].type, 0, sizeof(secondary_entries[2].type)); 596 EXPECT(0 == CheckEntries(e1, h1, gpt->drive_sectors));
782 secondary_entries[2].starting_lba = secondary_entries[2].ending_lba + 1;
783 EXPECT(MASK_BOTH == CheckValidEntries(gpt));
784 597
785 return TEST_OK; 598 return TEST_OK;
786 } 599 }
787 600
601
788 /* Tests if overlapped partition tables can be detected. */ 602 /* Tests if overlapped partition tables can be detected. */
789 int OverlappedPartitionTest() { 603 static int OverlappedPartitionTest() {
790 GptData *gpt; 604 GptData* gpt = GetEmptyGptData();
605 GptHeader* h = (GptHeader*)gpt->primary_header;
606 GptEntry* e = (GptEntry*)gpt->primary_entries;
607 int i, j;
608
791 struct { 609 struct {
792 int overlapped; 610 int overlapped;
793 struct { 611 struct {
794 int active; 612 int active;
795 uint64_t starting_lba; 613 uint64_t starting_lba;
796 uint64_t ending_lba; 614 uint64_t ending_lba;
797 } entries[16]; /* enough for testing. */ 615 } entries[16]; /* enough for testing. */
798 } cases[] = { 616 } cases[] = {
799 {0, {{0, 100, 199}, {0, 0, 0}}}, 617 {0, {{0, 100, 199}}},
800 {0, {{1, 100, 199}, {0, 0, 0}}}, 618 {0, {{1, 100, 199}}},
801 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}, {0, 0, 0}}}, 619 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
802 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}, {0, 0, 0}}}, 620 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
803 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}, {0, 0, 0}}}, 621 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
804 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}, {0, 0, 0}}}, 622 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
805 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}, {0, 0, 0}}}, 623 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
806 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}, {0, 0, 0}}}, 624 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
807 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}, {0, 0, 0}}}, 625 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
808 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}, {0, 0, 0}}}, 626 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
809 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}, 627 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
810 {0, 0, 0}}}, 628 {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
811 {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}}},
812 {0, 0, 0}}}, 630 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
813 {1, {{1, 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}}},
814 {0, 0, 0}}}, 632 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
815 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}, 633 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
816 {0, 0, 0}}}, 634 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
817 {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400},
818 {0, 0, 0}}},
819 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}, {0, 0, 0}}},
820 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}, {0, 0, 0}}},
821 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}, {0, 0, 0}}},
822 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202}, 635 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
823 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206}, 636 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
824 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}, {0, 0, 0}}}, 637 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
825 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202}, 638 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
826 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206}, 639 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
827 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}, {0, 0, 0}}}, 640 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
828 }; 641 };
829 Guid any_type = GPT_ENT_TYPE_CHROMEOS_KERNEL; 642
830 int i, j;
831 int test_mask;
832 GptEntry *entries[2];
833
834 gpt = GetEmptyGptData();
835 entries[PRIMARY] = (GptEntry*)gpt->primary_entries;
836 entries[SECONDARY] = (GptEntry*)gpt->secondary_entries;
837 643
838 for (i = 0; i < ARRAY_SIZE(cases); ++i) { 644 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
839 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { 645 BuildTestGptData(gpt);
840 BuildTestGptData(gpt); 646 ZeroEntries(gpt);
841 ZeroEntries(gpt); 647 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
842 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) { 648 if (!cases[i].entries[j].starting_lba)
843 if (!cases[i].entries[j].starting_lba) break; 649 break;
844 if (test_mask & MASK_PRIMARY) { 650
845 if (cases[i].entries[j].active) 651 if (cases[i].entries[j].active)
846 Memcpy(&entries[PRIMARY][j].type, &any_type, sizeof(any_type)); 652 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
847 entries[PRIMARY][j].starting_lba = cases[i].entries[j].starting_lba; 653 e[j].starting_lba = cases[i].entries[j].starting_lba;
848 entries[PRIMARY][j].ending_lba = cases[i].entries[j].ending_lba; 654 e[j].ending_lba = cases[i].entries[j].ending_lba;
849 }
850 if (test_mask & MASK_SECONDARY) {
851 if (cases[i].entries[j].active)
852 Memcpy(&entries[SECONDARY][j].type, &any_type, sizeof(any_type));
853 entries[SECONDARY][j].starting_lba = cases[i].entries[j].starting_lba;
854 entries[SECONDARY][j].ending_lba = cases[i].entries[j].ending_lba;
855 }
856 }
857 EXPECT((cases[i].overlapped * test_mask) ==
858 (OverlappedEntries(entries[PRIMARY], j) |
859 (OverlappedEntries(entries[SECONDARY], j) << SECONDARY))
860 );
861
862 EXPECT((MASK_BOTH ^ (cases[i].overlapped * test_mask)) ==
863 CheckOverlappedPartition(gpt));
864 } 655 }
656 RefreshCrc32(gpt);
657
658 EXPECT(cases[i].overlapped == CheckEntries(e, h, gpt->drive_sectors));
865 } 659 }
866 return TEST_OK; 660 return TEST_OK;
867 } 661 }
868 662
869 /* Tests if GptInit() can survive in different corrupt header/entries 663
870 * combinations, like: 664 /* Test both sanity checking and repair. */
871 * primary GPT header - valid 665 static int SanityCheckTest() {
872 * primary partition table - invalid 666 GptData* gpt = GetEmptyGptData();
873 * secondary GPT header - invalid 667 GptHeader* h1 = (GptHeader*)gpt->primary_header;
874 * secondary partition table - valid 668
875 */ 669 /* Unmodified test data is completely sane */
876 int CorruptCombinationTest() { 670 BuildTestGptData(gpt);
877 GptData *gpt; 671 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
878 GptHeader *primary_header, *secondary_header; 672 EXPECT(MASK_BOTH == gpt->valid_headers);
879 GptEntry *primary_entries, *secondary_entries; 673 EXPECT(MASK_BOTH == gpt->valid_entries);
880 674 /* Repair doesn't damage it */
881 gpt = GetEmptyGptData(); 675 GptRepair(gpt);
882 primary_header = (GptHeader*)gpt->primary_header; 676 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
883 secondary_header = (GptHeader*)gpt->secondary_header; 677 EXPECT(MASK_BOTH == gpt->valid_headers);
884 primary_entries = (GptEntry*)gpt->primary_entries; 678 EXPECT(MASK_BOTH == gpt->valid_entries);
885 secondary_entries = (GptEntry*)gpt->secondary_entries; 679 EXPECT(0 == gpt->modified);
886 680
887 /* Make primary entries and secondary header invalid, we expect GptInit() 681 /* Modify headers */
888 * can recover them (returns GPT_SUCCESS and MODIFIED flasgs). */ 682 BuildTestGptData(gpt);
889 BuildTestGptData(gpt); 683 gpt->primary_header[0]++;
890 primary_entries[0].type.u.raw[0] ^= 0x33; 684 gpt->secondary_header[0]++;
891 secondary_header->header_crc32 ^= 0x55; 685 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
892 EXPECT(GPT_SUCCESS == GptInit(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);
893 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified); 790 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
894 EXPECT(0 == Memcmp(primary_entries, secondary_entries, TOTAL_ENTRIES_SIZE)); 791
895 /* We expect the modified header/entries can pass GptInit(). */ 792 /* Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.
896 EXPECT(GPT_SUCCESS == GptInit(gpt)); 793 * This simulates a partial update of the drive. */
897 EXPECT(0 == gpt->modified); 794 BuildTestGptData(gpt);
898 795 gpt->secondary_entries[0]++;
899 /* Make primary header invalid (the entries is not damaged actually). */ 796 RefreshCrc32(gpt);
900 BuildTestGptData(gpt); 797 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
901 primary_header->entries_crc32 ^= 0x73; 798 EXPECT(MASK_PRIMARY == gpt->valid_headers);
902 EXPECT(GPT_SUCCESS == GptInit(gpt)); 799 EXPECT(MASK_PRIMARY == gpt->valid_entries);
903 /* After header is repaired, the entries are valid actually. */ 800 GptRepair(gpt);
904 EXPECT((gpt->modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_HEADER2)) == 801 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
905 GPT_MODIFIED_HEADER1); 802 EXPECT(MASK_BOTH == gpt->valid_headers);
906 /* We expect the modified header/entries can pass GptInit(). */ 803 EXPECT(MASK_BOTH == gpt->valid_entries);
907 EXPECT(GPT_SUCCESS == GptInit(gpt)); 804 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
908 EXPECT(0 == gpt->modified); 805
909 806 return TEST_OK;
910 return TEST_OK; 807 }
911 } 808
809
810 static int EntryAttributeGetSetTest() {
811 GptData* gpt = GetEmptyGptData();
812 GptEntry* e = (GptEntry*)(gpt->primary_entries);
813
814 e->attributes = 0x0000000000000000;
815 SetEntrySuccessful(e, 1);
816 EXPECT(0x0100000000000000 == e->attributes);
817 EXPECT(1 == GetEntrySuccessful(e));
818 e->attributes = 0xFFFFFFFFFFFFFFFF;
819 SetEntrySuccessful(e, 0);
820 EXPECT(0xFEFFFFFFFFFFFFFF == e->attributes);
821 EXPECT(0 == GetEntrySuccessful(e));
822
823 e->attributes = 0x0000000000000000;
824 SetEntryTries(e, 15);
825 EXPECT(15 == GetEntryTries(e));
826 EXPECT(0x00F0000000000000 == e->attributes);
827 e->attributes = 0xFFFFFFFFFFFFFFFF;
828 SetEntryTries(e, 0);
829 EXPECT(0xFF0FFFFFFFFFFFFF == e->attributes);
830 EXPECT(0 == GetEntryTries(e));
831
832 e->attributes = 0x0000000000000000;
833 SetEntryPriority(e, 15);
834 EXPECT(0x000F000000000000 == e->attributes);
835 EXPECT(15 == GetEntryPriority(e));
836 e->attributes = 0xFFFFFFFFFFFFFFFF;
837 SetEntryPriority(e, 0);
838 EXPECT(0xFFF0FFFFFFFFFFFF == e->attributes);
839 EXPECT(0 == GetEntryPriority(e));
840
841 e->attributes = 0xFFFFFFFFFFFFFFFF;
842 EXPECT(1 == GetEntrySuccessful(e));
843 EXPECT(15 == GetEntryPriority(e));
844 EXPECT(15 == GetEntryTries(e));
845
846 e->attributes = 0x0123000000000000;
847 EXPECT(1 == GetEntrySuccessful(e));
848 EXPECT(2 == GetEntryTries(e));
849 EXPECT(3 == GetEntryPriority(e));
850
851 return TEST_OK;
852 }
853
854
855 static 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. */
876 static void FreeEntry(GptEntry* e) {
877 Memset(&e->type, 0, sizeof(Guid));
878 }
879
880
881 /* Set up an entry. */
882 static 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
912 890
913 /* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find 891 /* Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
914 * any usable kernel entry. 892 * any usable kernel entry.
915 */ 893 */
916 int NoValidKernelEntryTest() { 894 static int NoValidKernelEntryTest() {
917 GptData *gpt; 895 GptData* gpt = GetEmptyGptData();
918 GptEntry *entries, *entries2; 896 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
919 897
920 gpt = GetEmptyGptData(); 898 BuildTestGptData(gpt);
921 entries = (GptEntry*)gpt->primary_entries; 899 SetEntryPriority(e1 + KERNEL_A, 0);
922 entries2 = (GptEntry*)gpt->secondary_entries; 900 FreeEntry(e1 + KERNEL_B);
923 901 RefreshCrc32(gpt);
924 BuildTestGptData(gpt);
925 entries[KERNEL_A].attributes |= CGPT_ATTRIBUTE_BAD_MASK;
926 Memset(&entries[KERNEL_B].type, 0, sizeof(Guid));
927 RefreshCrc32(gpt);
928
929 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL)); 902 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, NULL, NULL));
930 903
931 return TEST_OK; 904 return TEST_OK;
932 } 905 }
933 906
934 /* This is the combination test. Both kernel A and B could be either inactive 907
935 * or invalid. We expect GptNextKetnelEntry() returns good kernel or 908 static int GetNextNormalTest() {
936 * GPT_ERROR_NO_VALID_KERNEL if no kernel is available. */ 909 GptData* gpt = GetEmptyGptData();
937 enum FAILURE_MASK { 910 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
938 MASK_INACTIVE = 1, 911 uint64_t start, size;
939 MASK_BAD_ENTRY = 2, 912
940 MASK_FAILURE_BOTH = 3, 913 /* Normal case - both kernels successful */
941 }; 914 BuildTestGptData(gpt);
942 void BreakAnEntry(GptEntry *entry, enum FAILURE_MASK failure) { 915 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
943 if (failure & MASK_INACTIVE) 916 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
944 Memset(&entry->type, 0, sizeof(Guid)); 917 RefreshCrc32(gpt);
945 if (failure & MASK_BAD_ENTRY) 918 GptInit(gpt);
946 entry->attributes |= CGPT_ATTRIBUTE_BAD_MASK; 919
947 } 920 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
948 921 EXPECT(KERNEL_A == gpt->current_kernel);
949 int CombinationalNextKernelEntryTest() { 922 EXPECT(34 == start);
950 GptData *gpt; 923 EXPECT(100 == size);
951 enum { 924
952 MASK_KERNEL_A = 1, 925 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
953 MASK_KERNEL_B = 2, 926 EXPECT(KERNEL_B == gpt->current_kernel);
954 MASK_KERNEL_BOTH = 3, 927 EXPECT(134 == start);
955 } kernel; 928 EXPECT(99 == size);
956 enum FAILURE_MASK failure; 929
957 uint64_t start_sector, size; 930 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
958 int retval; 931 EXPECT(-1 == gpt->current_kernel);
959 932
960 for (kernel = MASK_KERNEL_A; kernel <= MASK_KERNEL_BOTH; ++kernel) { 933 /* Call as many times as you want; you won't get another kernel... */
961 for (failure = MASK_INACTIVE; failure < MASK_FAILURE_BOTH; ++failure) { 934 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
962 gpt = GetEmptyGptData(); 935 EXPECT(-1 == gpt->current_kernel);
963 BuildTestGptData(gpt); 936
964 937 return TEST_OK;
965 if (kernel & MASK_KERNEL_A) 938 }
966 BreakAnEntry(GetEntry(gpt, PRIMARY, KERNEL_A), failure); 939
967 if (kernel & MASK_KERNEL_B) 940
968 BreakAnEntry(GetEntry(gpt, PRIMARY, KERNEL_B), failure); 941 static int GetNextPrioTest() {
969 942 GptData* gpt = GetEmptyGptData();
970 retval = GptNextKernelEntry(gpt, &start_sector, &size); 943 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
971 944 uint64_t start, size;
972 if (kernel == MASK_KERNEL_A) { 945
973 EXPECT(retval == GPT_SUCCESS); 946 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
974 EXPECT(start_sector == 334); 947 BuildTestGptData(gpt);
975 } else if (kernel == MASK_KERNEL_B) { 948 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
976 EXPECT(retval == GPT_SUCCESS); 949 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
977 EXPECT(start_sector == 34); 950 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
978 } else { /* MASK_KERNEL_BOTH */ 951 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
979 EXPECT(retval == GPT_ERROR_NO_VALID_KERNEL); 952 RefreshCrc32(gpt);
980 } 953 GptInit(gpt);
981 } 954
982 } 955 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
983 return TEST_OK; 956 EXPECT(KERNEL_B == gpt->current_kernel);
984 } 957 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
985 958 EXPECT(KERNEL_Y == gpt->current_kernel);
986 /* Increase tries value from zero, expect it won't explode/overflow after 959 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
987 * CGPT_ATTRIBUTE_TRIES_MASK. 960 EXPECT(KERNEL_A == gpt->current_kernel);
988 */ 961 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
989 /* Tries would not count up after CGPT_ATTRIBUTE_MAX_TRIES. */ 962
990 #define EXPECTED_TRIES(tries) \ 963 return TEST_OK;
991 ((tries >= CGPT_ATTRIBUTE_MAX_TRIES) ? CGPT_ATTRIBUTE_MAX_TRIES \ 964 }
992 : tries) 965
993 int IncreaseTriesTest() { 966
994 GptData *gpt; 967 static int GetNextTriesTest() {
995 int kernel_index[] = { 968 GptData* gpt = GetEmptyGptData();
996 KERNEL_B, 969 GptEntry* e1 = (GptEntry*)(gpt->primary_entries);
997 KERNEL_A, 970 uint64_t start, size;
998 }; 971
999 int i, tries, j; 972 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1000 973 BuildTestGptData(gpt);
1001 gpt = GetEmptyGptData(); 974 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1002 for (i = 0; i < ARRAY_SIZE(kernel_index); ++i) { 975 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1003 GptEntry *entries[2] = { 976 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1004 (GptEntry*)gpt->primary_entries, 977 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1005 (GptEntry*)gpt->secondary_entries, 978 RefreshCrc32(gpt);
1006 }; 979 GptInit(gpt);
1007 int current; 980
1008 981 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1009 BuildTestGptData(gpt); 982 EXPECT(KERNEL_X == gpt->current_kernel);
1010 current = gpt->current_kernel = kernel_index[i]; 983 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1011 984 EXPECT(KERNEL_A == gpt->current_kernel);
1012 for (tries = 0; tries < 2 * CGPT_ATTRIBUTE_MAX_TRIES; ++tries) { 985 EXPECT(GPT_ERROR_NO_VALID_KERNEL == GptNextKernelEntry(gpt, &start, &size));
1013 for (j = 0; j < ARRAY_SIZE(entries); ++j) { 986
1014 EXPECT(EXPECTED_TRIES(tries) == 987 return TEST_OK;
1015 ((entries[j][current].attributes & CGPT_ATTRIBUTE_TRIES_MASK) >> 988 }
1016 CGPT_ATTRIBUTE_TRIES_OFFSET)); 989
1017 } 990
1018 991 static int GptUpdateTest() {
1019 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY)); 992 GptData* gpt = GetEmptyGptData();
1020 /* The expected tries value will be checked in next iteration. */ 993 GptEntry* e = (GptEntry*)(gpt->primary_entries);
1021 994 GptEntry* e2 = (GptEntry*)(gpt->secondary_entries);
1022 if (tries < CGPT_ATTRIBUTE_MAX_TRIES) 995 uint64_t start, size;
1023 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | 996
1024 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified); 997 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1025 gpt->modified = 0; /* reset before next test */ 998 BuildTestGptData(gpt);
1026 EXPECT(0 == 999 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1027 Memcmp(entries[PRIMARY], entries[SECONDARY], TOTAL_ENTRIES_SIZE)); 1000 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1028 } 1001 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1029 } 1002 RefreshCrc32(gpt);
1030 return TEST_OK; 1003 GptInit(gpt);
1031 } 1004 gpt->modified = 0; /* Nothing modified yet */
1032 1005
1033 /* Mark a kernel as bad. Expect: 1006 /* Successful kernel */
1034 * 1. the both bad bits of kernel A in primary and secondary entries are set. 1007 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1035 * 2. headers and entries are marked as modified. 1008 EXPECT(KERNEL_A == gpt->current_kernel);
1036 * 3. primary and secondary entries are identical. 1009 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1037 */ 1010 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1038 int MarkBadKernelEntryTest() { 1011 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1039 GptData *gpt; 1012 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1040 GptEntry *entries, *entries2; 1013 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1041 1014 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1042 gpt = GetEmptyGptData(); 1015 /* Trying successful kernel changes nothing */
1043 entries = (GptEntry*)gpt->primary_entries; 1016 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1044 entries2 = (GptEntry*)gpt->secondary_entries; 1017 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1045 1018 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1046 BuildTestGptData(gpt); 1019 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1047 gpt->current_kernel = KERNEL_A; 1020 EXPECT(0 == gpt->modified);
1021 /* Marking it bad does, though */
1048 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD)); 1022 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1049 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | 1023 EXPECT(0 == GetEntrySuccessful(e + KERNEL_A));
1050 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified); 1024 EXPECT(0 == GetEntryPriority(e + KERNEL_A));
1051 EXPECT(entries[KERNEL_A].attributes & CGPT_ATTRIBUTE_BAD_MASK); 1025 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1052 EXPECT(entries2[KERNEL_A].attributes & CGPT_ATTRIBUTE_BAD_MASK); 1026 /* Which affects both copies of the partition entries */
1053 EXPECT(0 == Memcmp(entries, entries2, TOTAL_ENTRIES_SIZE)); 1027 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_A));
1054 1028 EXPECT(0 == GetEntryPriority(e2 + KERNEL_A));
1055 return TEST_OK; 1029 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1056 } 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
1057 1068
1058 /* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns 1069 /* Given an invalid kernel type, and expect GptUpdateKernelEntry() returns
1059 * GPT_ERROR_INVALID_UPDATE_TYPE. */ 1070 * GPT_ERROR_INVALID_UPDATE_TYPE. */
1060 int UpdateInvalidKernelTypeTest() { 1071 static int UpdateInvalidKernelTypeTest() {
1061 GptData *gpt; 1072 GptData* gpt = GetEmptyGptData();
1062 1073
1063 gpt = GetEmptyGptData();
1064 BuildTestGptData(gpt); 1074 BuildTestGptData(gpt);
1065 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */ 1075 gpt->current_kernel = 0; /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1066 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE == 1076 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1067 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */ 1077 GptUpdateKernelEntry(gpt, 99)); /* any invalid update_type value */
1068 1078
1069 return TEST_OK; 1079 return TEST_OK;
1070 } 1080 }
1071 1081
1072 /* A normal boot case:
1073 * GptInit()
1074 * GptNextKernelEntry()
1075 * GptUpdateKernelEntry()
1076 */
1077 int NormalBootCase() {
1078 GptData *gpt;
1079 GptEntry *entries;
1080 uint64_t start_sector, size;
1081
1082 gpt = GetEmptyGptData();
1083 entries = (GptEntry*)gpt->primary_entries;
1084 BuildTestGptData(gpt);
1085
1086 EXPECT(GPT_SUCCESS == GptInit(gpt));
1087 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start_sector, &size));
1088 EXPECT(start_sector == 34); /* Kernel A, see top of this file. */
1089 EXPECT(size == 100);
1090
1091 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1092 EXPECT(((entries[KERNEL_A].attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
1093 CGPT_ATTRIBUTE_TRIES_OFFSET) == 1);
1094
1095 return TEST_OK;
1096 }
1097
1098 /* Higher priority kernel should boot first.
1099 * KERNEL_A is low priority
1100 * KERNEL_B is high priority.
1101 * We expect KERNEL_B is selected in first run, and then KERNEL_A.
1102 * We also expect the GptNextKernelEntry() wraps back to KERNEL_B if it's called
1103 * after twice.
1104 */
1105 int HigherPriorityTest() {
1106 GptData *gpt;
1107 GptEntry *entries;
1108
1109 gpt = GetEmptyGptData();
1110 entries = (GptEntry*)gpt->primary_entries;
1111 BuildTestGptData(gpt);
1112
1113 SetPriority(gpt, PRIMARY, KERNEL_A, 0);
1114 SetPriority(gpt, PRIMARY, KERNEL_B, 1);
1115 RefreshCrc32(gpt);
1116
1117 EXPECT(GPT_SUCCESS == GptInit(gpt));
1118 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, NULL, NULL));
1119 EXPECT(KERNEL_B == gpt->current_kernel);
1120
1121 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, NULL, NULL));
1122 EXPECT(KERNEL_A == gpt->current_kernel);
1123
1124 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, NULL, NULL));
1125 EXPECT(KERNEL_B == gpt->current_kernel);
1126
1127 return TEST_OK;
1128 }
1129 1082
1130 int main(int argc, char *argv[]) { 1083 int main(int argc, char *argv[]) {
1131 int i; 1084 int i;
1132 int error_count = 0; 1085 int error_count = 0;
1133 struct { 1086 struct {
1134 char *name; 1087 char *name;
1135 test_func fp; 1088 test_func fp;
1136 int retval; 1089 int retval;
1137 } test_cases[] = { 1090 } test_cases[] = {
1138 { TEST_CASE(TestBuildTestGptData), }, 1091 { TEST_CASE(TestBuildTestGptData), },
1139 { TEST_CASE(ParameterTests), }, 1092 { TEST_CASE(ParameterTests), },
1093 { TEST_CASE(HeaderCrcTest), },
1140 { TEST_CASE(SignatureTest), }, 1094 { TEST_CASE(SignatureTest), },
1141 { TEST_CASE(RevisionTest), }, 1095 { TEST_CASE(RevisionTest), },
1142 { TEST_CASE(SizeTest), }, 1096 { TEST_CASE(SizeTest), },
1097 { TEST_CASE(CrcFieldTest), },
1143 { TEST_CASE(ReservedFieldsTest), }, 1098 { TEST_CASE(ReservedFieldsTest), },
1144 { TEST_CASE(MyLbaTest), },
1145 { TEST_CASE(SizeOfPartitionEntryTest), }, 1099 { TEST_CASE(SizeOfPartitionEntryTest), },
1146 { TEST_CASE(NumberOfPartitionEntriesTest), }, 1100 { TEST_CASE(NumberOfPartitionEntriesTest), },
1147 { TEST_CASE(PartitionEntryLbaTest), }, 1101 { TEST_CASE(MyLbaTest), },
1148 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), }, 1102 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1149 { TEST_CASE(HeaderCrcTest), },
1150 { TEST_CASE(EntriesCrcTest), }, 1103 { TEST_CASE(EntriesCrcTest), },
1151 { TEST_CASE(IdenticalEntriesTest), },
1152 { TEST_CASE(SynonymousHeaderTest), },
1153 { TEST_CASE(ValidEntryTest), }, 1104 { TEST_CASE(ValidEntryTest), },
1154 { TEST_CASE(OverlappedPartitionTest), }, 1105 { TEST_CASE(OverlappedPartitionTest), },
1155 { TEST_CASE(CorruptCombinationTest), }, 1106 { TEST_CASE(SanityCheckTest), },
1156 { TEST_CASE(TestQuickSortFixed), },
1157 { TEST_CASE(TestQuickSortRandom), },
1158 { TEST_CASE(NoValidKernelEntryTest), }, 1107 { TEST_CASE(NoValidKernelEntryTest), },
1159 { TEST_CASE(CombinationalNextKernelEntryTest), }, 1108 { TEST_CASE(EntryAttributeGetSetTest), },
1160 { TEST_CASE(IncreaseTriesTest), }, 1109 { TEST_CASE(EntryTypeTest), },
1161 { TEST_CASE(MarkBadKernelEntryTest), }, 1110 { TEST_CASE(GetNextNormalTest), },
1111 { TEST_CASE(GetNextPrioTest), },
1112 { TEST_CASE(GetNextTriesTest), },
1113 { TEST_CASE(GptUpdateTest), },
1162 { TEST_CASE(UpdateInvalidKernelTypeTest), }, 1114 { TEST_CASE(UpdateInvalidKernelTypeTest), },
1163 { TEST_CASE(NormalBootCase), },
1164 { TEST_CASE(HigherPriorityTest), },
1165 { TEST_CASE(TestCrc32TestVectors), }, 1115 { TEST_CASE(TestCrc32TestVectors), },
1166 }; 1116 };
1167 1117
1168 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { 1118 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1169 printf("Running %s() ...\n", test_cases[i].name); 1119 printf("Running %s() ...\n", test_cases[i].name);
1170 test_cases[i].retval = test_cases[i].fp(); 1120 test_cases[i].retval = test_cases[i].fp();
1171 if (test_cases[i].retval) { 1121 if (test_cases[i].retval) {
1172 printf(COL_RED "[ERROR]\n\n" COL_STOP); 1122 printf(COL_RED "[ERROR]\n\n" COL_STOP);
1173 ++error_count; 1123 ++error_count;
1174 } else { 1124 } else {
1175 printf(COL_GREEN "[PASS]\n\n" COL_STOP); 1125 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1176 } 1126 }
1177 } 1127 }
1178 1128
1179 if (error_count) { 1129 if (error_count) {
1180 printf("\n--------------------------------------------------\n"); 1130 printf("\n--------------------------------------------------\n");
1181 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP, 1131 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP,
1182 error_count); 1132 error_count);
1183 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { 1133 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1184 if (test_cases[i].retval) 1134 if (test_cases[i].retval)
1185 printf(" %s()\n", test_cases[i].name); 1135 printf(" %s()\n", test_cases[i].name);
1186 } 1136 }
1187 } 1137 }
1188 1138
1189 return (error_count) ? 1 : 0; 1139 return (error_count) ? 1 : 0;
1190 } 1140 }
OLDNEW
« no previous file with comments | « src/platform/vboot_reference/tests/Makefile ('k') | src/platform/vboot_reference/tests/quick_sort_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698