mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers strategy.c Source File

strategy.c

00001 /*
00002  * Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "flash-journal-strategy-sequential/flash_journal_crc.h"
00019 #include "flash-journal-strategy-sequential/flash_journal_private.h"
00020 #include "flash-journal-strategy-sequential/flash_journal_strategy_sequential.h"
00021 #include "support_funcs.h"
00022 #include <string.h>
00023 #include <stdio.h>
00024 
00025 SequentialFlashJournal_t *activeJournal;
00026 
00027 /*
00028  * forward declarations of static-inline helper functions.
00029  */
00030 static inline int32_t mtdGetTotalCapacity(ARM_DRIVER_STORAGE *mtd, uint64_t *capacityP);
00031 static inline int32_t flashJournalStrategySequential_format_sanityChecks(ARM_DRIVER_STORAGE *mtd, uint32_t numSlots);
00032 static inline int32_t flashJournalStrategySequential_read_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob);
00033 static inline int32_t flashJournalStrategySequential_log_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob);
00034 static inline int32_t flashJournalStrategySequential_commit_sanityChecks(SequentialFlashJournal_t *journal);
00035 
00036 
00037 int32_t flashJournalStrategySequential_format(ARM_DRIVER_STORAGE      *mtd,
00038                                               uint32_t                 numSlots,
00039                                               FlashJournal_Callback_t  callback)
00040 {
00041     int32_t rc;
00042     if ((rc = flashJournalStrategySequential_format_sanityChecks(mtd, numSlots)) != JOURNAL_STATUS_OK) {
00043         return rc;
00044     }
00045 
00046     ARM_STORAGE_INFO mtdInfo;
00047     if (mtd->GetInfo(&mtdInfo) < ARM_DRIVER_OK) {
00048         return JOURNAL_STATUS_STORAGE_API_ERROR;
00049     }
00050     uint64_t mtdAddr;
00051     if (mtdGetStartAddr(mtd, &mtdAddr) < JOURNAL_STATUS_OK) {
00052         return JOURNAL_STATUS_STORAGE_API_ERROR;
00053     }
00054 
00055     formatInfoSingleton.mtd            = mtd;
00056     formatInfoSingleton.mtdAddr        = mtdAddr;
00057     formatInfoSingleton.callback       = callback;
00058     formatInfoSingleton.mtdProgramUnit = mtdInfo.program_unit;
00059 
00060     if ((rc = setupSequentialJournalHeader(&formatInfoSingleton.header, mtd, mtdInfo.total_storage, numSlots)) != JOURNAL_STATUS_OK) {
00061         return rc;
00062     }
00063 
00064     /* initialize MTD */
00065     rc = mtd->Initialize(formatHandler);
00066     if (rc < ARM_DRIVER_OK) {
00067         return JOURNAL_STATUS_STORAGE_API_ERROR;
00068     } else if (rc == ARM_DRIVER_OK) {
00069         return JOURNAL_STATUS_OK; /* An asynchronous operation is pending; it will result in a completion callback
00070                                    * where the rest of processing will take place. */
00071     }
00072     if (rc != 1) {
00073         return JOURNAL_STATUS_STORAGE_API_ERROR; /* synchronous completion is expected to return 1 */
00074     }
00075 
00076     /* progress the rest of the create state-machine */
00077     return flashJournalStrategySequential_format_progress(ARM_DRIVER_OK, ARM_STORAGE_OPERATION_INITIALIZE);
00078 }
00079 
00080 /**
00081  * Validate a header at the start of the MTD.
00082  *
00083  * @param [in/out] headerP
00084  *                     Caller-allocated header which gets filled in during validation.
00085 
00086  * @return JOURNAL_STATUS_OK if the header is sane. As a side-effect, the memory
00087  *         pointed to by 'headerP' is initialized with the header.
00088  */
00089 int32_t readAndVerifyJournalHeader(SequentialFlashJournal_t *journal, SequentialFlashJournalHeader_t *headerP)
00090 {
00091     if (headerP == NULL) {
00092         return JOURNAL_STATUS_PARAMETER;
00093     }
00094 
00095     int32_t rc = journal->mtd->ReadData(journal->mtdStartOffset, headerP, sizeof(SequentialFlashJournalHeader_t));
00096     if (rc < ARM_DRIVER_OK) {
00097         return JOURNAL_STATUS_STORAGE_IO_ERROR;
00098     } else if (rc == ARM_DRIVER_OK) {
00099         ARM_STORAGE_CAPABILITIES mtdCaps = journal->mtd->GetCapabilities();
00100         if (!mtdCaps.asynchronous_ops) {
00101             return JOURNAL_STATUS_ERROR; /* asynchronous_ops must be set if MTD returns ARM_DRIVER_OK. */
00102         }
00103 
00104         return JOURNAL_STATUS_ERROR; /* TODO: handle init with pending asynchronous activity. */
00105     }
00106 
00107     if ((headerP->genericHeader.magic        != FLASH_JOURNAL_HEADER_MAGIC)             ||
00108         (headerP->genericHeader.version      != FLASH_JOURNAL_HEADER_VERSION)           ||
00109         (headerP->genericHeader.sizeofHeader != sizeof(SequentialFlashJournalHeader_t)) ||
00110         (headerP->magic                      != SEQUENTIAL_FLASH_JOURNAL_HEADER_MAGIC)  ||
00111         (headerP->version                    != SEQUENTIAL_FLASH_JOURNAL_HEADER_VERSION)) {
00112         return JOURNAL_STATUS_NOT_FORMATTED;
00113     }
00114 
00115     uint32_t expectedCRC = headerP->genericHeader.checksum;
00116     headerP->genericHeader.checksum = 0;
00117     flashJournalCrcReset();
00118     uint32_t computedCRC = flashJournalCrcCummulative((const unsigned char *)&headerP->genericHeader, sizeof(SequentialFlashJournalLogHead_t));
00119     if (computedCRC != expectedCRC) {
00120         //printf("readAndVerifyJournalHeader: checksum mismatch during header verification: expected = %u, computed = %u\n", (unsigned int) expectedCRC, (unsigned int) computedCRC);
00121         return JOURNAL_STATUS_METADATA_ERROR;
00122     }
00123 
00124     return JOURNAL_STATUS_OK;
00125 }
00126 
00127 int32_t flashJournalStrategySequential_initialize(FlashJournal_t           *_journal,
00128                                                   ARM_DRIVER_STORAGE       *mtd,
00129                                                   const FlashJournal_Ops_t *ops,
00130                                                   FlashJournal_Callback_t   callback)
00131 {
00132     int32_t rc;
00133 
00134     /* initialize MTD */
00135     rc = mtd->Initialize(mtdHandler);
00136     if (rc < ARM_DRIVER_OK) {
00137         memset(_journal, 0, sizeof(FlashJournal_t));
00138         return JOURNAL_STATUS_STORAGE_API_ERROR;
00139     }
00140     if (rc == ARM_DRIVER_OK) {
00141         ARM_STORAGE_CAPABILITIES mtdCaps = mtd->GetCapabilities();
00142         if (!mtdCaps.asynchronous_ops) {
00143             return JOURNAL_STATUS_ERROR; /* asynchronous_ops must be set if MTD returns ARM_DRIVER_OK. */
00144         }
00145 
00146         return JOURNAL_STATUS_ERROR; /* TODO: handle init with pending asynchronous activity. */
00147     }
00148 
00149     SequentialFlashJournal_t *journal;
00150     activeJournal = journal    = (SequentialFlashJournal_t *)_journal;
00151     journal->state             = SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED;
00152     journal->mtd               = mtd;
00153 
00154     /* Setup start address within MTD. */
00155     if ((rc = mtdGetStartAddr(journal->mtd, &journal->mtdStartOffset)) != JOURNAL_STATUS_OK) {
00156         return rc;
00157     }
00158 
00159     /* fetch MTD's total capacity */
00160     uint64_t mtdCapacity;
00161     if ((rc = mtdGetTotalCapacity(mtd, &mtdCapacity)) != JOURNAL_STATUS_OK) {
00162         return rc;
00163     }
00164     ARM_STORAGE_INFO mtdInfo;
00165     if ((rc = mtd->GetInfo(&mtdInfo)) != ARM_DRIVER_OK) {
00166         return JOURNAL_STATUS_STORAGE_API_ERROR;
00167     }
00168 
00169     SequentialFlashJournalHeader_t journalHeader;
00170     if ((rc = readAndVerifyJournalHeader(journal, &journalHeader)) != JOURNAL_STATUS_OK) {
00171         return rc;
00172     }
00173 
00174     /* initialize the journal structure */
00175     memcpy(&journal->ops, ops, sizeof(FlashJournal_Ops_t));
00176     journal->mtdCapabilities   = mtd->GetCapabilities(); /* fetch MTD's capabilities */
00177 
00178     journal->firstSlotOffset   = journalHeader.genericHeader.journalOffset;
00179     journal->numSlots          = journalHeader.numSlots;
00180     journal->sizeofSlot        = journalHeader.sizeofSlot;
00181 
00182     /* effective capacity */
00183     journal->info.capacity     = journal->sizeofSlot
00184                                  - roundUp_uint32(sizeof(SequentialFlashJournalLogHead_t), mtdInfo.program_unit)
00185                                  - roundUp_uint32(sizeof(SequentialFlashJournalLogTail_t), mtdInfo.program_unit);
00186     journal->info.program_unit = mtdInfo.program_unit;
00187     journal->callback          = callback;
00188     journal->prevCommand       = FLASH_JOURNAL_OPCODE_INITIALIZE;
00189 
00190     if ((rc = discoverLatestLoggedBlob(journal)) != JOURNAL_STATUS_OK) {
00191         return rc;
00192     }
00193 
00194     return 1; /* synchronous completion */
00195 }
00196 
00197 FlashJournal_Status_t flashJournalStrategySequential_getInfo(FlashJournal_t *_journal, FlashJournal_Info_t *infoP)
00198 {
00199     SequentialFlashJournal_t *journal;
00200     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00201 
00202     memcpy(infoP, &journal->info, sizeof(FlashJournal_Info_t));
00203     return JOURNAL_STATUS_OK;
00204 }
00205 
00206 int32_t flashJournalStrategySequential_read(FlashJournal_t *_journal, void *blob, size_t sizeofBlob)
00207 {
00208     SequentialFlashJournal_t *journal;
00209     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00210 
00211     if (journal->prevCommand != FLASH_JOURNAL_OPCODE_READ_BLOB) {
00212         journal->read.logicalOffset = 0;
00213     }
00214 
00215     int32_t rc;
00216     if ((rc = flashJournalStrategySequential_read_sanityChecks(journal, blob, sizeofBlob)) != JOURNAL_STATUS_OK) {
00217         return rc;
00218     }
00219 
00220     journal->read.blob       = blob;
00221     journal->read.sizeofBlob = sizeofBlob;
00222 
00223     if (journal->read.logicalOffset == 0) {
00224         { /* Establish the sanity of this slot before proceeding with the read. */
00225             uint32_t headSequenceNumber;
00226             SequentialFlashJournalLogTail_t tail;
00227             if (slotIsSane(journal,
00228                            SLOT_ADDRESS(journal, journal->currentBlobIndex),
00229                            &headSequenceNumber,
00230                            &tail) != 1) {
00231                 /* TODO: rollback to an older slot. */
00232                 return JOURNAL_STATUS_STORAGE_IO_ERROR;
00233             }
00234         }
00235 
00236         journal->read.mtdOffset = SLOT_ADDRESS(journal, journal->currentBlobIndex) + sizeof(SequentialFlashJournalLogHead_t);
00237     } else {
00238         /* journal->read.offset is already set from the previous read execution */
00239         // printf("flashJournalStrategySequential_read: continuing read of %lu from offset %lu\n", sizeofBlob, (uint32_t)journal->read.offset);
00240     }
00241     journal->read.dataBeingRead    = blob;
00242     journal->read.amountLeftToRead = ((journal->info.sizeofJournaledBlob - journal->read.logicalOffset) < sizeofBlob) ?
00243                                         (journal->info.sizeofJournaledBlob - journal->read.logicalOffset) : sizeofBlob;
00244     // printf("amount left to read %u\n", journal->read.amountLeftToRead);
00245 
00246     journal->state       = SEQUENTIAL_JOURNAL_STATE_READING;
00247     journal->prevCommand = FLASH_JOURNAL_OPCODE_READ_BLOB;
00248     return flashJournalStrategySequential_read_progress();
00249 }
00250 
00251 int32_t flashJournalStrategySequential_readFrom(FlashJournal_t *_journal, size_t offset, void *blob, size_t sizeofBlob)
00252 {
00253     SequentialFlashJournal_t *journal;
00254     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00255 
00256     journal->read.logicalOffset = offset;
00257     int32_t rc;
00258     if ((rc = flashJournalStrategySequential_read_sanityChecks(journal, blob, sizeofBlob)) != JOURNAL_STATUS_OK) {
00259         return rc;
00260     }
00261 
00262     journal->read.blob             = blob;
00263     journal->read.sizeofBlob       = sizeofBlob;
00264 
00265     journal->read.mtdOffset        = SLOT_ADDRESS(journal, journal->currentBlobIndex) + sizeof(SequentialFlashJournalLogHead_t) + offset;
00266 
00267     journal->read.dataBeingRead    = blob;
00268     journal->read.amountLeftToRead = ((journal->info.sizeofJournaledBlob - journal->read.logicalOffset) < sizeofBlob) ?
00269                                         (journal->info.sizeofJournaledBlob - journal->read.logicalOffset) : sizeofBlob;
00270     // printf("amount left to read %u\n", journal->read.amountLeftToRead);
00271 
00272     journal->state       = SEQUENTIAL_JOURNAL_STATE_READING;
00273     journal->prevCommand = FLASH_JOURNAL_OPCODE_READ_BLOB;
00274     return flashJournalStrategySequential_read_progress();
00275 }
00276 
00277 int32_t flashJournalStrategySequential_log(FlashJournal_t *_journal, const void *blob, size_t size)
00278 {
00279     SequentialFlashJournal_t *journal;
00280     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00281 
00282     int32_t rc;
00283     if ((rc = flashJournalStrategySequential_log_sanityChecks(journal, blob, size)) != JOURNAL_STATUS_OK) {
00284         return rc;
00285     }
00286 
00287     journal->log.blob       = blob;
00288     journal->log.sizeofBlob = size;
00289 
00290     if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) {
00291         /*
00292          * This is the first log in the sequence. We have to begin by identifying a new slot and erasing it.
00293          */
00294 
00295          /* choose the next slot */
00296         uint32_t logBlobIndex = journal->currentBlobIndex + 1;
00297         if (logBlobIndex == journal->numSlots) {
00298             logBlobIndex = 0;
00299         }
00300 
00301         /* setup an erase for the slot */
00302         journal->log.mtdEraseOffset = SLOT_ADDRESS(journal, logBlobIndex);
00303         journal->state              = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE; /* start with erasing the log region */
00304         journal->prevCommand        = FLASH_JOURNAL_OPCODE_LOG_BLOB;
00305     } else {
00306         /* This is a continuation of an ongoing logging sequence. */
00307         journal->log.dataBeingLogged = blob;
00308         journal->log.amountLeftToLog = size;
00309     }
00310 
00311     /* progress the state machine for log() */
00312     return flashJournalStrategySequential_log_progress();
00313 }
00314 
00315 int32_t flashJournalStrategySequential_commit(FlashJournal_t *_journal)
00316 {
00317     SequentialFlashJournal_t *journal;
00318     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00319 
00320     int32_t rc;
00321     if ((rc = flashJournalStrategySequential_commit_sanityChecks(journal)) != JOURNAL_STATUS_OK) {
00322         return rc;
00323     }
00324 
00325     if (journal->prevCommand == FLASH_JOURNAL_OPCODE_LOG_BLOB) {
00326         /* the tail has already been setup during previous calls to log(); we can now include it in the crc32. */
00327         journal->log.tail.crc32 = flashJournalCrcCummulative((const unsigned char *)&journal->log.tail, sizeof(SequentialFlashJournalLogTail_t));
00328         flashJournalCrcReset();
00329 
00330         journal->log.mtdOffset       = journal->log.mtdTailOffset;
00331         journal->log.dataBeingLogged = (const uint8_t *)&journal->log.tail;
00332         journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogTail_t);
00333         journal->state               = SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL;
00334     } else {
00335         uint32_t logBlobIndex = journal->currentBlobIndex + 1;
00336         if (logBlobIndex == journal->numSlots) {
00337             logBlobIndex = 0;
00338         }
00339         journal->log.mtdEraseOffset = SLOT_ADDRESS(journal, logBlobIndex);
00340         journal->state              = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE;
00341     }
00342 
00343     journal->prevCommand = FLASH_JOURNAL_OPCODE_COMMIT;
00344     return flashJournalStrategySequential_log_progress();
00345 }
00346 
00347 int32_t flashJournalStrategySequential_reset(FlashJournal_t *_journal)
00348 {
00349     SequentialFlashJournal_t *journal;
00350     activeJournal = journal = (SequentialFlashJournal_t *)_journal;
00351 
00352     journal->state = SEQUENTIAL_JOURNAL_STATE_RESETING;
00353 
00354     journal->prevCommand = FLASH_JOURNAL_OPCODE_RESET;
00355     return flashJournalStrategySequential_reset_progress();
00356 }
00357 
00358 int32_t mtdGetTotalCapacity(ARM_DRIVER_STORAGE *mtd, uint64_t *capacityP)
00359 {
00360     /* fetch MTD's INFO */
00361     ARM_STORAGE_INFO mtdInfo;
00362     int32_t rc = mtd->GetInfo(&mtdInfo);
00363     if (rc != ARM_DRIVER_OK) {
00364         return JOURNAL_STATUS_STORAGE_API_ERROR;
00365     }
00366     *capacityP = mtdInfo.total_storage;
00367 
00368     return JOURNAL_STATUS_OK;
00369 }
00370 
00371 int32_t flashJournalStrategySequential_format_sanityChecks(ARM_DRIVER_STORAGE *mtd, uint32_t numSlots)
00372 {
00373     /*
00374      * basic parameter checking
00375      */
00376     if ((mtd == NULL) || (numSlots == 0)) {
00377         return JOURNAL_STATUS_PARAMETER;
00378     }
00379 
00380     ARM_STORAGE_INFO mtdInfo;
00381     if (mtd->GetInfo(&mtdInfo) < ARM_DRIVER_OK) {
00382         return JOURNAL_STATUS_STORAGE_API_ERROR;
00383     }
00384     if (mtdInfo.total_storage == 0) {
00385         return JOURNAL_STATUS_STORAGE_API_ERROR;
00386     }
00387 
00388     uint64_t mtdAddr;
00389     if (mtdGetStartAddr(mtd, &mtdAddr) < JOURNAL_STATUS_OK) {
00390         return JOURNAL_STATUS_STORAGE_API_ERROR;
00391     }
00392     if (mtd->GetBlock(mtdAddr, NULL) < ARM_DRIVER_OK) { /* check validity of journal's start address */
00393         return JOURNAL_STATUS_PARAMETER;
00394     }
00395     if (mtd->GetBlock(mtdAddr + mtdInfo.total_storage - 1, NULL) < ARM_DRIVER_OK) { /* check validity of the journal's end address */
00396         return JOURNAL_STATUS_PARAMETER;
00397     }
00398 
00399     if ((mtdAddr % mtdInfo.program_unit) != 0) { /* ensure that the journal starts at a programmable unit */
00400         return JOURNAL_STATUS_PARAMETER;
00401     }
00402     if ((mtdAddr % LCM_OF_ALL_ERASE_UNITS) != 0) { /* ensure that the journal starts and ends at an erase-boundary */
00403         return JOURNAL_STATUS_PARAMETER;
00404     }
00405 
00406     return JOURNAL_STATUS_OK;
00407 }
00408 
00409 int32_t flashJournalStrategySequential_read_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob)
00410 {
00411     if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) {
00412         return JOURNAL_STATUS_PARAMETER;
00413     }
00414     if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) {
00415         return JOURNAL_STATUS_NOT_INITIALIZED;
00416     }
00417     if (journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) {
00418         return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00419     }
00420     // printf("read sanity checks: logicalOffset = %lu, sizeofJournaledBlob = %lu\n", (uint32_t)journal->read.logicalOffset, (uint32_t)journal->info.sizeofJournaledBlob);
00421     if ((journal->info.sizeofJournaledBlob == 0) || (journal->read.logicalOffset >= journal->info.sizeofJournaledBlob)) {
00422         journal->read.logicalOffset = 0;
00423         return JOURNAL_STATUS_EMPTY;
00424     }
00425 
00426     return JOURNAL_STATUS_OK;
00427 }
00428 
00429 int32_t flashJournalStrategySequential_log_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob)
00430 {
00431     if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) {
00432         return JOURNAL_STATUS_PARAMETER;
00433     }
00434     if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) {
00435         return JOURNAL_STATUS_NOT_INITIALIZED;
00436     }
00437     if ((journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) && (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY)) {
00438         return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00439     }
00440     if (journal->state == SEQUENTIAL_JOURNAL_STATE_INITIALIZED) {
00441         if (sizeofBlob > journal->info.capacity) {
00442             return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */
00443         }
00444     } else if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
00445         if (journal->log.mtdOffset + sizeofBlob > journal->log.mtdTailOffset) {
00446             return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */
00447         }
00448     }
00449 
00450     /* ensure that the request is at least as large as the minimum program unit */
00451     if (sizeofBlob < journal->info.program_unit) {
00452         return JOURNAL_STATUS_SMALL_LOG_REQUEST;
00453     }
00454 
00455     return JOURNAL_STATUS_OK;
00456 }
00457 
00458 int32_t flashJournalStrategySequential_commit_sanityChecks(SequentialFlashJournal_t *journal)
00459 {
00460     if (journal == NULL) {
00461         return JOURNAL_STATUS_PARAMETER;
00462     }
00463     if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) {
00464         if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) {
00465             return JOURNAL_STATUS_ERROR;
00466         }
00467         if ((journal->log.mtdOffset       == ARM_STORAGE_INVALID_OFFSET) ||
00468             (journal->log.mtdTailOffset   == ARM_STORAGE_INVALID_OFFSET) ||
00469             (journal->log.mtdTailOffset    < journal->log.mtdOffset)     ||
00470             (journal->log.tail.sizeofBlob == 0)                          ||
00471             (journal->log.tail.sizeofBlob  > journal->info.capacity)) {
00472             return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */
00473         }
00474     }
00475 
00476     return JOURNAL_STATUS_OK;
00477 }