diff --git a/Makefile b/Makefile index dff0a386cd..33ca966e2f 100644 --- a/Makefile +++ b/Makefile @@ -362,9 +362,9 @@ UTILLIB_SRCS = \ cgpt/cgpt_repair.c \ cgpt/cgpt_prioritize.c \ cgpt/cgpt_common.c \ + cgpt/flash_ts.c \ cgpt/flash_ts_drv.c \ firmware/lib/cgptlib/mtdlib.c \ - firmware/lib/flash_ts.c \ host/arch/${ARCH}/lib/crossystem_arch.c \ host/lib/crossystem.c \ host/lib/file_keys.c \ @@ -391,12 +391,12 @@ HOSTLIB_SRCS = \ cgpt/cgpt_common.c \ cgpt/cgpt_create.c \ cgpt/cgpt_prioritize.c \ + cgpt/flash_ts.c \ cgpt/flash_ts_drv.c \ firmware/lib/cgptlib/cgptlib_internal.c \ firmware/lib/cgptlib/crc32.c \ firmware/lib/cgptlib/mtdlib.c \ firmware/lib/crc8.c \ - firmware/lib/flash_ts.c \ firmware/lib/tpm_lite/tlcl.c \ firmware/lib/utility_string.c \ firmware/lib/vboot_nvstorage.c \ @@ -422,11 +422,11 @@ TINYHOSTLIB_SRCS = \ cgpt/cgpt_common.c \ cgpt/cgpt_create.c \ cgpt/cgpt_prioritize.c \ + cgpt/flash_ts.c \ cgpt/flash_ts_drv.c \ firmware/lib/cgptlib/cgptlib_internal.c \ firmware/lib/cgptlib/crc32.c \ firmware/lib/cgptlib/mtdlib.c \ - firmware/lib/flash_ts.c \ firmware/lib/utility_string.c \ firmware/stub/utility_stub.c \ utility/dump_kernel_config_lib.c @@ -457,8 +457,8 @@ CGPT_SRCS = \ cgpt/cmd_prioritize.c \ cgpt/cmd_repair.c \ cgpt/cmd_show.c \ - cgpt/flash_ts_drv.c \ - firmware/lib/flash_ts.c + cgpt/flash_ts.c \ + cgpt/flash_ts_drv.c CGPT_OBJS = ${CGPT_SRCS:%.c=${BUILD}/%.o} ALL_OBJS += ${CGPT_OBJS} @@ -1021,6 +1021,10 @@ ${BUILD}/tests/vb2_common3_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vboot_common2_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vboot_common3_tests: LDLIBS += ${CRYPTO_LIBS} +${BUILD}/tests/cgptlib_test: OBJS += \ + ${BUILD}/firmware/lib/cgptlib/mtdlib_unused.o +${BUILD}/tests/cgptlib_test: ${BUILD}/firmware/lib/cgptlib/mtdlib_unused.o + ${BUILD}/utility/bmpblk_utility: LD = ${CXX} ${BUILD}/utility/bmpblk_utility: LDLIBS = -llzma -lyaml diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c index b87fe4b4ae..1ff9e56007 100644 --- a/cgpt/cgpt_add.c +++ b/cgpt/cgpt_add.c @@ -307,7 +307,7 @@ bad: return result; } -int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { +static int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { GptEntry *entry, backup; int rv; @@ -336,7 +336,7 @@ int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { return 0; } -int MtdAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { +static int MtdAdd(struct drive *drive, CgptAddParams *params, uint32_t index) { MtdDiskPartition *entry, backup; entry = MtdGetEntry(&drive->mtd, PRIMARY, index); memcpy(&backup, entry, sizeof(backup)); diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c index ff3ae696fc..bfc138647e 100644 --- a/cgpt/cgpt_common.c +++ b/cgpt/cgpt_common.c @@ -156,7 +156,7 @@ static int get_hex_char_value(char ch) { return -1; } -int TryInitMtd(const char *dev) { +static int TryInitMtd(const char *dev) { static int already_inited = 0; if (already_inited) return nand.use_host_ioctl; @@ -298,7 +298,7 @@ int MtdSave(struct drive *drive) { sizeof(mtd->primary)); } -int GptLoad(struct drive *drive, uint32_t sector_bytes) { +static int GptLoad(struct drive *drive, uint32_t sector_bytes) { drive->gpt.sector_bytes = sector_bytes; if (drive->size % drive->gpt.sector_bytes) { Error("Media size (%llu) is not a multiple of sector size(%d)\n", @@ -332,7 +332,7 @@ int GptLoad(struct drive *drive, uint32_t sector_bytes) { return 0; } -int GptSave(struct drive *drive) { +static int GptSave(struct drive *drive) { int errors = 0; if (drive->gpt.modified & GPT_MODIFIED_HEADER1) { if (CGPT_OK != Save(drive, drive->gpt.primary_header, @@ -838,7 +838,7 @@ void PrintTypes(void) { printf("\n"); } -GptHeader* GetGptHeader(const GptData *gpt) { +static GptHeader* GetGptHeader(const GptData *gpt) { if (gpt->valid_headers & MASK_PRIMARY) return (GptHeader*)gpt->primary_header; else if (gpt->valid_headers & MASK_SECONDARY) diff --git a/cgpt/cgpt_create.c b/cgpt/cgpt_create.c index 3341fa2557..9f60b3a1f0 100644 --- a/cgpt/cgpt_create.c +++ b/cgpt/cgpt_create.c @@ -9,7 +9,7 @@ #include "cgptlib_internal.h" #include "vboot_host.h" -int GptCreate(struct drive *drive, CgptCreateParams *params) { +static int GptCreate(struct drive *drive, CgptCreateParams *params) { // Erase the data memset(drive->gpt.primary_header, 0, drive->gpt.sector_bytes * GPT_HEADER_SECTOR); @@ -50,7 +50,7 @@ int GptCreate(struct drive *drive, CgptCreateParams *params) { return 0; } -int MtdCreate(struct drive *drive, CgptCreateParams *params) { +static int MtdCreate(struct drive *drive, CgptCreateParams *params) { MtdDiskLayout *h = &drive->mtd.primary; memset(h, 0, sizeof(*h)); drive->mtd.modified = 1; diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c index a2b7c95129..f5d6001e3e 100644 --- a/cgpt/cgpt_show.c +++ b/cgpt/cgpt_show.c @@ -66,7 +66,8 @@ void PrintSignature(const char *indent, const char *sig, size_t n, int raw) { printf("\n"); } -void MtdHeaderDetails(MtdDiskLayout *header, const char *indent, int raw) { +static void MtdHeaderDetails(MtdDiskLayout *header, const char *indent, + int raw) { PrintSignature(indent, (char*)header->signature, sizeof(header->signature), raw); @@ -300,7 +301,7 @@ int MtdShow(struct drive *drive, CgptShowParams *params) { return CGPT_OK; } -int GptShow(struct drive *drive, CgptShowParams *params) { +static int GptShow(struct drive *drive, CgptShowParams *params) { int gpt_retval; if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) { Error("GptSanityCheck() returned %d: %s\n", diff --git a/firmware/lib/flash_ts.c b/cgpt/flash_ts.c similarity index 100% rename from firmware/lib/flash_ts.c rename to cgpt/flash_ts.c diff --git a/firmware/lib/include/flash_ts.h b/cgpt/flash_ts.h similarity index 100% rename from firmware/lib/include/flash_ts.h rename to cgpt/flash_ts.h diff --git a/firmware/lib/cgptlib/include/mtdlib.h b/firmware/lib/cgptlib/include/mtdlib.h index fd749aca03..916c9fab47 100644 --- a/firmware/lib/cgptlib/include/mtdlib.h +++ b/firmware/lib/cgptlib/include/mtdlib.h @@ -123,17 +123,10 @@ typedef struct { /* APIs are documented in cgptlib.h & cgptlib_internal.h */ -int MtdInit(MtdData *mtd); -int MtdCheckParameters(MtdData *mtd); - -int MtdNextKernelEntry(MtdData *gpt, uint64_t *start_sector, uint64_t *size); -int MtdUpdateKernelEntry(MtdData *gpt, uint32_t update_type); - int MtdGetEntryPriority(const MtdDiskPartition *e); int MtdGetEntryTries(const MtdDiskPartition *e); int MtdGetEntrySuccessful(const MtdDiskPartition *e); int MtdGetEntryType(const MtdDiskPartition *e); -int MtdIsKernelEntry(const MtdDiskPartition *e); void MtdSetEntrySuccessful(MtdDiskPartition *e, int successful) ; void MtdSetEntryPriority(MtdDiskPartition *e, int priority); void MtdSetEntryTries(MtdDiskPartition *e, int tries); @@ -145,15 +138,8 @@ void MtdGetPartitionSize(const MtdDiskPartition *e, void MtdGetPartitionSizeInSectors(const MtdDiskPartition *e, uint64_t *start, uint64_t *end, uint64_t *size); -void MtdModified(MtdData *mtd); int MtdGptInit(MtdData *mtd); -int MtdIsPartitionValid(const MtdDiskPartition *part); -int MtdCheckEntries(MtdDiskPartition *entries, MtdDiskLayout *h); -int MtdSanityCheck(MtdData *disk); -void MtdRepair(MtdData *gpt); -void MtdGetCurrentKernelUniqueGuid(MtdData *gpt, void *dest); uint32_t MtdHeaderCrc(MtdDiskLayout *h); - #endif diff --git a/firmware/lib/cgptlib/include/mtdlib_unused.h b/firmware/lib/cgptlib/include/mtdlib_unused.h new file mode 100644 index 0000000000..f331decdc4 --- /dev/null +++ b/firmware/lib/cgptlib/include/mtdlib_unused.h @@ -0,0 +1,19 @@ +/* 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. + */ + +#ifndef VBOOT_REFERENCE_MTDLIB_UNUSED_H_ +#define VBOOT_REFERENCE_MTDLIB_UNUSED_H_ + +int MtdIsKernelEntry(const MtdDiskPartition *e); +void MtdModified(MtdData *mtd); +int MtdIsPartitionValid(const MtdDiskPartition *part); +int MtdCheckParameters(MtdData *disk); +int MtdCheckEntries(MtdDiskPartition *entries, MtdDiskLayout *h); +int MtdSanityCheck(MtdData *disk); +int MtdInit(MtdData *mtd); +int MtdNextKernelEntry(MtdData *mtd, uint64_t *start_sector, uint64_t *size); +int MtdUpdateKernelEntry(MtdData *mtd, uint32_t update_type); + +#endif /* VBOOT_REFERENCE_MTDLIB_UNUSED_H_ */ diff --git a/firmware/lib/cgptlib/mtdlib.c b/firmware/lib/cgptlib/mtdlib.c index 18aa7c5a45..98662523a3 100644 --- a/firmware/lib/cgptlib/mtdlib.c +++ b/firmware/lib/cgptlib/mtdlib.c @@ -13,51 +13,6 @@ const int kSectorShift = 9; /* 512 bytes / sector. */ -int MtdInit(MtdData *mtd) { - int ret; - - mtd->modified = 0; - mtd->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND; - mtd->current_priority = 999; - - ret = MtdSanityCheck(mtd); - if (GPT_SUCCESS != ret) { - VBDEBUG(("MtdInit() failed sanity check\n")); - return ret; - } - - return GPT_SUCCESS; -} - -int MtdCheckParameters(MtdData *disk) { - if (disk->sector_bytes != 512) { - return GPT_ERROR_INVALID_SECTOR_SIZE; - } - - /* At minimum, the disk must consist of at least one erase block */ - if (disk->drive_sectors < disk->flash_block_bytes / disk->sector_bytes) { - return GPT_ERROR_INVALID_SECTOR_NUMBER; - } - - /* Write pages must be an integer multiple of sector size */ - if (disk->flash_page_bytes == 0 || - disk->flash_page_bytes % disk->sector_bytes != 0) { - return GPT_ERROR_INVALID_FLASH_GEOMETRY; - } - - /* Erase blocks must be an integer multiple of write pages */ - if (disk->flash_block_bytes == 0 || - disk->flash_block_bytes % disk->flash_page_bytes != 0) { - return GPT_ERROR_INVALID_FLASH_GEOMETRY; - } - - /* Without a FTS region, why are you using MTD? */ - if (disk->fts_block_size == 0) { - return GPT_ERROR_INVALID_FLASH_GEOMETRY; - } - return GPT_SUCCESS; -} - int MtdGetEntryPriority(const MtdDiskPartition *e) { return ((e->flags & MTD_ATTRIBUTE_PRIORITY_MASK) >> MTD_ATTRIBUTE_PRIORITY_OFFSET); @@ -77,11 +32,6 @@ int MtdGetEntryType(const MtdDiskPartition *e) { return ((e->flags & MTD_ATTRIBUTE_TYPE_MASK) >> MTD_ATTRIBUTE_TYPE_OFFSET); } -int MtdIsKernelEntry(const MtdDiskPartition *e) { - return MtdGetEntryType(e) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL; -} - - static void SetBitfield(MtdDiskPartition *e, uint32_t offset, uint32_t mask, uint32_t v) { e->flags = (e->flags & ~mask) | ((v << offset) & mask); @@ -101,96 +51,6 @@ void MtdSetEntryType(MtdDiskPartition *e, int type) { SetBitfield(e, MTD_ATTRIBUTE_TYPE_OFFSET, MTD_ATTRIBUTE_TYPE_MASK, type); } -void MtdModified(MtdData *mtd) { - mtd->modified = 1; - mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary); -} - -int MtdIsPartitionValid(const MtdDiskPartition *part) { - return MtdGetEntryType(part) != 0; -} - -int MtdCheckEntries(MtdDiskPartition *entries, MtdDiskLayout *h) { - uint32_t i, j; - - for (i = 0; i < MTD_MAX_PARTITIONS; i++) { - for (j = 0; j < MTD_MAX_PARTITIONS; j++) { - if (i != j) { - MtdDiskPartition *entry = entries + i; - MtdDiskPartition *e2 = entries + j; - uint64_t start, end; - uint64_t other_start, other_end; - - if (!MtdIsPartitionValid(entry) || !MtdIsPartitionValid(e2)) - continue; - - MtdGetPartitionSize(entry, &start, &end, NULL); - MtdGetPartitionSize(e2, &other_start, &other_end, NULL); - - if((start == 0 && end == 0) || - (other_start == 0 && other_end == 0)) { - continue; - } - - if (end > h->last_offset) { - return GPT_ERROR_OUT_OF_REGION; - } - if (start < h->first_offset) { - return GPT_ERROR_OUT_OF_REGION; - } - if (start > end) { - return GPT_ERROR_OUT_OF_REGION; - } - - if ((start >= other_start) && - (start <= other_end)) { - return GPT_ERROR_START_LBA_OVERLAP; - } - if ((end >= other_start) && - (end <= other_end)) { - return GPT_ERROR_END_LBA_OVERLAP; - } - } - } - } - return GPT_SUCCESS; -} - -int MtdSanityCheck(MtdData *disk) { - MtdDiskLayout *h = &disk->primary; - int ret; - - ret = MtdCheckParameters(disk); - if(GPT_SUCCESS != ret) - return ret; - - if (Memcmp(disk->primary.signature, MTD_DRIVE_SIGNATURE, - sizeof(disk->primary.signature))) { - return GPT_ERROR_INVALID_HEADERS; - } - - if (disk->primary.first_offset > disk->primary.last_offset || - disk->primary.last_offset > disk->drive_sectors * disk->sector_bytes) { - return GPT_ERROR_INVALID_SECTOR_NUMBER; - } - - if (h->crc32 != MtdHeaderCrc(h)) { - return GPT_ERROR_CRC_CORRUPTED; - } - if (h->size < MTD_DRIVE_V1_SIZE) { - return GPT_ERROR_INVALID_HEADERS; - } - return MtdCheckEntries(h->partitions, h); -} - -void MtdRepair(MtdData *gpt) { - -} - -void MtdGetCurrentKernelUniqueGuid(MtdData *gpt, void *dest) { - Memset(dest, 0, 16); -} - uint32_t MtdHeaderCrc(MtdDiskLayout *h) { uint32_t crc32, original_crc32; @@ -230,139 +90,4 @@ void MtdGetPartitionSizeInSectors(const MtdDiskPartition *e, uint64_t *start, } -int MtdNextKernelEntry(MtdData *mtd, uint64_t *start_sector, uint64_t *size) -{ - MtdDiskLayout *header = &mtd->primary; - MtdDiskPartition *entries = header->partitions; - MtdDiskPartition *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 (mtd->current_kernel != CGPT_KERNEL_ENTRY_NOT_FOUND) { - for (i = mtd->current_kernel + 1; - i < MTD_MAX_PARTITIONS; i++) { - e = entries + i; - if (!MtdIsKernelEntry(e)) - continue; - VBDEBUG(("MtdNextKernelEntry looking at same prio " - "partition %d\n", i+1)); - VBDEBUG(("MtdNextKernelEntry s%d t%d p%d\n", - MtdGetEntrySuccessful(e), MtdGetEntryTries(e), - MtdGetEntryPriority(e))); - if (!(MtdGetEntrySuccessful(e) || MtdGetEntryTries(e))) - continue; - if (MtdGetEntryPriority(e) == mtd->current_priority) { - MtdGetPartitionSizeInSectors(e, start_sector, NULL, size); - mtd->current_kernel = i; - VBDEBUG(("MtdNextKernelEntry 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 < MTD_MAX_PARTITIONS; i++, e++) { - int current_prio = MtdGetEntryPriority(e); - if (!MtdIsKernelEntry(e)) - continue; - VBDEBUG(("MtdNextKernelEntry looking at new prio " - "partition %d\n", i+1)); - VBDEBUG(("MtdNextKernelEntry s%d t%d p%d\n", - MtdGetEntrySuccessful(e), MtdGetEntryTries(e), - MtdGetEntryPriority(e))); - if (!(MtdGetEntrySuccessful(e) || MtdGetEntryTries(e))) - continue; - if (current_prio >= mtd->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. - */ - mtd->current_kernel = new_kernel; - mtd->current_priority = new_prio; - - if (CGPT_KERNEL_ENTRY_NOT_FOUND == new_kernel) { - VBDEBUG(("MtdNextKernelEntry no more kernels\n")); - return GPT_ERROR_NO_VALID_KERNEL; - } - - VBDEBUG(("MtdNextKernelEntry likes partition %d\n", new_kernel + 1)); - e = entries + new_kernel; - MtdGetPartitionSizeInSectors(e, start_sector, NULL, size); - - return GPT_SUCCESS; -} - -int MtdUpdateKernelEntry(MtdData *mtd, uint32_t update_type) -{ - MtdDiskLayout *header = &mtd->primary; - MtdDiskPartition *entries = header->partitions; - MtdDiskPartition *e = entries + mtd->current_kernel; - int modified = 0; - - if (mtd->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND) - return GPT_ERROR_INVALID_UPDATE_TYPE; - if (!MtdIsKernelEntry(e)) - return GPT_ERROR_INVALID_UPDATE_TYPE; - - switch (update_type) { - case GPT_UPDATE_ENTRY_TRY: { - /* Used up a try */ - int tries; - if (MtdGetEntrySuccessful(e)) { - /* - * Successfully booted this partition, so tries field - * is ignored. - */ - return GPT_SUCCESS; - } - tries = MtdGetEntryTries(e); - if (tries > 1) { - /* Still have tries left */ - modified = 1; - MtdSetEntryTries(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 (!MtdGetEntrySuccessful(e)) { - /* - * Only clear tries and priority if the successful bit - * is not set. - */ - modified = 1; - MtdSetEntryTries(e, 0); - MtdSetEntryPriority(e, 0); - } - break; - } - default: - return GPT_ERROR_INVALID_UPDATE_TYPE; - } - - if (modified) { - MtdModified(mtd); - } - - return GPT_SUCCESS; -} diff --git a/firmware/lib/cgptlib/mtdlib_unused.c b/firmware/lib/cgptlib/mtdlib_unused.c new file mode 100644 index 0000000000..bf28500547 --- /dev/null +++ b/firmware/lib/cgptlib/mtdlib_unused.c @@ -0,0 +1,284 @@ +/* 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 "mtdlib.h" +#include "mtdlib_unused.h" + +#include "cgptlib.h" +#include "cgptlib_internal.h" +#include "crc32.h" +#include "utility.h" +#include "vboot_api.h" + +int MtdIsKernelEntry(const MtdDiskPartition *e) { + return MtdGetEntryType(e) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL; +} + +void MtdModified(MtdData *mtd) { + mtd->modified = 1; + mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary); +} + +int MtdIsPartitionValid(const MtdDiskPartition *part) { + return MtdGetEntryType(part) != 0; +} + +int MtdCheckParameters(MtdData *disk) { + if (disk->sector_bytes != 512) { + return GPT_ERROR_INVALID_SECTOR_SIZE; + } + + /* At minimum, the disk must consist of at least one erase block */ + if (disk->drive_sectors < disk->flash_block_bytes / disk->sector_bytes) { + return GPT_ERROR_INVALID_SECTOR_NUMBER; + } + + /* Write pages must be an integer multiple of sector size */ + if (disk->flash_page_bytes == 0 || + disk->flash_page_bytes % disk->sector_bytes != 0) { + return GPT_ERROR_INVALID_FLASH_GEOMETRY; + } + + /* Erase blocks must be an integer multiple of write pages */ + if (disk->flash_block_bytes == 0 || + disk->flash_block_bytes % disk->flash_page_bytes != 0) { + return GPT_ERROR_INVALID_FLASH_GEOMETRY; + } + + /* Without a FTS region, why are you using MTD? */ + if (disk->fts_block_size == 0) { + return GPT_ERROR_INVALID_FLASH_GEOMETRY; + } + return GPT_SUCCESS; +} + + +int MtdCheckEntries(MtdDiskPartition *entries, MtdDiskLayout *h) { + uint32_t i, j; + + for (i = 0; i < MTD_MAX_PARTITIONS; i++) { + for (j = 0; j < MTD_MAX_PARTITIONS; j++) { + if (i != j) { + MtdDiskPartition *entry = entries + i; + MtdDiskPartition *e2 = entries + j; + uint64_t start, end; + uint64_t other_start, other_end; + + if (!MtdIsPartitionValid(entry) || !MtdIsPartitionValid(e2)) + continue; + + MtdGetPartitionSize(entry, &start, &end, NULL); + MtdGetPartitionSize(e2, &other_start, &other_end, NULL); + + if((start == 0 && end == 0) || + (other_start == 0 && other_end == 0)) { + continue; + } + + if (end > h->last_offset) { + return GPT_ERROR_OUT_OF_REGION; + } + if (start < h->first_offset) { + return GPT_ERROR_OUT_OF_REGION; + } + if (start > end) { + return GPT_ERROR_OUT_OF_REGION; + } + + if ((start >= other_start) && + (start <= other_end)) { + return GPT_ERROR_START_LBA_OVERLAP; + } + if ((end >= other_start) && + (end <= other_end)) { + return GPT_ERROR_END_LBA_OVERLAP; + } + } + } + } + return GPT_SUCCESS; +} + +int MtdSanityCheck(MtdData *disk) { + MtdDiskLayout *h = &disk->primary; + int ret; + + ret = MtdCheckParameters(disk); + if(GPT_SUCCESS != ret) + return ret; + + if (Memcmp(disk->primary.signature, MTD_DRIVE_SIGNATURE, + sizeof(disk->primary.signature))) { + return GPT_ERROR_INVALID_HEADERS; + } + + if (disk->primary.first_offset > disk->primary.last_offset || + disk->primary.last_offset > disk->drive_sectors * disk->sector_bytes) { + return GPT_ERROR_INVALID_SECTOR_NUMBER; + } + + if (h->crc32 != MtdHeaderCrc(h)) { + return GPT_ERROR_CRC_CORRUPTED; + } + if (h->size < MTD_DRIVE_V1_SIZE) { + return GPT_ERROR_INVALID_HEADERS; + } + return MtdCheckEntries(h->partitions, h); +} + + +int MtdInit(MtdData *mtd) { + int ret; + + mtd->modified = 0; + mtd->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND; + mtd->current_priority = 999; + + ret = MtdSanityCheck(mtd); + if (GPT_SUCCESS != ret) { + VBDEBUG(("MtdInit() failed sanity check\n")); + return ret; + } + + return GPT_SUCCESS; +} + +int MtdNextKernelEntry(MtdData *mtd, uint64_t *start_sector, uint64_t *size) +{ + MtdDiskLayout *header = &mtd->primary; + MtdDiskPartition *entries = header->partitions; + MtdDiskPartition *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 (mtd->current_kernel != CGPT_KERNEL_ENTRY_NOT_FOUND) { + for (i = mtd->current_kernel + 1; + i < MTD_MAX_PARTITIONS; i++) { + e = entries + i; + if (!MtdIsKernelEntry(e)) + continue; + VBDEBUG(("MtdNextKernelEntry looking at same prio " + "partition %d\n", i+1)); + VBDEBUG(("MtdNextKernelEntry s%d t%d p%d\n", + MtdGetEntrySuccessful(e), MtdGetEntryTries(e), + MtdGetEntryPriority(e))); + if (!(MtdGetEntrySuccessful(e) || MtdGetEntryTries(e))) + continue; + if (MtdGetEntryPriority(e) == mtd->current_priority) { + MtdGetPartitionSizeInSectors(e, start_sector, NULL, size); + mtd->current_kernel = i; + VBDEBUG(("MtdNextKernelEntry 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 < MTD_MAX_PARTITIONS; i++, e++) { + int current_prio = MtdGetEntryPriority(e); + if (!MtdIsKernelEntry(e)) + continue; + VBDEBUG(("MtdNextKernelEntry looking at new prio " + "partition %d\n", i+1)); + VBDEBUG(("MtdNextKernelEntry s%d t%d p%d\n", + MtdGetEntrySuccessful(e), MtdGetEntryTries(e), + MtdGetEntryPriority(e))); + if (!(MtdGetEntrySuccessful(e) || MtdGetEntryTries(e))) + continue; + if (current_prio >= mtd->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. + */ + mtd->current_kernel = new_kernel; + mtd->current_priority = new_prio; + + if (CGPT_KERNEL_ENTRY_NOT_FOUND == new_kernel) { + VBDEBUG(("MtdNextKernelEntry no more kernels\n")); + return GPT_ERROR_NO_VALID_KERNEL; + } + + VBDEBUG(("MtdNextKernelEntry likes partition %d\n", new_kernel + 1)); + e = entries + new_kernel; + MtdGetPartitionSizeInSectors(e, start_sector, NULL, size); + + return GPT_SUCCESS; +} + + +int MtdUpdateKernelEntry(MtdData *mtd, uint32_t update_type) +{ + MtdDiskLayout *header = &mtd->primary; + MtdDiskPartition *entries = header->partitions; + MtdDiskPartition *e = entries + mtd->current_kernel; + int modified = 0; + + if (mtd->current_kernel == CGPT_KERNEL_ENTRY_NOT_FOUND) + return GPT_ERROR_INVALID_UPDATE_TYPE; + if (!MtdIsKernelEntry(e)) + return GPT_ERROR_INVALID_UPDATE_TYPE; + + switch (update_type) { + case GPT_UPDATE_ENTRY_TRY: { + /* Used up a try */ + int tries; + if (MtdGetEntrySuccessful(e)) { + /* + * Successfully booted this partition, so tries field + * is ignored. + */ + return GPT_SUCCESS; + } + tries = MtdGetEntryTries(e); + if (tries > 1) { + /* Still have tries left */ + modified = 1; + MtdSetEntryTries(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 (!MtdGetEntrySuccessful(e)) { + /* + * Only clear tries and priority if the successful bit + * is not set. + */ + modified = 1; + MtdSetEntryTries(e, 0); + MtdSetEntryPriority(e, 0); + } + break; + } + default: + return GPT_ERROR_INVALID_UPDATE_TYPE; + } + + if (modified) { + MtdModified(mtd); + } + + return GPT_SUCCESS; +} diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c index 1ee551d042..e7a9748ae8 100644 --- a/tests/cgptlib_test.c +++ b/tests/cgptlib_test.c @@ -6,14 +6,15 @@ #include #include "../cgpt/cgpt.h" +#include "../cgpt/flash_ts.h" #include "cgptlib_internal.h" #include "cgptlib_test.h" #include "crc32.h" #include "crc32_test.h" #include "errno.h" -#include "flash_ts.h" #include "gpt.h" #include "mtdlib.h" +#include "mtdlib_unused.h" #include "test_common.h" #define _STUB_IMPLEMENTATION_ #include "utility.h"