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.h" | 6 #include "cgpt.h" |
7 #include <string.h> | 7 #include <string.h> |
| 8 #include "cgpt_internal.h" |
| 9 #include "crc32.h" |
8 #include "gpt.h" | 10 #include "gpt.h" |
| 11 #include "quick_sort.h" |
9 #include "utility.h" | 12 #include "utility.h" |
10 | 13 |
| 14 /* Macro to invalidate a GPT header/entries */ |
| 15 #define INVALIDATE_HEADER(valid_headers, index) \ |
| 16 do { \ |
| 17 valid_headers &= ~(1<<index); \ |
| 18 } while (0) |
| 19 #define INVALIDATE_ENTRIES(valid_entries, index) \ |
| 20 do { \ |
| 21 valid_entries &= ~(1<<index); \ |
| 22 } while (0) |
| 23 |
| 24 /* Checks if sector_bytes and drive_sectors are valid values. */ |
| 25 int CheckParameters(GptData *gpt) { |
| 26 /* Currently, we only support 512-byte sector. In the future, we may support |
| 27 * larger sector. */ |
| 28 if (gpt->sector_bytes != 512) |
| 29 return GPT_ERROR_INVALID_SECTOR_SIZE; |
| 30 |
| 31 /* The sector number of a drive should be reasonable. If the given value is |
| 32 * too small to contain basic GPT structure (PMBR + Headers + Entries), |
| 33 * the value is wrong. */ |
| 34 if (gpt->drive_sectors < (GPT_PMBR_SECTOR + |
| 35 GPT_HEADER_SECTOR * 2 + |
| 36 GPT_ENTRIES_SECTORS * 2)) |
| 37 return GPT_ERROR_INVALID_SECTOR_NUMBER; |
| 38 |
| 39 return GPT_SUCCESS; |
| 40 } |
| 41 |
| 42 /* Expects header signature should be GPT_HEADER_SIGNATURE. */ |
| 43 uint32_t CheckHeaderSignature(GptData *gpt) { |
| 44 uint32_t valid_headers = MASK_BOTH; |
| 45 GptHeader *headers[] = { |
| 46 (GptHeader*)gpt->primary_header, |
| 47 (GptHeader*)gpt->secondary_header, |
| 48 }; |
| 49 int i; |
| 50 |
| 51 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 52 if (Memcmp(headers[i]->signature, |
| 53 GPT_HEADER_SIGNATURE, |
| 54 GPT_HEADER_SIGNATURE_SIZE)) { |
| 55 INVALIDATE_HEADER(valid_headers, i); |
| 56 } |
| 57 } |
| 58 return valid_headers; |
| 59 } |
| 60 |
| 61 /* The header revision should be GPT_HEADER_REVISION. */ |
| 62 uint32_t CheckRevision(GptData *gpt) { |
| 63 uint32_t valid_headers = MASK_BOTH; |
| 64 GptHeader *headers[] = { |
| 65 (GptHeader*)gpt->primary_header, |
| 66 (GptHeader*)gpt->secondary_header, |
| 67 }; |
| 68 int i; |
| 69 |
| 70 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 71 if (headers[i]->revision != GPT_HEADER_REVISION) |
| 72 INVALIDATE_HEADER(valid_headers, i); |
| 73 } |
| 74 return valid_headers; |
| 75 } |
| 76 |
| 77 /* A valid header size should be between MIN_SIZE_OF_HEADER and |
| 78 * MAX_SIZE_OF_HEADER. */ |
| 79 uint32_t CheckSize(GptData *gpt) { |
| 80 uint32_t valid_headers = MASK_BOTH; |
| 81 GptHeader *headers[] = { |
| 82 (GptHeader*)gpt->primary_header, |
| 83 (GptHeader*)gpt->secondary_header, |
| 84 }; |
| 85 int i; |
| 86 |
| 87 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 88 if ((headers[i]->size < MIN_SIZE_OF_HEADER) || |
| 89 (headers[i]->size > MAX_SIZE_OF_HEADER)) |
| 90 INVALIDATE_HEADER(valid_headers, i); |
| 91 } |
| 92 return valid_headers; |
| 93 } |
| 94 |
| 95 /* Reserved and padding fields should be zero. */ |
| 96 uint32_t CheckReservedFields(GptData *gpt) { |
| 97 uint32_t valid_headers = MASK_BOTH; |
| 98 GptHeader *headers[] = { |
| 99 (GptHeader*)gpt->primary_header, |
| 100 (GptHeader*)gpt->secondary_header, |
| 101 }; |
| 102 int i; |
| 103 |
| 104 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 105 if (headers[i]->reserved || headers[i]->padding) |
| 106 INVALIDATE_HEADER(valid_headers, i); |
| 107 } |
| 108 return valid_headers; |
| 109 } |
| 110 |
| 111 /* my_lba field points to the header itself. |
| 112 * So that the my_lba of primary header should be 1 (right after PMBR). |
| 113 * The my_lba of secondary header should be the last secotr on drive. */ |
| 114 uint32_t CheckMyLba(GptData *gpt) { |
| 115 uint32_t valid_headers = MASK_BOTH; |
| 116 GptHeader *primary_header, *secondary_header; |
| 117 |
| 118 primary_header = (GptHeader*)gpt->primary_header; |
| 119 secondary_header = (GptHeader*)gpt->secondary_header; |
| 120 |
| 121 if (primary_header->my_lba != GPT_PMBR_SECTOR) /* 2nd sector on drive */ |
| 122 INVALIDATE_HEADER(valid_headers, PRIMARY); |
| 123 if (secondary_header->my_lba != (gpt->drive_sectors - 1)) /* last sector */ |
| 124 INVALIDATE_HEADER(valid_headers, SECONDARY); |
| 125 return valid_headers; |
| 126 } |
| 127 |
| 128 /* SizeOfPartitionEntry must be between MIN_SIZE_OF_ENTRY and |
| 129 * MAX_SIZE_OF_ENTRY, and a multiple of SIZE_OF_ENTRY_MULTIPLE. */ |
| 130 uint32_t CheckSizeOfPartitionEntry(GptData *gpt) { |
| 131 uint32_t valid_headers = MASK_BOTH; |
| 132 GptHeader *headers[] = { |
| 133 (GptHeader*)gpt->primary_header, |
| 134 (GptHeader*)gpt->secondary_header, |
| 135 }; |
| 136 int i; |
| 137 |
| 138 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 139 uint32_t size_of_entry = headers[i]->size_of_entry; |
| 140 if ((size_of_entry < MIN_SIZE_OF_ENTRY) || |
| 141 (size_of_entry > MAX_SIZE_OF_ENTRY) || |
| 142 (size_of_entry & (SIZE_OF_ENTRY_MULTIPLE - 1))) |
| 143 INVALIDATE_HEADER(valid_headers, i); |
| 144 } |
| 145 return valid_headers; |
| 146 } |
| 147 |
| 148 /* number_of_entries must be between MIN_NUMBER_OF_ENTRIES and |
| 149 * MAX_NUMBER_OF_ENTRIES, and size_of_entry * number_of_entries must be |
| 150 * equal to TOTAL_ENTRIES_SIZE. */ |
| 151 uint32_t CheckNumberOfEntries(GptData *gpt) { |
| 152 uint32_t valid_headers = MASK_BOTH; |
| 153 GptHeader *headers[] = { |
| 154 (GptHeader*)gpt->primary_header, |
| 155 (GptHeader*)gpt->secondary_header, |
| 156 }; |
| 157 int i; |
| 158 |
| 159 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 160 uint32_t number_of_entries = headers[i]->number_of_entries; |
| 161 if ((number_of_entries < MIN_NUMBER_OF_ENTRIES) || |
| 162 (number_of_entries > MAX_NUMBER_OF_ENTRIES) || |
| 163 (number_of_entries * headers[i]->size_of_entry != TOTAL_ENTRIES_SIZE)) |
| 164 INVALIDATE_HEADER(valid_headers, i); |
| 165 } |
| 166 return valid_headers; |
| 167 } |
| 168 |
| 169 /* Make sure entries_lba is correct. |
| 170 * 2 for primary entries |
| 171 * drive_sectors-1-GPT_ENTRIES_SECTORS for secondary entries. */ |
| 172 uint32_t CheckEntriesLba(GptData *gpt) { |
| 173 uint32_t valid_headers = MASK_BOTH; |
| 174 GptHeader *primary_header, *secondary_header; |
| 175 |
| 176 primary_header = (GptHeader*)gpt->primary_header; |
| 177 secondary_header = (GptHeader*)gpt->secondary_header; |
| 178 |
| 179 /* We assume the primary partition entry table is located at the sector |
| 180 * right after primary partition header. */ |
| 181 if (primary_header->entries_lba != (GPT_PMBR_SECTOR + GPT_HEADER_SECTOR)) |
| 182 INVALIDATE_HEADER(valid_headers, PRIMARY); |
| 183 /* We assume the secondary partition entry table is the 32 sectors |
| 184 * right before the secondary partition header. */ |
| 185 if (secondary_header->entries_lba != |
| 186 (gpt->drive_sectors - 1 - GPT_ENTRIES_SECTORS)) |
| 187 INVALIDATE_HEADER(valid_headers, SECONDARY); |
| 188 return valid_headers; |
| 189 } |
| 190 |
| 191 /* FirstUsableLBA must be after the end of the primary GPT table array. |
| 192 * LastUsableLBA must be before the start of the secondary GPT table array. |
| 193 * FirstUsableLBA <= LastUsableLBA. */ |
| 194 uint32_t CheckValidUsableLbas(GptData *gpt) { |
| 195 uint32_t valid_headers = MASK_BOTH; |
| 196 uint64_t end_of_primary_entries; |
| 197 uint64_t start_of_secondary_entries; |
| 198 GptHeader *headers[] = { |
| 199 (GptHeader*)gpt->primary_header, |
| 200 (GptHeader*)gpt->secondary_header, |
| 201 }; |
| 202 int i; |
| 203 |
| 204 end_of_primary_entries = GPT_PMBR_SECTOR + GPT_HEADER_SECTOR + |
| 205 GPT_ENTRIES_SECTORS; |
| 206 start_of_secondary_entries = (gpt->drive_sectors - 1 - GPT_ENTRIES_SECTORS); |
| 207 |
| 208 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 209 if (headers[i]->first_usable_lba < end_of_primary_entries) |
| 210 INVALIDATE_HEADER(valid_headers, i); |
| 211 if (headers[i]->last_usable_lba >= start_of_secondary_entries) |
| 212 INVALIDATE_HEADER(valid_headers, i); |
| 213 if (headers[i]->first_usable_lba > headers[i]->last_usable_lba) |
| 214 INVALIDATE_HEADER(valid_headers, i); |
| 215 } |
| 216 |
| 217 if (headers[PRIMARY]->first_usable_lba - headers[PRIMARY]->entries_lba < |
| 218 GPT_ENTRIES_SECTORS) |
| 219 INVALIDATE_HEADER(valid_headers, PRIMARY); |
| 220 if (headers[SECONDARY]->last_usable_lba >= headers[SECONDARY]->entries_lba) |
| 221 INVALIDATE_HEADER(valid_headers, SECONDARY); |
| 222 |
| 223 return valid_headers; |
| 224 } |
| 225 |
| 226 /* Checks header CRC */ |
| 227 uint32_t CheckHeaderCrc(GptData *gpt) { |
| 228 uint32_t crc32, original_crc32; |
| 229 uint32_t valid_headers = MASK_BOTH; |
| 230 GptHeader *headers[] = { |
| 231 (GptHeader*)gpt->primary_header, |
| 232 (GptHeader*)gpt->secondary_header, |
| 233 }; |
| 234 int i; |
| 235 |
| 236 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 237 original_crc32 = headers[i]->header_crc32; |
| 238 headers[i]->header_crc32 = 0; |
| 239 crc32 = Crc32((const uint8_t *)headers[i], headers[i]->size); |
| 240 headers[i]->header_crc32 = original_crc32; |
| 241 if (crc32 != original_crc32) |
| 242 INVALIDATE_HEADER(valid_headers, i); |
| 243 } |
| 244 return valid_headers; |
| 245 } |
| 246 |
| 247 /* Checks entries CRC */ |
| 248 uint32_t CheckEntriesCrc(GptData *gpt) { |
| 249 uint32_t crc32; |
| 250 uint32_t valid_entries = MASK_BOTH; |
| 251 GptHeader *headers[] = { |
| 252 (GptHeader*)gpt->primary_header, |
| 253 (GptHeader*)gpt->secondary_header, |
| 254 }; |
| 255 GptEntry *entries[] = { |
| 256 (GptEntry*)gpt->primary_entries, |
| 257 (GptEntry*)gpt->secondary_entries, |
| 258 }; |
| 259 int i; |
| 260 |
| 261 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 262 crc32 = Crc32((const uint8_t *)entries[i], TOTAL_ENTRIES_SIZE); |
| 263 if (crc32 != headers[i]->entries_crc32) |
| 264 INVALIDATE_HEADER(valid_entries, i); |
| 265 } |
| 266 return valid_entries; |
| 267 } |
| 268 |
| 269 /* Returns non-zero if the given GUID is non-zero. */ |
| 270 static int NonZeroGuid(const Guid *guid) { |
| 271 static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}}; |
| 272 return Memcmp(&zero, guid, sizeof(zero)); |
| 273 } |
| 274 |
| 275 /* Checks if entries geometry is valid. |
| 276 * All active (non-zero PartitionTypeGUID) partition entries should have: |
| 277 * entry.StartingLBA >= header.FirstUsableLBA |
| 278 * entry.EndingLBA <= header.LastUsableLBA |
| 279 * entry.StartingLBA <= entry.EndingLBA |
| 280 */ |
| 281 uint32_t CheckValidEntries(GptData *gpt) { |
| 282 uint32_t valid_entries = MASK_BOTH; |
| 283 GptHeader *headers[] = { |
| 284 (GptHeader*)gpt->primary_header, |
| 285 (GptHeader*)gpt->secondary_header, |
| 286 }; |
| 287 GptEntry *entries[] = { |
| 288 (GptEntry*)gpt->primary_entries, |
| 289 (GptEntry*)gpt->secondary_entries, |
| 290 }; |
| 291 int copy, entry_index; |
| 292 GptEntry *entry; |
| 293 |
| 294 for (copy = PRIMARY; copy <= SECONDARY; ++copy) { |
| 295 for (entry_index = 0; |
| 296 entry_index < headers[copy]->number_of_entries; |
| 297 ++entry_index) { |
| 298 entry = (GptEntry*)&(((uint8_t*)entries[copy]) |
| 299 [entry_index * headers[copy]->size_of_entry]); |
| 300 if (NonZeroGuid(&entry->type)) { |
| 301 if ((entry->starting_lba < headers[copy]->first_usable_lba) || |
| 302 (entry->ending_lba > headers[copy]->last_usable_lba) || |
| 303 (entry->ending_lba < entry->starting_lba)) |
| 304 INVALIDATE_HEADER(valid_entries, copy); |
| 305 } |
| 306 } |
| 307 } |
| 308 return valid_entries; |
| 309 } |
| 310 |
| 311 static pair_t pairs[MAX_NUMBER_OF_ENTRIES]; |
| 312 /* Callback function for QuickSort(). Returns 1 if 'a_' should precede 'b_'. */ |
| 313 int compare_pair(const void *a_, const void *b_) { |
| 314 const pair_t *a = a_; |
| 315 const pair_t *b = b_; |
| 316 if (a->starting <= b->starting) return 1; |
| 317 return 0; |
| 318 } |
| 319 |
| 320 /* First sorts by starting_lba, and traverse everyone once if its starting_lba |
| 321 * is between previous starting_lba and ending_lba. If yes, overlapped. |
| 322 * Returns 1 if overlap is found. */ |
| 323 int OverlappedEntries(GptEntry *entries, uint32_t number_of_entries) { |
| 324 int i, num_of_pair = 0; |
| 325 for (i = 0; i < number_of_entries; ++i) { |
| 326 if (NonZeroGuid(&entries[i].type)) { |
| 327 pairs[num_of_pair].starting = entries[i].starting_lba; |
| 328 pairs[num_of_pair].ending = entries[i].ending_lba; |
| 329 ++num_of_pair; |
| 330 } |
| 331 } |
| 332 QuickSort(&pairs, num_of_pair, sizeof(pair_t), compare_pair); |
| 333 |
| 334 for (i = 1; i < num_of_pair; ++i) { |
| 335 if ((pairs[i].starting >= pairs[i-1].starting) && |
| 336 (pairs[i].starting <= pairs[i-1].ending)) |
| 337 return 1; |
| 338 } |
| 339 |
| 340 return 0; |
| 341 } |
| 342 |
| 343 /* Checks if any two partitions are overlapped in primary and secondary entries. |
| 344 */ |
| 345 uint32_t CheckOverlappedPartition(GptData *gpt) { |
| 346 uint32_t valid_entries = MASK_BOTH; |
| 347 GptHeader *headers[] = { |
| 348 (GptHeader*)gpt->primary_header, |
| 349 (GptHeader*)gpt->secondary_header, |
| 350 }; |
| 351 GptEntry *entries[] = { |
| 352 (GptEntry*)gpt->primary_entries, |
| 353 (GptEntry*)gpt->secondary_entries, |
| 354 }; |
| 355 int i; |
| 356 |
| 357 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 358 if (OverlappedEntries(entries[i], headers[i]->number_of_entries)) |
| 359 INVALIDATE_ENTRIES(valid_entries, i); |
| 360 } |
| 361 return valid_entries; |
| 362 } |
| 363 |
| 364 /* Primary entries and secondary entries should be bitwise identical. |
| 365 * If two entries tables are valid, compare them. If not the same, |
| 366 * overwrites secondary with primary (primary always has higher priority), |
| 367 * and marks secondary as modified. |
| 368 * If only one is valid, overwrites invalid one. |
| 369 * If all are invalid, does nothing. |
| 370 * This function returns bit masks for GptData.modified field. */ |
| 371 uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) { |
| 372 if (valid_entries == MASK_BOTH) { |
| 373 if (Memcmp(gpt->primary_entries, gpt->secondary_entries, |
| 374 TOTAL_ENTRIES_SIZE)) { |
| 375 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); |
| 376 return GPT_MODIFIED_ENTRIES2; |
| 377 } |
| 378 } else if (valid_entries == MASK_PRIMARY) { |
| 379 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); |
| 380 return GPT_MODIFIED_ENTRIES2; |
| 381 } else if (valid_entries == MASK_SECONDARY) { |
| 382 Memcpy(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE); |
| 383 return GPT_MODIFIED_ENTRIES1; |
| 384 } |
| 385 |
| 386 return 0; |
| 387 } |
| 388 |
| 389 /* Two headers are NOT bitwise identical. For example, my_lba pointers to header |
| 390 * itself so that my_lba in primary and secondary is definitely different. |
| 391 * Only the following fields should be identical. |
| 392 * |
| 393 * first_usable_lba |
| 394 * last_usable_lba |
| 395 * number_of_entries |
| 396 * size_of_entry |
| 397 * disk_uuid |
| 398 * |
| 399 * If any of above field are not matched, overwrite secondary with primary since |
| 400 * we always trust primary. |
| 401 * If any one of header is invalid, copy from another. */ |
| 402 int IsSynonymous(const GptHeader* a, const GptHeader* b) { |
| 403 if ((a->first_usable_lba == b->first_usable_lba) && |
| 404 (a->last_usable_lba == b->last_usable_lba) && |
| 405 (a->number_of_entries == b->number_of_entries) && |
| 406 (a->size_of_entry == b->size_of_entry) && |
| 407 (!Memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid)))) |
| 408 return 1; |
| 409 return 0; |
| 410 } |
| 411 |
| 412 /* The above five fields are shared between primary and secondary headers. |
| 413 * We can recover one header from another through copying those fields. */ |
| 414 void CopySynonymousParts(GptHeader* target, const GptHeader* source) { |
| 415 target->first_usable_lba = source->first_usable_lba; |
| 416 target->last_usable_lba = source->last_usable_lba; |
| 417 target->number_of_entries = source->number_of_entries; |
| 418 target->size_of_entry = source->size_of_entry; |
| 419 Memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid)); |
| 420 } |
| 421 |
| 422 /* This function repairs primary and secondary headers if possible. |
| 423 * If both headers are valid (CRC32 is correct) but |
| 424 * a) indicate inconsistent usable LBA ranges, |
| 425 * b) inconsistent partition entry size and number, |
| 426 * c) inconsistent disk_uuid, |
| 427 * we will use the primary header to overwrite secondary header. |
| 428 * If primary is invalid (CRC32 is wrong), then we repair it from secondary. |
| 429 * If secondary is invalid (CRC32 is wrong), then we repair it from primary. |
| 430 * This function returns the bitmasks for modified header. |
| 431 * Note that CRC value is not re-computed in this function. UpdateCrc() will |
| 432 * do it later. |
| 433 */ |
| 434 uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) { |
| 435 GptHeader *primary_header, *secondary_header; |
| 436 |
| 437 primary_header = (GptHeader*)gpt->primary_header; |
| 438 secondary_header = (GptHeader*)gpt->secondary_header; |
| 439 |
| 440 if (valid_headers == MASK_BOTH) { |
| 441 if (!IsSynonymous(primary_header, secondary_header)) { |
| 442 CopySynonymousParts(secondary_header, primary_header); |
| 443 return GPT_MODIFIED_HEADER2; |
| 444 } |
| 445 } else if (valid_headers == MASK_PRIMARY) { |
| 446 Memcpy(secondary_header, primary_header, primary_header->size); |
| 447 secondary_header->my_lba = gpt->drive_sectors - 1; /* the last sector */ |
| 448 secondary_header->entries_lba = secondary_header->my_lba - |
| 449 GPT_ENTRIES_SECTORS; |
| 450 return GPT_MODIFIED_HEADER2; |
| 451 } else if (valid_headers == MASK_SECONDARY) { |
| 452 Memcpy(primary_header, secondary_header, secondary_header->size); |
| 453 primary_header->my_lba = GPT_PMBR_SECTOR; /* the second sector on drive */ |
| 454 primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTOR; |
| 455 return GPT_MODIFIED_HEADER1; |
| 456 } |
| 457 |
| 458 return 0; |
| 459 } |
| 460 |
| 461 /* Update CRC value if necessary. */ |
| 462 void UpdateCrc(GptData *gpt) { |
| 463 GptHeader *primary_header, *secondary_header; |
| 464 |
| 465 primary_header = (GptHeader*)gpt->primary_header; |
| 466 secondary_header = (GptHeader*)gpt->secondary_header; |
| 467 |
| 468 if (gpt->modified & GPT_MODIFIED_HEADER1) { |
| 469 primary_header->header_crc32 = 0; |
| 470 primary_header->header_crc32 = Crc32( |
| 471 (const uint8_t *)primary_header, primary_header->size); |
| 472 } |
| 473 if (gpt->modified & GPT_MODIFIED_HEADER2) { |
| 474 secondary_header->header_crc32 = 0; |
| 475 secondary_header->header_crc32 = Crc32( |
| 476 (const uint8_t *)secondary_header, secondary_header->size); |
| 477 } |
| 478 if (gpt->modified & GPT_MODIFIED_ENTRIES1) { |
| 479 primary_header->entries_crc32 = |
| 480 Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE); |
| 481 } |
| 482 if (gpt->modified & GPT_MODIFIED_ENTRIES2) { |
| 483 secondary_header->entries_crc32 = |
| 484 Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE); |
| 485 } |
| 486 } |
| 487 |
| 488 /* Does every sanity check, and returns if any header/entries needs to be |
| 489 * written back. */ |
| 490 int GptInit(GptData *gpt) { |
| 491 uint32_t valid_headers = MASK_BOTH; |
| 492 uint32_t valid_entries = MASK_BOTH; |
| 493 int retval; |
| 494 |
| 495 retval = CheckParameters(gpt); |
| 496 if (retval != GPT_SUCCESS) |
| 497 return retval; |
| 498 |
| 499 /* Initialize values */ |
| 500 gpt->modified = 0; |
| 501 |
| 502 /* Start checking if header parameters are valid. */ |
| 503 valid_headers &= CheckHeaderSignature(gpt); |
| 504 valid_headers &= CheckRevision(gpt); |
| 505 valid_headers &= CheckSize(gpt); |
| 506 valid_headers &= CheckReservedFields(gpt); |
| 507 valid_headers &= CheckMyLba(gpt); |
| 508 valid_headers &= CheckSizeOfPartitionEntry(gpt); |
| 509 valid_headers &= CheckNumberOfEntries(gpt); |
| 510 valid_headers &= CheckEntriesLba(gpt); |
| 511 valid_headers &= CheckValidUsableLbas(gpt); |
| 512 |
| 513 /* Checks if headers are valid. */ |
| 514 valid_headers &= CheckHeaderCrc(gpt); |
| 515 gpt->modified |= RepairHeader(gpt, valid_headers); |
| 516 |
| 517 /* Checks if entries are valid. */ |
| 518 valid_entries &= CheckEntriesCrc(gpt); |
| 519 valid_entries &= CheckValidEntries(gpt); |
| 520 valid_entries &= CheckOverlappedPartition(gpt); |
| 521 gpt->modified |= RepairEntries(gpt, valid_entries); |
| 522 |
| 523 /* Returns error if we don't have any valid header/entries to use. */ |
| 524 if (!valid_headers) |
| 525 return GPT_ERROR_INVALID_HEADERS; |
| 526 if (!valid_entries) |
| 527 return GPT_ERROR_INVALID_ENTRIES; |
| 528 |
| 529 UpdateCrc(gpt); |
| 530 |
| 531 /* FIXME: will remove the next line soon. */ |
| 532 gpt->current_kernel = 1; |
| 533 return GPT_SUCCESS; |
| 534 } |
| 535 |
11 /* stub code */ | 536 /* stub code */ |
12 static int start[] = { 34, 10034 }; | 537 static int start[] = { 34, 10034 }; |
13 | 538 |
14 int GptInit(GptData_t *gpt) { | 539 int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size) { |
15 int valid_headers[2] = {1, 1}; | |
16 | |
17 /* check header signature */ | |
18 if (Memcmp(gpt->primary_header, GPT_HEADER_SIGNATURE, | |
19 GPT_HEADER_SIGNATURE_SIZE)) | |
20 valid_headers[0] = 0; | |
21 if (Memcmp(gpt->secondary_header, GPT_HEADER_SIGNATURE, | |
22 GPT_HEADER_SIGNATURE_SIZE)) | |
23 valid_headers[1] = 0; | |
24 | |
25 if (!valid_headers[0] && !valid_headers[1]) | |
26 return GPT_ERROR_INVALID_HEADERS; | |
27 | |
28 gpt->current_kernel = 1; | |
29 return GPT_SUCCESS; | |
30 } | |
31 | |
32 int GptNextKernelEntry(GptData_t *gpt, uint64_t *start_sector, uint64_t *size) { | |
33 /* FIXME: the following code is not really code, just returns anything */ | 540 /* FIXME: the following code is not really code, just returns anything */ |
34 gpt->current_kernel ^= 1; | 541 gpt->current_kernel ^= 1; |
35 if (start_sector) *start_sector = start[gpt->current_kernel]; | 542 if (start_sector) *start_sector = start[gpt->current_kernel]; |
36 if (size) *size = 10000; | 543 if (size) *size = 10000; |
37 return GPT_SUCCESS; | 544 return GPT_SUCCESS; |
38 } | 545 } |
39 | 546 |
40 int GptUpdateKernelEntry(GptData_t *gpt, uint32_t update_type) { | 547 int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type) { |
41 /* FIXME: the following code is not really code, just return anything */ | 548 /* FIXME: the following code is not really code, just return anything */ |
42 gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << | 549 gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << |
43 gpt->current_kernel; | 550 gpt->current_kernel; |
44 return GPT_SUCCESS; | 551 return GPT_SUCCESS; |
45 } | 552 } |
OLD | NEW |