| 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 "cgptlib.h" | 6 #include "cgptlib.h" |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include "cgptlib_internal.h" | 8 #include "cgptlib_internal.h" |
| 9 #include "crc32.h" | 9 #include "crc32.h" |
| 10 #include "gpt.h" | 10 #include "gpt.h" |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 INVALIDATE_HEADER(valid_headers, PRIMARY); | 236 INVALIDATE_HEADER(valid_headers, PRIMARY); |
| 237 if (headers[SECONDARY]->last_usable_lba >= headers[SECONDARY]->entries_lba) | 237 if (headers[SECONDARY]->last_usable_lba >= headers[SECONDARY]->entries_lba) |
| 238 INVALIDATE_HEADER(valid_headers, SECONDARY); | 238 INVALIDATE_HEADER(valid_headers, SECONDARY); |
| 239 | 239 |
| 240 return valid_headers; | 240 return valid_headers; |
| 241 } | 241 } |
| 242 | 242 |
| 243 /* Checks header CRC */ | 243 /* Checks header CRC */ |
| 244 uint32_t CheckHeaderCrc(GptData *gpt) { | 244 uint32_t CheckHeaderCrc(GptData *gpt) { |
| 245 uint32_t crc32, original_crc32; | 245 uint32_t crc32, original_crc32; |
| 246 uint32_t valid_headers = MASK_BOTH; | |
| 247 GptHeader *headers[] = { | 246 GptHeader *headers[] = { |
| 248 (GptHeader*)gpt->primary_header, | 247 (GptHeader*)gpt->primary_header, |
| 249 (GptHeader*)gpt->secondary_header, | 248 (GptHeader*)gpt->secondary_header, |
| 250 }; | 249 }; |
| 251 int i; | 250 int i; |
| 252 | 251 |
| 253 for (i = PRIMARY; i <= SECONDARY; ++i) { | 252 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 253 if (!(gpt->valid_headers & (1 << i))) continue; |
| 254 original_crc32 = headers[i]->header_crc32; | 254 original_crc32 = headers[i]->header_crc32; |
| 255 headers[i]->header_crc32 = 0; | 255 headers[i]->header_crc32 = 0; |
| 256 crc32 = Crc32((const uint8_t *)headers[i], headers[i]->size); | 256 crc32 = Crc32((const uint8_t *)headers[i], headers[i]->size); |
| 257 headers[i]->header_crc32 = original_crc32; | 257 headers[i]->header_crc32 = original_crc32; |
| 258 if (crc32 != original_crc32) | 258 if (crc32 != original_crc32) |
| 259 INVALIDATE_HEADER(valid_headers, i); | 259 INVALIDATE_HEADER(gpt->valid_headers, i); |
| 260 } | 260 } |
| 261 return valid_headers; | 261 return gpt->valid_headers; |
| 262 } | 262 } |
| 263 | 263 |
| 264 /* Checks entries CRC */ | 264 /* Checks entries CRC */ |
| 265 uint32_t CheckEntriesCrc(GptData *gpt) { | 265 uint32_t CheckEntriesCrc(GptData *gpt) { |
| 266 uint32_t crc32; | 266 uint32_t crc32; |
| 267 uint32_t valid_entries = MASK_BOTH; | |
| 268 GptHeader *headers[] = { | 267 GptHeader *headers[] = { |
| 269 (GptHeader*)gpt->primary_header, | 268 (GptHeader*)gpt->primary_header, |
| 270 (GptHeader*)gpt->secondary_header, | 269 (GptHeader*)gpt->secondary_header, |
| 271 }; | 270 }; |
| 272 GptEntry *entries[] = { | 271 GptEntry *entries[] = { |
| 273 (GptEntry*)gpt->primary_entries, | 272 (GptEntry*)gpt->primary_entries, |
| 274 (GptEntry*)gpt->secondary_entries, | 273 (GptEntry*)gpt->secondary_entries, |
| 275 }; | 274 }; |
| 275 uint32_t entries_crc32; |
| 276 int i; | 276 int i; |
| 277 | 277 |
| 278 if (gpt->valid_headers & MASK_PRIMARY) |
| 279 entries_crc32 = headers[PRIMARY]->entries_crc32; |
| 280 else |
| 281 entries_crc32 = headers[SECONDARY]->entries_crc32; |
| 282 |
| 278 for (i = PRIMARY; i <= SECONDARY; ++i) { | 283 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 279 crc32 = Crc32((const uint8_t *)entries[i], TOTAL_ENTRIES_SIZE); | 284 crc32 = Crc32((const uint8_t *)entries[i], TOTAL_ENTRIES_SIZE); |
| 280 if (crc32 != headers[i]->entries_crc32) | 285 if (crc32 != entries_crc32) |
| 281 INVALIDATE_HEADER(valid_entries, i); | 286 INVALIDATE_ENTRIES(gpt->valid_entries, i); |
| 282 } | 287 } |
| 283 return valid_entries; | 288 return gpt->valid_entries; |
| 284 } | 289 } |
| 285 | 290 |
| 286 /* Returns non-zero if the given GUID is non-zero. */ | 291 /* Returns non-zero if the given GUID is non-zero. */ |
| 287 static int NonZeroGuid(const Guid *guid) { | 292 static int NonZeroGuid(const Guid *guid) { |
| 288 static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}}; | 293 static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}}; |
| 289 return Memcmp(&zero, guid, sizeof(zero)); | 294 return Memcmp(&zero, guid, sizeof(zero)); |
| 290 } | 295 } |
| 291 | 296 |
| 292 /* Checks if entries geometry is valid. | 297 /* Checks if entries geometry is valid. |
| 293 * All active (non-zero PartitionTypeGUID) partition entries should have: | 298 * All active (non-zero PartitionTypeGUID) partition entries should have: |
| 294 * entry.StartingLBA >= header.FirstUsableLBA | 299 * entry.StartingLBA >= header.FirstUsableLBA |
| 295 * entry.EndingLBA <= header.LastUsableLBA | 300 * entry.EndingLBA <= header.LastUsableLBA |
| 296 * entry.StartingLBA <= entry.EndingLBA | 301 * entry.StartingLBA <= entry.EndingLBA |
| 297 */ | 302 */ |
| 298 uint32_t CheckValidEntries(GptData *gpt) { | 303 uint32_t CheckValidEntries(GptData *gpt) { |
| 299 uint32_t valid_entries = MASK_BOTH; | 304 uint32_t valid_entries = MASK_BOTH; |
| 300 GptHeader *headers[] = { | 305 GptHeader *headers[] = { |
| 301 (GptHeader*)gpt->primary_header, | 306 (GptHeader*)gpt->primary_header, |
| 302 (GptHeader*)gpt->secondary_header, | 307 (GptHeader*)gpt->secondary_header, |
| 303 }; | 308 }; |
| 304 GptEntry *entries[] = { | 309 GptEntry *entries[] = { |
| 305 (GptEntry*)gpt->primary_entries, | 310 (GptEntry*)gpt->primary_entries, |
| 306 (GptEntry*)gpt->secondary_entries, | 311 (GptEntry*)gpt->secondary_entries, |
| 307 }; | 312 }; |
| 313 uint32_t number_of_entries, size_of_entry; |
| 314 uint64_t first_usable_lba, last_usable_lba; |
| 308 int copy, entry_index; | 315 int copy, entry_index; |
| 309 GptEntry *entry; | 316 GptEntry *entry; |
| 310 | 317 |
| 318 if (gpt->valid_headers & MASK_PRIMARY) |
| 319 copy = PRIMARY; |
| 320 else |
| 321 copy = SECONDARY; |
| 322 number_of_entries = headers[copy]->number_of_entries; |
| 323 size_of_entry = headers[copy]->size_of_entry; |
| 324 first_usable_lba = headers[copy]->first_usable_lba; |
| 325 last_usable_lba = headers[copy]->last_usable_lba; |
| 326 |
| 311 for (copy = PRIMARY; copy <= SECONDARY; ++copy) { | 327 for (copy = PRIMARY; copy <= SECONDARY; ++copy) { |
| 312 for (entry_index = 0; | 328 for (entry_index = 0; |
| 313 entry_index < headers[copy]->number_of_entries; | 329 entry_index < number_of_entries; |
| 314 ++entry_index) { | 330 ++entry_index) { |
| 315 entry = (GptEntry*)&(((uint8_t*)entries[copy]) | 331 entry = (GptEntry*)&(((uint8_t*)entries[copy]) |
| 316 [entry_index * headers[copy]->size_of_entry]); | 332 [entry_index * size_of_entry]); |
| 317 if (NonZeroGuid(&entry->type)) { | 333 if (NonZeroGuid(&entry->type)) { |
| 318 if ((entry->starting_lba < headers[copy]->first_usable_lba) || | 334 if ((entry->starting_lba < first_usable_lba) || |
| 319 (entry->ending_lba > headers[copy]->last_usable_lba) || | 335 (entry->ending_lba > last_usable_lba) || |
| 320 (entry->ending_lba < entry->starting_lba)) | 336 (entry->ending_lba < entry->starting_lba)) |
| 321 INVALIDATE_HEADER(valid_entries, copy); | 337 INVALIDATE_ENTRIES(valid_entries, copy); |
| 322 } | 338 } |
| 323 } | 339 } |
| 324 } | 340 } |
| 325 return valid_entries; | 341 return valid_entries; |
| 326 } | 342 } |
| 327 | 343 |
| 328 static pair_t pairs[MAX_NUMBER_OF_ENTRIES]; | 344 static pair_t pairs[MAX_NUMBER_OF_ENTRIES]; |
| 329 /* Callback function for QuickSort(). Returns 1 if 'a_' should precede 'b_'. */ | 345 /* Callback function for QuickSort(). Returns 1 if 'a_' should precede 'b_'. */ |
| 330 int compare_pair(const void *a_, const void *b_) { | 346 int compare_pair(const void *a_, const void *b_) { |
| 331 const pair_t *a = a_; | 347 const pair_t *a = a_; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 uint32_t valid_entries = MASK_BOTH; | 379 uint32_t valid_entries = MASK_BOTH; |
| 364 GptHeader *headers[] = { | 380 GptHeader *headers[] = { |
| 365 (GptHeader*)gpt->primary_header, | 381 (GptHeader*)gpt->primary_header, |
| 366 (GptHeader*)gpt->secondary_header, | 382 (GptHeader*)gpt->secondary_header, |
| 367 }; | 383 }; |
| 368 GptEntry *entries[] = { | 384 GptEntry *entries[] = { |
| 369 (GptEntry*)gpt->primary_entries, | 385 (GptEntry*)gpt->primary_entries, |
| 370 (GptEntry*)gpt->secondary_entries, | 386 (GptEntry*)gpt->secondary_entries, |
| 371 }; | 387 }; |
| 372 int i; | 388 int i; |
| 389 uint32_t number_of_entries; |
| 390 |
| 391 if (gpt->valid_headers & MASK_PRIMARY) |
| 392 number_of_entries = headers[PRIMARY]->number_of_entries; |
| 393 else |
| 394 number_of_entries = headers[SECONDARY]->number_of_entries; |
| 373 | 395 |
| 374 for (i = PRIMARY; i <= SECONDARY; ++i) { | 396 for (i = PRIMARY; i <= SECONDARY; ++i) { |
| 375 if (OverlappedEntries(entries[i], headers[i]->number_of_entries)) | 397 if (OverlappedEntries(entries[i], number_of_entries)) |
| 376 INVALIDATE_ENTRIES(valid_entries, i); | 398 INVALIDATE_ENTRIES(valid_entries, i); |
| 377 } | 399 } |
| 378 return valid_entries; | 400 return valid_entries; |
| 379 } | 401 } |
| 380 | 402 |
| 381 /* Primary entries and secondary entries should be bitwise identical. | 403 /* Primary entries and secondary entries should be bitwise identical. |
| 382 * If two entries tables are valid, compare them. If not the same, | 404 * If two entries tables are valid, compare them. If not the same, |
| 383 * overwrites secondary with primary (primary always has higher priority), | 405 * overwrites secondary with primary (primary always has higher priority), |
| 384 * and marks secondary as modified. | 406 * and marks secondary as modified. |
| 385 * If only one is valid, overwrites invalid one. | 407 * If only one is valid, overwrites invalid one. |
| 386 * If all are invalid, does nothing. | 408 * If all are invalid, does nothing. |
| 387 * This function returns bit masks for GptData.modified field. */ | 409 * This function returns bit masks for GptData.modified field. |
| 410 * Note that CRC is NOT re-computed in this function. |
| 411 */ |
| 388 uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) { | 412 uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) { |
| 389 if (valid_entries == MASK_BOTH) { | 413 if (valid_entries == MASK_BOTH) { |
| 390 if (Memcmp(gpt->primary_entries, gpt->secondary_entries, | 414 if (Memcmp(gpt->primary_entries, gpt->secondary_entries, |
| 391 TOTAL_ENTRIES_SIZE)) { | 415 TOTAL_ENTRIES_SIZE)) { |
| 392 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); | 416 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); |
| 393 return GPT_MODIFIED_ENTRIES2; | 417 return GPT_MODIFIED_ENTRIES2; |
| 394 } | 418 } |
| 395 } else if (valid_entries == MASK_PRIMARY) { | 419 } else if (valid_entries == MASK_PRIMARY) { |
| 396 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); | 420 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE); |
| 397 return GPT_MODIFIED_ENTRIES2; | 421 return GPT_MODIFIED_ENTRIES2; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 | 462 |
| 439 /* This function repairs primary and secondary headers if possible. | 463 /* This function repairs primary and secondary headers if possible. |
| 440 * If both headers are valid (CRC32 is correct) but | 464 * If both headers are valid (CRC32 is correct) but |
| 441 * a) indicate inconsistent usable LBA ranges, | 465 * a) indicate inconsistent usable LBA ranges, |
| 442 * b) inconsistent partition entry size and number, | 466 * b) inconsistent partition entry size and number, |
| 443 * c) inconsistent disk_uuid, | 467 * c) inconsistent disk_uuid, |
| 444 * we will use the primary header to overwrite secondary header. | 468 * we will use the primary header to overwrite secondary header. |
| 445 * If primary is invalid (CRC32 is wrong), then we repair it from secondary. | 469 * If primary is invalid (CRC32 is wrong), then we repair it from secondary. |
| 446 * If secondary is invalid (CRC32 is wrong), then we repair it from primary. | 470 * If secondary is invalid (CRC32 is wrong), then we repair it from primary. |
| 447 * This function returns the bitmasks for modified header. | 471 * This function returns the bitmasks for modified header. |
| 448 * Note that CRC value is not re-computed in this function. UpdateCrc() will | 472 * Note that CRC value is NOT re-computed in this function. UpdateCrc() will |
| 449 * do it later. | 473 * do it later. |
| 450 */ | 474 */ |
| 451 uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) { | 475 uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) { |
| 452 GptHeader *primary_header, *secondary_header; | 476 GptHeader *primary_header, *secondary_header; |
| 453 | 477 |
| 454 primary_header = (GptHeader*)gpt->primary_header; | 478 primary_header = (GptHeader*)gpt->primary_header; |
| 455 secondary_header = (GptHeader*)gpt->secondary_header; | 479 secondary_header = (GptHeader*)gpt->secondary_header; |
| 456 | 480 |
| 457 if (valid_headers == MASK_BOTH) { | 481 if (valid_headers == MASK_BOTH) { |
| 458 if (!IsSynonymous(primary_header, secondary_header)) { | 482 if (!IsSynonymous(primary_header, secondary_header)) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 primary_header->header_crc32 = Crc32( | 519 primary_header->header_crc32 = Crc32( |
| 496 (const uint8_t *)primary_header, primary_header->size); | 520 (const uint8_t *)primary_header, primary_header->size); |
| 497 } | 521 } |
| 498 if (gpt->modified & GPT_MODIFIED_HEADER2) { | 522 if (gpt->modified & GPT_MODIFIED_HEADER2) { |
| 499 secondary_header->header_crc32 = 0; | 523 secondary_header->header_crc32 = 0; |
| 500 secondary_header->header_crc32 = Crc32( | 524 secondary_header->header_crc32 = Crc32( |
| 501 (const uint8_t *)secondary_header, secondary_header->size); | 525 (const uint8_t *)secondary_header, secondary_header->size); |
| 502 } | 526 } |
| 503 } | 527 } |
| 504 | 528 |
| 505 /* Does every sanity check, and returns if any header/entries needs to be | 529 /* This function only checks GptData. |
| 506 * written back. */ | 530 * valid_headers and valid_entries are used to store the checking results. |
| 507 int GptInit(GptData *gpt) { | 531 * |
| 508 uint32_t valid_headers = MASK_BOTH; | 532 * Returns: |
| 509 uint32_t valid_entries = MASK_BOTH; | 533 * GPT_ERROR_INVALID_HEADERS -- both headers are invalid. |
| 534 * GPT_ERROR_INVALID_ENTRIES -- both entries are invalid. |
| 535 * GPT_SUCCESS -- everything looks fine. |
| 536 */ |
| 537 int GptSanityCheck(GptData *gpt) { |
| 510 int retval; | 538 int retval; |
| 511 | 539 |
| 540 assert(gpt); |
| 541 |
| 512 retval = CheckParameters(gpt); | 542 retval = CheckParameters(gpt); |
| 513 if (retval != GPT_SUCCESS) | 543 if (retval != GPT_SUCCESS) |
| 514 return retval; | 544 return retval; |
| 515 | 545 |
| 516 /* Initialize values */ | 546 /* Initialize values */ |
| 517 gpt->modified = 0; | 547 gpt->valid_headers = MASK_BOTH; |
| 548 gpt->valid_entries = MASK_BOTH; |
| 518 | 549 |
| 519 /* Start checking if header parameters are valid. */ | 550 /* Start checking if header parameters are valid. */ |
| 520 valid_headers &= CheckHeaderSignature(gpt); | 551 CheckHeaderSignature(gpt); |
| 521 valid_headers &= CheckRevision(gpt); | 552 CheckRevision(gpt); |
| 522 valid_headers &= CheckSize(gpt); | 553 CheckSize(gpt); |
| 523 valid_headers &= CheckReservedFields(gpt); | 554 CheckReservedFields(gpt); |
| 524 valid_headers &= CheckMyLba(gpt); | 555 CheckMyLba(gpt); |
| 525 valid_headers &= CheckSizeOfPartitionEntry(gpt); | 556 CheckSizeOfPartitionEntry(gpt); |
| 526 valid_headers &= CheckNumberOfEntries(gpt); | 557 CheckNumberOfEntries(gpt); |
| 527 valid_headers &= CheckEntriesLba(gpt); | 558 CheckEntriesLba(gpt); |
| 528 valid_headers &= CheckValidUsableLbas(gpt); | 559 CheckValidUsableLbas(gpt); |
| 560 CheckHeaderCrc(gpt); |
| 529 | 561 |
| 530 /* Checks if headers are valid. */ | 562 /* Returns error if we don't have any valid header to use. */ |
| 531 valid_headers &= CheckHeaderCrc(gpt); | 563 if (!gpt->valid_headers) |
| 532 gpt->modified |= RepairHeader(gpt, valid_headers); | 564 return GPT_ERROR_INVALID_HEADERS; |
| 533 | 565 |
| 534 /* Checks if entries are valid. */ | 566 /* Checks if entries are valid. */ |
| 535 valid_entries &= CheckEntriesCrc(gpt); | 567 CheckEntriesCrc(gpt); |
| 536 valid_entries &= CheckValidEntries(gpt); | 568 CheckValidEntries(gpt); |
| 537 valid_entries &= CheckOverlappedPartition(gpt); | 569 CheckOverlappedPartition(gpt); |
| 538 gpt->modified |= RepairEntries(gpt, valid_entries); | |
| 539 | 570 |
| 540 /* Returns error if we don't have any valid header/entries to use. */ | 571 /* Returns error if we don't have any valid entries to use. */ |
| 541 if (!valid_headers) | 572 if (!gpt->valid_entries) |
| 542 return GPT_ERROR_INVALID_HEADERS; | |
| 543 if (!valid_entries) | |
| 544 return GPT_ERROR_INVALID_ENTRIES; | 573 return GPT_ERROR_INVALID_ENTRIES; |
| 545 | 574 |
| 575 return GPT_SUCCESS; |
| 576 } |
| 577 |
| 578 void GptRepair(GptData *gpt) { |
| 579 gpt->modified |= RepairHeader(gpt, gpt->valid_headers); |
| 580 gpt->modified |= RepairEntries(gpt, gpt->valid_entries); |
| 546 UpdateCrc(gpt); | 581 UpdateCrc(gpt); |
| 582 } |
| 583 |
| 584 /* Does every sanity check, and returns if any header/entries needs to be |
| 585 * written back. */ |
| 586 int GptInit(GptData *gpt) { |
| 587 int retval; |
| 588 |
| 589 retval = GptSanityCheck(gpt); |
| 590 if (GPT_SUCCESS != retval) return retval; |
| 591 |
| 592 gpt->modified = 0; |
| 593 GptRepair(gpt); |
| 547 | 594 |
| 548 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND; | 595 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND; |
| 549 | 596 |
| 550 return GPT_SUCCESS; | 597 return GPT_SUCCESS; |
| 551 } | 598 } |
| 552 | 599 |
| 553 /* Helper function to get a pointer to the partition entry. | 600 /* Helper function to get a pointer to the partition entry. |
| 554 * 'secondary' is either PRIMARY or SECONDARY. | 601 * 'secondary' is either PRIMARY or SECONDARY. |
| 555 * 'entry_index' is the partition index: [0, number_of_entries). | 602 * 'entry_index' is the partition index: [0, number_of_entries). |
| 556 */ | 603 */ |
| 557 GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) { | 604 GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) { |
| 558 GptHeader *header; | |
| 559 uint8_t *entries; | 605 uint8_t *entries; |
| 560 | 606 |
| 561 if (secondary == PRIMARY) { | 607 if (secondary == PRIMARY) { |
| 562 header = (GptHeader*)gpt->primary_header; | |
| 563 entries = gpt->primary_entries; | 608 entries = gpt->primary_entries; |
| 564 } else { | 609 } else { |
| 565 header = (GptHeader*)gpt->secondary_header; | |
| 566 entries = gpt->secondary_entries; | 610 entries = gpt->secondary_entries; |
| 567 } | 611 } |
| 568 | 612 |
| 569 return (GptEntry*)(&entries[header->size_of_entry * entry_index]); | 613 return (GptEntry*)(&entries[GetNumberOfEntries(gpt) * entry_index]); |
| 570 } | 614 } |
| 571 | 615 |
| 572 /* The following functions are helpers to access attributes bit more easily. | 616 /* The following functions are helpers to access attributes bit more easily. |
| 573 * 'secondary' is either PRIMARY or SECONDARY. | 617 * 'secondary' is either PRIMARY or SECONDARY. |
| 574 * 'entry_index' is the partition index: [0, number_of_entries). | 618 * 'entry_index' is the partition index: [0, number_of_entries). |
| 575 * | 619 * |
| 576 * Get*() return the exact value (shifted and masked). | 620 * Get*() return the exact value (shifted and masked). |
| 577 */ | 621 */ |
| 578 void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) { | 622 void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) { |
| 579 GptEntry *entry; | 623 GptEntry *entry; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 } | 677 } |
| 634 | 678 |
| 635 int GetSuccessful(GptData *gpt, int secondary, int entry_index) { | 679 int GetSuccessful(GptData *gpt, int secondary, int entry_index) { |
| 636 GptEntry *entry; | 680 GptEntry *entry; |
| 637 entry = GetEntry(gpt, secondary, entry_index); | 681 entry = GetEntry(gpt, secondary, entry_index); |
| 638 return (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >> | 682 return (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >> |
| 639 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; | 683 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; |
| 640 } | 684 } |
| 641 | 685 |
| 642 uint32_t GetNumberOfEntries(const GptData *gpt) { | 686 uint32_t GetNumberOfEntries(const GptData *gpt) { |
| 643 GptHeader *header; | 687 GptHeader *header = 0; |
| 644 header = (GptHeader*)gpt->primary_header; | 688 if (gpt->valid_headers & MASK_PRIMARY) |
| 689 header = (GptHeader*)gpt->primary_header; |
| 690 else if (gpt->valid_headers & MASK_SECONDARY) |
| 691 header = (GptHeader*)gpt->secondary_header; |
| 692 else |
| 693 assert(0); |
| 645 return header->number_of_entries; | 694 return header->number_of_entries; |
| 646 } | 695 } |
| 647 | 696 |
| 648 | 697 |
| 649 /* Compare two priority values. Actually it is a circular priority, which is: | 698 /* Compare two priority values. Actually it is a circular priority, which is: |
| 650 * 3 > 2 > 1 > 0, but 0 > 3. (-1 means very low, and anyone is higher than -1) | 699 * 3 > 2 > 1 > 0, but 0 > 3. (-1 means very low, and anyone is higher than -1) |
| 651 * | 700 * |
| 652 * Return 1 if 'a' has higher priority than 'b'. | 701 * Return 1 if 'a' has higher priority than 'b'. |
| 653 */ | 702 */ |
| 654 int IsHigherPriority(int a, int b) { | 703 int IsHigherPriority(int a, int b) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 RepairEntries(gpt, MASK_PRIMARY); | 810 RepairEntries(gpt, MASK_PRIMARY); |
| 762 /* Actually two entries are dirty now. | 811 /* Actually two entries are dirty now. |
| 763 * Also two headers are dirty because entries_crc32 has been updated. */ | 812 * Also two headers are dirty because entries_crc32 has been updated. */ |
| 764 gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | | 813 gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | |
| 765 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); | 814 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); |
| 766 UpdateCrc(gpt); | 815 UpdateCrc(gpt); |
| 767 } | 816 } |
| 768 | 817 |
| 769 return GPT_SUCCESS; | 818 return GPT_SUCCESS; |
| 770 } | 819 } |
| OLD | NEW |