Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
support_funcs.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 "support_funcs.h" 00020 #include <string.h> 00021 #include <stdio.h> 00022 #include <inttypes.h> 00023 00024 struct FormatInfo_t formatInfoSingleton; 00025 00026 int32_t mtdGetStartAddr(ARM_DRIVER_STORAGE *mtd, uint64_t *startAddrP) 00027 { 00028 ARM_STORAGE_BLOCK mtdBlock; 00029 if ((mtd->GetNextBlock(NULL, &mtdBlock)) != ARM_DRIVER_OK) { 00030 return JOURNAL_STATUS_STORAGE_API_ERROR; 00031 } 00032 if (!ARM_STORAGE_VALID_BLOCK(&mtdBlock)) { 00033 return JOURNAL_STATUS_ERROR; 00034 } 00035 00036 *startAddrP = mtdBlock.addr; 00037 return JOURNAL_STATUS_OK; 00038 } 00039 00040 /** 00041 * Check the sanity of a given slot 00042 * @param journal 00043 * @param slotOffset 00044 * @param [out] headSequenceNumberP 00045 * sequence number of the slot as read from the header. 00046 * @param [out] tailP 00047 * the tail of the slot 00048 * @return 1 if the slot is valid; i.e. if head and tail match, and if CRC32 agrees. 00049 */ 00050 int32_t slotIsSane(SequentialFlashJournal_t *journal, 00051 uint64_t slotOffset, 00052 uint32_t *headSequenceNumberP, 00053 SequentialFlashJournalLogTail_t *tailP) 00054 { 00055 int32_t rc; 00056 ARM_DRIVER_STORAGE *mtd = journal->mtd; 00057 00058 SequentialFlashJournalLogHead_t head; 00059 /* TODO: add support for asynchronous read */ 00060 if (((rc = mtd->ReadData(slotOffset, &head, sizeof(SequentialFlashJournalLogHead_t))) < ARM_DRIVER_OK) || 00061 (rc != sizeof(SequentialFlashJournalLogHead_t))) { 00062 if ((rc == ARM_DRIVER_OK) && (journal->mtdCapabilities.asynchronous_ops)) { 00063 return JOURNAL_STATUS_UNSUPPORTED; 00064 } 00065 00066 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00067 } 00068 00069 /* compute the CRC32 of the header */ 00070 flashJournalCrcReset(); 00071 flashJournalCrcCummulative((const unsigned char *)&head, sizeof(SequentialFlashJournalLogHead_t)); 00072 00073 // printf("head->version: %lu\n", journal->initScan.head.version); 00074 // printf("head->magic: %lx\n", journal->initScan.head.magic); 00075 // printf("head->sequenceNumber: %lu\n", journal->initScan.head.sequenceNumber); 00076 // printf("head->reserved: %lu\n", journal->initScan.head.reserved); 00077 00078 if (SEQUENTIAL_JOURNAL_VALID_HEAD(&head)) { 00079 *headSequenceNumberP = head.sequenceNumber; 00080 // printf("found valid header with sequenceNumber %" PRIu32 "\n", *headSequenceNumberP); 00081 00082 uint64_t tailoffset = slotOffset 00083 - ((slotOffset - SLOT_ADDRESS(journal, 0)) % journal->sizeofSlot) 00084 + journal->sizeofSlot 00085 - sizeof(SequentialFlashJournalLogTail_t); 00086 // printf("hoping to read a tail at offset %lu\n", (uint32_t)tailoffset); 00087 00088 /* TODO: add support for asynchronous read */ 00089 if (((rc = mtd->ReadData(tailoffset, tailP, sizeof(SequentialFlashJournalLogTail_t))) < ARM_DRIVER_OK) || 00090 (rc != sizeof(SequentialFlashJournalLogTail_t))) { 00091 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00092 } 00093 00094 if (SEQUENTIAL_JOURNAL_VALID_TAIL(tailP) && (tailP->sequenceNumber == *headSequenceNumberP)) { 00095 // printf("found valid tail\n"); 00096 00097 /* iterate over the body of the slot computing CRC */ 00098 #define CRC_CHUNK_SIZE 64 00099 uint8_t crcBuffer[CRC_CHUNK_SIZE]; 00100 uint64_t bodyIndex = 0; 00101 uint64_t bodyOffset = slotOffset + sizeof(SequentialFlashJournalLogHead_t); 00102 while (bodyIndex < tailP->sizeofBlob) { 00103 size_t sizeofReadOperation; 00104 if ((tailP->sizeofBlob - bodyIndex) > CRC_CHUNK_SIZE) { 00105 sizeofReadOperation = CRC_CHUNK_SIZE; 00106 } else { 00107 sizeofReadOperation = (tailP->sizeofBlob - bodyIndex); 00108 } 00109 00110 /* TODO: add support for asynchronous read */ 00111 rc = mtd->ReadData(bodyOffset + bodyIndex, crcBuffer, sizeofReadOperation); 00112 if (rc != (int32_t)sizeofReadOperation) { 00113 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00114 } 00115 00116 bodyIndex += sizeofReadOperation; 00117 flashJournalCrcCummulative(crcBuffer, sizeofReadOperation); 00118 } 00119 00120 /* compute CRC32 over the tail */ 00121 /* extract existing CRC32 from the tail. The CRC32 field in the tail needs to contain 0 before CRC32 can be computed over it. */ 00122 uint32_t expectedCRC32 = tailP->crc32; 00123 tailP->crc32 = 0; 00124 00125 uint32_t crc32 = flashJournalCrcCummulative((const unsigned char *)tailP, sizeof(SequentialFlashJournalLogTail_t)); 00126 flashJournalCrcReset(); 00127 // printf("expectedCRC32: 0x%x, computedCRC32: 0x%x\n", expectedCRC32, crc32); 00128 if (crc32 == expectedCRC32) { 00129 return 1; 00130 } 00131 } 00132 } 00133 00134 return JOURNAL_STATUS_ERROR; 00135 } 00136 00137 int32_t setupSequentialJournalHeader(SequentialFlashJournalHeader_t *headerP, ARM_DRIVER_STORAGE *mtd, uint64_t totalSize, uint32_t numSlots) 00138 { 00139 ARM_STORAGE_INFO mtdInfo; 00140 if (mtd->GetInfo(&mtdInfo) < ARM_DRIVER_OK) { 00141 return JOURNAL_STATUS_STORAGE_API_ERROR; 00142 } 00143 00144 headerP->genericHeader.magic = FLASH_JOURNAL_HEADER_MAGIC; 00145 headerP->genericHeader.version = FLASH_JOURNAL_HEADER_VERSION; 00146 headerP->genericHeader.sizeofHeader = sizeof(SequentialFlashJournalHeader_t); 00147 00148 /* Determine 'journalOffset'. 00149 * Constraint: journal header should start and terminate at an erase-boundary 00150 * (so that slot-0 can be erased independently), and also a program-unit boundary. 00151 */ 00152 headerP->genericHeader.journalOffset = roundUp_uint32(headerP->genericHeader.sizeofHeader, LCM_OF_ALL_ERASE_UNITS); 00153 if ((headerP->genericHeader.journalOffset % mtdInfo.program_unit) != 0) { 00154 //printf("setupSequentialJournalHeader: journalOffset is not a multiple of MTD's program_unit\r\n"); 00155 return JOURNAL_STATUS_PARAMETER; 00156 } 00157 00158 headerP->magic = SEQUENTIAL_FLASH_JOURNAL_HEADER_MAGIC; 00159 headerP->version = SEQUENTIAL_FLASH_JOURNAL_HEADER_VERSION; 00160 headerP->numSlots = numSlots; 00161 00162 /* Determine 'sizeofSlot'. 00163 * Constraint: slot-size should be a multiple of the erase-units of all involved storage blocks. 00164 */ 00165 uint64_t spaceAvailableForSlots = totalSize - headerP->genericHeader.journalOffset; 00166 headerP->sizeofSlot = roundDown_uint32(spaceAvailableForSlots / numSlots, LCM_OF_ALL_ERASE_UNITS); 00167 if (headerP->sizeofSlot == 0) { 00168 //printf("setupSequentialJournalHeader: not enough space to create %" PRIu32 " slots\r\n", numSlots); 00169 return JOURNAL_STATUS_PARAMETER; 00170 } 00171 00172 headerP->genericHeader.totalSize = headerP->genericHeader.journalOffset + (headerP->sizeofSlot * numSlots); 00173 //printf("setupSequentialJournalHeader: header size = %" PRIu32 ", journalOffset = %" PRIu32 ", sizeofSlot = %" PRIu32 ", totalSize = %lu\n", headerP->genericHeader.sizeofHeader, headerP->genericHeader.journalOffset, headerP->sizeofSlot, (uint32_t)headerP->genericHeader.totalSize); 00174 00175 /* compute checksum over the entire header */ 00176 headerP->genericHeader.checksum = 0; 00177 flashJournalCrcReset(); 00178 headerP->genericHeader.checksum = flashJournalCrcCummulative((const unsigned char *)&headerP->genericHeader, sizeof(SequentialFlashJournalLogHead_t)); 00179 00180 return JOURNAL_STATUS_OK; 00181 } 00182 00183 int32_t discoverLatestLoggedBlob(SequentialFlashJournal_t *journal) 00184 { 00185 /* reset top level journal metadata prior to scanning headers. */ 00186 journal->nextSequenceNumber = SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER; /* we are currently unaware of previously written blobs */ 00187 journal->currentBlobIndex = journal->numSlots; 00188 journal->info.sizeofJournaledBlob = 0; 00189 00190 /* begin header-scan from the first block of the MTD */ 00191 journal->initScan.currentOffset = SLOT_ADDRESS(journal, 0); 00192 journal->state = SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS; 00193 00194 // printf("discoverLatestLoggedBlob: start of init scan\n"); 00195 for (unsigned blobIndex = 0; 00196 blobIndex < journal->numSlots; 00197 blobIndex++, journal->initScan.currentOffset += journal->sizeofSlot) { 00198 // printf("discoverLatestLoggedBlob: blob index %u\n", blobIndex); 00199 /* TODO: it is possible that the header structure spans multiple blocks, needing multiple reads. */ 00200 00201 if (slotIsSane(journal, 00202 journal->initScan.currentOffset, 00203 &journal->initScan.headSequenceNumber, 00204 &journal->initScan.tail) == 1) { 00205 // printf("found valid blob with sequence number %lu\n", journal->initScan.headSequenceNumber); 00206 uint32_t nextSequenceNumber = journal->initScan.headSequenceNumber + 1; 00207 if (nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) { 00208 nextSequenceNumber = 0; 00209 } 00210 00211 /* Have we found the best of the slots seen so far? */ 00212 if ((journal->nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) || 00213 /* We take advantage of properties of unsigned arithmetic in the following 00214 * expression. 00215 * 00216 * We want to calculate if (nextSequenceNumber > journal->nextSequenceNumber), 00217 * instead we use the expression ((nextSequenceNumber - journal->nextSequenceNumber) > 0) 00218 * to take wraparounds into account. 00219 */ 00220 ((int32_t)(nextSequenceNumber - journal->nextSequenceNumber) > 0)) { 00221 journal->currentBlobIndex = blobIndex; 00222 journal->nextSequenceNumber = nextSequenceNumber; 00223 journal->info.sizeofJournaledBlob = journal->initScan.tail.sizeofBlob; 00224 // printf("discoverLatestLoggedBlob: index %lu, sizeofBlob: %lu, nextSequenceNumber: %lu\n", 00225 // journal->currentBlobIndex, (uint32_t)journal->info.sizeofJournaledBlob, journal->nextSequenceNumber); 00226 } 00227 } 00228 } 00229 // printf("discoverLatestLoggedBlob: finished init scan\n"); 00230 00231 /* Handle the case where our scan hasn't yielded any results. */ 00232 if (journal->nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) { 00233 // printf("discoverLatestLoggedBlob: initializing to defaults\n"); 00234 journal->currentBlobIndex = (uint32_t)-1; /* to be incremented to 0 during the first attempt to log(). */ 00235 journal->nextSequenceNumber = 0; 00236 } 00237 00238 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00239 return JOURNAL_STATUS_OK; 00240 } 00241 00242 /** 00243 * Progress the state machine for the 'format' operation. This method can also be called from an interrupt handler. 00244 * @return < JOURNAL_STATUS_OK for error 00245 * = JOURNAL_STATUS_OK to signal pending asynchronous activity 00246 * > JOURNAL_STATUS_OK for completion 00247 */ 00248 int32_t flashJournalStrategySequential_format_progress(int32_t status, ARM_STORAGE_OPERATION operationWhichJustFinshed) 00249 { 00250 int32_t rc; 00251 size_t sizeofWrite = roundUp_uint32(formatInfoSingleton.header.genericHeader.sizeofHeader, formatInfoSingleton.mtdProgramUnit); 00252 size_t sizeofErase = roundUp_uint32(formatInfoSingleton.header.genericHeader.sizeofHeader, LCM_OF_ALL_ERASE_UNITS); 00253 switch (operationWhichJustFinshed) { 00254 case ARM_STORAGE_OPERATION_INITIALIZE: 00255 if (status != ARM_DRIVER_OK) { 00256 return JOURNAL_STATUS_STORAGE_API_ERROR; 00257 } 00258 00259 // printf("erasing %u bytes from offset %u\n", roundUp_uint32(header.genericHeader.sizeofHeader, mtdInfo.program_unit), mtdAddr); 00260 rc = (formatInfoSingleton.mtd)->Erase(formatInfoSingleton.mtdAddr, sizeofErase); 00261 if (rc < ARM_DRIVER_OK) { 00262 if (rc == ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE) { 00263 return JOURNAL_STATUS_STORAGE_RUNTIME_OR_INTEGRITY_FAILURE; 00264 } else { 00265 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00266 } 00267 } else if (rc == ARM_DRIVER_OK) { 00268 return JOURNAL_STATUS_OK; /* An asynchronous operation is pending; it will result in a completion callback 00269 * where the rest of processing will take place. */ 00270 } 00271 /* handle synchronous completion of programData */ 00272 status = rc; 00273 00274 /* intentional fall-through */ 00275 00276 case ARM_STORAGE_OPERATION_ERASE: 00277 if (status != (int32_t)sizeofErase) { 00278 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00279 } 00280 00281 // printf("calling ProgramData at address %u for %u bytes\n", 00282 // formatInfoSingleton.mtdAddr, roundUp_uint32(formatInfoSingleton.header.genericHeader.sizeofHeader, formatInfoSingleton.mtdProgramUnit)); 00283 rc = (formatInfoSingleton.mtd)->ProgramData(formatInfoSingleton.mtdAddr, &(formatInfoSingleton.header), sizeofWrite); 00284 if (rc < ARM_DRIVER_OK) { 00285 if (rc == ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE) { 00286 return JOURNAL_STATUS_STORAGE_RUNTIME_OR_INTEGRITY_FAILURE; 00287 } else { 00288 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00289 } 00290 } else if (rc == ARM_DRIVER_OK) { 00291 return JOURNAL_STATUS_OK; /* An asynchronous operation is pending; it will result in a completion callback 00292 * where the rest of processing will take place. */ 00293 } 00294 /* handle synchronous completion of programData */ 00295 status = rc; 00296 00297 /* intentional fall-through */ 00298 00299 case ARM_STORAGE_OPERATION_PROGRAM_DATA: 00300 if (status != (int32_t)sizeofWrite) { 00301 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00302 } 00303 00304 return 1; /* acknowledge the completion of create */ 00305 00306 default: 00307 return JOURNAL_STATUS_STORAGE_API_ERROR; /* we don't expect to be here */ 00308 } 00309 } 00310 00311 int32_t flashJournalStrategySequential_reset_progress(void) 00312 { 00313 int32_t rc; 00314 SequentialFlashJournal_t *journal = activeJournal; 00315 00316 if ((rc = journal->mtd->Erase(SLOT_ADDRESS(journal, 0), journal->numSlots * journal->sizeofSlot)) < ARM_DRIVER_OK) { 00317 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00318 if (rc == ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE) { 00319 return JOURNAL_STATUS_STORAGE_RUNTIME_OR_INTEGRITY_FAILURE; 00320 } else { 00321 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00322 } 00323 } 00324 if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) { 00325 //printf("eturning JOURNAL_STATUS_OK\n"); 00326 return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */ 00327 } 00328 /* else we fall through to handle synchronous completion */ 00329 00330 journal->nextSequenceNumber = 0; 00331 journal->currentBlobIndex = (uint32_t)-1; 00332 journal->info.sizeofJournaledBlob = 0; 00333 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00334 return 1; 00335 } 00336 00337 int32_t flashJournalStrategySequential_read_progress(void) 00338 { 00339 SequentialFlashJournal_t *journal = activeJournal; 00340 00341 // printf("flashJournalStrategySequential_read_progress\n"); 00342 if (journal->state != SEQUENTIAL_JOURNAL_STATE_READING) { 00343 return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */ 00344 } 00345 00346 int32_t rc; 00347 ARM_STORAGE_BLOCK storageBlock; 00348 00349 if ((journal->read.amountLeftToRead) && 00350 ((rc = journal->mtd->GetBlock(journal->read.mtdOffset, &storageBlock)) != ARM_DRIVER_OK)) { 00351 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00352 return JOURNAL_STATUS_STORAGE_API_ERROR; 00353 } 00354 uint64_t storageBlockAvailableCapacity = storageBlock.size - (journal->read.mtdOffset - storageBlock.addr); 00355 00356 while (journal->read.amountLeftToRead) { 00357 while (!storageBlockAvailableCapacity) { 00358 if ((rc = journal->mtd->GetNextBlock(&storageBlock, &storageBlock)) < ARM_DRIVER_OK) { 00359 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00360 return JOURNAL_STATUS_ERROR; /* We ran out of storage blocks. Journal is in an un-expected state. */ 00361 } 00362 journal->read.mtdOffset = storageBlock.addr; /* This should not be necessary since we assume 00363 * storage map manages a contiguous address space. */ 00364 storageBlockAvailableCapacity = storageBlock.size; 00365 } 00366 00367 /* compute the transfer size for this iteration. */ 00368 uint32_t xfer = (journal->read.amountLeftToRead < storageBlockAvailableCapacity) ? 00369 journal->read.amountLeftToRead : storageBlockAvailableCapacity; 00370 00371 /* perform the IO */ 00372 //printf("reading %lu bytes at offset %lu\n", xfer, (uint32_t)journal->read.mtdOffset); 00373 rc = journal->mtd->ReadData(journal->read.mtdOffset, journal->read.dataBeingRead, xfer); 00374 if (rc < ARM_DRIVER_OK) { 00375 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00376 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00377 } 00378 if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) { 00379 return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */ 00380 } else { 00381 /* synchronous completion. 'rc' contains the actual number of bytes transferred. */ 00382 journal->read.mtdOffset += rc; 00383 journal->read.amountLeftToRead -= rc; 00384 journal->read.dataBeingRead += rc; 00385 journal->read.logicalOffset += rc; 00386 } 00387 } 00388 00389 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00390 return (journal->read.dataBeingRead - journal->read.blob); 00391 } 00392 00393 /** 00394 * Progress the state machine for the 'log' operation. This method can also be called from an interrupt handler. 00395 * @return < JOURNAL_STATUS_OK for error 00396 * = JOURNAL_STATUS_OK to signal pending asynchronous activity 00397 * > JOURNAL_STATUS_OK for completion 00398 */ 00399 int32_t flashJournalStrategySequential_log_progress(void) 00400 { 00401 SequentialFlashJournal_t *journal = activeJournal; 00402 00403 if ((journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE) && 00404 (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD) && 00405 (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) && 00406 (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL)) { 00407 return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */ 00408 } 00409 00410 uint32_t blobIndexBeingLogged = journal->currentBlobIndex + 1; 00411 if (blobIndexBeingLogged == journal->numSlots) { 00412 blobIndexBeingLogged = 0; 00413 } 00414 00415 while (true) { 00416 int32_t rc; 00417 00418 if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE) { 00419 uint64_t amountLeftToErase = SLOT_ADDRESS(journal, blobIndexBeingLogged + 1) - journal->log.mtdEraseOffset; 00420 // printf("journal state: erasing; offset %lu [size %lu]\n", 00421 // (uint32_t)journal->log.eraseOffset, (uint32_t)amountLeftToErase); 00422 while (amountLeftToErase) { 00423 if ((rc = journal->mtd->Erase(journal->log.mtdEraseOffset, amountLeftToErase)) < ARM_DRIVER_OK) { 00424 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00425 if (rc == ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE) { 00426 return JOURNAL_STATUS_STORAGE_RUNTIME_OR_INTEGRITY_FAILURE; 00427 } else { 00428 return JOURNAL_STATUS_ERROR; 00429 } 00430 } 00431 if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) { 00432 return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */ 00433 } else { 00434 /* synchronous completion. */ 00435 journal->log.mtdEraseOffset += rc; 00436 amountLeftToErase -= rc; 00437 } 00438 } 00439 } else { 00440 ARM_STORAGE_BLOCK storageBlock; 00441 00442 /* find the available capacity in the current storage block */ 00443 while (journal->log.amountLeftToLog) { 00444 if (journal->log.amountLeftToLog < journal->info.program_unit) { 00445 /* We cannot log any smaller than info.program_unit. 'xfer' 00446 * amount of data would remain unlogged. We'll break out of this loop and report 00447 * the amount actually logged. */ 00448 break; 00449 } 00450 00451 /* check for alignment of next log offset with program_unit */ 00452 if ((rc = journal->mtd->GetBlock(journal->log.mtdOffset, &storageBlock)) != ARM_DRIVER_OK) { 00453 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00454 return JOURNAL_STATUS_STORAGE_API_ERROR; 00455 } 00456 if ((journal->log.mtdOffset - storageBlock.addr) % journal->info.program_unit) { 00457 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00458 return JOURNAL_STATUS_ERROR; /* Program offset doesn't align with info.program_unit. This would result in an IO error if attempted. */ 00459 } 00460 00461 uint32_t xfer = journal->log.amountLeftToLog; 00462 xfer -= xfer % journal->info.program_unit; /* align transfer-size with program_unit. */ 00463 00464 /* perform the IO */ 00465 // printf("programming %lu bytes at offset %lu\n", xfer, (uint32_t)journal->log.mtdOffset); 00466 rc = journal->mtd->ProgramData(journal->log.mtdOffset, journal->log.dataBeingLogged, xfer); 00467 if (rc < ARM_DRIVER_OK) { 00468 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00469 if (rc == ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE) { 00470 return JOURNAL_STATUS_STORAGE_RUNTIME_OR_INTEGRITY_FAILURE; 00471 } else { 00472 return JOURNAL_STATUS_STORAGE_IO_ERROR; 00473 } 00474 } 00475 if ((journal->mtdCapabilities.asynchronous_ops) && (rc == ARM_DRIVER_OK)) { 00476 return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */ 00477 } else { 00478 /* synchronous completion. 'rc' contains the actual number of bytes transferred. */ 00479 journal->log.mtdOffset += rc; 00480 journal->log.amountLeftToLog -= rc; 00481 journal->log.dataBeingLogged += rc; 00482 if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) { 00483 journal->log.tail.sizeofBlob += rc; 00484 } 00485 } 00486 } /* while (journal->log.amountLeftToLog) */ 00487 } 00488 00489 // printf("flashJournalStrategySequential_log_progress: state switch\n"); 00490 00491 /* state transition */ 00492 switch (journal->state) { 00493 case SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE: 00494 journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD; 00495 journal->log.mtdOffset = SLOT_ADDRESS(journal, blobIndexBeingLogged); 00496 journal->log.head.version = SEQUENTIAL_FLASH_JOURNAL_VERSION; 00497 journal->log.head.magic = SEQUENTIAL_FLASH_JOURNAL_MAGIC; 00498 journal->log.head.sequenceNumber = journal->nextSequenceNumber; 00499 journal->log.head.reserved = 0; 00500 journal->log.dataBeingLogged = (const uint8_t *)&journal->log.head; 00501 journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogHead_t); 00502 // printf("newstate: program HEAD; amount to log %u\n", journal->log.amountLeftToLog); 00503 break; 00504 00505 case SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD: /* we've finished writing the head */ 00506 /* compute CRC32 on the header */ 00507 flashJournalCrcReset(); 00508 flashJournalCrcCummulative((const unsigned char *)&journal->log.head, sizeof(SequentialFlashJournalLogHead_t)); 00509 00510 /* switch to writing the body */ 00511 00512 /* Prepare for the tail to be written out at a later time. 00513 * This will only be done once Commit() is called. */ 00514 journal->log.mtdTailOffset = SLOT_ADDRESS(journal, blobIndexBeingLogged + 1) - sizeof(SequentialFlashJournalLogTail_t); 00515 00516 journal->log.tail.magic = SEQUENTIAL_FLASH_JOURNAL_MAGIC; 00517 journal->log.tail.sequenceNumber = journal->nextSequenceNumber; 00518 journal->log.tail.sizeofBlob = 0; /* we'll update this as we complete our writes. */ 00519 journal->log.tail.crc32 = 0; 00520 00521 if (journal->prevCommand == FLASH_JOURNAL_OPCODE_COMMIT) { 00522 /* This branch is taken only when commit() is called without any preceding log() operations. */ 00523 journal->log.tail.crc32 = flashJournalCrcCummulative((const unsigned char *)&journal->log.tail, sizeof(SequentialFlashJournalLogTail_t)); 00524 flashJournalCrcReset(); 00525 00526 journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL; 00527 journal->log.dataBeingLogged = (const uint8_t *)&journal->log.tail; 00528 journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogTail_t); 00529 journal->log.mtdOffset = journal->log.mtdTailOffset; 00530 // printf("newstate: program TAIL at offset %lu\r\n", (uint32_t)journal->log.mtdOffset); 00531 } else { 00532 journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY; 00533 journal->log.dataBeingLogged = journal->log.blob; 00534 journal->log.amountLeftToLog = journal->log.sizeofBlob; 00535 // printf("newstate: program BODY; amount to log %u\n", journal->log.amountLeftToLog); 00536 } 00537 break; 00538 00539 case SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY: 00540 // printf("finished logging BODY; amount logged %u\n", journal->log.dataBeingLogged - journal->log.blob); 00541 if (journal->log.dataBeingLogged == journal->log.blob) { 00542 return JOURNAL_STATUS_SMALL_LOG_REQUEST; 00543 } else { 00544 uint32_t amountOfDataLogged = (journal->log.dataBeingLogged - journal->log.blob); 00545 flashJournalCrcCummulative(journal->log.blob, amountOfDataLogged); /* compute CRC32 on logged data */ 00546 return amountOfDataLogged; 00547 } 00548 00549 case SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL: 00550 // printf("crc32 of slot: 0x%x\n", journal->log.tail.crc32); 00551 00552 journal->info.sizeofJournaledBlob = journal->log.tail.sizeofBlob; 00553 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state to allow further operations */ 00554 00555 ++journal->currentBlobIndex; 00556 if (journal->currentBlobIndex == journal->numSlots) { 00557 journal->currentBlobIndex = 0; 00558 } 00559 // printf("currentBlobIndex: %lu\n", journal->currentBlobIndex); 00560 00561 /* increment next sequence number */ 00562 ++journal->nextSequenceNumber; 00563 if (journal->nextSequenceNumber == SEQUENTIAL_FLASH_JOURNAL_INVALD_NEXT_SEQUENCE_NUMBER) { 00564 ++journal->nextSequenceNumber; 00565 } 00566 // printf("nextSequenceNumber %lu\n", journal->nextSequenceNumber); 00567 00568 return 1; /* commit returns 1 upon completion. */ 00569 00570 default: 00571 journal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00572 return JOURNAL_STATUS_ERROR; 00573 } 00574 } 00575 } 00576 00577 void formatHandler(int32_t status, ARM_STORAGE_OPERATION operation) 00578 { 00579 if (status < ARM_DRIVER_OK) { 00580 if (formatInfoSingleton.callback) { 00581 formatInfoSingleton.callback(status, FLASH_JOURNAL_OPCODE_FORMAT); 00582 } 00583 return; 00584 } 00585 00586 int32_t rc = flashJournalStrategySequential_format_progress(status, operation); 00587 if (rc != JOURNAL_STATUS_OK) { 00588 if (formatInfoSingleton.callback) { 00589 formatInfoSingleton.callback(rc, FLASH_JOURNAL_OPCODE_FORMAT); 00590 } 00591 } 00592 } 00593 00594 void mtdHandler(int32_t status, ARM_STORAGE_OPERATION operation) 00595 { 00596 int32_t rc; 00597 00598 if (status < ARM_DRIVER_OK) { 00599 /* Map integrity failures reported by the Storage driver appropriately. */ 00600 if (status == ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE) { 00601 status = JOURNAL_STATUS_STORAGE_RUNTIME_OR_INTEGRITY_FAILURE; 00602 } else { 00603 status = JOURNAL_STATUS_STORAGE_IO_ERROR; 00604 } 00605 00606 // printf("journal mtdHandler: received error status %ld\n", status); 00607 switch (activeJournal->state) { 00608 case SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED: 00609 case SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS: 00610 if (activeJournal->callback) { 00611 activeJournal->callback(status, FLASH_JOURNAL_OPCODE_INITIALIZE); 00612 } 00613 break; 00614 00615 case SEQUENTIAL_JOURNAL_STATE_RESETING: 00616 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00617 if (activeJournal->callback) { 00618 activeJournal->callback(status, FLASH_JOURNAL_OPCODE_RESET); 00619 } 00620 break; 00621 00622 case SEQUENTIAL_JOURNAL_STATE_INITIALIZED: 00623 case SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE: 00624 case SEQUENTIAL_JOURNAL_STATE_LOGGING_HEAD: 00625 case SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY: 00626 case SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL: 00627 /* reset journal state to allow further operation. */ 00628 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00629 00630 if (activeJournal->callback) { 00631 activeJournal->callback(status, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00632 } 00633 break; 00634 case SEQUENTIAL_JOURNAL_STATE_READING: 00635 /* reset journal state to allow further operation. */ 00636 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00637 00638 if (activeJournal->callback) { 00639 activeJournal->callback(status, FLASH_JOURNAL_OPCODE_READ_BLOB); 00640 } 00641 break; 00642 } 00643 00644 return; 00645 } 00646 00647 switch (operation) { 00648 case ARM_STORAGE_OPERATION_INITIALIZE: 00649 if (activeJournal->callback) { 00650 activeJournal->callback(JOURNAL_STATUS_OK, FLASH_JOURNAL_OPCODE_INITIALIZE); 00651 } 00652 break; 00653 00654 case ARM_STORAGE_OPERATION_ERASE_ALL: 00655 if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_RESETING) { 00656 activeJournal->nextSequenceNumber = 0; 00657 activeJournal->currentBlobIndex = (uint32_t)-1; 00658 activeJournal->info.sizeofJournaledBlob = 0; 00659 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00660 if (activeJournal->callback) { 00661 activeJournal->callback(JOURNAL_STATUS_OK, FLASH_JOURNAL_OPCODE_RESET); 00662 } 00663 } 00664 break; 00665 00666 case ARM_STORAGE_OPERATION_ERASE: 00667 if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE) { 00668 if (status <= ARM_DRIVER_OK) { 00669 if (activeJournal->callback) { 00670 activeJournal->callback(JOURNAL_STATUS_STORAGE_API_ERROR, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00671 } 00672 return; 00673 } 00674 00675 activeJournal->log.mtdEraseOffset += status; 00676 00677 if ((rc = flashJournalStrategySequential_log_progress()) != JOURNAL_STATUS_OK) { 00678 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00679 if (activeJournal->callback) { 00680 activeJournal->callback(rc, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00681 } 00682 return; 00683 } 00684 } else if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_RESETING) { 00685 activeJournal->nextSequenceNumber = 0; 00686 activeJournal->currentBlobIndex = (uint32_t)-1; 00687 activeJournal->info.sizeofJournaledBlob = 0; 00688 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; 00689 if (activeJournal->callback) { 00690 activeJournal->callback(JOURNAL_STATUS_OK, FLASH_JOURNAL_OPCODE_RESET); 00691 } 00692 } 00693 break; 00694 00695 case ARM_STORAGE_OPERATION_PROGRAM_DATA: 00696 // printf("journal mtdHandler: PROGRAM_DATA: received status of %ld\n", status); 00697 rc = status; 00698 activeJournal->log.mtdOffset += rc; 00699 activeJournal->log.amountLeftToLog -= rc; 00700 activeJournal->log.dataBeingLogged += rc; 00701 if (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) { 00702 activeJournal->log.tail.sizeofBlob += rc; 00703 } 00704 00705 if ((rc = flashJournalStrategySequential_log_progress()) < JOURNAL_STATUS_OK) { 00706 activeJournal->state = SEQUENTIAL_JOURNAL_STATE_INITIALIZED; /* reset state */ 00707 if (activeJournal->callback) { 00708 activeJournal->callback(rc, 00709 (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL) ? 00710 FLASH_JOURNAL_OPCODE_COMMIT : FLASH_JOURNAL_OPCODE_LOG_BLOB); 00711 } 00712 return; 00713 } 00714 if ((rc == JOURNAL_STATUS_OK) && (activeJournal->log.amountLeftToLog > 0)) { 00715 return; /* we've got pending asynchronous activity */ 00716 } 00717 if (activeJournal->callback) { 00718 activeJournal->callback(rc, (activeJournal->state == SEQUENTIAL_JOURNAL_STATE_INITIALIZED) ? 00719 FLASH_JOURNAL_OPCODE_COMMIT : FLASH_JOURNAL_OPCODE_LOG_BLOB); 00720 } 00721 break; 00722 00723 default: 00724 //printf("mtdHandler: unknown operation %u\n", operation); 00725 break; 00726 } 00727 }
Generated on Sun Jul 17 2022 08:25:31 by 1.7.2