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" |
| 7 #include <string.h> |
6 #include "cgpt.h" | 8 #include "cgpt.h" |
7 #include "cgpt_test.h" | 9 #include "gpt.h" |
| 10 #include "utility.h" |
| 11 |
| 12 /* Testing partition layout (sector_bytes=512) |
| 13 * |
| 14 * LBA Size Usage |
| 15 * 0 1 PMBR |
| 16 * 1 1 primary partition header |
| 17 * 2 32 primary partition entries (128B * 128) |
| 18 * 34 100 kernel A |
| 19 * 134 100 kernel B |
| 20 * 234 100 root A |
| 21 * 334 100 root B |
| 22 * 434 32 secondary partition entries |
| 23 * 466 1 secondary partition header |
| 24 * 467 |
| 25 */ |
| 26 #define DEFAULT_SECTOR_SIZE 512 |
| 27 #define MAX_SECTOR_SIZE 4096 |
| 28 #define DEFAULT_DRIVE_SECTORS 467 |
| 29 #define PARTITION_ENTRIES_SIZE (16*1024) |
8 | 30 |
9 #define TEST_CASE(func) #func, func | 31 #define TEST_CASE(func) #func, func |
10 typedef int (*test_func)(void); | 32 typedef int (*test_func)(void); |
11 | 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 |
| 47 /* Given a GptData pointer, first re-calculate entries CRC32 value, |
| 48 * then reset header CRC32 value to 0, and calculate header CRC32 value. |
| 49 * Both primary and secondary are updated. */ |
| 50 void RefreshCrc32(struct GptData *gpt) { |
| 51 GptHeader *header, *header2; |
| 52 GptEntry *entries, *entries2; |
| 53 |
| 54 header = (GptHeader*)gpt->primary_header; |
| 55 entries = (GptEntry*)gpt->primary_entries; |
| 56 header2 = (GptHeader*)gpt->secondary_header; |
| 57 entries2 = (GptEntry*)gpt->secondary_entries; |
| 58 |
| 59 header->entries_crc32 = CalculateCrc32((uint8_t*)entries, |
| 60 sizeof(GptEntry)); |
| 61 header->header_crc32 = 0; |
| 62 header->header_crc32 = CalculateCrc32((uint8_t*)header, |
| 63 header->size); |
| 64 header2->entries_crc32 = CalculateCrc32((uint8_t*)entries2, |
| 65 sizeof(GptEntry)); |
| 66 header2->header_crc32 = 0; |
| 67 header2->header_crc32 = CalculateCrc32((uint8_t*)header2, |
| 68 header2->size); |
| 69 } |
| 70 |
| 71 /* 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. |
| 73 * All content of headers and entries are zero. */ |
| 74 struct GptData* GetAClearGptData() { |
| 75 static GptData_t gpt; |
| 76 static uint8_t primary_header[MAX_SECTOR_SIZE]; |
| 77 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE]; |
| 78 static uint8_t secondary_header[MAX_SECTOR_SIZE]; |
| 79 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE]; |
| 80 |
| 81 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; |
| 88 gpt.primary_entries = primary_entries; |
| 89 gpt.secondary_header = secondary_header; |
| 90 gpt.secondary_entries = secondary_entries; |
| 91 |
| 92 return &gpt; |
| 93 } |
| 94 |
| 95 /* Fills in most of fields and creates the layout described in the top of this |
| 96 * file. */ |
| 97 struct GptData* |
| 98 BuildTestGptData(uint32_t sector_bytes) { |
| 99 GptData_t *gpt; |
| 100 GptHeader *header, *header2; |
| 101 GptEntry *entries, *entries2; |
| 102 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; |
| 103 |
| 104 gpt = GetAClearGptData(); |
| 105 gpt->sector_bytes = sector_bytes; |
| 106 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS; |
| 107 |
| 108 /* build primary */ |
| 109 header = (GptHeader*)gpt->primary_header; |
| 110 entries = (GptEntry*)gpt->primary_entries; |
| 111 Memcpy(header->signature, GPT_HEADER_SIGNATURE, sizeof(GPT_HEADER_SIGNATURE)); |
| 112 header->revision = GPT_HEADER_REVISION; |
| 113 header->size = sizeof(GptHeader) - sizeof(header->padding); |
| 114 header->my_lba = 1; |
| 115 header->first_usable_lba = 34; |
| 116 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */ |
| 117 header->entries_lba = 2; |
| 118 header->number_of_entries = 128; /* 512B / 128B * 32sectors = 128 entries */ |
| 119 header->size_of_entry = 128; /* bytes */ |
| 120 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
| 121 entries[0].starting_lba = 34; |
| 122 entries[0].ending_lba = 133; |
| 123 Memcpy(&entries[1].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
| 124 entries[1].starting_lba = 134; |
| 125 entries[1].ending_lba = 233; |
| 126 Memcpy(&entries[2].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
| 127 entries[2].starting_lba = 234; |
| 128 entries[2].ending_lba = 333; |
| 129 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel)); |
| 130 entries[3].starting_lba = 334; |
| 131 entries[3].ending_lba = 433; |
| 132 |
| 133 /* build secondary */ |
| 134 header2 = (GptHeader*)gpt->secondary_header; |
| 135 entries2 = (GptEntry*)gpt->secondary_entries; |
| 136 Memcpy(header2, header, sizeof(header)); |
| 137 Memcpy(entries2, entries, sizeof(entries)); |
| 138 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */ |
| 139 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */ |
| 140 |
| 141 RefreshCrc32(gpt); |
| 142 return gpt; |
| 143 } |
| 144 |
| 145 /* Dumps memory starting from [vp] with [len] bytes. |
| 146 * Prints [memo] if not NULL. Example output: |
| 147 * |
| 148 * 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 |
| 150 * ... |
| 151 */ |
| 152 static void dump(void *vp, int len, char* memo) { |
| 153 uint8_t *start = vp; |
| 154 int i; |
| 155 if (memo) printf("--[%s]----------\n", memo); |
| 156 for (i = 0; i < len; ++i) { |
| 157 printf("%02x%s", start[i], |
| 158 (!(~i & 15) ? "\n" : |
| 159 !(~i & 7) ? " - ": " ")); |
| 160 } |
| 161 if (i&15) printf("\n"); |
| 162 } |
| 163 |
| 164 /* More formatted dump with GptData. */ |
| 165 void DumpGptData(struct GptData *gpt) { |
| 166 printf("DumpGptData(%p)...\n", gpt); |
| 167 dump(gpt, sizeof(gpt), NULL); |
| 168 dump(gpt->primary_header, sizeof(GptHeader), "Primary header"); |
| 169 dump(gpt->primary_entries, sizeof(GptEntry) * 8, "Primary entries"); |
| 170 dump(gpt->secondary_header, sizeof(GptHeader), "Secondary header"); |
| 171 dump(gpt->secondary_entries, sizeof(GptEntry) * 8, |
| 172 "Secondary entries"); |
| 173 } |
| 174 |
| 175 /* Tests if signature ("EFI PART") is checked. */ |
| 176 int SignatureTest() { |
| 177 int i; |
| 178 GptData_t *gpt; |
| 179 GptHeader *primary_header, *secondary_header; |
| 180 |
| 181 gpt = BuildTestGptData(DEFAULT_SECTOR_SIZE); |
| 182 primary_header = (GptHeader*)gpt->primary_header; |
| 183 secondary_header = (GptHeader*)gpt->secondary_header; |
| 184 |
| 185 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 186 |
| 187 /* change every char in signature of primary. Secondary is still valid. */ |
| 188 for (i = 0; i < 8; ++i) { |
| 189 gpt->primary_header[i] ^= 0xff; |
| 190 RefreshCrc32(gpt); |
| 191 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 192 gpt->primary_header[i] ^= 0xff; |
| 193 RefreshCrc32(gpt); |
| 194 } |
| 195 |
| 196 /* change every char in signature of secondary. Primary is still valid. */ |
| 197 for (i = 0; i < 8; ++i) { |
| 198 gpt->secondary_header[i] ^= 0xff; |
| 199 RefreshCrc32(gpt); |
| 200 EXPECT(GPT_SUCCESS == GptInit(gpt)); |
| 201 gpt->secondary_header[i] ^= 0xff; |
| 202 RefreshCrc32(gpt); |
| 203 } |
| 204 |
| 205 /* change every char in signature of primary and secondary. Expect fail. */ |
| 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 |
12 /* Tests if header CRC in two copies are calculated. */ | 219 /* Tests if header CRC in two copies are calculated. */ |
13 int HeaderCrcTest() { | 220 int HeaderCrcTest() { |
14 return TEST_FAIL; | 221 return TEST_FAIL; |
15 } | 222 } |
16 | 223 |
17 /* Tests if myLBA field is checked (1 for primary, last for secondary). */ | 224 /* Tests if myLBA field is checked (1 for primary, last for secondary). */ |
18 int MyLbaTest() { | 225 int MyLbaTest() { |
19 return TEST_FAIL; | 226 return TEST_FAIL; |
20 } | 227 } |
21 | 228 |
(...skipping 16 matching lines...) Expand all Loading... |
38 } | 245 } |
39 | 246 |
40 /* Tests if FirstUsableLBA and LastUsableLBA are checked. | 247 /* Tests if FirstUsableLBA and LastUsableLBA are checked. |
41 * FirstUsableLBA must be after the end of the primary GPT table array. | 248 * FirstUsableLBA must be after the end of the primary GPT table array. |
42 * LastUsableLBA must be before the start of the secondary GPT table array. | 249 * LastUsableLBA must be before the start of the secondary GPT table array. |
43 * FirstUsableLBA <= LastUsableLBA. */ | 250 * FirstUsableLBA <= LastUsableLBA. */ |
44 int FirstUsableLbaAndLastUsableLbaTest() { | 251 int FirstUsableLbaAndLastUsableLbaTest() { |
45 return TEST_FAIL; | 252 return TEST_FAIL; |
46 } | 253 } |
47 | 254 |
48 /* Tests if GPTInit() handles non-identical partition entries well. | 255 /* Tests if GptInit() handles non-identical partition entries well. |
49 * Two copies of partition table entries must be identical. If not, we trust the | 256 * Two copies of partition table entries must be identical. If not, we trust the |
50 * primary table entries, and mark secondary as modified (see Caller's write- | 257 * primary table entries, and mark secondary as modified (see Caller's write- |
51 * back order below). */ | 258 * back order below). */ |
52 int IdenticalEntriesTest() { | 259 int IdenticalEntriesTest() { |
53 return TEST_FAIL; | 260 return TEST_FAIL; |
54 } | 261 } |
55 | 262 |
56 /* Tests if GPTInit() handles non-identical headers well. | 263 /* Tests if GptInit() handles non-identical headers well. |
57 * Two partition headers must be identical. If not, we trust the primary | 264 * Two partition headers must be identical. If not, we trust the primary |
58 * partition header, and mark secondary as modified (see Caller's write-back | 265 * partition header, and mark secondary as modified (see Caller's write-back |
59 * order below). */ | 266 * order below). */ |
60 int IdenticalHeaderTest() { | 267 int IdenticalHeaderTest() { |
61 return TEST_FAIL; | 268 return TEST_FAIL; |
62 } | 269 } |
63 | 270 |
64 /* Tests if PartitionEntryArrayCRC32 is checked. | 271 /* Tests if PartitionEntryArrayCRC32 is checked. |
65 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry * | 272 * PartitionEntryArrayCRC32 must be calculated over SizeOfPartitionEntry * |
66 * NumberOfPartitionEntries bytes. | 273 * NumberOfPartitionEntries bytes. |
(...skipping 10 matching lines...) Expand all Loading... |
77 */ | 284 */ |
78 int ValidEntryTest() { | 285 int ValidEntryTest() { |
79 return TEST_FAIL; | 286 return TEST_FAIL; |
80 } | 287 } |
81 | 288 |
82 /* Tests if overlapped partition tables can be detected. */ | 289 /* Tests if overlapped partition tables can be detected. */ |
83 int NoOverlappedPartitionTest() { | 290 int NoOverlappedPartitionTest() { |
84 return TEST_FAIL; | 291 return TEST_FAIL; |
85 } | 292 } |
86 | 293 |
87 /* Tests if GPTNextKernelEntry() can survive in different corrupt header/entries | 294 /* Tests if GptNextKernelEntry() can survive in different corrupt header/entries |
88 * combinations, like: | 295 * combinations, like: |
89 * primary GPT header - valid | 296 * primary GPT header - valid |
90 * primary partition table - invalid | 297 * primary partition table - invalid |
91 * secondary partition table - valid | 298 * secondary partition table - valid |
92 * secondary GPT header - invalid | 299 * secondary GPT header - invalid |
93 */ | 300 */ |
94 int CorruptCombinationTest() { | 301 int CorruptCombinationTest() { |
95 return TEST_FAIL; | 302 return TEST_FAIL; |
96 } | 303 } |
97 | 304 |
98 int main(int argc, char *argv[]) { | 305 int main(int argc, char *argv[]) { |
99 int i; | 306 int i; |
100 struct { | 307 struct { |
101 char *name; | 308 char *name; |
102 test_func fp; | 309 test_func fp; |
103 int retval; | 310 int retval; |
104 } test_cases[] = { | 311 } test_cases[] = { |
| 312 { TEST_CASE(SignatureTest), }, |
| 313 #if 0 |
105 { TEST_CASE(HeaderCrcTest), }, | 314 { TEST_CASE(HeaderCrcTest), }, |
106 { TEST_CASE(MyLbaTest), }, | 315 { TEST_CASE(MyLbaTest), }, |
107 { TEST_CASE(SizeOfPartitionEntryTest), }, | 316 { TEST_CASE(SizeOfPartitionEntryTest), }, |
108 { TEST_CASE(NumberOfPartitionEntriesTest), }, | 317 { TEST_CASE(NumberOfPartitionEntriesTest), }, |
109 { TEST_CASE(PartitionEntryLbaTest), }, | 318 { TEST_CASE(PartitionEntryLbaTest), }, |
110 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), }, | 319 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), }, |
111 { TEST_CASE(IdenticalEntriesTest), }, | 320 { TEST_CASE(IdenticalEntriesTest), }, |
112 { TEST_CASE(IdenticalHeaderTest), }, | 321 { TEST_CASE(IdenticalHeaderTest), }, |
113 { TEST_CASE(EntriesCrcTest), }, | 322 { TEST_CASE(EntriesCrcTest), }, |
114 { TEST_CASE(ValidEntryTest), }, | 323 { TEST_CASE(ValidEntryTest), }, |
115 { TEST_CASE(NoOverlappedPartitionTest), }, | 324 { TEST_CASE(NoOverlappedPartitionTest), }, |
116 { TEST_CASE(CorruptCombinationTest), }, | 325 { TEST_CASE(CorruptCombinationTest), }, |
| 326 #endif |
117 }; | 327 }; |
118 | 328 |
119 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { | 329 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { |
120 printf("Running %s() ...\n", test_cases[i].name); | 330 printf("Running %s() ...\n", test_cases[i].name); |
121 test_cases[i].retval = test_cases[i].fp(); | 331 test_cases[i].retval = test_cases[i].fp(); |
122 if (test_cases[i].retval) | 332 if (test_cases[i].retval) |
123 printf(COL_RED "[ERROR]" COL_STOP " %s()\n\n", test_cases[i].name); | 333 printf(COL_RED "[ERROR]" COL_STOP " %s()\n\n", test_cases[i].name); |
124 else | 334 else |
125 printf(COL_GREEN "[PASS]" COL_STOP " %s()\n\n", test_cases[i].name); | 335 printf(COL_GREEN "[PASS]" COL_STOP " %s()\n\n", test_cases[i].name); |
126 } | 336 } |
127 | 337 |
128 printf("\n--------------------------------------------------\n"); | 338 printf("\n--------------------------------------------------\n"); |
129 printf("The following test cases are failed:\n"); | 339 printf("The following test cases are failed:\n"); |
130 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { | 340 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { |
131 if (test_cases[i].retval) | 341 if (test_cases[i].retval) |
132 printf(" %s()\n", test_cases[i].name); | 342 printf(" %s()\n", test_cases[i].name); |
133 } | 343 } |
134 | 344 |
135 return 0; | 345 return 0; |
136 } | 346 } |
OLD | NEW |