mirror of https://github.com/ARMmbed/mbed-os.git
478 lines
20 KiB
C
478 lines
20 KiB
C
/*
|
|
* Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
* not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "flash-journal-strategy-sequential/flash_journal_crc.h"
|
|
#include "flash-journal-strategy-sequential/flash_journal_private.h"
|
|
#include "flash-journal-strategy-sequential/flash_journal_strategy_sequential.h"
|
|
#include "support_funcs.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
SequentialFlashJournal_t *activeJournal;
|
|
|
|
/*
|
|
* forward declarations of static-inline helper functions.
|
|
*/
|
|
static inline int32_t mtdGetTotalCapacity(ARM_DRIVER_STORAGE *mtd, uint64_t *capacityP);
|
|
static inline int32_t flashJournalStrategySequential_format_sanityChecks(ARM_DRIVER_STORAGE *mtd, uint32_t numSlots);
|
|
static inline int32_t flashJournalStrategySequential_read_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob);
|
|
static inline int32_t flashJournalStrategySequential_log_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob);
|
|
static inline int32_t flashJournalStrategySequential_commit_sanityChecks(SequentialFlashJournal_t *journal);
|
|
|
|
|
|
int32_t flashJournalStrategySequential_format(ARM_DRIVER_STORAGE *mtd,
|
|
uint32_t numSlots,
|
|
FlashJournal_Callback_t callback)
|
|
{
|
|
int32_t rc;
|
|
if ((rc = flashJournalStrategySequential_format_sanityChecks(mtd, numSlots)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
ARM_STORAGE_INFO mtdInfo;
|
|
if (mtd->GetInfo(&mtdInfo) < ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
uint64_t mtdAddr;
|
|
if (mtdGetStartAddr(mtd, &mtdAddr) < JOURNAL_STATUS_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
|
|
formatInfoSingleton.mtd = mtd;
|
|
formatInfoSingleton.mtdAddr = mtdAddr;
|
|
formatInfoSingleton.callback = callback;
|
|
formatInfoSingleton.mtdProgramUnit = mtdInfo.program_unit;
|
|
|
|
if ((rc = setupSequentialJournalHeader(&formatInfoSingleton.header, mtd, mtdInfo.total_storage, numSlots)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
/* initialize MTD */
|
|
rc = mtd->Initialize(formatHandler);
|
|
if (rc < ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
} else if (rc == ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_OK; /* An asynchronous operation is pending; it will result in a completion callback
|
|
* where the rest of processing will take place. */
|
|
}
|
|
if (rc != 1) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR; /* synchronous completion is expected to return 1 */
|
|
}
|
|
|
|
/* progress the rest of the create state-machine */
|
|
return flashJournalStrategySequential_format_progress(ARM_DRIVER_OK, ARM_STORAGE_OPERATION_INITIALIZE);
|
|
}
|
|
|
|
/**
|
|
* Validate a header at the start of the MTD.
|
|
*
|
|
* @param [in/out] headerP
|
|
* Caller-allocated header which gets filled in during validation.
|
|
|
|
* @return JOURNAL_STATUS_OK if the header is sane. As a side-effect, the memory
|
|
* pointed to by 'headerP' is initialized with the header.
|
|
*/
|
|
int32_t readAndVerifyJournalHeader(SequentialFlashJournal_t *journal, SequentialFlashJournalHeader_t *headerP)
|
|
{
|
|
if (headerP == NULL) {
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
|
|
int32_t rc = journal->mtd->ReadData(journal->mtdStartOffset, headerP, sizeof(SequentialFlashJournalHeader_t));
|
|
if (rc < ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_STORAGE_IO_ERROR;
|
|
} else if (rc == ARM_DRIVER_OK) {
|
|
ARM_STORAGE_CAPABILITIES mtdCaps = journal->mtd->GetCapabilities();
|
|
if (!mtdCaps.asynchronous_ops) {
|
|
return JOURNAL_STATUS_ERROR; /* asynchronous_ops must be set if MTD returns ARM_DRIVER_OK. */
|
|
}
|
|
|
|
return JOURNAL_STATUS_ERROR; /* TODO: handle init with pending asynchronous activity. */
|
|
}
|
|
|
|
if ((headerP->genericHeader.magic != FLASH_JOURNAL_HEADER_MAGIC) ||
|
|
(headerP->genericHeader.version != FLASH_JOURNAL_HEADER_VERSION) ||
|
|
(headerP->genericHeader.sizeofHeader != sizeof(SequentialFlashJournalHeader_t)) ||
|
|
(headerP->magic != SEQUENTIAL_FLASH_JOURNAL_HEADER_MAGIC) ||
|
|
(headerP->version != SEQUENTIAL_FLASH_JOURNAL_HEADER_VERSION)) {
|
|
return JOURNAL_STATUS_NOT_FORMATTED;
|
|
}
|
|
|
|
uint32_t expectedCRC = headerP->genericHeader.checksum;
|
|
headerP->genericHeader.checksum = 0;
|
|
flashJournalCrcReset();
|
|
uint32_t computedCRC = flashJournalCrcCummulative((const unsigned char *)&headerP->genericHeader, sizeof(SequentialFlashJournalLogHead_t));
|
|
if (computedCRC != expectedCRC) {
|
|
//printf("readAndVerifyJournalHeader: checksum mismatch during header verification: expected = %u, computed = %u\n", (unsigned int) expectedCRC, (unsigned int) computedCRC);
|
|
return JOURNAL_STATUS_METADATA_ERROR;
|
|
}
|
|
|
|
return JOURNAL_STATUS_OK;
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_initialize(FlashJournal_t *_journal,
|
|
ARM_DRIVER_STORAGE *mtd,
|
|
const FlashJournal_Ops_t *ops,
|
|
FlashJournal_Callback_t callback)
|
|
{
|
|
int32_t rc;
|
|
|
|
/* initialize MTD */
|
|
rc = mtd->Initialize(mtdHandler);
|
|
if (rc < ARM_DRIVER_OK) {
|
|
memset(_journal, 0, sizeof(FlashJournal_t));
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
if (rc == ARM_DRIVER_OK) {
|
|
ARM_STORAGE_CAPABILITIES mtdCaps = mtd->GetCapabilities();
|
|
if (!mtdCaps.asynchronous_ops) {
|
|
return JOURNAL_STATUS_ERROR; /* asynchronous_ops must be set if MTD returns ARM_DRIVER_OK. */
|
|
}
|
|
|
|
return JOURNAL_STATUS_ERROR; /* TODO: handle init with pending asynchronous activity. */
|
|
}
|
|
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED;
|
|
journal->mtd = mtd;
|
|
|
|
/* Setup start address within MTD. */
|
|
if ((rc = mtdGetStartAddr(journal->mtd, &journal->mtdStartOffset)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
/* fetch MTD's total capacity */
|
|
uint64_t mtdCapacity;
|
|
if ((rc = mtdGetTotalCapacity(mtd, &mtdCapacity)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
ARM_STORAGE_INFO mtdInfo;
|
|
if ((rc = mtd->GetInfo(&mtdInfo)) != ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
|
|
SequentialFlashJournalHeader_t journalHeader;
|
|
if ((rc = readAndVerifyJournalHeader(journal, &journalHeader)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
/* initialize the journal structure */
|
|
memcpy(&journal->ops, ops, sizeof(FlashJournal_Ops_t));
|
|
journal->mtdCapabilities = mtd->GetCapabilities(); /* fetch MTD's capabilities */
|
|
|
|
journal->firstSlotOffset = journalHeader.genericHeader.journalOffset;
|
|
journal->numSlots = journalHeader.numSlots;
|
|
journal->sizeofSlot = journalHeader.sizeofSlot;
|
|
|
|
/* effective capacity */
|
|
journal->info.capacity = journal->sizeofSlot
|
|
- roundUp_uint32(sizeof(SequentialFlashJournalLogHead_t), mtdInfo.program_unit)
|
|
- roundUp_uint32(sizeof(SequentialFlashJournalLogTail_t), mtdInfo.program_unit);
|
|
journal->info.program_unit = mtdInfo.program_unit;
|
|
journal->callback = callback;
|
|
journal->prevCommand = FLASH_JOURNAL_OPCODE_INITIALIZE;
|
|
|
|
if ((rc = discoverLatestLoggedBlob(journal)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
return 1; /* synchronous completion */
|
|
}
|
|
|
|
FlashJournal_Status_t flashJournalStrategySequential_getInfo(FlashJournal_t *_journal, FlashJournal_Info_t *infoP)
|
|
{
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
|
|
memcpy(infoP, &journal->info, sizeof(FlashJournal_Info_t));
|
|
return JOURNAL_STATUS_OK;
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_read(FlashJournal_t *_journal, void *blob, size_t sizeofBlob)
|
|
{
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
|
|
if (journal->prevCommand != FLASH_JOURNAL_OPCODE_READ_BLOB) {
|
|
journal->read.logicalOffset = 0;
|
|
}
|
|
|
|
int32_t rc;
|
|
if ((rc = flashJournalStrategySequential_read_sanityChecks(journal, blob, sizeofBlob)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
journal->read.blob = blob;
|
|
journal->read.sizeofBlob = sizeofBlob;
|
|
|
|
if (journal->read.logicalOffset == 0) {
|
|
{ /* Establish the sanity of this slot before proceeding with the read. */
|
|
uint32_t headSequenceNumber;
|
|
SequentialFlashJournalLogTail_t tail;
|
|
if (slotIsSane(journal,
|
|
SLOT_ADDRESS(journal, journal->currentBlobIndex),
|
|
&headSequenceNumber,
|
|
&tail) != 1) {
|
|
/* TODO: rollback to an older slot. */
|
|
return JOURNAL_STATUS_STORAGE_IO_ERROR;
|
|
}
|
|
}
|
|
|
|
journal->read.mtdOffset = SLOT_ADDRESS(journal, journal->currentBlobIndex) + sizeof(SequentialFlashJournalLogHead_t);
|
|
} else {
|
|
/* journal->read.offset is already set from the previous read execution */
|
|
// printf("flashJournalStrategySequential_read: continuing read of %lu from offset %lu\n", sizeofBlob, (uint32_t)journal->read.offset);
|
|
}
|
|
journal->read.dataBeingRead = blob;
|
|
journal->read.amountLeftToRead = ((journal->info.sizeofJournaledBlob - journal->read.logicalOffset) < sizeofBlob) ?
|
|
(journal->info.sizeofJournaledBlob - journal->read.logicalOffset) : sizeofBlob;
|
|
// printf("amount left to read %u\n", journal->read.amountLeftToRead);
|
|
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_READING;
|
|
journal->prevCommand = FLASH_JOURNAL_OPCODE_READ_BLOB;
|
|
return flashJournalStrategySequential_read_progress();
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_readFrom(FlashJournal_t *_journal, size_t offset, void *blob, size_t sizeofBlob)
|
|
{
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
|
|
journal->read.logicalOffset = offset;
|
|
int32_t rc;
|
|
if ((rc = flashJournalStrategySequential_read_sanityChecks(journal, blob, sizeofBlob)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
journal->read.blob = blob;
|
|
journal->read.sizeofBlob = sizeofBlob;
|
|
|
|
journal->read.mtdOffset = SLOT_ADDRESS(journal, journal->currentBlobIndex) + sizeof(SequentialFlashJournalLogHead_t) + offset;
|
|
|
|
journal->read.dataBeingRead = blob;
|
|
journal->read.amountLeftToRead = ((journal->info.sizeofJournaledBlob - journal->read.logicalOffset) < sizeofBlob) ?
|
|
(journal->info.sizeofJournaledBlob - journal->read.logicalOffset) : sizeofBlob;
|
|
// printf("amount left to read %u\n", journal->read.amountLeftToRead);
|
|
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_READING;
|
|
journal->prevCommand = FLASH_JOURNAL_OPCODE_READ_BLOB;
|
|
return flashJournalStrategySequential_read_progress();
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_log(FlashJournal_t *_journal, const void *blob, size_t size)
|
|
{
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
|
|
int32_t rc;
|
|
if ((rc = flashJournalStrategySequential_log_sanityChecks(journal, blob, size)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
journal->log.blob = blob;
|
|
journal->log.sizeofBlob = size;
|
|
|
|
if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) {
|
|
/*
|
|
* This is the first log in the sequence. We have to begin by identifying a new slot and erasing it.
|
|
*/
|
|
|
|
/* choose the next slot */
|
|
uint32_t logBlobIndex = journal->currentBlobIndex + 1;
|
|
if (logBlobIndex == journal->numSlots) {
|
|
logBlobIndex = 0;
|
|
}
|
|
|
|
/* setup an erase for the slot */
|
|
journal->log.mtdEraseOffset = SLOT_ADDRESS(journal, logBlobIndex);
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE; /* start with erasing the log region */
|
|
journal->prevCommand = FLASH_JOURNAL_OPCODE_LOG_BLOB;
|
|
} else {
|
|
/* This is a continuation of an ongoing logging sequence. */
|
|
journal->log.dataBeingLogged = blob;
|
|
journal->log.amountLeftToLog = size;
|
|
}
|
|
|
|
/* progress the state machine for log() */
|
|
return flashJournalStrategySequential_log_progress();
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_commit(FlashJournal_t *_journal)
|
|
{
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
|
|
int32_t rc;
|
|
if ((rc = flashJournalStrategySequential_commit_sanityChecks(journal)) != JOURNAL_STATUS_OK) {
|
|
return rc;
|
|
}
|
|
|
|
if (journal->prevCommand == FLASH_JOURNAL_OPCODE_LOG_BLOB) {
|
|
/* the tail has already been setup during previous calls to log(); we can now include it in the crc32. */
|
|
journal->log.tail.crc32 = flashJournalCrcCummulative((const unsigned char *)&journal->log.tail, sizeof(SequentialFlashJournalLogTail_t));
|
|
flashJournalCrcReset();
|
|
|
|
journal->log.mtdOffset = journal->log.mtdTailOffset;
|
|
journal->log.dataBeingLogged = (const uint8_t *)&journal->log.tail;
|
|
journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogTail_t);
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL;
|
|
} else {
|
|
uint32_t logBlobIndex = journal->currentBlobIndex + 1;
|
|
if (logBlobIndex == journal->numSlots) {
|
|
logBlobIndex = 0;
|
|
}
|
|
journal->log.mtdEraseOffset = SLOT_ADDRESS(journal, logBlobIndex);
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE;
|
|
}
|
|
|
|
journal->prevCommand = FLASH_JOURNAL_OPCODE_COMMIT;
|
|
return flashJournalStrategySequential_log_progress();
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_reset(FlashJournal_t *_journal)
|
|
{
|
|
SequentialFlashJournal_t *journal;
|
|
activeJournal = journal = (SequentialFlashJournal_t *)_journal;
|
|
|
|
journal->state = SEQUENTIAL_JOURNAL_STATE_RESETING;
|
|
|
|
journal->prevCommand = FLASH_JOURNAL_OPCODE_RESET;
|
|
return flashJournalStrategySequential_reset_progress();
|
|
}
|
|
|
|
int32_t mtdGetTotalCapacity(ARM_DRIVER_STORAGE *mtd, uint64_t *capacityP)
|
|
{
|
|
/* fetch MTD's INFO */
|
|
ARM_STORAGE_INFO mtdInfo;
|
|
int32_t rc = mtd->GetInfo(&mtdInfo);
|
|
if (rc != ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
*capacityP = mtdInfo.total_storage;
|
|
|
|
return JOURNAL_STATUS_OK;
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_format_sanityChecks(ARM_DRIVER_STORAGE *mtd, uint32_t numSlots)
|
|
{
|
|
/*
|
|
* basic parameter checking
|
|
*/
|
|
if ((mtd == NULL) || (numSlots == 0)) {
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
|
|
ARM_STORAGE_INFO mtdInfo;
|
|
if (mtd->GetInfo(&mtdInfo) < ARM_DRIVER_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
if (mtdInfo.total_storage == 0) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
|
|
uint64_t mtdAddr;
|
|
if (mtdGetStartAddr(mtd, &mtdAddr) < JOURNAL_STATUS_OK) {
|
|
return JOURNAL_STATUS_STORAGE_API_ERROR;
|
|
}
|
|
if (mtd->GetBlock(mtdAddr, NULL) < ARM_DRIVER_OK) { /* check validity of journal's start address */
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
if (mtd->GetBlock(mtdAddr + mtdInfo.total_storage - 1, NULL) < ARM_DRIVER_OK) { /* check validity of the journal's end address */
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
|
|
if ((mtdAddr % mtdInfo.program_unit) != 0) { /* ensure that the journal starts at a programmable unit */
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
if ((mtdAddr % LCM_OF_ALL_ERASE_UNITS) != 0) { /* ensure that the journal starts and ends at an erase-boundary */
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
|
|
return JOURNAL_STATUS_OK;
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_read_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob)
|
|
{
|
|
if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) {
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) {
|
|
return JOURNAL_STATUS_NOT_INITIALIZED;
|
|
}
|
|
if (journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) {
|
|
return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
|
|
}
|
|
// printf("read sanity checks: logicalOffset = %lu, sizeofJournaledBlob = %lu\n", (uint32_t)journal->read.logicalOffset, (uint32_t)journal->info.sizeofJournaledBlob);
|
|
if ((journal->info.sizeofJournaledBlob == 0) || (journal->read.logicalOffset >= journal->info.sizeofJournaledBlob)) {
|
|
journal->read.logicalOffset = 0;
|
|
return JOURNAL_STATUS_EMPTY;
|
|
}
|
|
|
|
return JOURNAL_STATUS_OK;
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_log_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob)
|
|
{
|
|
if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) {
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) {
|
|
return JOURNAL_STATUS_NOT_INITIALIZED;
|
|
}
|
|
if ((journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) && (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY)) {
|
|
return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
|
|
}
|
|
if (journal->state == SEQUENTIAL_JOURNAL_STATE_INITIALIZED) {
|
|
if (sizeofBlob > journal->info.capacity) {
|
|
return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */
|
|
}
|
|
} else if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
|
|
if (journal->log.mtdOffset + sizeofBlob > journal->log.mtdTailOffset) {
|
|
return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */
|
|
}
|
|
}
|
|
|
|
/* ensure that the request is at least as large as the minimum program unit */
|
|
if (sizeofBlob < journal->info.program_unit) {
|
|
return JOURNAL_STATUS_SMALL_LOG_REQUEST;
|
|
}
|
|
|
|
return JOURNAL_STATUS_OK;
|
|
}
|
|
|
|
int32_t flashJournalStrategySequential_commit_sanityChecks(SequentialFlashJournal_t *journal)
|
|
{
|
|
if (journal == NULL) {
|
|
return JOURNAL_STATUS_PARAMETER;
|
|
}
|
|
if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
|
|
if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) {
|
|
return JOURNAL_STATUS_ERROR;
|
|
}
|
|
if ((journal->log.mtdOffset == ARM_STORAGE_INVALID_OFFSET) ||
|
|
(journal->log.mtdTailOffset == ARM_STORAGE_INVALID_OFFSET) ||
|
|
(journal->log.mtdTailOffset < journal->log.mtdOffset) ||
|
|
(journal->log.tail.sizeofBlob == 0) ||
|
|
(journal->log.tail.sizeofBlob > journal->info.capacity)) {
|
|
return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
|
|
}
|
|
}
|
|
|
|
return JOURNAL_STATUS_OK;
|
|
}
|