mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
This is part 3 of the vboot wrapper API refactoring. It replaces the function calls to utility.c functions with new API calls. (It also fixes up some integer type mismatches in cryptolib that were causing warnings on the H2C build; those had been fixed a while ago in H2C but hadn't been propagated across.) This is a re-commit of the original; I've verified it compiles on both x86-alex and tegra2, for both vboot_reference and vboot_reference-firmware, now that the patch from1c1a883bc7is checked in. BUG=chromium-os:17006 TEST=make && make runtests, and emerged on both x86-alex and tegra2 Original-Change-Id: I771085dcdf79d9592de64f35e3b758111a80dd9f Original-Reviewed-on: http://gerrit.chromium.org/gerrit/3263 Original-Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org> (cherry picked from commitbd81b3a7d3) Change-Id: Iefdbfb3d10eb9aa385fb6dfc3bf0896f637cb64b Reviewed-on: http://gerrit.chromium.org/gerrit/3582 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org>
160 lines
5.2 KiB
C
160 lines
5.2 KiB
C
/* Copyright (c) 2011 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 "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) {
|
|
VBDEBUG(("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 prioity, 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;
|
|
VBDEBUG(("GptNextKernelEntry looking at same prio partition %d\n", i));
|
|
VBDEBUG(("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;
|
|
VBDEBUG(("GptNextKernelEntry likes that one\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;
|
|
VBDEBUG(("GptNextKernelEntry looking at new prio partition %d\n", i));
|
|
VBDEBUG(("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)
|
|
continue; /* Already returned this kernel in a previous call */
|
|
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) {
|
|
VBDEBUG(("GptNextKernelEntry no more kernels\n"));
|
|
return GPT_ERROR_NO_VALID_KERNEL;
|
|
}
|
|
|
|
VBDEBUG(("GptNextKernelEntry likes that one\n"));
|
|
e = entries + new_kernel;
|
|
*start_sector = e->starting_lba;
|
|
*size = e->ending_lba - e->starting_lba + 1;
|
|
return GPT_SUCCESS;
|
|
}
|
|
|
|
|
|
int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type) {
|
|
GptHeader* header = (GptHeader*)gpt->primary_header;
|
|
GptEntry* entries = (GptEntry*)gpt->primary_entries;
|
|
GptEntry* e = entries + gpt->current_kernel;
|
|
uint16_t previous_attr = e->attrs.fields.gpt_att;
|
|
|
|
if (gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND)
|
|
return GPT_ERROR_INVALID_UPDATE_TYPE;
|
|
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))
|
|
return GPT_SUCCESS; /* Successfully booted this partition, so
|
|
* tries field is ignored. */
|
|
tries = GetEntryTries(e);
|
|
if (tries > 1) {
|
|
/* Still have tries left */
|
|
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. */
|
|
e->attrs.fields.gpt_att = previous_attr & ~(
|
|
CGPT_ATTRIBUTE_TRIES_MASK |
|
|
CGPT_ATTRIBUTE_PRIORITY_MASK);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return GPT_ERROR_INVALID_UPDATE_TYPE;
|
|
}
|
|
|
|
/* If no change to attributes, we're done */
|
|
if (e->attrs.fields.gpt_att == previous_attr)
|
|
return GPT_SUCCESS;
|
|
|
|
/* Update the CRCs */
|
|
header->entries_crc32 = Crc32((const uint8_t *)entries,
|
|
header->size_of_entry *
|
|
header->number_of_entries);
|
|
header->header_crc32 = HeaderCrc(header);
|
|
gpt->modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
|
|
|
|
/* Use the repair function to update the other copy of the GPT.
|
|
* This is a tad inefficient, but is much faster than the disk I/O
|
|
* to update the GPT on disk so it doesn't matter. */
|
|
gpt->valid_headers = MASK_PRIMARY;
|
|
gpt->valid_entries = MASK_PRIMARY;
|
|
GptRepair(gpt);
|
|
|
|
return GPT_SUCCESS;
|
|
}
|