OLD | NEW |
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 "cgpt_test.h" | 6 #include "cgpt_test.h" |
7 #include <string.h> | 7 #include <string.h> |
8 #include "cgpt.h" | 8 #include "cgpt.h" |
| 9 #include "cgpt_internal.h" |
| 10 #include "crc32.h" |
9 #include "gpt.h" | 11 #include "gpt.h" |
| 12 #include "quick_sort_test.h" |
10 #include "utility.h" | 13 #include "utility.h" |
11 | 14 |
12 /* Testing partition layout (sector_bytes=512) | 15 /* Testing partition layout (sector_bytes=512) |
13 * | 16 * |
14 * LBA Size Usage | 17 * LBA Size Usage |
15 * 0 1 PMBR | 18 * 0 1 PMBR |
16 * 1 1 primary partition header | 19 * 1 1 primary partition header |
17 * 2 32 primary partition entries (128B * 128) | 20 * 2 32 primary partition entries (128B * 128) |
18 * 34 100 kernel A | 21 * 34 100 kernel A |
19 * 134 100 kernel B | 22 * 134 100 kernel B |
20 * 234 100 root A | 23 * 234 100 root A |
21 * 334 100 root B | 24 * 334 100 root B |
22 * 434 32 secondary partition entries | 25 * 434 32 secondary partition entries |
23 * 466 1 secondary partition header | 26 * 466 1 secondary partition header |
24 * 467 | 27 * 467 |
25 */ | 28 */ |
26 #define DEFAULT_SECTOR_SIZE 512 | 29 #define DEFAULT_SECTOR_SIZE 512 |
27 #define MAX_SECTOR_SIZE 4096 | 30 #define MAX_SECTOR_SIZE 4096 |
28 #define DEFAULT_DRIVE_SECTORS 467 | 31 #define DEFAULT_DRIVE_SECTORS 467 |
29 #define PARTITION_ENTRIES_SIZE (16*1024) | 32 #define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */ |
30 | |
31 #define TEST_CASE(func) #func, func | |
32 typedef int (*test_func)(void); | |
33 | |
34 /* NOT A REAL CRC32, it is fake before I call real one . FIXME */ | |
35 uint32_t CalculateCrc32(const uint8_t *start, size_t len) { | |
36 uint32_t buf = 0; | |
37 int i; | |
38 for (i = 0; i < len; i += 4, len -= 4) { | |
39 buf ^= *(uint32_t*)&start[i]; | |
40 } | |
41 if (len >= 3) buf ^= start[i-2] << 16; | |
42 if (len >= 2) buf ^= start[i-3] << 8; | |
43 if (len >= 1) buf ^= start[i-4]; | |
44 return buf; | |
45 } | |
46 | 33 |
47 /* Given a GptData pointer, first re-calculate entries CRC32 value, | 34 /* Given a GptData pointer, first re-calculate entries CRC32 value, |
48 * then reset header CRC32 value to 0, and calculate header CRC32 value. | 35 * then reset header CRC32 value to 0, and calculate header CRC32 value. |
49 * Both primary and secondary are updated. */ | 36 * Both primary and secondary are updated. */ |
50 void RefreshCrc32(struct GptData *gpt) { | 37 void RefreshCrc32(GptData *gpt) { |
51 GptHeader *header, *header2; | 38 GptHeader *header, *header2; |
52 GptEntry *entries, *entries2; | 39 GptEntry *entries, *entries2; |
53 | 40 |
54 header = (GptHeader*)gpt->primary_header; | 41 header = (GptHeader*)gpt->primary_header; |
55 entries = (GptEntry*)gpt->primary_entries; | 42 entries = (GptEntry*)gpt->primary_entries; |
56 header2 = (GptHeader*)gpt->secondary_header; | 43 header2 = (GptHeader*)gpt->secondary_header; |
57 entries2 = (GptEntry*)gpt->secondary_entries; | 44 entries2 = (GptEntry*)gpt->secondary_entries; |
58 | 45 |
59 header->entries_crc32 = CalculateCrc32((uint8_t*)entries, | 46 header->entries_crc32 = |
60 sizeof(GptEntry)); | 47 Crc32((uint8_t*)entries, |
| 48 header->number_of_entries * header->size_of_entry); |
61 header->header_crc32 = 0; | 49 header->header_crc32 = 0; |
62 header->header_crc32 = CalculateCrc32((uint8_t*)header, | 50 header->header_crc32 = Crc32((uint8_t*)header, header->size); |
63 header->size); | 51 header2->entries_crc32 = |
64 header2->entries_crc32 = CalculateCrc32((uint8_t*)entries2, | 52 Crc32((uint8_t*)entries2, |
65 sizeof(GptEntry)); | 53 header2->number_of_entries * header2->size_of_entry); |
66 header2->header_crc32 = 0; | 54 header2->header_crc32 = 0; |
67 header2->header_crc32 = CalculateCrc32((uint8_t*)header2, | 55 header2->header_crc32 = Crc32((uint8_t*)header2, header2->size); |
68 header2->size); | 56 } |
| 57 |
| 58 void ZeroHeaders(GptData* gpt) { |
| 59 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE); |
| 60 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE); |
| 61 } |
| 62 |
| 63 void ZeroEntries(GptData* gpt) { |
| 64 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE); |
| 65 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE); |
| 66 } |
| 67 |
| 68 void ZeroHeadersEntries(GptData* gpt) { |
| 69 ZeroHeaders(gpt); |
| 70 ZeroEntries(gpt); |
69 } | 71 } |
70 | 72 |
71 /* Returns a pointer to a static GptData instance (no free is required). | 73 /* Returns a pointer to a static GptData instance (no free is required). |
72 * All fields are zero except 4 pointers linking to header and entries. | 74 * All fields are zero except 4 pointers linking to header and entries. |
73 * All content of headers and entries are zero. */ | 75 * All content of headers and entries are zero. */ |
74 struct GptData* GetAClearGptData() { | 76 GptData* GetEmptyGptData() { |
75 static GptData_t gpt; | 77 static GptData gpt; |
76 static uint8_t primary_header[MAX_SECTOR_SIZE]; | 78 static uint8_t primary_header[MAX_SECTOR_SIZE]; |
77 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE]; | 79 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE]; |
78 static uint8_t secondary_header[MAX_SECTOR_SIZE]; | 80 static uint8_t secondary_header[MAX_SECTOR_SIZE]; |
79 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE]; | 81 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE]; |
80 | 82 |
81 Memset(&gpt, 0, sizeof(gpt)); | 83 Memset(&gpt, 0, sizeof(gpt)); |
82 Memset(&primary_header, 0, sizeof(primary_header)); | |
83 Memset(&primary_entries, 0, sizeof(primary_entries)); | |
84 Memset(&secondary_header, 0, sizeof(secondary_header)); | |
85 Memset(&secondary_entries, 0, sizeof(secondary_entries)); | |
86 | |
87 gpt.primary_header = primary_header; | 84 gpt.primary_header = primary_header; |
88 gpt.primary_entries = primary_entries; | 85 gpt.primary_entries = primary_entries; |
89 gpt.secondary_header = secondary_header; | 86 gpt.secondary_header = secondary_header; |
90 gpt.secondary_entries = secondary_entries; | 87 gpt.secondary_entries = secondary_entries; |
| 88 ZeroHeadersEntries(&gpt); |
91 | 89 |
92 return &gpt; | 90 return &gpt; |
93 } | 91 } |
94 | 92 |
95 /* Fills in most of fields and creates the layout described in the top of this | 93 /* Fills in most of fields and creates the layout described in the top of this |
96 * file. */ | 94 * file. Before calling this function, primary/secondary header/entries must |
97 struct GptData* | 95 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData(). |
98 BuildTestGptData(uint32_t sector_bytes) { | 96 * This function returns a good (valid) copy of GPT layout described in top of |
99 GptData_t *gpt; | 97 * this file. */ |
| 98 void BuildTestGptData(GptData *gpt) { |
100 GptHeader *header, *header2; | 99 GptHeader *header, *header2; |
101 GptEntry *entries, *entries2; | 100 GptEntry *entries, *entries2; |
102 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; | 101 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; |
103 | 102 |
104 gpt = GetAClearGptData(); | 103 gpt->sector_bytes = DEFAULT_SECTOR_SIZE; |
105 gpt->sector_bytes = sector_bytes; | |
106 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS; | 104 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS; |
107 | 105 |
108 /* build primary */ | 106 /* build primary */ |
109 header = (GptHeader*)gpt->primary_header; | 107 header = (GptHeader*)gpt->primary_header; |
110 entries = (GptEntry*)gpt->primary_entries; | 108 entries = (GptEntry*)gpt->primary_entries; |
111 Memcpy(header->signature, GPT_HEADER_SIGNATURE, sizeof(GPT_HEADER_SIGNATURE)); | 109 Memcpy(header->signature, GPT_HEADER_SIGNATURE, sizeof(GPT_HEADER_SIGNATURE)); |
112 header->revision = GPT_HEADER_REVISION; | 110 header->revision = GPT_HEADER_REVISION; |
113 header->size = sizeof(GptHeader) - sizeof(header->padding); | 111 header->size = sizeof(GptHeader) - sizeof(header->padding); |
| 112 header->reserved = 0; |
114 header->my_lba = 1; | 113 header->my_lba = 1; |
115 header->first_usable_lba = 34; | 114 header->first_usable_lba = 34; |
116 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */ | 115 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */ |
117 header->entries_lba = 2; | 116 header->entries_lba = 2; |
118 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */ | 117 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */ |
119 header->size_of_entry = 128; /* bytes */ | 118 header->size_of_entry = 128; /* bytes */ |
120 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel)); | 119 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
121 entries[0].starting_lba = 34; | 120 entries[0].starting_lba = 34; |
122 entries[0].ending_lba = 133; | 121 entries[0].ending_lba = 133; |
123 Memcpy(&entries[1].type, &chromeos_kernel, sizeof(chromeos_kernel)); | 122 Memcpy(&entries[1].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
124 entries[1].starting_lba = 134; | 123 entries[1].starting_lba = 134; |
125 entries[1].ending_lba = 233; | 124 entries[1].ending_lba = 233; |
126 Memcpy(&entries[2].type, &chromeos_kernel, sizeof(chromeos_kernel)); | 125 Memcpy(&entries[2].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
127 entries[2].starting_lba = 234; | 126 entries[2].starting_lba = 234; |
128 entries[2].ending_lba = 333; | 127 entries[2].ending_lba = 333; |
129 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel)); | 128 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
130 entries[3].starting_lba = 334; | 129 entries[3].starting_lba = 334; |
131 entries[3].ending_lba = 433; | 130 entries[3].ending_lba = 433; |
| 131 header->padding = 0; |
132 | 132 |
133 /* build secondary */ | 133 /* build secondary */ |
134 header2 = (GptHeader*)gpt->secondary_header; | 134 header2 = (GptHeader*)gpt->secondary_header; |
135 entries2 = (GptEntry*)gpt->secondary_entries; | 135 entries2 = (GptEntry*)gpt->secondary_entries; |
136 Memcpy(header2, header, sizeof(header)); | 136 Memcpy(header2, header, sizeof(GptHeader)); |
137 Memcpy(entries2, entries, sizeof(entries)); | 137 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE); |
138 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */ | 138 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */ |
139 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */ | 139 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */ |
140 | 140 |
141 RefreshCrc32(gpt); | 141 RefreshCrc32(gpt); |
142 return gpt; | |
143 } | 142 } |
144 | 143 |
145 /* Dumps memory starting from [vp] with [len] bytes. | 144 /* Dumps memory starting from [vp] with [len] bytes. |
146 * Prints [memo] if not NULL. Example output: | 145 * Prints [memo] if not NULL. Example output: |
147 * | 146 * |
148 * 00 01 02 03 04 05 06 07 - 08 09 0a 0b 0c 0d 0e 0f | 147 * 00 01 02 03 04 05 06 07 - 08 09 0a 0b 0c 0d 0e 0f |
149 * 10 11 12 13 14 15 16 17 - 18 19 1a 1b 1c 1d 1e 1f | 148 * 10 11 12 13 14 15 16 17 - 18 19 1a 1b 1c 1d 1e 1f |
150 * ... | 149 * ... |
151 */ | 150 */ |
152 static void dump(void *vp, int len, char* memo) { | 151 static void Dump(void *vp, int len, char* memo) { |
153 uint8_t *start = vp; | 152 uint8_t *start = vp; |
154 int i; | 153 int i; |
155 if (memo) printf("--[%s]----------\n", memo); | 154 if (memo) printf("--[%s]----------\n", memo); |
156 for (i = 0; i < len; ++i) { | 155 for (i = 0; i < len; ++i) { |
157 printf("%02x%s", start[i], | 156 printf("%02x%s", start[i], |
158 (!(~i & 15) ? "\n" : | 157 (!(~i & 15) ? "\n" : |
159 !(~i & 7) ? " - ": " ")); | 158 !(~i & 7) ? " - ": " ")); |
160 } | 159 } |
161 if (i&15) printf("\n"); | 160 if (i&15) printf("\n"); |
162 } | 161 } |
163 | 162 |
164 /* More formatted dump with GptData. */ | 163 /* More formatted dump with GptData. */ |
165 void DumpGptData(struct GptData *gpt) { | 164 void DumpGptData(GptData *gpt) { |
166 printf("DumpGptData(%p)...\n", gpt); | 165 printf("DumpGptData(%p)...\n", gpt); |
167 dump(gpt, sizeof(gpt), NULL); | 166 Dump(gpt, sizeof(gpt), NULL); |
168 dump(gpt->primary_header, sizeof(GptHeader), "Primary header"); | 167 Dump(gpt->primary_header, sizeof(GptHeader), "Primary header"); |
169 dump(gpt->primary_entries, sizeof(GptEntry) * 8, "Primary entries"); | 168 Dump(gpt->primary_entries, sizeof(GptEntry) * 8, "Primary entries"); |
170 dump(gpt->secondary_header, sizeof(GptHeader), "Secondary header"); | 169 Dump(gpt->secondary_header, sizeof(GptHeader), "Secondary header"); |
171 dump(gpt->secondary_entries, sizeof(GptEntry) * 8, | 170 Dump(gpt->secondary_entries, sizeof(GptEntry) * 8, |
172 "Secondary entries"); | 171 "Secondary entries"); |
173 } | 172 } |
174 | 173 |
| 174 /* Tests if the default structure returned by BuildTestGptData() is good. */ |
| 175 int TestBuildTestGptData() { |
| 176 GptData *gpt; |
| 177 gpt = GetEmptyGptData(); |
| 178 BuildTestGptData(gpt); |
| 179 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 180 return TEST_OK; |
| 181 } |
| 182 |
| 183 /* Tests if wrong sector_bytes or drive_sectors is detected by GptInit(). |
| 184 * Currently we only support 512 bytes per sector. |
| 185 * In the future, we may support other sizes. |
| 186 * A too small drive_sectors should be rejected by GptInit(). */ |
| 187 int ParameterTests() { |
| 188 GptData *gpt; |
| 189 struct { |
| 190 uint32_t sector_bytes; |
| 191 uint64_t drive_sectors; |
| 192 int expected_retval; |
| 193 } cases[] = { |
| 194 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS}, |
| 195 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE}, |
| 196 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER}, |
| 197 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER}, |
| 198 {512, GPT_PMBR_SECTOR + GPT_HEADER_SECTOR * 2 + GPT_ENTRIES_SECTORS * 2, |
| 199 GPT_SUCCESS}, |
| 200 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE}, |
| 201 }; |
| 202 int i; |
| 203 |
| 204 gpt = GetEmptyGptData(); |
| 205 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 206 BuildTestGptData(gpt); |
| 207 gpt->sector_bytes = cases[i].sector_bytes; |
| 208 gpt->drive_sectors = cases[i].drive_sectors; |
| 209 EXPECT(cases[i].expected_retval == CheckParameters(gpt)); |
| 210 } |
| 211 |
| 212 return TEST_OK; |
| 213 } |
| 214 |
175 /* Tests if signature ("EFI PART") is checked. */ | 215 /* Tests if signature ("EFI PART") is checked. */ |
176 int SignatureTest() { | 216 int SignatureTest() { |
177 int i; | 217 int i; |
178 GptData_t *gpt; | 218 GptData *gpt; |
| 219 int test_mask; |
| 220 GptHeader *headers[2]; |
| 221 |
| 222 gpt = GetEmptyGptData(); |
| 223 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 224 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 225 |
| 226 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 227 for (i = 0; i < 8; ++i) { |
| 228 BuildTestGptData(gpt); |
| 229 if (test_mask & MASK_PRIMARY) |
| 230 headers[PRIMARY]->signature[i] ^= 0xff; |
| 231 if (test_mask & MASK_SECONDARY) |
| 232 headers[SECONDARY]->signature[i] ^= 0xff; |
| 233 EXPECT((MASK_BOTH ^ test_mask) == CheckHeaderSignature(gpt)); |
| 234 } |
| 235 } |
| 236 |
| 237 return TEST_OK; |
| 238 } |
| 239 |
| 240 /* The revision we currently support is GPT_HEADER_REVISION. |
| 241 * If the revision in header is not that, we expect the header is invalid. */ |
| 242 int RevisionTest() { |
| 243 GptData *gpt; |
| 244 struct { |
| 245 uint32_t value_to_test; |
| 246 int is_valid_value; |
| 247 } cases[] = { |
| 248 {0x01000000, 0}, |
| 249 {0x00010000, 1}, /* GPT_HEADER_REVISION */ |
| 250 {0x00000100, 0}, |
| 251 {0x00000001, 0}, |
| 252 {0x23010456, 0}, |
| 253 }; |
| 254 int i; |
| 255 int test_mask; |
| 256 GptHeader *headers[2]; |
| 257 uint32_t valid_headers; |
| 258 |
| 259 gpt = GetEmptyGptData(); |
| 260 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 261 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 262 |
| 263 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 264 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 265 BuildTestGptData(gpt); |
| 266 if (test_mask & MASK_PRIMARY) |
| 267 headers[PRIMARY]->revision = cases[i].value_to_test; |
| 268 if (test_mask & MASK_SECONDARY) |
| 269 headers[SECONDARY]->revision = cases[i].value_to_test; |
| 270 valid_headers = CheckRevision(gpt); |
| 271 if (cases[i].is_valid_value) |
| 272 EXPECT(MASK_BOTH == valid_headers); |
| 273 else |
| 274 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); |
| 275 } |
| 276 } |
| 277 return TEST_OK; |
| 278 } |
| 279 |
| 280 int SizeTest() { |
| 281 GptData *gpt; |
| 282 struct { |
| 283 uint32_t value_to_test; |
| 284 int is_valid_value; |
| 285 } cases[] = { |
| 286 {91, 0}, |
| 287 {92, 1}, |
| 288 {93, 1}, |
| 289 {511, 1}, |
| 290 {512, 1}, |
| 291 {513, 0}, |
| 292 }; |
| 293 int i; |
| 294 int test_mask; |
| 295 GptHeader *headers[2]; |
| 296 uint32_t valid_headers; |
| 297 |
| 298 gpt = GetEmptyGptData(); |
| 299 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 300 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 301 |
| 302 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 303 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 304 BuildTestGptData(gpt); |
| 305 if (test_mask & MASK_PRIMARY) |
| 306 headers[PRIMARY]->size = cases[i].value_to_test; |
| 307 if (test_mask & MASK_SECONDARY) |
| 308 headers[SECONDARY]->size = cases[i].value_to_test; |
| 309 valid_headers = CheckSize(gpt); |
| 310 if (cases[i].is_valid_value) |
| 311 EXPECT(MASK_BOTH == valid_headers); |
| 312 else |
| 313 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); |
| 314 } |
| 315 } |
| 316 return TEST_OK; |
| 317 } |
| 318 |
| 319 /* Tests if reserved fields are checked. |
| 320 * We'll try non-zero values to test. */ |
| 321 int ReservedFieldsTest() { |
| 322 GptData *gpt; |
179 GptHeader *primary_header, *secondary_header; | 323 GptHeader *primary_header, *secondary_header; |
180 | 324 |
181 gpt = BuildTestGptData(DEFAULT_SECTOR_SIZE); | 325 gpt = GetEmptyGptData(); |
182 primary_header = (GptHeader*)gpt->primary_header; | 326 primary_header = (GptHeader*)gpt->primary_header; |
183 secondary_header = (GptHeader*)gpt->secondary_header; | 327 secondary_header = (GptHeader*)gpt->secondary_header; |
184 | 328 |
185 EXPECT(GPT_SUCCESS == GptInit(gpt)); | 329 /* expect secondary is still valid. */ |
186 | 330 BuildTestGptData(gpt); |
187 /* change every char in signature of primary. Secondary is still valid. */ | 331 primary_header->reserved ^= 0x12345678; /* whatever random */ |
188 for (i = 0; i < 8; ++i) { | 332 EXPECT(MASK_SECONDARY == CheckReservedFields(gpt)); |
189 gpt->primary_header[i] ^= 0xff; | 333 |
190 RefreshCrc32(gpt); | 334 /* expect secondary is still valid. */ |
191 EXPECT(GPT_SUCCESS == GptInit(gpt)); | 335 BuildTestGptData(gpt); |
192 gpt->primary_header[i] ^= 0xff; | 336 primary_header->padding ^= 0x12345678; /* whatever random */ |
193 RefreshCrc32(gpt); | 337 EXPECT(MASK_SECONDARY == CheckReservedFields(gpt)); |
194 } | 338 |
195 | 339 /* expect primary is still valid. */ |
196 /* change every char in signature of secondary. Primary is still valid. */ | 340 BuildTestGptData(gpt); |
197 for (i = 0; i < 8; ++i) { | 341 secondary_header->reserved ^= 0x12345678; /* whatever random */ |
198 gpt->secondary_header[i] ^= 0xff; | 342 EXPECT(MASK_PRIMARY == CheckReservedFields(gpt)); |
199 RefreshCrc32(gpt); | 343 |
200 EXPECT(GPT_SUCCESS == GptInit(gpt)); | 344 /* expect primary is still valid. */ |
201 gpt->secondary_header[i] ^= 0xff; | 345 BuildTestGptData(gpt); |
202 RefreshCrc32(gpt); | 346 secondary_header->padding ^= 0x12345678; /* whatever random */ |
203 } | 347 EXPECT(MASK_PRIMARY == CheckReservedFields(gpt)); |
204 | 348 |
205 /* change every char in signature of primary and secondary. Expect fail. */ | 349 return TEST_OK; |
206 for (i = 0; i < 8; ++i) { | |
207 gpt->primary_header[i] ^= 0xff; | |
208 gpt->secondary_header[i] ^= 0xff; | |
209 RefreshCrc32(gpt); | |
210 EXPECT(GPT_ERROR_INVALID_HEADERS == GptInit(gpt)); | |
211 gpt->primary_header[i] ^= 0xff; | |
212 gpt->secondary_header[i] ^= 0xff; | |
213 RefreshCrc32(gpt); | |
214 } | |
215 | |
216 return TEST_OK; | |
217 } | |
218 | |
219 /* Tests if header CRC in two copies are calculated. */ | |
220 int HeaderCrcTest() { | |
221 return TEST_FAIL; | |
222 } | 350 } |
223 | 351 |
224 /* Tests if myLBA field is checked (1 for primary, last for secondary). */ | 352 /* Tests if myLBA field is checked (1 for primary, last for secondary). */ |
225 int MyLbaTest() { | 353 int MyLbaTest() { |
226 return TEST_FAIL; | 354 GptData *gpt; |
| 355 int test_mask; |
| 356 GptHeader *headers[2]; |
| 357 uint32_t valid_headers; |
| 358 |
| 359 gpt = GetEmptyGptData(); |
| 360 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 361 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 362 |
| 363 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 364 BuildTestGptData(gpt); |
| 365 if (test_mask & MASK_PRIMARY) |
| 366 ++headers[PRIMARY]->my_lba; |
| 367 if (test_mask & MASK_SECONDARY) |
| 368 --headers[SECONDARY]->my_lba; |
| 369 valid_headers = CheckMyLba(gpt); |
| 370 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); |
| 371 } |
| 372 return TEST_OK; |
227 } | 373 } |
228 | 374 |
229 /* Tests if SizeOfPartitionEntry is checked. SizeOfPartitionEntry must be | 375 /* Tests if SizeOfPartitionEntry is checked. SizeOfPartitionEntry must be |
230 * between 128 and 512, and a multiple of 8. */ | 376 * between 128 and 512, and a multiple of 8. */ |
231 int SizeOfPartitionEntryTest() { | 377 int SizeOfPartitionEntryTest() { |
232 return TEST_FAIL; | 378 GptData *gpt; |
| 379 struct { |
| 380 uint32_t value_to_test; |
| 381 int is_valid_value; |
| 382 } cases[] = { |
| 383 {127, 0}, |
| 384 {128, 1}, |
| 385 {129, 0}, |
| 386 {130, 0}, |
| 387 {131, 0}, |
| 388 {132, 0}, |
| 389 {133, 0}, |
| 390 {134, 0}, |
| 391 {135, 0}, |
| 392 {136, 1}, |
| 393 {144, 1}, |
| 394 {160, 1}, |
| 395 {192, 1}, |
| 396 {256, 1}, |
| 397 {384, 1}, |
| 398 {504, 1}, |
| 399 {512, 1}, |
| 400 {513, 0}, |
| 401 {520, 0}, |
| 402 }; |
| 403 int i; |
| 404 int test_mask; |
| 405 GptHeader *headers[2]; |
| 406 uint32_t valid_headers; |
| 407 |
| 408 gpt = GetEmptyGptData(); |
| 409 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 410 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 411 |
| 412 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 413 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 414 BuildTestGptData(gpt); |
| 415 if (test_mask & MASK_PRIMARY) { |
| 416 headers[PRIMARY]->size_of_entry = cases[i].value_to_test; |
| 417 headers[PRIMARY]->number_of_entries = |
| 418 TOTAL_ENTRIES_SIZE / cases[i].value_to_test; |
| 419 } |
| 420 if (test_mask & MASK_SECONDARY) { |
| 421 headers[SECONDARY]->size_of_entry = cases[i].value_to_test; |
| 422 headers[SECONDARY]->number_of_entries = |
| 423 TOTAL_ENTRIES_SIZE / cases[i].value_to_test; |
| 424 } |
| 425 valid_headers = CheckSizeOfPartitionEntry(gpt); |
| 426 if (cases[i].is_valid_value) |
| 427 EXPECT(MASK_BOTH == valid_headers); |
| 428 else |
| 429 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); |
| 430 } |
| 431 } |
| 432 return TEST_OK; |
233 } | 433 } |
234 | 434 |
235 /* Tests if NumberOfPartitionEntries is checes. NumberOfPartitionEntries must | 435 /* Tests if NumberOfPartitionEntries is checes. NumberOfPartitionEntries must |
236 * be between 32 and 512, and SizeOfPartitionEntry * NumberOfPartitionEntries | 436 * be between 32 and 512, and SizeOfPartitionEntry * NumberOfPartitionEntries |
237 * must be 16384. */ | 437 * must be 16384. */ |
238 int NumberOfPartitionEntriesTest() { | 438 int NumberOfPartitionEntriesTest() { |
239 return TEST_FAIL; | 439 GptData *gpt; |
| 440 struct { |
| 441 uint32_t size_of_entry; |
| 442 uint32_t number_of_entries; |
| 443 int is_valid_value; |
| 444 } cases[] = { |
| 445 {111, 147, 0}, |
| 446 {111, 149, 0}, |
| 447 {128, 32, 0}, |
| 448 {128, 64, 0}, |
| 449 {128, 127, 0}, |
| 450 {128, 128, 1}, |
| 451 {128, 129, 0}, |
| 452 {128, 256, 0}, |
| 453 {256, 32, 0}, |
| 454 {256, 64, 1}, |
| 455 {256, 128, 0}, |
| 456 {256, 256, 0}, |
| 457 {512, 32, 1}, |
| 458 {512, 64, 0}, |
| 459 {512, 128, 0}, |
| 460 {512, 256, 0}, |
| 461 {1024, 128, 0}, |
| 462 }; |
| 463 int i; |
| 464 int test_mask; |
| 465 GptHeader *headers[2]; |
| 466 uint32_t valid_headers; |
| 467 |
| 468 gpt = GetEmptyGptData(); |
| 469 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 470 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 471 |
| 472 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 473 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 474 BuildTestGptData(gpt); |
| 475 if (test_mask & MASK_PRIMARY) { |
| 476 headers[PRIMARY]->size_of_entry = cases[i].size_of_entry; |
| 477 headers[PRIMARY]->number_of_entries = cases[i].number_of_entries; |
| 478 } |
| 479 if (test_mask & MASK_SECONDARY) { |
| 480 headers[SECONDARY]->size_of_entry = cases[i].size_of_entry; |
| 481 headers[SECONDARY]->number_of_entries = cases[i].number_of_entries; |
| 482 } |
| 483 valid_headers = CheckNumberOfEntries(gpt); |
| 484 if (cases[i].is_valid_value) |
| 485 EXPECT(MASK_BOTH == valid_headers); |
| 486 else |
| 487 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); |
| 488 } |
| 489 } |
| 490 return TEST_OK; |
240 } | 491 } |
241 | 492 |
242 /* Tests if PartitionEntryLBA in primary/secondary headers is checked. */ | 493 /* Tests if PartitionEntryLBA in primary/secondary headers is checked. */ |
243 int PartitionEntryLbaTest() { | 494 int PartitionEntryLbaTest() { |
244 return TEST_FAIL; | 495 GptData *gpt; |
| 496 int test_mask; |
| 497 GptHeader *headers[2]; |
| 498 uint32_t valid_headers; |
| 499 |
| 500 gpt = GetEmptyGptData(); |
| 501 headers[PRIMARY] = (GptHeader*)gpt->primary_header; |
| 502 headers[SECONDARY] = (GptHeader*)gpt->secondary_header; |
| 503 |
| 504 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 505 BuildTestGptData(gpt); |
| 506 if (test_mask & MASK_PRIMARY) |
| 507 headers[PRIMARY]->entries_lba = 0; |
| 508 if (test_mask & MASK_SECONDARY) |
| 509 headers[SECONDARY]->entries_lba = DEFAULT_DRIVE_SECTORS - 31 - 1; |
| 510 valid_headers = CheckEntriesLba(gpt); |
| 511 EXPECT((MASK_BOTH ^ test_mask) == valid_headers); |
| 512 } |
| 513 return TEST_OK; |
245 } | 514 } |
246 | 515 |
247 /* Tests if FirstUsableLBA and LastUsableLBA are checked. | 516 /* Tests if FirstUsableLBA and LastUsableLBA are checked. |
248 * FirstUsableLBA must be after the end of the primary GPT table array. | 517 * FirstUsableLBA must be after the end of the primary GPT table array. |
249 * LastUsableLBA must be before the start of the secondary GPT table array. | 518 * LastUsableLBA must be before the start of the secondary GPT table array. |
250 * FirstUsableLBA <= LastUsableLBA. */ | 519 * FirstUsableLBA <= LastUsableLBA. */ |
251 int FirstUsableLbaAndLastUsableLbaTest() { | 520 int FirstUsableLbaAndLastUsableLbaTest() { |
252 return TEST_FAIL; | 521 GptData *gpt; |
| 522 GptHeader *primary_header, *secondary_header; |
| 523 uint32_t valid_headers; |
| 524 int i; |
| 525 struct { |
| 526 uint64_t primary_entries_lba; |
| 527 uint64_t primary_first_usable_lba; |
| 528 uint64_t primary_last_usable_lba; |
| 529 uint64_t secondary_first_usable_lba; |
| 530 uint64_t secondary_last_usable_lba; |
| 531 uint64_t secondary_entries_lba; |
| 532 int expected_masks; |
| 533 } cases[] = { |
| 534 {2, 34, 433, 34, 433, 434, MASK_BOTH}, |
| 535 {2, 34, 432, 34, 430, 434, MASK_BOTH}, |
| 536 {2, 33, 433, 33, 433, 434, MASK_NONE}, |
| 537 {3, 34, 433, 35, 433, 434, MASK_SECONDARY}, |
| 538 {3, 35, 433, 33, 433, 434, MASK_PRIMARY}, |
| 539 {2, 34, 434, 34, 433, 434, MASK_SECONDARY}, |
| 540 {2, 34, 433, 34, 434, 434, MASK_PRIMARY}, |
| 541 {2, 35, 433, 35, 433, 434, MASK_BOTH}, |
| 542 {2, 433, 433, 433, 433, 434, MASK_BOTH}, |
| 543 {2, 434, 433, 434, 434, 434, MASK_NONE}, |
| 544 {2, 433, 34, 34, 433, 434, MASK_SECONDARY}, |
| 545 {2, 34, 433, 433, 34, 434, MASK_PRIMARY}, |
| 546 }; |
| 547 |
| 548 gpt = GetEmptyGptData(); |
| 549 primary_header = (GptHeader*)gpt->primary_header; |
| 550 secondary_header = (GptHeader*)gpt->secondary_header; |
| 551 |
| 552 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 553 BuildTestGptData(gpt); |
| 554 primary_header->entries_lba = cases[i].primary_entries_lba; |
| 555 primary_header->first_usable_lba = cases[i].primary_first_usable_lba; |
| 556 primary_header->last_usable_lba = cases[i].primary_last_usable_lba; |
| 557 secondary_header->entries_lba = cases[i].secondary_entries_lba; |
| 558 secondary_header->first_usable_lba = cases[i].secondary_first_usable_lba; |
| 559 secondary_header->last_usable_lba = cases[i].secondary_last_usable_lba; |
| 560 valid_headers = CheckValidUsableLbas(gpt); |
| 561 EXPECT(cases[i].expected_masks == valid_headers); |
| 562 } |
| 563 |
| 564 return TEST_OK; |
253 } | 565 } |
254 | 566 |
255 /* Tests if GptInit() handles non-identical partition entries well. | 567 /* Tests if header CRC in two copies are calculated. */ |
256 * Two copies of partition table entries must be identical. If not, we trust the | 568 int HeaderCrcTest() { |
257 * primary table entries, and mark secondary as modified (see Caller's write- | 569 GptData *gpt; |
258 * back order below). */ | 570 GptHeader *primary_header, *secondary_header; |
259 int IdenticalEntriesTest() { | |
260 return TEST_FAIL; | |
261 } | |
262 | 571 |
263 /* Tests if GptInit() handles non-identical headers well. | 572 gpt = GetEmptyGptData(); |
264 * Two partition headers must be identical. If not, we trust the primary | 573 primary_header = (GptHeader*)gpt->primary_header; |
265 * partition header, and mark secondary as modified (see Caller's write-back | 574 secondary_header = (GptHeader*)gpt->secondary_header; |
266 * order below). */ | 575 |
267 int IdenticalHeaderTest() { | 576 /* Modify the first byte of primary header, and expect the CRC is wrong. */ |
268 return TEST_FAIL; | 577 BuildTestGptData(gpt); |
| 578 gpt->primary_header[0] ^= 0xa5; /* just XOR a non-zero value */ |
| 579 EXPECT(MASK_SECONDARY == CheckHeaderCrc(gpt)); |
| 580 |
| 581 /* Modify the last byte of secondary header, and expect the CRC is wrong. */ |
| 582 BuildTestGptData(gpt); |
| 583 gpt->secondary_header[secondary_header->size-1] ^= 0x5a; |
| 584 EXPECT(MASK_PRIMARY == CheckHeaderCrc(gpt)); |
| 585 |
| 586 /* Modify out of CRC range, expect CRC is still right. */ |
| 587 BuildTestGptData(gpt); |
| 588 gpt->primary_header[primary_header->size] ^= 0x87; |
| 589 EXPECT(MASK_BOTH == CheckHeaderCrc(gpt)); |
| 590 |
| 591 return TEST_OK; |
269 } | 592 } |
270 | 593 |
271 /* Tests if PartitionEntryArrayCRC32 is checked. | 594 /* Tests if PartitionEntryArrayCRC32 is checked. |
272 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry * | 595 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry * |
273 * NumberOfPartitionEntries bytes. | 596 * NumberOfPartitionEntries bytes. |
274 */ | 597 */ |
275 int EntriesCrcTest() { | 598 int EntriesCrcTest() { |
276 return TEST_FAIL; | 599 GptData *gpt; |
| 600 |
| 601 gpt = GetEmptyGptData(); |
| 602 |
| 603 /* Modify the first byte of primary entries, and expect the CRC is wrong. */ |
| 604 BuildTestGptData(gpt); |
| 605 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */ |
| 606 EXPECT(MASK_SECONDARY == CheckEntriesCrc(gpt)); |
| 607 |
| 608 /* Modify the last byte of secondary entries, and expect the CRC is wrong. */ |
| 609 BuildTestGptData(gpt); |
| 610 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a; |
| 611 EXPECT(MASK_PRIMARY == CheckEntriesCrc(gpt)); |
| 612 |
| 613 return TEST_OK; |
| 614 } |
| 615 |
| 616 /* Tests if GptInit() handles non-identical partition entries well. |
| 617 * Two copies of partition table entries must be identical. If not, we trust the |
| 618 * primary table entries, and mark secondary as modified. */ |
| 619 int IdenticalEntriesTest() { |
| 620 GptData *gpt; |
| 621 |
| 622 gpt = GetEmptyGptData(); |
| 623 |
| 624 /* Tests RepairEntries() first. */ |
| 625 BuildTestGptData(gpt); |
| 626 EXPECT(0 == RepairEntries(gpt, MASK_BOTH)); |
| 627 gpt->secondary_entries[0] ^= 0xa5; /* XOR any number */ |
| 628 EXPECT(GPT_MODIFIED_ENTRIES2 == RepairEntries(gpt, MASK_BOTH)); |
| 629 EXPECT(GPT_MODIFIED_ENTRIES2 == RepairEntries(gpt, MASK_PRIMARY)); |
| 630 EXPECT(GPT_MODIFIED_ENTRIES1 == RepairEntries(gpt, MASK_SECONDARY)); |
| 631 EXPECT(0 == RepairEntries(gpt, MASK_NONE)); |
| 632 |
| 633 /* The first byte is different. We expect secondary entries is marked as |
| 634 * modified. */ |
| 635 BuildTestGptData(gpt); |
| 636 gpt->primary_entries[0] ^= 0xff; |
| 637 RefreshCrc32(gpt); |
| 638 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 639 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified); |
| 640 EXPECT(0 == Memcmp(gpt->primary_entries, gpt->secondary_entries, |
| 641 TOTAL_ENTRIES_SIZE)); |
| 642 |
| 643 /* The last byte is different, but the primary entries CRC is bad. |
| 644 * We expect primary entries is marked as modified. */ |
| 645 BuildTestGptData(gpt); |
| 646 gpt->primary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0xff; |
| 647 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 648 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified); |
| 649 EXPECT(0 == Memcmp(gpt->primary_entries, gpt->secondary_entries, |
| 650 TOTAL_ENTRIES_SIZE)); |
| 651 |
| 652 return TEST_OK; |
| 653 } |
| 654 |
| 655 /* Tests if GptInit() handles synonymous headers well. |
| 656 * Note that two partition headers are NOT bit-swise identical. |
| 657 * For exmaple, my_lba must be different (pointing to respective self). |
| 658 * So in normal case, they are synonymous, not identical. |
| 659 * If not synonymous, we trust the primary partition header, and |
| 660 * overwrite secondary, then mark secondary as modified.*/ |
| 661 int SynonymousHeaderTest() { |
| 662 GptData *gpt; |
| 663 GptHeader *primary_header, *secondary_header; |
| 664 |
| 665 gpt = GetEmptyGptData(); |
| 666 primary_header = (GptHeader*)gpt->primary_header; |
| 667 secondary_header = (GptHeader*)gpt->secondary_header; |
| 668 |
| 669 /* Tests RepairHeader() for synonymous cases first. */ |
| 670 BuildTestGptData(gpt); |
| 671 EXPECT(0 == RepairHeader(gpt, MASK_BOTH)); |
| 672 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_PRIMARY)); |
| 673 EXPECT(GPT_MODIFIED_HEADER1 == RepairHeader(gpt, MASK_SECONDARY)); |
| 674 EXPECT(0 == RepairHeader(gpt, MASK_NONE)); |
| 675 /* Then tests non-synonymous cases. */ |
| 676 BuildTestGptData(gpt); |
| 677 ++secondary_header->first_usable_lba; /* chnage any bit */ |
| 678 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH)); |
| 679 EXPECT(primary_header->first_usable_lba == |
| 680 secondary_header->first_usable_lba); |
| 681 /* ---- */ |
| 682 BuildTestGptData(gpt); |
| 683 --secondary_header->last_usable_lba; |
| 684 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH)); |
| 685 EXPECT(primary_header->last_usable_lba == secondary_header->last_usable_lba); |
| 686 /* ---- */ |
| 687 BuildTestGptData(gpt); |
| 688 ++secondary_header->number_of_entries; |
| 689 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH)); |
| 690 EXPECT(primary_header->number_of_entries == |
| 691 secondary_header->number_of_entries); |
| 692 /* ---- */ |
| 693 BuildTestGptData(gpt); |
| 694 --secondary_header->size_of_entry; |
| 695 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH)); |
| 696 EXPECT(primary_header->size_of_entry == |
| 697 secondary_header->size_of_entry); |
| 698 /* ---- */ |
| 699 BuildTestGptData(gpt); |
| 700 secondary_header->disk_uuid.u.raw[0] ^= 0x56; |
| 701 EXPECT(GPT_MODIFIED_HEADER2 == RepairHeader(gpt, MASK_BOTH)); |
| 702 EXPECT(0 == Memcmp(&primary_header->disk_uuid, |
| 703 &secondary_header->disk_uuid, sizeof(Guid))); |
| 704 |
| 705 /* Consider header repairing in GptInit(). */ |
| 706 BuildTestGptData(gpt); |
| 707 ++secondary_header->first_usable_lba; |
| 708 RefreshCrc32(gpt); |
| 709 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 710 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified); |
| 711 EXPECT(primary_header->first_usable_lba == |
| 712 secondary_header->first_usable_lba); |
| 713 |
| 714 return TEST_OK; |
277 } | 715 } |
278 | 716 |
279 /* Tests if partition geometry is checked. | 717 /* Tests if partition geometry is checked. |
280 * All active (non-zero PartitionTypeGUID) partition entries should have: | 718 * All active (non-zero PartitionTypeGUID) partition entries should have: |
281 * entry.StartingLBA >= header.FirstUsableLBA | 719 * entry.StartingLBA >= header.FirstUsableLBA |
282 * entry.EndingLBA <= header.LastUsableLBA | 720 * entry.EndingLBA <= header.LastUsableLBA |
283 * entry.StartingLBA <= entry.EndingLBA | 721 * entry.StartingLBA <= entry.EndingLBA |
284 */ | 722 */ |
285 int ValidEntryTest() { | 723 int ValidEntryTest() { |
286 return TEST_FAIL; | 724 GptData *gpt; |
| 725 GptHeader *primary_header, *secondary_header; |
| 726 GptEntry *primary_entries, *secondary_entries; |
| 727 |
| 728 gpt = GetEmptyGptData(); |
| 729 primary_header = (GptHeader*)gpt->primary_header; |
| 730 secondary_header = (GptHeader*)gpt->secondary_header; |
| 731 primary_entries = (GptEntry*)gpt->primary_entries; |
| 732 secondary_entries = (GptEntry*)gpt->secondary_entries; |
| 733 |
| 734 /* error case: entry.StartingLBA < header.FirstUsableLBA */ |
| 735 BuildTestGptData(gpt); |
| 736 primary_entries[0].starting_lba = primary_header->first_usable_lba - 1; |
| 737 EXPECT(MASK_SECONDARY == CheckValidEntries(gpt)); |
| 738 secondary_entries[1].starting_lba = secondary_header->first_usable_lba - 1; |
| 739 EXPECT(MASK_NONE == CheckValidEntries(gpt)); |
| 740 |
| 741 /* error case: entry.EndingLBA > header.LastUsableLBA */ |
| 742 BuildTestGptData(gpt); |
| 743 primary_entries[2].ending_lba = primary_header->last_usable_lba + 1; |
| 744 EXPECT(MASK_SECONDARY == CheckValidEntries(gpt)); |
| 745 secondary_entries[3].ending_lba = secondary_header->last_usable_lba + 1; |
| 746 EXPECT(MASK_NONE == CheckValidEntries(gpt)); |
| 747 |
| 748 /* error case: entry.StartingLBA > entry.EndingLBA */ |
| 749 BuildTestGptData(gpt); |
| 750 primary_entries[3].starting_lba = primary_entries[3].ending_lba + 1; |
| 751 EXPECT(MASK_SECONDARY == CheckValidEntries(gpt)); |
| 752 secondary_entries[1].starting_lba = secondary_entries[1].ending_lba + 1; |
| 753 EXPECT(MASK_NONE == CheckValidEntries(gpt)); |
| 754 |
| 755 /* case: non active entry should be ignored. */ |
| 756 BuildTestGptData(gpt); |
| 757 Memset(&primary_entries[1].type, 0, sizeof(primary_entries[1].type)); |
| 758 primary_entries[1].starting_lba = primary_entries[1].ending_lba + 1; |
| 759 EXPECT(MASK_BOTH == CheckValidEntries(gpt)); |
| 760 Memset(&secondary_entries[2].type, 0, sizeof(secondary_entries[2].type)); |
| 761 secondary_entries[2].starting_lba = secondary_entries[2].ending_lba + 1; |
| 762 EXPECT(MASK_BOTH == CheckValidEntries(gpt)); |
| 763 |
| 764 return TEST_OK; |
287 } | 765 } |
288 | 766 |
289 /* Tests if overlapped partition tables can be detected. */ | 767 /* Tests if overlapped partition tables can be detected. */ |
290 int NoOverlappedPartitionTest() { | 768 int OverlappedPartitionTest() { |
291 return TEST_FAIL; | 769 GptData *gpt; |
292 } | 770 struct { |
293 | 771 int overlapped; |
294 /* Tests if GptNextKernelEntry() can survive in different corrupt header/entries | 772 struct { |
| 773 int active; |
| 774 uint64_t starting_lba; |
| 775 uint64_t ending_lba; |
| 776 } entries[16]; /* enough for testing. */ |
| 777 } cases[] = { |
| 778 {0, {{0, 100, 199}, {0, 0, 0}}}, |
| 779 {0, {{1, 100, 199}, {0, 0, 0}}}, |
| 780 {0, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}, {0, 0, 0}}}, |
| 781 {1, {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}, {0, 0, 0}}}, |
| 782 {1, {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}, {0, 0, 0}}}, |
| 783 {0, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}, {0, 0, 0}}}, |
| 784 {1, {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}, {0, 0, 0}}}, |
| 785 {1, {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}, {0, 0, 0}}}, |
| 786 {1, {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}, {0, 0, 0}}}, |
| 787 {1, {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}, {0, 0, 0}}}, |
| 788 {1, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}, |
| 789 {0, 0, 0}}}, |
| 790 {0, {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}, |
| 791 {0, 0, 0}}}, |
| 792 {1, {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}, |
| 793 {0, 0, 0}}}, |
| 794 {1, {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}, |
| 795 {0, 0, 0}}}, |
| 796 {0, {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}, |
| 797 {0, 0, 0}}}, |
| 798 {1, {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}, {0, 0, 0}}}, |
| 799 {0, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}, {0, 0, 0}}}, |
| 800 {0, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}, {0, 0, 0}}}, |
| 801 {1, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202}, |
| 802 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206}, |
| 803 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}, {0, 0, 0}}}, |
| 804 {0, {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202}, |
| 805 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206}, |
| 806 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}, {0, 0, 0}}}, |
| 807 }; |
| 808 Guid any_type = GPT_ENT_TYPE_CHROMEOS_KERNEL; |
| 809 int i, j; |
| 810 int test_mask; |
| 811 GptEntry *entries[2]; |
| 812 |
| 813 gpt = GetEmptyGptData(); |
| 814 entries[PRIMARY] = (GptEntry*)gpt->primary_entries; |
| 815 entries[SECONDARY] = (GptEntry*)gpt->secondary_entries; |
| 816 |
| 817 for (i = 0; i < ARRAY_SIZE(cases); ++i) { |
| 818 for (test_mask = MASK_PRIMARY; test_mask <= MASK_BOTH; ++test_mask) { |
| 819 BuildTestGptData(gpt); |
| 820 ZeroEntries(gpt); |
| 821 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) { |
| 822 if (!cases[i].entries[j].starting_lba) break; |
| 823 if (test_mask & MASK_PRIMARY) { |
| 824 if (cases[i].entries[j].active) |
| 825 Memcpy(&entries[PRIMARY][j].type, &any_type, sizeof(any_type)); |
| 826 entries[PRIMARY][j].starting_lba = cases[i].entries[j].starting_lba; |
| 827 entries[PRIMARY][j].ending_lba = cases[i].entries[j].ending_lba; |
| 828 } |
| 829 if (test_mask & MASK_SECONDARY) { |
| 830 if (cases[i].entries[j].active) |
| 831 Memcpy(&entries[SECONDARY][j].type, &any_type, sizeof(any_type)); |
| 832 entries[SECONDARY][j].starting_lba = cases[i].entries[j].starting_lba; |
| 833 entries[SECONDARY][j].ending_lba = cases[i].entries[j].ending_lba; |
| 834 } |
| 835 } |
| 836 EXPECT((cases[i].overlapped * test_mask) == |
| 837 (OverlappedEntries(entries[PRIMARY], j) | |
| 838 (OverlappedEntries(entries[SECONDARY], j) << SECONDARY)) |
| 839 ); |
| 840 |
| 841 EXPECT((MASK_BOTH ^ (cases[i].overlapped * test_mask)) == |
| 842 CheckOverlappedPartition(gpt)); |
| 843 } |
| 844 } |
| 845 return TEST_OK; |
| 846 } |
| 847 |
| 848 /* Tests if GptInit() can survive in different corrupt header/entries |
295 * combinations, like: | 849 * combinations, like: |
296 * primary GPT header - valid | 850 * primary GPT header - valid |
297 * primary partition table - invalid | 851 * primary partition table - invalid |
| 852 * secondary GPT header - invalid |
298 * secondary partition table - valid | 853 * secondary partition table - valid |
299 * secondary GPT header - invalid | |
300 */ | 854 */ |
301 int CorruptCombinationTest() { | 855 int CorruptCombinationTest() { |
302 return TEST_FAIL; | 856 GptData *gpt; |
| 857 GptHeader *primary_header, *secondary_header; |
| 858 GptEntry *primary_entries, *secondary_entries; |
| 859 |
| 860 gpt = GetEmptyGptData(); |
| 861 primary_header = (GptHeader*)gpt->primary_header; |
| 862 secondary_header = (GptHeader*)gpt->secondary_header; |
| 863 primary_entries = (GptEntry*)gpt->primary_entries; |
| 864 secondary_entries = (GptEntry*)gpt->secondary_entries; |
| 865 |
| 866 /* Make primary entries and secondary header invalid, we expect GptInit() |
| 867 * can recover them (returns GPT_SUCCESS and MODIFIED flasgs). */ |
| 868 BuildTestGptData(gpt); |
| 869 primary_entries[0].type.u.raw[0] ^= 0x33; |
| 870 secondary_header->header_crc32 ^= 0x55; |
| 871 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 872 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified); |
| 873 EXPECT(0 == Memcmp(primary_entries, secondary_entries, TOTAL_ENTRIES_SIZE)); |
| 874 /* We expect the modified header/entries can pass GptInit(). */ |
| 875 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 876 EXPECT(0 == gpt->modified); |
| 877 |
| 878 /* Make primary header invalid (the entries is not damaged actually). */ |
| 879 BuildTestGptData(gpt); |
| 880 primary_header->entries_crc32 ^= 0x73; |
| 881 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 882 /* After header is repaired, the entries are valid actually. */ |
| 883 EXPECT((GPT_MODIFIED_HEADER1) == gpt->modified); |
| 884 /* We expect the modified header/entries can pass GptInit(). */ |
| 885 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 886 EXPECT(0 == gpt->modified); |
| 887 |
| 888 return TEST_OK; |
303 } | 889 } |
304 | 890 |
305 int main(int argc, char *argv[]) { | 891 int main(int argc, char *argv[]) { |
306 int i; | 892 int i; |
| 893 int error_count = 0; |
307 struct { | 894 struct { |
308 char *name; | 895 char *name; |
309 test_func fp; | 896 test_func fp; |
310 int retval; | 897 int retval; |
311 } test_cases[] = { | 898 } test_cases[] = { |
| 899 { TEST_CASE(TestBuildTestGptData), }, |
| 900 { TEST_CASE(ParameterTests), }, |
312 { TEST_CASE(SignatureTest), }, | 901 { TEST_CASE(SignatureTest), }, |
313 #if 0 | 902 { TEST_CASE(RevisionTest), }, |
314 { TEST_CASE(HeaderCrcTest), }, | 903 { TEST_CASE(SizeTest), }, |
| 904 { TEST_CASE(ReservedFieldsTest), }, |
315 { TEST_CASE(MyLbaTest), }, | 905 { TEST_CASE(MyLbaTest), }, |
316 { TEST_CASE(SizeOfPartitionEntryTest), }, | 906 { TEST_CASE(SizeOfPartitionEntryTest), }, |
317 { TEST_CASE(NumberOfPartitionEntriesTest), }, | 907 { TEST_CASE(NumberOfPartitionEntriesTest), }, |
318 { TEST_CASE(PartitionEntryLbaTest), }, | 908 { TEST_CASE(PartitionEntryLbaTest), }, |
319 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), }, | 909 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), }, |
| 910 { TEST_CASE(HeaderCrcTest), }, |
| 911 { TEST_CASE(EntriesCrcTest), }, |
320 { TEST_CASE(IdenticalEntriesTest), }, | 912 { TEST_CASE(IdenticalEntriesTest), }, |
321 { TEST_CASE(IdenticalHeaderTest), }, | 913 { TEST_CASE(SynonymousHeaderTest), }, |
322 { TEST_CASE(EntriesCrcTest), }, | |
323 { TEST_CASE(ValidEntryTest), }, | 914 { TEST_CASE(ValidEntryTest), }, |
324 { TEST_CASE(NoOverlappedPartitionTest), }, | 915 { TEST_CASE(OverlappedPartitionTest), }, |
325 { TEST_CASE(CorruptCombinationTest), }, | 916 { TEST_CASE(CorruptCombinationTest), }, |
326 #endif | 917 { TEST_CASE(TestQuickSortFixed), }, |
| 918 { TEST_CASE(TestQuickSortRandom), }, |
327 }; | 919 }; |
328 | 920 |
329 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { | 921 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { |
330 printf("Running %s() ...\n", test_cases[i].name); | 922 printf("Running %s() ...\n", test_cases[i].name); |
331 test_cases[i].retval = test_cases[i].fp(); | 923 test_cases[i].retval = test_cases[i].fp(); |
332 if (test_cases[i].retval) | 924 if (test_cases[i].retval) { |
333 printf(COL_RED "[ERROR]" COL_STOP " %s()\n\n", test_cases[i].name); | 925 printf(COL_RED "[ERROR]\n\n" COL_STOP); |
334 else | 926 ++error_count; |
335 printf(COL_GREEN "[PASS]" COL_STOP " %s()\n\n", test_cases[i].name); | 927 } else { |
| 928 printf(COL_GREEN "[PASS]\n\n" COL_STOP); |
| 929 } |
336 } | 930 } |
337 | 931 |
338 printf("\n--------------------------------------------------\n"); | 932 if (error_count) { |
339 printf("The following test cases are failed:\n"); | 933 printf("\n--------------------------------------------------\n"); |
340 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { | 934 printf(COL_RED "The following %d test cases are failed:\n" COL_STOP, |
341 if (test_cases[i].retval) | 935 error_count); |
342 printf(" %s()\n", test_cases[i].name); | 936 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { |
| 937 if (test_cases[i].retval) |
| 938 printf(" %s()\n", test_cases[i].name); |
| 939 } |
343 } | 940 } |
344 | 941 |
345 return 0; | 942 return (error_count) ? 1 : 0; |
346 } | 943 } |
OLD | NEW |