123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "2sysincludes.h"
- #include "2common.h"
- #include "sysincludes.h"
- #include "cgptlib.h"
- #include "cgptlib_internal.h"
- #include "crc32.h"
- #include "gpt.h"
- #include "utility.h"
- #include "vboot_api.h"
- int GptInit(GptData *gpt)
- {
- int retval;
- gpt->modified = 0;
- gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
- gpt->current_priority = 999;
- retval = GptSanityCheck(gpt);
- if (GPT_SUCCESS != retval) {
- VB2_DEBUG("GptInit() failed sanity check\n");
- return retval;
- }
- GptRepair(gpt);
- return GPT_SUCCESS;
- }
- int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
- {
- GptHeader *header = (GptHeader *)gpt->primary_header;
- GptEntry *entries = (GptEntry *)gpt->primary_entries;
- GptEntry *e;
- int new_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
- int new_prio = 0;
- uint32_t i;
- /*
- * If we already found a kernel, continue the scan at the current
- * kernel's priority, in case there is another kernel with the same
- * priority.
- */
- if (gpt->current_kernel != CGPT_KERNEL_ENTRY_NOT_FOUND) {
- for (i = gpt->current_kernel + 1;
- i < header->number_of_entries; i++) {
- e = entries + i;
- if (!IsKernelEntry(e))
- continue;
- VB2_DEBUG("GptNextKernelEntry looking at same prio "
- "partition %d\n", i+1);
- VB2_DEBUG("GptNextKernelEntry s%d t%d p%d\n",
- GetEntrySuccessful(e), GetEntryTries(e),
- GetEntryPriority(e));
- if (!(GetEntrySuccessful(e) || GetEntryTries(e)))
- continue;
- if (GetEntryPriority(e) == gpt->current_priority) {
- gpt->current_kernel = i;
- *start_sector = e->starting_lba;
- *size = e->ending_lba - e->starting_lba + 1;
- VB2_DEBUG("GptNextKernelEntry likes it\n");
- return GPT_SUCCESS;
- }
- }
- }
- /*
- * We're still here, so scan for the remaining kernel with the highest
- * priority less than the previous attempt.
- */
- for (i = 0, e = entries; i < header->number_of_entries; i++, e++) {
- int current_prio = GetEntryPriority(e);
- if (!IsKernelEntry(e))
- continue;
- VB2_DEBUG("GptNextKernelEntry looking at new prio "
- "partition %d\n", i+1);
- VB2_DEBUG("GptNextKernelEntry s%d t%d p%d\n",
- GetEntrySuccessful(e), GetEntryTries(e),
- GetEntryPriority(e));
- if (!(GetEntrySuccessful(e) || GetEntryTries(e)))
- continue;
- if (current_prio >= gpt->current_priority) {
- /* Already returned this kernel in a previous call */
- continue;
- }
- if (current_prio > new_prio) {
- new_kernel = i;
- new_prio = current_prio;
- }
- }
- /*
- * Save what we found. Note that if we didn't find a new kernel,
- * new_prio will still be -1, so future calls to this function will
- * also fail.
- */
- gpt->current_kernel = new_kernel;
- gpt->current_priority = new_prio;
- if (CGPT_KERNEL_ENTRY_NOT_FOUND == new_kernel) {
- VB2_DEBUG("GptNextKernelEntry no more kernels\n");
- return GPT_ERROR_NO_VALID_KERNEL;
- }
- VB2_DEBUG("GptNextKernelEntry likes partition %d\n", new_kernel + 1);
- e = entries + new_kernel;
- *start_sector = e->starting_lba;
- *size = e->ending_lba - e->starting_lba + 1;
- return GPT_SUCCESS;
- }
- /*
- * Func: GptUpdateKernelWithEntry
- * Desc: This function updates the given kernel entry according to the provided
- * update_type.
- */
- int GptUpdateKernelWithEntry(GptData *gpt, GptEntry *e, uint32_t update_type)
- {
- int modified = 0;
- if (!IsKernelEntry(e))
- return GPT_ERROR_INVALID_UPDATE_TYPE;
- switch (update_type) {
- case GPT_UPDATE_ENTRY_TRY: {
- /* Used up a try */
- int tries;
- if (GetEntrySuccessful(e)) {
- /*
- * Successfully booted this partition, so tries field
- * is ignored.
- */
- return GPT_SUCCESS;
- }
- tries = GetEntryTries(e);
- if (tries > 1) {
- /* Still have tries left */
- modified = 1;
- SetEntryTries(e, tries - 1);
- break;
- }
- /* Out of tries, so drop through and mark partition bad. */
- }
- case GPT_UPDATE_ENTRY_BAD: {
- /* Giving up on this partition entirely. */
- if (!GetEntrySuccessful(e)) {
- /*
- * Only clear tries and priority if the successful bit
- * is not set.
- */
- modified = 1;
- SetEntryTries(e, 0);
- SetEntryPriority(e, 0);
- }
- break;
- }
- case GPT_UPDATE_ENTRY_ACTIVE: {
- /*
- * Used for fastboot mode. If kernel partition slot is marked
- * active, its GPT entry is marked with S1,P2,T0.
- */
- modified = 1;
- SetEntryTries(e, 0);
- SetEntryPriority(e, 2);
- SetEntrySuccessful(e, 1);
- break;
- }
- case GPT_UPDATE_ENTRY_INVALID: {
- /*
- * Used for fastboot mode. If kernel partition slot is marked
- * invalid, its GPT entry is marked with S0,P0,T0
- */
- modified = 1;
- SetEntryTries(e, 0);
- SetEntryPriority(e, 0);
- SetEntrySuccessful(e, 0);
- break;
- }
- default:
- return GPT_ERROR_INVALID_UPDATE_TYPE;
- }
- if (modified) {
- GptModified(gpt);
- }
- return GPT_SUCCESS;
- }
- /*
- * Func: GptUpdateKernelEntry
- * Desc: This function updates current_kernel entry with provided
- * update_type. If current_kernel is not set, then it returns error.
- */
- int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type)
- {
- GptEntry *entries = (GptEntry *)gpt->primary_entries;
- GptEntry *e = entries + gpt->current_kernel;
- if (gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND)
- return GPT_ERROR_INVALID_UPDATE_TYPE;
- return GptUpdateKernelWithEntry(gpt, e, update_type);
- }
- /*
- * Func: GptFindNthEntry
- * Desc: This function returns the nth instance of parition entry matching the
- * partition type guid from the gpt table. Instance value starts from 0. If the
- * entry is not found it returns NULL.
- */
- GptEntry *GptFindNthEntry(GptData *gpt, const Guid *guid, unsigned int n)
- {
- GptHeader *header = (GptHeader *)gpt->primary_header;
- GptEntry *entries = (GptEntry *)gpt->primary_entries;
- GptEntry *e;
- int i;
- for (i = 0, e = entries; i < header->number_of_entries; i++, e++) {
- if (!memcmp(&e->type, guid, sizeof(*guid))) {
- if (n == 0)
- return e;
- n--;
- }
- }
- return NULL;
- }
|