mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
Reformat cgptlib to kernel style
No code changes, just reformatting. BUG=none BRANCH=none TEST=make runtests Change-Id: Ib8748df93c64395c88e1f789805393fcfe3ac419 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/42397 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
committed by
ChromeBot
parent
7993f257af
commit
cefe12c105
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
/* 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
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "vboot_api.h"
|
#include "vboot_api.h"
|
||||||
|
|
||||||
int GptInit(GptData *gpt) {
|
int GptInit(GptData *gpt)
|
||||||
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
gpt->modified = 0;
|
gpt->modified = 0;
|
||||||
@@ -27,60 +28,73 @@ int GptInit(GptData *gpt) {
|
|||||||
return GPT_SUCCESS;
|
return GPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
|
||||||
int GptNextKernelEntry(GptData* gpt, uint64_t* start_sector, uint64_t* size) {
|
{
|
||||||
GptHeader* header = (GptHeader*)gpt->primary_header;
|
GptHeader *header = (GptHeader *)gpt->primary_header;
|
||||||
GptEntry* entries = (GptEntry*)gpt->primary_entries;
|
GptEntry *entries = (GptEntry *)gpt->primary_entries;
|
||||||
GptEntry* e;
|
GptEntry *e;
|
||||||
int new_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
|
int new_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
|
||||||
int new_prio = 0;
|
int new_prio = 0;
|
||||||
uint32_t i;
|
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
|
* If we already found a kernel, continue the scan at the current
|
||||||
* priority. */
|
* kernel's priority, in case there is another kernel with the same
|
||||||
|
* priority.
|
||||||
|
*/
|
||||||
if (gpt->current_kernel != CGPT_KERNEL_ENTRY_NOT_FOUND) {
|
if (gpt->current_kernel != CGPT_KERNEL_ENTRY_NOT_FOUND) {
|
||||||
for (i = gpt->current_kernel + 1; i < header->number_of_entries; i++) {
|
for (i = gpt->current_kernel + 1;
|
||||||
|
i < header->number_of_entries; i++) {
|
||||||
e = entries + i;
|
e = entries + i;
|
||||||
if (!IsKernelEntry(e))
|
if (!IsKernelEntry(e))
|
||||||
continue;
|
continue;
|
||||||
VBDEBUG(("GptNextKernelEntry looking at same prio partition %d\n", i+1));
|
VBDEBUG(("GptNextKernelEntry looking at same prio "
|
||||||
|
"partition %d\n", i+1));
|
||||||
VBDEBUG(("GptNextKernelEntry s%d t%d p%d\n",
|
VBDEBUG(("GptNextKernelEntry s%d t%d p%d\n",
|
||||||
GetEntrySuccessful(e), GetEntryTries(e), GetEntryPriority(e)));
|
GetEntrySuccessful(e), GetEntryTries(e),
|
||||||
|
GetEntryPriority(e)));
|
||||||
if (!(GetEntrySuccessful(e) || GetEntryTries(e)))
|
if (!(GetEntrySuccessful(e) || GetEntryTries(e)))
|
||||||
continue;
|
continue;
|
||||||
if (GetEntryPriority(e) == gpt->current_priority) {
|
if (GetEntryPriority(e) == gpt->current_priority) {
|
||||||
gpt->current_kernel = i;
|
gpt->current_kernel = i;
|
||||||
*start_sector = e->starting_lba;
|
*start_sector = e->starting_lba;
|
||||||
*size = e->ending_lba - e->starting_lba + 1;
|
*size = e->ending_lba - e->starting_lba + 1;
|
||||||
VBDEBUG(("GptNextKernelEntry likes that one\n"));
|
VBDEBUG(("GptNextKernelEntry likes it\n"));
|
||||||
return GPT_SUCCESS;
|
return GPT_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're still here, so scan for the remaining kernel with the
|
/*
|
||||||
* highest priority less than the previous attempt. */
|
* 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++) {
|
for (i = 0, e = entries; i < header->number_of_entries; i++, e++) {
|
||||||
int current_prio = GetEntryPriority(e);
|
int current_prio = GetEntryPriority(e);
|
||||||
if (!IsKernelEntry(e))
|
if (!IsKernelEntry(e))
|
||||||
continue;
|
continue;
|
||||||
VBDEBUG(("GptNextKernelEntry looking at new prio partition %d\n", i+1));
|
VBDEBUG(("GptNextKernelEntry looking at new prio "
|
||||||
|
"partition %d\n", i+1));
|
||||||
VBDEBUG(("GptNextKernelEntry s%d t%d p%d\n",
|
VBDEBUG(("GptNextKernelEntry s%d t%d p%d\n",
|
||||||
GetEntrySuccessful(e), GetEntryTries(e), GetEntryPriority(e)));
|
GetEntrySuccessful(e), GetEntryTries(e),
|
||||||
|
GetEntryPriority(e)));
|
||||||
if (!(GetEntrySuccessful(e) || GetEntryTries(e)))
|
if (!(GetEntrySuccessful(e) || GetEntryTries(e)))
|
||||||
continue;
|
continue;
|
||||||
if (current_prio >= gpt->current_priority)
|
if (current_prio >= gpt->current_priority) {
|
||||||
continue; /* Already returned this kernel in a previous call */
|
/* Already returned this kernel in a previous call */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (current_prio > new_prio) {
|
if (current_prio > new_prio) {
|
||||||
new_kernel = i;
|
new_kernel = i;
|
||||||
new_prio = current_prio;
|
new_prio = current_prio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save what we found. Note that if we didn't find a new kernel,
|
/*
|
||||||
|
* 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
|
* new_prio will still be -1, so future calls to this function will
|
||||||
* also fail. */
|
* also fail.
|
||||||
|
*/
|
||||||
gpt->current_kernel = new_kernel;
|
gpt->current_kernel = new_kernel;
|
||||||
gpt->current_priority = new_prio;
|
gpt->current_priority = new_prio;
|
||||||
|
|
||||||
@@ -89,18 +103,18 @@ int GptNextKernelEntry(GptData* gpt, uint64_t* start_sector, uint64_t* size) {
|
|||||||
return GPT_ERROR_NO_VALID_KERNEL;
|
return GPT_ERROR_NO_VALID_KERNEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VBDEBUG(("GptNextKernelEntry likes partition %d\n", new_kernel+1));
|
VBDEBUG(("GptNextKernelEntry likes partition %d\n", new_kernel + 1));
|
||||||
e = entries + new_kernel;
|
e = entries + new_kernel;
|
||||||
*start_sector = e->starting_lba;
|
*start_sector = e->starting_lba;
|
||||||
*size = e->ending_lba - e->starting_lba + 1;
|
*size = e->ending_lba - e->starting_lba + 1;
|
||||||
return GPT_SUCCESS;
|
return GPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type)
|
||||||
int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type) {
|
{
|
||||||
GptHeader* header = (GptHeader*)gpt->primary_header;
|
GptHeader *header = (GptHeader *)gpt->primary_header;
|
||||||
GptEntry* entries = (GptEntry*)gpt->primary_entries;
|
GptEntry *entries = (GptEntry *)gpt->primary_entries;
|
||||||
GptEntry* e = entries + gpt->current_kernel;
|
GptEntry *e = entries + gpt->current_kernel;
|
||||||
uint16_t previous_attr = e->attrs.fields.gpt_att;
|
uint16_t previous_attr = e->attrs.fields.gpt_att;
|
||||||
|
|
||||||
if (gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND)
|
if (gpt->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND)
|
||||||
@@ -112,9 +126,13 @@ int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type) {
|
|||||||
case GPT_UPDATE_ENTRY_TRY: {
|
case GPT_UPDATE_ENTRY_TRY: {
|
||||||
/* Used up a try */
|
/* Used up a try */
|
||||||
int tries;
|
int tries;
|
||||||
if (GetEntrySuccessful(e))
|
if (GetEntrySuccessful(e)) {
|
||||||
return GPT_SUCCESS; /* Successfully booted this partition, so
|
/*
|
||||||
* tries field is ignored. */
|
* Successfully booted this partition, so tries field
|
||||||
|
* is ignored.
|
||||||
|
*/
|
||||||
|
return GPT_SUCCESS;
|
||||||
|
}
|
||||||
tries = GetEntryTries(e);
|
tries = GetEntryTries(e);
|
||||||
if (tries > 1) {
|
if (tries > 1) {
|
||||||
/* Still have tries left */
|
/* Still have tries left */
|
||||||
@@ -126,9 +144,12 @@ int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type) {
|
|||||||
case GPT_UPDATE_ENTRY_BAD: {
|
case GPT_UPDATE_ENTRY_BAD: {
|
||||||
/* Giving up on this partition entirely. */
|
/* Giving up on this partition entirely. */
|
||||||
if (!GetEntrySuccessful(e)) {
|
if (!GetEntrySuccessful(e)) {
|
||||||
/* Only clear tries and priority if the successful bit is not set. */
|
/*
|
||||||
e->attrs.fields.gpt_att = previous_attr & ~(
|
* Only clear tries and priority if the successful bit
|
||||||
CGPT_ATTRIBUTE_TRIES_MASK |
|
* is not set.
|
||||||
|
*/
|
||||||
|
e->attrs.fields.gpt_att = previous_attr &
|
||||||
|
~(CGPT_ATTRIBUTE_TRIES_MASK |
|
||||||
CGPT_ATTRIBUTE_PRIORITY_MASK);
|
CGPT_ATTRIBUTE_PRIORITY_MASK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -148,9 +169,11 @@ int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type) {
|
|||||||
header->header_crc32 = HeaderCrc(header);
|
header->header_crc32 = HeaderCrc(header);
|
||||||
gpt->modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
|
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
|
* Use the repair function to update the other copy of the GPT. This
|
||||||
* to update the GPT on disk so it doesn't matter. */
|
* 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_headers = MASK_PRIMARY;
|
||||||
gpt->valid_entries = MASK_PRIMARY;
|
gpt->valid_entries = MASK_PRIMARY;
|
||||||
GptRepair(gpt);
|
GptRepair(gpt);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
/* 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
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@@ -10,23 +10,25 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
|
||||||
int CheckParameters(GptData *gpt) {
|
int CheckParameters(GptData *gpt)
|
||||||
/* Currently, we only support 512-byte sector. In the future, we may support
|
{
|
||||||
* larger sector. */
|
/* Currently, we only support 512-byte sectors. */
|
||||||
if (gpt->sector_bytes != 512)
|
if (gpt->sector_bytes != 512)
|
||||||
return GPT_ERROR_INVALID_SECTOR_SIZE;
|
return GPT_ERROR_INVALID_SECTOR_SIZE;
|
||||||
|
|
||||||
/* The sector number of a drive should be reasonable. If the given value is
|
/*
|
||||||
|
* Sector count of a drive should be reasonable. If the given value is
|
||||||
* too small to contain basic GPT structure (PMBR + Headers + Entries),
|
* too small to contain basic GPT structure (PMBR + Headers + Entries),
|
||||||
* the value is wrong. */
|
* the value is wrong.
|
||||||
|
*/
|
||||||
if (gpt->drive_sectors < (1 + 2 * (1 + GPT_ENTRIES_SECTORS)))
|
if (gpt->drive_sectors < (1 + 2 * (1 + GPT_ENTRIES_SECTORS)))
|
||||||
return GPT_ERROR_INVALID_SECTOR_NUMBER;
|
return GPT_ERROR_INVALID_SECTOR_NUMBER;
|
||||||
|
|
||||||
return GPT_SUCCESS;
|
return GPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t HeaderCrc(GptHeader *h)
|
||||||
uint32_t HeaderCrc(GptHeader* h) {
|
{
|
||||||
uint32_t crc32, original_crc32;
|
uint32_t crc32, original_crc32;
|
||||||
|
|
||||||
/* Original CRC is calculated with the CRC field 0. */
|
/* Original CRC is calculated with the CRC field 0. */
|
||||||
@@ -38,15 +40,19 @@ uint32_t HeaderCrc(GptHeader* h) {
|
|||||||
return crc32;
|
return crc32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors)
|
||||||
int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors) {
|
{
|
||||||
if (!h)
|
if (!h)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Make sure we're looking at a header of reasonable size before
|
/*
|
||||||
* attempting to calculate CRC. */
|
* Make sure we're looking at a header of reasonable size before
|
||||||
if (Memcmp(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE) &&
|
* attempting to calculate CRC.
|
||||||
Memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE))
|
*/
|
||||||
|
if (Memcmp(h->signature, GPT_HEADER_SIGNATURE,
|
||||||
|
GPT_HEADER_SIGNATURE_SIZE) &&
|
||||||
|
Memcmp(h->signature, GPT_HEADER_SIGNATURE2,
|
||||||
|
GPT_HEADER_SIGNATURE_SIZE))
|
||||||
return 1;
|
return 1;
|
||||||
if (h->revision != GPT_HEADER_REVISION)
|
if (h->revision != GPT_HEADER_REVISION)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -63,8 +69,10 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors) {
|
|||||||
|
|
||||||
/* Could check that padding is zero, but that doesn't matter to us. */
|
/* Could check that padding is zero, but that doesn't matter to us. */
|
||||||
|
|
||||||
/* If entry size is different than our struct, we won't be able to
|
/*
|
||||||
* parse it. Technically, any size 2^N where N>=7 is valid. */
|
* If entry size is different than our struct, we won't be able to
|
||||||
|
* parse it. Technically, any size 2^N where N>=7 is valid.
|
||||||
|
*/
|
||||||
if (h->size_of_entry != sizeof(GptEntry))
|
if (h->size_of_entry != sizeof(GptEntry))
|
||||||
return 1;
|
return 1;
|
||||||
if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
|
if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
|
||||||
@@ -72,10 +80,11 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors) {
|
|||||||
(h->number_of_entries * h->size_of_entry != TOTAL_ENTRIES_SIZE))
|
(h->number_of_entries * h->size_of_entry != TOTAL_ENTRIES_SIZE))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Check locations for the header and its entries. The primary
|
/*
|
||||||
* immediately follows the PMBR, and is followed by its entries.
|
* Check locations for the header and its entries. The primary
|
||||||
* The secondary is at the end of the drive, preceded by its
|
* immediately follows the PMBR, and is followed by its entries. The
|
||||||
* entries. */
|
* secondary is at the end of the drive, preceded by its entries.
|
||||||
|
*/
|
||||||
if (is_secondary) {
|
if (is_secondary) {
|
||||||
if (h->my_lba != drive_sectors - 1)
|
if (h->my_lba != drive_sectors - 1)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -88,9 +97,11 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FirstUsableLBA must be after the end of the primary GPT table
|
/*
|
||||||
* array. LastUsableLBA must be before the start of the secondary
|
* FirstUsableLBA must be after the end of the primary GPT table array.
|
||||||
* GPT table array. FirstUsableLBA <= LastUsableLBA. */
|
* LastUsableLBA must be before the start of the secondary GPT table
|
||||||
|
* array. FirstUsableLBA <= LastUsableLBA.
|
||||||
|
*/
|
||||||
if (h->first_usable_lba < 2 + GPT_ENTRIES_SECTORS)
|
if (h->first_usable_lba < 2 + GPT_ENTRIES_SECTORS)
|
||||||
return 1;
|
return 1;
|
||||||
if (h->last_usable_lba >= drive_sectors - 1 - GPT_ENTRIES_SECTORS)
|
if (h->last_usable_lba >= drive_sectors - 1 - GPT_ENTRIES_SECTORS)
|
||||||
@@ -102,23 +113,21 @@ int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IsUnusedEntry(const GptEntry *e)
|
||||||
/* Return non-zero if the entry is unused, 0 if it is used. */
|
{
|
||||||
int IsUnusedEntry(const GptEntry* e) {
|
|
||||||
static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
|
static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
|
||||||
return !Memcmp(&zero, (const uint8_t*)(&e->type), sizeof(zero));
|
return !Memcmp(&zero, (const uint8_t*)(&e->type), sizeof(zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns non-zero if the entry is a Chrome OS kernel partition, else 0. */
|
int IsKernelEntry(const GptEntry *e)
|
||||||
int IsKernelEntry(const GptEntry* e) {
|
{
|
||||||
static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
|
static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
|
||||||
return !Memcmp(&e->type, &chromeos_kernel, sizeof(Guid));
|
return !Memcmp(&e->type, &chromeos_kernel, sizeof(Guid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CheckEntries(GptEntry *entries, GptHeader *h)
|
||||||
int CheckEntries(GptEntry* entries, GptHeader* h) {
|
{
|
||||||
|
GptEntry *entry;
|
||||||
GptEntry* entry;
|
|
||||||
uint32_t crc32;
|
uint32_t crc32;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
@@ -130,7 +139,7 @@ int CheckEntries(GptEntry* entries, GptHeader* h) {
|
|||||||
|
|
||||||
/* Check all entries. */
|
/* Check all entries. */
|
||||||
for (i = 0, entry = entries; i < h->number_of_entries; i++, entry++) {
|
for (i = 0, entry = entries; i < h->number_of_entries; i++, entry++) {
|
||||||
GptEntry* e2;
|
GptEntry *e2;
|
||||||
uint32_t i2;
|
uint32_t i2;
|
||||||
|
|
||||||
if (IsUnusedEntry(entry))
|
if (IsUnusedEntry(entry))
|
||||||
@@ -143,7 +152,8 @@ int CheckEntries(GptEntry* entries, GptHeader* h) {
|
|||||||
return GPT_ERROR_OUT_OF_REGION;
|
return GPT_ERROR_OUT_OF_REGION;
|
||||||
|
|
||||||
/* Entry must not overlap other entries. */
|
/* Entry must not overlap other entries. */
|
||||||
for (i2 = 0, e2 = entries; i2 < h->number_of_entries; i2++, e2++) {
|
for (i2 = 0, e2 = entries; i2 < h->number_of_entries;
|
||||||
|
i2++, e2++) {
|
||||||
if (i2 == i || IsUnusedEntry(e2))
|
if (i2 == i || IsUnusedEntry(e2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -155,7 +165,8 @@ int CheckEntries(GptEntry* entries, GptHeader* h) {
|
|||||||
return GPT_ERROR_END_LBA_OVERLAP;
|
return GPT_ERROR_END_LBA_OVERLAP;
|
||||||
|
|
||||||
/* UniqueGuid field must be unique. */
|
/* UniqueGuid field must be unique. */
|
||||||
if (0 == Memcmp(&entry->unique, &e2->unique, sizeof(Guid)))
|
if (0 == Memcmp(&entry->unique, &e2->unique,
|
||||||
|
sizeof(Guid)))
|
||||||
return GPT_ERROR_DUP_GUID;
|
return GPT_ERROR_DUP_GUID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,15 +175,8 @@ int CheckEntries(GptEntry* entries, GptHeader* h) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HeaderFieldsSame(GptHeader *h1, GptHeader *h2)
|
||||||
/* Returns 0 if the GptHeaders are the same for all fields which don't
|
{
|
||||||
* differ between the primary and secondary headers - that is, all
|
|
||||||
* fields other than:
|
|
||||||
*
|
|
||||||
* my_lba
|
|
||||||
* alternate_lba
|
|
||||||
* entries_lba */
|
|
||||||
int HeaderFieldsSame(GptHeader *h1, GptHeader *h2) {
|
|
||||||
if (Memcmp(h1->signature, h2->signature, sizeof(h1->signature)))
|
if (Memcmp(h1->signature, h2->signature, sizeof(h1->signature)))
|
||||||
return 1;
|
return 1;
|
||||||
if (h1->revision != h2->revision)
|
if (h1->revision != h2->revision)
|
||||||
@@ -197,14 +201,14 @@ int HeaderFieldsSame(GptHeader *h1, GptHeader *h2) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GptSanityCheck(GptData *gpt)
|
||||||
int GptSanityCheck(GptData *gpt) {
|
{
|
||||||
int retval;
|
int retval;
|
||||||
GptHeader* header1 = (GptHeader*)(gpt->primary_header);
|
GptHeader *header1 = (GptHeader *)(gpt->primary_header);
|
||||||
GptHeader* header2 = (GptHeader*)(gpt->secondary_header);
|
GptHeader *header2 = (GptHeader *)(gpt->secondary_header);
|
||||||
GptEntry* entries1 = (GptEntry*)(gpt->primary_entries);
|
GptEntry *entries1 = (GptEntry *)(gpt->primary_entries);
|
||||||
GptEntry* entries2 = (GptEntry*)(gpt->secondary_entries);
|
GptEntry *entries2 = (GptEntry *)(gpt->secondary_entries);
|
||||||
GptHeader* goodhdr = NULL;
|
GptHeader *goodhdr = NULL;
|
||||||
|
|
||||||
gpt->valid_headers = 0;
|
gpt->valid_headers = 0;
|
||||||
gpt->valid_entries = 0;
|
gpt->valid_entries = 0;
|
||||||
@@ -227,26 +231,33 @@ int GptSanityCheck(GptData *gpt) {
|
|||||||
if (!gpt->valid_headers)
|
if (!gpt->valid_headers)
|
||||||
return GPT_ERROR_INVALID_HEADERS;
|
return GPT_ERROR_INVALID_HEADERS;
|
||||||
|
|
||||||
/* Checks if entries are valid.
|
/*
|
||||||
|
* Check if entries are valid.
|
||||||
*
|
*
|
||||||
* Note that we use the same header in both checks. This way we'll
|
* Note that we use the same header in both checks. This way we'll
|
||||||
* catch the case where (header1,entries1) and (header2,entries2)
|
* catch the case where (header1,entries1) and (header2,entries2) are
|
||||||
* are both valid, but (entries1 != entries2). */
|
* both valid, but (entries1 != entries2).
|
||||||
|
*/
|
||||||
if (0 == CheckEntries(entries1, goodhdr))
|
if (0 == CheckEntries(entries1, goodhdr))
|
||||||
gpt->valid_entries |= MASK_PRIMARY;
|
gpt->valid_entries |= MASK_PRIMARY;
|
||||||
if (0 == CheckEntries(entries2, goodhdr))
|
if (0 == CheckEntries(entries2, goodhdr))
|
||||||
gpt->valid_entries |= MASK_SECONDARY;
|
gpt->valid_entries |= MASK_SECONDARY;
|
||||||
|
|
||||||
/* If both headers are good but neither entries were good, check the
|
/*
|
||||||
* entries with the secondary header. */
|
* If both headers are good but neither entries were good, check the
|
||||||
|
* entries with the secondary header.
|
||||||
|
*/
|
||||||
if (MASK_BOTH == gpt->valid_headers && !gpt->valid_entries) {
|
if (MASK_BOTH == gpt->valid_headers && !gpt->valid_entries) {
|
||||||
if (0 == CheckEntries(entries1, header2))
|
if (0 == CheckEntries(entries1, header2))
|
||||||
gpt->valid_entries |= MASK_PRIMARY;
|
gpt->valid_entries |= MASK_PRIMARY;
|
||||||
if (0 == CheckEntries(entries2, header2))
|
if (0 == CheckEntries(entries2, header2))
|
||||||
gpt->valid_entries |= MASK_SECONDARY;
|
gpt->valid_entries |= MASK_SECONDARY;
|
||||||
if (gpt->valid_entries) {
|
if (gpt->valid_entries) {
|
||||||
/* Sure enough, header2 had a good CRC for one of the entries. Mark
|
/*
|
||||||
* header1 invalid, so we'll update its entries CRC. */
|
* Sure enough, header2 had a good CRC for one of the
|
||||||
|
* entries. Mark header1 invalid, so we'll update its
|
||||||
|
* entries CRC.
|
||||||
|
*/
|
||||||
gpt->valid_headers &= ~MASK_PRIMARY;
|
gpt->valid_headers &= ~MASK_PRIMARY;
|
||||||
goodhdr = header2;
|
goodhdr = header2;
|
||||||
}
|
}
|
||||||
@@ -255,8 +266,10 @@ int GptSanityCheck(GptData *gpt) {
|
|||||||
if (!gpt->valid_entries)
|
if (!gpt->valid_entries)
|
||||||
return GPT_ERROR_INVALID_ENTRIES;
|
return GPT_ERROR_INVALID_ENTRIES;
|
||||||
|
|
||||||
/* Now that we've determined which header contains a good CRC for
|
/*
|
||||||
* the entries, make sure the headers are otherwise identical. */
|
* Now that we've determined which header contains a good CRC for
|
||||||
|
* the entries, make sure the headers are otherwise identical.
|
||||||
|
*/
|
||||||
if (MASK_BOTH == gpt->valid_headers &&
|
if (MASK_BOTH == gpt->valid_headers &&
|
||||||
0 != HeaderFieldsSame(header1, header2))
|
0 != HeaderFieldsSame(header1, header2))
|
||||||
gpt->valid_headers &= ~MASK_SECONDARY;
|
gpt->valid_headers &= ~MASK_SECONDARY;
|
||||||
@@ -264,12 +277,12 @@ int GptSanityCheck(GptData *gpt) {
|
|||||||
return GPT_SUCCESS;
|
return GPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GptRepair(GptData *gpt)
|
||||||
void GptRepair(GptData *gpt) {
|
{
|
||||||
GptHeader* header1 = (GptHeader*)(gpt->primary_header);
|
GptHeader *header1 = (GptHeader *)(gpt->primary_header);
|
||||||
GptHeader* header2 = (GptHeader*)(gpt->secondary_header);
|
GptHeader *header2 = (GptHeader *)(gpt->secondary_header);
|
||||||
GptEntry* entries1 = (GptEntry*)(gpt->primary_entries);
|
GptEntry *entries1 = (GptEntry *)(gpt->primary_entries);
|
||||||
GptEntry* entries2 = (GptEntry*)(gpt->secondary_entries);
|
GptEntry *entries2 = (GptEntry *)(gpt->secondary_entries);
|
||||||
int entries_size;
|
int entries_size;
|
||||||
|
|
||||||
/* Need at least one good header and one good set of entries. */
|
/* Need at least one good header and one good set of entries. */
|
||||||
@@ -312,54 +325,55 @@ void GptRepair(GptData *gpt) {
|
|||||||
gpt->valid_entries = MASK_BOTH;
|
gpt->valid_entries = MASK_BOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetEntrySuccessful(const GptEntry *e)
|
||||||
int GetEntrySuccessful(const GptEntry* e) {
|
{
|
||||||
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
|
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
|
||||||
CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
|
CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetEntryPriority(const GptEntry *e)
|
||||||
int GetEntryPriority(const GptEntry* e) {
|
{
|
||||||
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
|
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
|
||||||
CGPT_ATTRIBUTE_PRIORITY_OFFSET;
|
CGPT_ATTRIBUTE_PRIORITY_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetEntryTries(const GptEntry *e)
|
||||||
int GetEntryTries(const GptEntry* e) {
|
{
|
||||||
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_TRIES_MASK) >>
|
return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_TRIES_MASK) >>
|
||||||
CGPT_ATTRIBUTE_TRIES_OFFSET;
|
CGPT_ATTRIBUTE_TRIES_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEntrySuccessful(GptEntry *e, int successful)
|
||||||
void SetEntrySuccessful(GptEntry* e, int successful) {
|
{
|
||||||
if (successful)
|
if (successful)
|
||||||
e->attrs.fields.gpt_att |= CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
|
e->attrs.fields.gpt_att |= CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
|
||||||
else
|
else
|
||||||
e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
|
e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEntryPriority(GptEntry *e, int priority)
|
||||||
void SetEntryPriority(GptEntry* e, int priority) {
|
{
|
||||||
e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
|
e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
|
||||||
e->attrs.fields.gpt_att |= (priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET) &
|
e->attrs.fields.gpt_att |=
|
||||||
|
(priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET) &
|
||||||
CGPT_ATTRIBUTE_PRIORITY_MASK;
|
CGPT_ATTRIBUTE_PRIORITY_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEntryTries(GptEntry *e, int tries)
|
||||||
void SetEntryTries(GptEntry* e, int tries) {
|
{
|
||||||
e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_TRIES_MASK;
|
e->attrs.fields.gpt_att &= ~CGPT_ATTRIBUTE_TRIES_MASK;
|
||||||
e->attrs.fields.gpt_att |= (tries << CGPT_ATTRIBUTE_TRIES_OFFSET) &
|
e->attrs.fields.gpt_att |= (tries << CGPT_ATTRIBUTE_TRIES_OFFSET) &
|
||||||
CGPT_ATTRIBUTE_TRIES_MASK;
|
CGPT_ATTRIBUTE_TRIES_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest) {
|
void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
|
||||||
GptEntry* entries = (GptEntry*)gpt->primary_entries;
|
{
|
||||||
GptEntry* e = entries + gpt->current_kernel;
|
GptEntry *entries = (GptEntry *)gpt->primary_entries;
|
||||||
|
GptEntry *e = entries + gpt->current_kernel;
|
||||||
Memcpy(dest, &e->unique, sizeof(Guid));
|
Memcpy(dest, &e->unique, sizeof(Guid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *GptErrorText(int error_code)
|
||||||
const char* GptErrorText(int error_code)
|
|
||||||
{
|
{
|
||||||
switch(error_code) {
|
switch(error_code) {
|
||||||
case GPT_SUCCESS:
|
case GPT_SUCCESS:
|
||||||
|
|||||||
@@ -96,9 +96,10 @@ static uint32_t crc32_tab[] = {
|
|||||||
0x2d02ef8dU
|
0x2d02ef8dU
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns a 32-bit CRC of the contents of the buffer. */
|
|
||||||
uint32_t Crc32(const void *buffer, uint32_t len) {
|
uint32_t Crc32(const void *buffer, uint32_t len)
|
||||||
uint8_t *byte = (uint8_t*)buffer;
|
{
|
||||||
|
uint8_t *byte = (uint8_t *)buffer;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t value = ~0U;
|
uint32_t value = ~0U;
|
||||||
|
|
||||||
|
|||||||
@@ -31,56 +31,64 @@ enum {
|
|||||||
#define GPT_MODIFIED_ENTRIES1 0x04
|
#define GPT_MODIFIED_ENTRIES1 0x04
|
||||||
#define GPT_MODIFIED_ENTRIES2 0x08
|
#define GPT_MODIFIED_ENTRIES2 0x08
|
||||||
|
|
||||||
#define TOTAL_ENTRIES_SIZE 16384 /* Size of GptData.primary_entries
|
/*
|
||||||
* and secondary_entries: 128
|
* Size of GptData.primary_entries and secondary_entries: 128 bytes/entry * 128
|
||||||
* bytes/entry * 128 entries. */
|
* entries.
|
||||||
|
*/
|
||||||
|
#define TOTAL_ENTRIES_SIZE 16384
|
||||||
|
|
||||||
/* The 'update_type' of GptUpdateKernelEntry()
|
/*
|
||||||
* We expose TRY and BAD only because those are what verified boot needs.
|
* The 'update_type' of GptUpdateKernelEntry(). We expose TRY and BAD only
|
||||||
* For more precise control on GPT attribute bits, please refer to
|
* because those are what verified boot needs. For more precise control on GPT
|
||||||
* gpt_internal.h */
|
* attribute bits, please refer to gpt_internal.h.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
|
/*
|
||||||
|
* System will be trying to boot the currently selected kernel
|
||||||
|
* partition. Update its try count if necessary.
|
||||||
|
*/
|
||||||
GPT_UPDATE_ENTRY_TRY = 1,
|
GPT_UPDATE_ENTRY_TRY = 1,
|
||||||
/* System will be trying to boot the currently selected kernel partition.
|
/*
|
||||||
* Update its try count if necessary. */
|
* The currently selected kernel partition failed validation. Mark
|
||||||
|
* entry as invalid.
|
||||||
|
*/
|
||||||
GPT_UPDATE_ENTRY_BAD = 2,
|
GPT_UPDATE_ENTRY_BAD = 2,
|
||||||
/* The currently selected kernel partition failed validation. Mark entry as
|
|
||||||
* invalid. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Fill in the following fields before calling GptInit() */
|
/* Fill in the following fields before calling GptInit() */
|
||||||
uint8_t *primary_header; /* GPT primary header, from sector 1 of disk
|
/* GPT primary header, from sector 1 of disk (size: 512 bytes) */
|
||||||
* (size: 512 bytes) */
|
uint8_t *primary_header;
|
||||||
uint8_t *secondary_header; /* GPT secondary header, from last sector of
|
/* GPT secondary header, from last sector of disk (size: 512 bytes) */
|
||||||
* disk (size: 512 bytes) */
|
uint8_t *secondary_header;
|
||||||
uint8_t *primary_entries; /* primary GPT table, follows primary header
|
/* Primary GPT table, follows primary header (size: 16 KB) */
|
||||||
* (size: 16 KB) */
|
uint8_t *primary_entries;
|
||||||
uint8_t *secondary_entries; /* secondary GPT table, precedes secondary
|
/* Secondary GPT table, precedes secondary header (size: 16 KB) */
|
||||||
* header (size: 16 KB) */
|
uint8_t *secondary_entries;
|
||||||
uint32_t sector_bytes; /* Size of a LBA sector, in bytes */
|
/* Size of a LBA sector, in bytes */
|
||||||
uint64_t drive_sectors; /* Size of drive in LBA sectors, in sectors */
|
uint32_t sector_bytes;
|
||||||
|
/* Size of drive in LBA sectors, in sectors */
|
||||||
|
uint64_t drive_sectors;
|
||||||
|
|
||||||
/* Outputs */
|
/* Outputs */
|
||||||
uint8_t modified; /* Which inputs have been modified?
|
/* Which inputs have been modified? GPT_MODIFIED_* */
|
||||||
* 0x01 = header1
|
uint8_t modified;
|
||||||
* 0x02 = header2
|
/*
|
||||||
* 0x04 = table1
|
* The current chromeos kernel index in partition table. -1 means not
|
||||||
* 0x08 = table2 */
|
* found on drive. Note that GPT partition numbers are traditionally
|
||||||
int current_kernel; /* the current chromeos kernel index in partition table.
|
* 1-based, but we're using a zero-based index here.
|
||||||
* -1 means not found on drive. Note that GPT partition
|
|
||||||
* numbers are traditionally 1-based, but we're using
|
|
||||||
* a zero-based index here.
|
|
||||||
*/
|
*/
|
||||||
|
int current_kernel;
|
||||||
|
|
||||||
/* Internal variables */
|
/* Internal variables */
|
||||||
uint32_t valid_headers, valid_entries;
|
uint32_t valid_headers, valid_entries;
|
||||||
int current_priority;
|
int current_priority;
|
||||||
} GptData;
|
} GptData;
|
||||||
|
|
||||||
int GptInit(GptData* gpt);
|
/**
|
||||||
/* Initializes the GPT data structure's internal state. The following fields
|
* Initializes the GPT data structure's internal state.
|
||||||
* must be filled before calling this function:
|
*
|
||||||
|
* The following fields must be filled before calling this function:
|
||||||
*
|
*
|
||||||
* primary_header
|
* primary_header
|
||||||
* secondary_header
|
* secondary_header
|
||||||
@@ -100,19 +108,23 @@ int GptInit(GptData* gpt);
|
|||||||
* GPT_ERROR_INVALID_SECTOR_SIZE, size of a sector is not supported,
|
* GPT_ERROR_INVALID_SECTOR_SIZE, size of a sector is not supported,
|
||||||
* GPT_ERROR_INVALID_SECTOR_NUMBER, number of sectors in drive is invalid (too
|
* GPT_ERROR_INVALID_SECTOR_NUMBER, number of sectors in drive is invalid (too
|
||||||
* small) */
|
* small) */
|
||||||
|
int GptInit(GptData *gpt);
|
||||||
|
|
||||||
int GptNextKernelEntry(GptData* gpt, uint64_t* start_sector, uint64_t* size);
|
/**
|
||||||
/* Provides the location of the next kernel partition, in order of decreasing
|
* Provides the location of the next kernel partition, in order of decreasing
|
||||||
* priority. On return the start_sector parameter contains the LBA sector
|
* priority.
|
||||||
* for the start of the kernel partition, and the size parameter contains the
|
*
|
||||||
* size of the kernel partition in LBA sectors. gpt.current_kernel contains
|
* On return the start_sector parameter contains the LBA sector for the start
|
||||||
* the partition index of the current chromeos kernel partition.
|
* of the kernel partition, and the size parameter contains the size of the
|
||||||
|
* kernel partition in LBA sectors. gpt.current_kernel contains the partition
|
||||||
|
* index of the current chromeos kernel partition.
|
||||||
*
|
*
|
||||||
* Returns GPT_SUCCESS if successful, else
|
* Returns GPT_SUCCESS if successful, else
|
||||||
* GPT_ERROR_NO_VALID_KERNEL, no avaliable kernel, enters recovery mode */
|
* GPT_ERROR_NO_VALID_KERNEL, no avaliable kernel, enters recovery mode */
|
||||||
|
int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size);
|
||||||
|
|
||||||
int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type);
|
/**
|
||||||
/* Updates the kernel entry with the specified index, using the specified type
|
* Updates the kernel entry with the specified index, using the specified type
|
||||||
* of update (GPT_UPDATE_ENTRY_*).
|
* of update (GPT_UPDATE_ENTRY_*).
|
||||||
*
|
*
|
||||||
* On return the modified field may be set, if the GPT data has been modified
|
* On return the modified field may be set, if the GPT data has been modified
|
||||||
@@ -121,5 +133,6 @@ int GptUpdateKernelEntry(GptData* gpt, uint32_t update_type);
|
|||||||
* Returns GPT_SUCCESS if successful, else
|
* Returns GPT_SUCCESS if successful, else
|
||||||
* GPT_ERROR_INVALID_UPDATE_TYPE, invalid 'update_type' is given.
|
* GPT_ERROR_INVALID_UPDATE_TYPE, invalid 'update_type' is given.
|
||||||
*/
|
*/
|
||||||
|
int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type);
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_CGPTLIB_H_ */
|
#endif /* VBOOT_REFERENCE_CGPTLIB_H_ */
|
||||||
|
|||||||
@@ -10,13 +10,15 @@
|
|||||||
#include "cgptlib.h"
|
#include "cgptlib.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
|
|
||||||
/* If gpt->current_kernel is this value, means either:
|
/*
|
||||||
|
* If gpt->current_kernel is this value, means either:
|
||||||
* 1. an initial value before scanning GPT entries,
|
* 1. an initial value before scanning GPT entries,
|
||||||
* 2. after scanning, no any valid kernel is found.
|
* 2. after scanning, no any valid kernel is found.
|
||||||
*/
|
*/
|
||||||
#define CGPT_KERNEL_ENTRY_NOT_FOUND (-1)
|
#define CGPT_KERNEL_ENTRY_NOT_FOUND (-1)
|
||||||
|
|
||||||
/* Bit definitions and masks for GPT attributes.
|
/*
|
||||||
|
* Bit definitions and masks for GPT attributes.
|
||||||
*
|
*
|
||||||
* 63-61 -- (reserved)
|
* 63-61 -- (reserved)
|
||||||
* 60 -- read-only
|
* 60 -- read-only
|
||||||
@@ -55,11 +57,16 @@
|
|||||||
/* Defines GPT sizes */
|
/* Defines GPT sizes */
|
||||||
#define GPT_PMBR_SECTOR 1 /* size (in sectors) of PMBR */
|
#define GPT_PMBR_SECTOR 1 /* size (in sectors) of PMBR */
|
||||||
#define GPT_HEADER_SECTOR 1
|
#define GPT_HEADER_SECTOR 1
|
||||||
#define GPT_ENTRIES_SECTORS 32 /* assume sector size if 512 bytes, then
|
/*
|
||||||
* (TOTAL_ENTRIES_SIZE / 512) = 32 */
|
* Entries sectors assumes sector size if 512 bytes; then (TOTAL_ENTRIES_SIZE /
|
||||||
|
* 512) = 32
|
||||||
|
*/
|
||||||
|
#define GPT_ENTRIES_SECTORS 32
|
||||||
|
|
||||||
/* alias name of index in internal array for primary and secondary header and
|
/*
|
||||||
* entries. */
|
* Alias name of index in internal array for primary and secondary header and
|
||||||
|
* entries.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
/* constants for index */
|
/* constants for index */
|
||||||
PRIMARY = 0,
|
PRIMARY = 0,
|
||||||
@@ -73,62 +80,84 @@ enum {
|
|||||||
MASK_BOTH = 3,
|
MASK_BOTH = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Verify GptData parameters are sane. */
|
/**
|
||||||
|
* Verify GptData parameters are sane.
|
||||||
|
*/
|
||||||
int CheckParameters(GptData* gpt);
|
int CheckParameters(GptData* gpt);
|
||||||
|
|
||||||
/* Check header fields.
|
/**
|
||||||
|
* Check header fields.
|
||||||
*
|
*
|
||||||
* Returns 0 if header is valid, 1 if invalid. */
|
* Returns 0 if header is valid, 1 if invalid.
|
||||||
int CheckHeader(GptHeader* h, int is_secondary, uint64_t drive_sectors);
|
*/
|
||||||
|
int CheckHeader(GptHeader *h, int is_secondary, uint64_t drive_sectors);
|
||||||
|
|
||||||
/* Calculate and return the header CRC. */
|
/**
|
||||||
uint32_t HeaderCrc(GptHeader* h);
|
* Calculate and return the header CRC.
|
||||||
|
*/
|
||||||
|
uint32_t HeaderCrc(GptHeader *h);
|
||||||
|
|
||||||
/* Check entries.
|
/**
|
||||||
|
* Check entries.
|
||||||
*
|
*
|
||||||
* Returns 0 if entries are valid, 1 if invalid. */
|
* Returns 0 if entries are valid, 1 if invalid.
|
||||||
int CheckEntries(GptEntry* entries, GptHeader* h);
|
*/
|
||||||
|
int CheckEntries(GptEntry *entries, GptHeader *h);
|
||||||
|
|
||||||
/* Return 0 if the GptHeaders are the same for all fields which don't
|
/**
|
||||||
* differ between the primary and secondary headers - that is, all
|
* Return 0 if the GptHeaders are the same for all fields which don't differ
|
||||||
* fields other than:
|
* between the primary and secondary headers - that is, all fields other than:
|
||||||
*
|
*
|
||||||
* my_lba
|
* my_lba
|
||||||
* alternate_lba
|
* alternate_lba
|
||||||
* entries_lba */
|
* entries_lba
|
||||||
|
*/
|
||||||
int HeaderFieldsSame(GptHeader *h1, GptHeader *h2);
|
int HeaderFieldsSame(GptHeader *h1, GptHeader *h2);
|
||||||
|
|
||||||
/* Check GptData, headers, entries.
|
/**
|
||||||
|
* Check GptData, headers, entries.
|
||||||
*
|
*
|
||||||
* If successful, sets gpt->valid_headers and gpt->valid_entries and returns
|
* If successful, sets gpt->valid_headers and gpt->valid_entries and returns
|
||||||
* GPT_SUCCESS.
|
* GPT_SUCCESS.
|
||||||
*
|
*
|
||||||
* On error, returns a GPT_ERROR_* return code. */
|
* On error, returns a GPT_ERROR_* return code.
|
||||||
int GptSanityCheck(GptData* gpt);
|
*/
|
||||||
|
int GptSanityCheck(GptData *gpt);
|
||||||
|
|
||||||
/* Repairs GPT data by copying from one set of valid headers/entries to the
|
/**
|
||||||
|
* Repair GPT data by copying from one set of valid headers/entries to the
|
||||||
* other. Assumes GptSanityCheck() has been run to determine which headers
|
* other. Assumes GptSanityCheck() has been run to determine which headers
|
||||||
* and/or entries are already valid. */
|
* and/or entries are already valid.
|
||||||
void GptRepair(GptData* gpt);
|
*/
|
||||||
|
void GptRepair(GptData *gpt);
|
||||||
|
|
||||||
/* Getters and setters for partition attribute fields. */
|
/* Getters and setters for partition attribute fields. */
|
||||||
int GetEntrySuccessful(const GptEntry* e);
|
|
||||||
int GetEntryPriority(const GptEntry* e);
|
|
||||||
int GetEntryTries(const GptEntry* e);
|
|
||||||
void SetEntrySuccessful(GptEntry* e, int successful);
|
|
||||||
void SetEntryPriority(GptEntry* e, int priority);
|
|
||||||
void SetEntryTries(GptEntry* e, int tries);
|
|
||||||
|
|
||||||
/* Return 1 if the entry is unused, 0 if it is used. */
|
int GetEntrySuccessful(const GptEntry *e);
|
||||||
int IsUnusedEntry(const GptEntry* e);
|
int GetEntryPriority(const GptEntry *e);
|
||||||
|
int GetEntryTries(const GptEntry *e);
|
||||||
|
void SetEntrySuccessful(GptEntry *e, int successful);
|
||||||
|
void SetEntryPriority(GptEntry *e, int priority);
|
||||||
|
void SetEntryTries(GptEntry *e, int tries);
|
||||||
|
|
||||||
/* Returns 1 if the entry is a Chrome OS kernel partition, else 0. */
|
/**
|
||||||
int IsKernelEntry(const GptEntry* e);
|
* Return 1 if the entry is unused, 0 if it is used.
|
||||||
|
*/
|
||||||
|
int IsUnusedEntry(const GptEntry *e);
|
||||||
|
|
||||||
/* Copies the current kernel partition's UniquePartitionGuid to the dest */
|
/**
|
||||||
|
* Return 1 if the entry is a Chrome OS kernel partition, else 0.
|
||||||
|
*/
|
||||||
|
int IsKernelEntry(const GptEntry *e);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the current kernel partition's UniquePartitionGuid to the dest.
|
||||||
|
*/
|
||||||
void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest);
|
void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest);
|
||||||
|
|
||||||
/* Returns a pointer to text describing the passed in error */
|
/**
|
||||||
const char* GptErrorText(int error_code);
|
* Return a pointer to text describing the passed in error.
|
||||||
|
*/
|
||||||
|
const char *GptErrorText(int error_code);
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_CGPTLIB_INTERNAL_H_ */
|
#endif /* VBOOT_REFERENCE_CGPTLIB_INTERNAL_H_ */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
|
/* 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
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*
|
*
|
||||||
@@ -19,14 +19,15 @@ __pragma(pack(push,1)) /* Support packing for MSVC. */
|
|||||||
#define GPT_HEADER_SIGNATURE_SIZE sizeof(GPT_HEADER_SIGNATURE)
|
#define GPT_HEADER_SIGNATURE_SIZE sizeof(GPT_HEADER_SIGNATURE)
|
||||||
#define GPT_HEADER_REVISION 0x00010000
|
#define GPT_HEADER_REVISION 0x00010000
|
||||||
|
|
||||||
/* The first 3 numbers should be stored in network-endian format
|
/*
|
||||||
* according to the GUID RFC. The UEFI spec appendix A claims they
|
* The first 3 numbers should be stored in network-endian format according to
|
||||||
* should be stored in little-endian format. But they need to be
|
* the GUID RFC. The UEFI spec appendix A claims they should be stored in
|
||||||
* _displayed_ in network-endian format, which is also how they're
|
* little-endian format. But they need to be _displayed_ in network-endian
|
||||||
* documented in the specs.
|
* format, which is also how they're documented in the specs.
|
||||||
*
|
*
|
||||||
* Since what we have here are little-endian constants, they're
|
* Since what we have here are little-endian constants, they're byte-swapped
|
||||||
* byte-swapped from the normal display order. */
|
* from the normal display order.
|
||||||
|
*/
|
||||||
#define GPT_ENT_TYPE_UNUSED \
|
#define GPT_ENT_TYPE_UNUSED \
|
||||||
{{{0x00000000,0x0000,0x0000,0x00,0x00,{0x00,0x00,0x00,0x00,0x00,0x00}}}}
|
{{{0x00000000,0x0000,0x0000,0x00,0x00,{0x00,0x00,0x00,0x00,0x00,0x00}}}}
|
||||||
#define GPT_ENT_TYPE_EFI \
|
#define GPT_ENT_TYPE_EFI \
|
||||||
@@ -42,13 +43,10 @@ __pragma(pack(push,1)) /* Support packing for MSVC. */
|
|||||||
#define GPT_ENT_TYPE_LINUX_DATA \
|
#define GPT_ENT_TYPE_LINUX_DATA \
|
||||||
{{{0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}}}}
|
{{{0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}}}}
|
||||||
|
|
||||||
|
|
||||||
#define UUID_NODE_LEN 6
|
#define UUID_NODE_LEN 6
|
||||||
#define GUID_SIZE 16
|
#define GUID_SIZE 16
|
||||||
|
|
||||||
/* GUID definition.
|
/* GUID definition. Defined in appendix A of EFI standard. */
|
||||||
* Defined in appendix A of EFI standard.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@@ -65,9 +63,10 @@ typedef struct {
|
|||||||
|
|
||||||
#define GUID_EXPECTED_SIZE GUID_SIZE
|
#define GUID_EXPECTED_SIZE GUID_SIZE
|
||||||
|
|
||||||
/* GPT header defines how many partitions exist on a drive and sectors managed.
|
/*
|
||||||
* For every drive device, there are 2 headers, primary and secondary.
|
* GPT header defines how many partitions exist on a drive and sectors managed.
|
||||||
* Most of fields are duplicated except my_lba and entries_lba.
|
* For every drive device, there are 2 headers, primary and secondary. Most of
|
||||||
|
* fields are duplicated except my_lba and entries_lba.
|
||||||
*
|
*
|
||||||
* You may find more details in chapter 5 of EFI standard.
|
* You may find more details in chapter 5 of EFI standard.
|
||||||
*/
|
*/
|
||||||
@@ -91,8 +90,9 @@ typedef struct {
|
|||||||
|
|
||||||
#define GPTHEADER_EXPECTED_SIZE 92
|
#define GPTHEADER_EXPECTED_SIZE 92
|
||||||
|
|
||||||
/* GPT partition entry defines the starting and ending LBAs of a partition.
|
/*
|
||||||
* It also contains the unique GUID, type, and attribute bits.
|
* GPT partition entry defines the starting and ending LBAs of a partition. It
|
||||||
|
* also contains the unique GUID, type, and attribute bits.
|
||||||
*
|
*
|
||||||
* You may find more details in chapter 5 of EFI standard.
|
* You may find more details in chapter 5 of EFI standard.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user