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

Side by Side Diff: src/platform/vboot_reference/cgptlib/cgpt.c

Issue 1922004: cgpt supports GptNextKernelEntry() and GptUpdateKernelEntry() (Closed)
Patch Set: Move cgpt attribute bits to bit [57,48] Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 */ 4 */
5 5
6 #include "cgpt.h" 6 #include "cgpt.h"
7 #include <string.h> 7 #include <string.h>
8 #include "cgpt_internal.h" 8 #include "cgpt_internal.h"
9 #include "crc32.h" 9 #include "crc32.h"
10 #include "gpt.h" 10 #include "gpt.h"
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 return 0; 458 return 0;
459 } 459 }
460 460
461 /* Update CRC value if necessary. */ 461 /* Update CRC value if necessary. */
462 void UpdateCrc(GptData *gpt) { 462 void UpdateCrc(GptData *gpt) {
463 GptHeader *primary_header, *secondary_header; 463 GptHeader *primary_header, *secondary_header;
464 464
465 primary_header = (GptHeader*)gpt->primary_header; 465 primary_header = (GptHeader*)gpt->primary_header;
466 secondary_header = (GptHeader*)gpt->secondary_header; 466 secondary_header = (GptHeader*)gpt->secondary_header;
467 467
468 if (gpt->modified & GPT_MODIFIED_ENTRIES1) {
469 primary_header->entries_crc32 =
470 Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE);
471 }
472 if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
473 secondary_header->entries_crc32 =
474 Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
475 }
468 if (gpt->modified & GPT_MODIFIED_HEADER1) { 476 if (gpt->modified & GPT_MODIFIED_HEADER1) {
469 primary_header->header_crc32 = 0; 477 primary_header->header_crc32 = 0;
470 primary_header->header_crc32 = Crc32( 478 primary_header->header_crc32 = Crc32(
471 (const uint8_t *)primary_header, primary_header->size); 479 (const uint8_t *)primary_header, primary_header->size);
472 } 480 }
473 if (gpt->modified & GPT_MODIFIED_HEADER2) { 481 if (gpt->modified & GPT_MODIFIED_HEADER2) {
474 secondary_header->header_crc32 = 0; 482 secondary_header->header_crc32 = 0;
475 secondary_header->header_crc32 = Crc32( 483 secondary_header->header_crc32 = Crc32(
476 (const uint8_t *)secondary_header, secondary_header->size); 484 (const uint8_t *)secondary_header, secondary_header->size);
477 } 485 }
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 } 486 }
487 487
488 /* Does every sanity check, and returns if any header/entries needs to be 488 /* Does every sanity check, and returns if any header/entries needs to be
489 * written back. */ 489 * written back. */
490 int GptInit(GptData *gpt) { 490 int GptInit(GptData *gpt) {
491 uint32_t valid_headers = MASK_BOTH; 491 uint32_t valid_headers = MASK_BOTH;
492 uint32_t valid_entries = MASK_BOTH; 492 uint32_t valid_entries = MASK_BOTH;
493 int retval; 493 int retval;
494 494
495 retval = CheckParameters(gpt); 495 retval = CheckParameters(gpt);
(...skipping 25 matching lines...) Expand all
521 gpt->modified |= RepairEntries(gpt, valid_entries); 521 gpt->modified |= RepairEntries(gpt, valid_entries);
522 522
523 /* Returns error if we don't have any valid header/entries to use. */ 523 /* Returns error if we don't have any valid header/entries to use. */
524 if (!valid_headers) 524 if (!valid_headers)
525 return GPT_ERROR_INVALID_HEADERS; 525 return GPT_ERROR_INVALID_HEADERS;
526 if (!valid_entries) 526 if (!valid_entries)
527 return GPT_ERROR_INVALID_ENTRIES; 527 return GPT_ERROR_INVALID_ENTRIES;
528 528
529 UpdateCrc(gpt); 529 UpdateCrc(gpt);
530 530
531 /* FIXME: will remove the next line soon. */ 531 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
532 gpt->current_kernel = 1; 532
533 return GPT_SUCCESS; 533 return GPT_SUCCESS;
534 } 534 }
535 535
536 /* stub code */ 536 /* Helper function to get a pointer to the partition entry.
537 static int start[] = { 34, 10034 }; 537 * 'secondary' is either PRIMARY or SECONDARY.
538 538 * 'entry_index' is the partition index: [0, number_of_entries).
539 */
540 GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) {
541 GptHeader *header;
542 uint8_t *entries;
543
544 if (secondary == PRIMARY) {
545 header = (GptHeader*)gpt->primary_header;
546 entries = gpt->primary_entries;
547 } else {
548 header = (GptHeader*)gpt->secondary_header;
549 entries = gpt->secondary_entries;
550 }
551
552 return (GptEntry*)(&entries[header->size_of_entry * entry_index]);
553 }
554
555 /* The following functions are helpers to access attributes bit more easily.
556 * 'secondary' is either PRIMARY or SECONDARY.
557 * 'entry_index' is the partition index: [0, number_of_entries).
558 *
559 * Get*() return the exact value (shifted and masked).
560 */
561 void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) {
562 GptEntry *entry;
563 entry = GetEntry(gpt, secondary, entry_index);
564
565 assert(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
566 entry->attributes &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
567 entry->attributes |= (uint64_t)priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET;
568 }
569
570 int GetPriority(GptData *gpt, int secondary, int entry_index) {
571 GptEntry *entry;
572 entry = GetEntry(gpt, secondary, entry_index);
573 return (entry->attributes & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
574 CGPT_ATTRIBUTE_PRIORITY_OFFSET;
575 }
576
577 void SetBad(GptData *gpt, int secondary, int entry_index, int bad) {
578 GptEntry *entry;
579 entry = GetEntry(gpt, secondary, entry_index);
580
581 assert(bad >= 0 && bad <= CGPT_ATTRIBUTE_MAX_BAD);
582 entry->attributes &= ~CGPT_ATTRIBUTE_BAD_MASK;
583 entry->attributes |= (uint64_t)bad << CGPT_ATTRIBUTE_BAD_OFFSET;
584 }
585
586 int GetBad(GptData *gpt, int secondary, int entry_index) {
587 GptEntry *entry;
588 entry = GetEntry(gpt, secondary, entry_index);
589 return (entry->attributes & CGPT_ATTRIBUTE_BAD_MASK) >>
590 CGPT_ATTRIBUTE_BAD_OFFSET;
591 }
592
593 void SetTries(GptData *gpt, int secondary, int entry_index, int tries) {
594 GptEntry *entry;
595 entry = GetEntry(gpt, secondary, entry_index);
596
597 assert(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
598 entry->attributes &= ~CGPT_ATTRIBUTE_TRIES_MASK;
599 entry->attributes |= (uint64_t)tries << CGPT_ATTRIBUTE_TRIES_OFFSET;
600 }
601
602 int GetTries(GptData *gpt, int secondary, int entry_index) {
603 GptEntry *entry;
604 entry = GetEntry(gpt, secondary, entry_index);
605 return (entry->attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
606 CGPT_ATTRIBUTE_TRIES_OFFSET;
607 }
608
609 void SetSuccess(GptData *gpt, int secondary, int entry_index, int success) {
610 GptEntry *entry;
611 entry = GetEntry(gpt, secondary, entry_index);
612
613 assert(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESS);
614 entry->attributes &= ~CGPT_ATTRIBUTE_SUCCESS_MASK;
615 entry->attributes |= (uint64_t)success << CGPT_ATTRIBUTE_SUCCESS_OFFSET;
616 }
617
618 int GetSuccess(GptData *gpt, int secondary, int entry_index) {
619 GptEntry *entry;
620 entry = GetEntry(gpt, secondary, entry_index);
621 return (entry->attributes & CGPT_ATTRIBUTE_SUCCESS_MASK) >>
622 CGPT_ATTRIBUTE_SUCCESS_OFFSET;
623 }
624
625 /* Compare two priority values. Actually it is a circular priority, which is:
626 * 3 > 2 > 1 > 0, but 0 > 3. (-1 means very low, and anyone is higher than -1)
627 *
628 * Return 1 if 'a' has higher priority than 'b'.
629 */
630 int IsHigherPriority(int a, int b) {
631 if ((a == 0) && (b == CGPT_ATTRIBUTE_MAX_PRIORITY))
632 return 1;
633 else if ((a == CGPT_ATTRIBUTE_MAX_PRIORITY) && (b == 0))
634 return 0;
635 else
636 return (a > b) ? 1 : 0;
637 }
638
639 /* This function walks through the whole partition table (see note below),
640 * and pick up the active and valid (not marked as bad) kernel entry with
641 * *highest* priority (except gpt->current_kernel itself).
642 *
643 * Returns start_sector and its size if a candidate kernel is found.
644 *
645 * Note: in the first walk (gpt->current_kernel==CGPT_KERNEL_ENTRY_NOT_FOUND),
646 * the scan range is whole table. But in later scans, we only scan
647 * (header->number_of_entries - 1) entries because we are looking for
648 * next kernel with lower priority (consider the case that highest
649 * priority kernel is still active and valid).
650 */
539 int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size) { 651 int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size) {
540 /* FIXME: the following code is not really code, just returns anything */ 652 GptHeader *header;
541 gpt->current_kernel ^= 1; 653 GptEntry *entry;
542 if (start_sector) *start_sector = start[gpt->current_kernel]; 654 int scan, current_priority;
543 if (size) *size = 10000; 655 int begin, end; /* [begin, end], which end is included. */
656 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
657
658 header = (GptHeader*)gpt->primary_header;
659 current_priority = -1; /* pretty low priority */
660 if (gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND) {
661 begin = 0;
662 end = header->number_of_entries - 1;
663 } else {
664 begin = (gpt->current_kernel + 1) % header->number_of_entries;
665 end = (gpt->current_kernel - 1 + header->number_of_entries) %
666 header->number_of_entries;
667 }
668
669 scan = begin;
670 do {
671 entry = GetEntry(gpt, PRIMARY, scan);
672 if (!Memcmp(&entry->type, &chromeos_kernel, sizeof(Guid)) &&
673 !GetBad(gpt, PRIMARY, scan) &&
674 ((gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND) ||
675 (IsHigherPriority(GetPriority(gpt, PRIMARY, scan),
676 current_priority)))) {
677 gpt->current_kernel = scan;
678 current_priority = GetPriority(gpt, PRIMARY, gpt->current_kernel);
679 }
680
681 if (scan == end) break;
682 scan = (scan + 1) % header->number_of_entries;
683 } while (1);
684
685 if (gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND)
686 return GPT_ERROR_NO_VALID_KERNEL;
687
688 entry = GetEntry(gpt, PRIMARY, gpt->current_kernel);
689 assert(entry->starting_lba <= entry->ending_lba);
690
691 if (start_sector) *start_sector = entry->starting_lba;
692 if (size) *size = entry->ending_lba - entry->starting_lba + 1;
693
544 return GPT_SUCCESS; 694 return GPT_SUCCESS;
545 } 695 }
546 696
697 /* Given a update_type, this function updates the corresponding bits in GptData.
698 *
699 * Returns GPT_SUCCESS if no error. gpt->modified is set if any header and
700 * entries needs to be updated to hard drive.
701 * GPT_ERROR_INVALID_UPDATE_TYPE if given an invalid update_type.
702 */
547 int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type) { 703 int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type) {
548 /* FIXME: the following code is not really code, just return anything */ 704 Guid chromeos_type = GPT_ENT_TYPE_CHROMEOS_KERNEL;
549 gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) << 705 int primary_is_modified = 0;
550 gpt->current_kernel; 706
707 assert(gpt->current_kernel != CGPT_KERNEL_ENTRY_NOT_FOUND);
708 assert(!Memcmp(&(GetEntry(gpt, PRIMARY, gpt->current_kernel)->type),
709 &chromeos_type, sizeof(Guid)));
710
711 /* Modify primary entries first, then copy to secondary later. */
712 switch (update_type) {
713 case GPT_UPDATE_ENTRY_TRY: {
714 /* Increase tries value until CGPT_ATTRIBUTE_MAX_TRIES. */
715 int tries;
716 tries = GetTries(gpt, PRIMARY, gpt->current_kernel);
717 if (tries < CGPT_ATTRIBUTE_MAX_TRIES) {
718 ++tries;
719 SetTries(gpt, PRIMARY, gpt->current_kernel, tries);
720 primary_is_modified = 1;
721 }
722 break;
723 }
724 case GPT_UPDATE_ENTRY_BAD: {
725 GetEntry(gpt, PRIMARY, gpt->current_kernel)->attributes |=
726 CGPT_ATTRIBUTE_BAD_MASK;
727 primary_is_modified = 1;
728 break;
729 }
730 default: {
731 return GPT_ERROR_INVALID_UPDATE_TYPE;
732 }
733 }
734
735 if (primary_is_modified) {
736 /* Claim only primary is valid so that secondary is overwritten. */
737 RepairEntries(gpt, MASK_PRIMARY);
738 /* Actually two entries are dirty now.
739 * Also two headers are dirty because entries_crc32 has been updated. */
740 gpt->modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
741 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
742 UpdateCrc(gpt);
743 }
744
551 return GPT_SUCCESS; 745 return GPT_SUCCESS;
552 } 746 }
OLDNEW
« no previous file with comments | « src/platform/vboot_reference/cgptlib/cgpt.h ('k') | src/platform/vboot_reference/cgptlib/cgpt_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698