Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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_private.h" 00019 #include "flash-journal-strategy-sequential/flash_journal_strategy_sequential.h" 00020 #include "support_funcs.h" 00021 #include <string.h> 00022 #include <stdio.h> 00023 00024 SequentialFlashJournal_t *activeJournal; 00025 00026 /* forward declarations */ 00027 void mtdHandler(int32_t status, ARM_STORAGE_OPERATION operation); 00028 00029 static inline int32_t mtdGetTotalCapacity(ARM_DRIVER_STORAGE *mtd, uint64_t *capacityP) 00030 { 00031 /* fetch MTD's INFO */ 00032 ARM_STORAGE_INFO mtdInfo; 00033 int32_t rc = mtd->GetInfo(&mtdInfo); 00034 if (rc != ARM_DRIVER_OK) { 00035 return JOURNAL_STATUS_STORAGE_API_ERROR; 00036 } 00037 *capacityP = mtdInfo.total_storage; 00038 00039 return JOURNAL_STATUS_OK; 00040 } 00041 00042 static inline int32_t flashJournalStrategySequential_read_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob) 00043 { 00044 if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) { 00045 return JOURNAL_STATUS_PARAMETER; 00046 } 00047 if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) { 00048 return JOURNAL_STATUS_NOT_INITIALIZED; 00049 } 00050 if (journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) { 00051 return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */ 00052 } 00053 // printf("read sanity checks: totalDataRead = %lu, sizeofJournaledBlob = %lu\n", (uint32_t)journal->read.totalDataRead, (uint32_t)journal->info.sizeofJournaledBlob); 00054 if ((journal->info.sizeofJournaledBlob == 0) || (journal->read.totalDataRead == journal->info.sizeofJournaledBlob)) { 00055 journal->read.totalDataRead = 0; 00056 return JOURNAL_STATUS_EMPTY; 00057 } 00058 00059 return JOURNAL_STATUS_OK; 00060 } 00061 00062 static inline int32_t flashJournalStrategySequential_log_sanityChecks(SequentialFlashJournal_t *journal, const void *blob, size_t sizeofBlob) 00063 { 00064 if ((journal == NULL) || (blob == NULL) || (sizeofBlob == 0)) { 00065 return JOURNAL_STATUS_PARAMETER; 00066 } 00067 if ((journal->state == SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED) || (journal->state == SEQUENTIAL_JOURNAL_STATE_INIT_SCANNING_LOG_HEADERS)) { 00068 return JOURNAL_STATUS_NOT_INITIALIZED; 00069 } 00070 if ((journal->state != SEQUENTIAL_JOURNAL_STATE_INITIALIZED) && (journal->state != SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY)) { 00071 return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */ 00072 } 00073 if (journal->state == SEQUENTIAL_JOURNAL_STATE_INITIALIZED) { 00074 if (sizeofBlob > journal->info.capacity) { 00075 return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */ 00076 } 00077 } else if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) { 00078 if (journal->log.offset + sizeofBlob > journal->log.tailOffset) { 00079 return JOURNAL_STATUS_BOUNDED_CAPACITY; /* adding this log chunk would cause us to exceed capacity (write past the tail). */ 00080 } 00081 } 00082 00083 return JOURNAL_STATUS_OK; 00084 } 00085 00086 static inline int32_t flashJournalStrategySequential_commit_sanityChecks(SequentialFlashJournal_t *journal) 00087 { 00088 if (journal == NULL) { 00089 return JOURNAL_STATUS_PARAMETER; 00090 } 00091 if (journal->state == SEQUENTIAL_JOURNAL_STATE_LOGGING_BODY) { 00092 if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) { 00093 return JOURNAL_STATUS_ERROR; 00094 } 00095 if ((journal->log.offset == ARM_STORAGE_INVALID_OFFSET) || 00096 (journal->log.tailOffset == ARM_STORAGE_INVALID_OFFSET) || 00097 (journal->log.tailOffset < journal->log.offset) || 00098 (journal->log.tail.sizeofBlob == 0) || 00099 (journal->log.tail.sizeofBlob > journal->info.capacity)) { 00100 return JOURNAL_STATUS_ERROR; /* journal is in an un-expected state. */ 00101 } 00102 } 00103 00104 return JOURNAL_STATUS_OK; 00105 } 00106 00107 int32_t flashJournalStrategySequential_initialize(FlashJournal_t *_journal, 00108 ARM_DRIVER_STORAGE *mtd, 00109 const FlashJournal_Ops_t *ops, 00110 FlashJournal_Callback_t callback) 00111 { 00112 int32_t rc; 00113 00114 SequentialFlashJournal_t *journal; 00115 activeJournal = journal = (SequentialFlashJournal_t *)_journal; 00116 journal->state = SEQUENTIAL_JOURNAL_STATE_NOT_INITIALIZED; 00117 00118 /* fetch MTD's total capacity */ 00119 uint64_t mtdCapacity; 00120 if ((rc = mtdGetTotalCapacity(mtd, &mtdCapacity)) != JOURNAL_STATUS_OK) { 00121 return rc; 00122 } 00123 ARM_STORAGE_INFO mtdInfo; 00124 if ((rc = mtd->GetInfo(&mtdInfo)) != ARM_DRIVER_OK) { 00125 return JOURNAL_STATUS_STORAGE_API_ERROR; 00126 } 00127 00128 /* initialize the journal structure */ 00129 memcpy(&journal->ops, ops, sizeof(FlashJournal_Ops_t)); 00130 journal->mtd = mtd; 00131 journal->mtdCapabilities = mtd->GetCapabilities(); /* fetch MTD's capabilities */ 00132 journal->sequentialSkip = mtdCapacity / SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS; 00133 journal->info.capacity = journal->sequentialSkip - (sizeof(SequentialFlashJournalLogHead_t) + sizeof(SequentialFlashJournalLogTail_t)); /* effective capacity */ 00134 journal->info.program_unit = mtdInfo.program_unit; 00135 journal->callback = callback; 00136 journal->prevCommand = FLASH_JOURNAL_OPCODE_INITIALIZE; 00137 00138 /* initialize MTD */ 00139 ARM_STORAGE_CAPABILITIES mtdCaps = mtd->GetCapabilities(); 00140 rc = mtd->Initialize(mtdHandler); 00141 if (rc < ARM_DRIVER_OK) { 00142 memset(journal, 0, sizeof(FlashJournal_t)); 00143 return JOURNAL_STATUS_STORAGE_API_ERROR; 00144 } 00145 if ((mtdCaps.asynchronous_ops) && (rc == ARM_DRIVER_OK)) { 00146 return JOURNAL_STATUS_OK; /* we've got pending asynchronous activity. */ 00147 } 00148 00149 if ((rc = discoverLatestLoggedBlob(journal)) != JOURNAL_STATUS_OK) { 00150 return rc; 00151 } 00152 00153 return 1; /* synchronous completion */ 00154 } 00155 00156 FlashJournal_Status_t flashJournalStrategySequential_getInfo(FlashJournal_t *_journal, FlashJournal_Info_t *infoP) 00157 { 00158 SequentialFlashJournal_t *journal; 00159 activeJournal = journal = (SequentialFlashJournal_t *)_journal; 00160 00161 memcpy(infoP, &journal->info, sizeof(FlashJournal_Info_t)); 00162 return JOURNAL_STATUS_OK; 00163 } 00164 00165 int32_t flashJournalStrategySequential_read(FlashJournal_t *_journal, void *blob, size_t sizeofBlob) 00166 { 00167 SequentialFlashJournal_t *journal; 00168 activeJournal = journal = (SequentialFlashJournal_t *)_journal; 00169 00170 int32_t rc; 00171 if ((rc = flashJournalStrategySequential_read_sanityChecks(journal, blob, sizeofBlob)) != JOURNAL_STATUS_OK) { 00172 return rc; 00173 } 00174 00175 journal->read.blob = blob; 00176 journal->read.sizeofBlob = sizeofBlob; 00177 00178 if ((journal->prevCommand != FLASH_JOURNAL_OPCODE_READ_BLOB) || (journal->read.totalDataRead == 0)) { 00179 journal->read.offset = journal->mtdStartOffset 00180 + (journal->currentBlobIndex * journal->sequentialSkip) 00181 + sizeof(SequentialFlashJournalLogHead_t); 00182 journal->read.totalDataRead = 0; 00183 } else { 00184 /* journal->read.offset is already set from the previous read execution */ 00185 // printf("flashJournalStrategySequential_read: continuing read of %lu from offset %lu\n", sizeofBlob, (uint32_t)journal->read.offset); 00186 } 00187 journal->read.dataBeingRead = blob; 00188 journal->read.amountLeftToRead = ((journal->info.sizeofJournaledBlob - journal->read.totalDataRead) < sizeofBlob) ? 00189 (journal->info.sizeofJournaledBlob - journal->read.totalDataRead) : sizeofBlob; 00190 // printf("amount left to read %u\n", journal->read.amountLeftToRead); 00191 00192 journal->state = SEQUENTIAL_JOURNAL_STATE_READING; 00193 journal->prevCommand = FLASH_JOURNAL_OPCODE_READ_BLOB; 00194 return flashJournalStrategySequential_read_progress(); 00195 } 00196 00197 int32_t flashJournalStrategySequential_log(FlashJournal_t *_journal, const void *blob, size_t size) 00198 { 00199 SequentialFlashJournal_t *journal; 00200 activeJournal = journal = (SequentialFlashJournal_t *)_journal; 00201 00202 int32_t rc; 00203 if ((rc = flashJournalStrategySequential_log_sanityChecks(journal, blob, size)) != JOURNAL_STATUS_OK) { 00204 return rc; 00205 } 00206 00207 journal->log.blob = blob; 00208 journal->log.sizeofBlob = size; 00209 00210 if (journal->prevCommand != FLASH_JOURNAL_OPCODE_LOG_BLOB) { 00211 uint32_t logBlobIndex = journal->currentBlobIndex + 1; 00212 if (logBlobIndex == SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS) { 00213 logBlobIndex = 0; 00214 } 00215 journal->log.eraseOffset = journal->mtdStartOffset + (logBlobIndex * journal->sequentialSkip); 00216 00217 /* ensure that the request is at least as large as the minimum program unit */ 00218 if (size < journal->info.program_unit) { 00219 return JOURNAL_STATUS_SMALL_LOG_REQUEST; 00220 } 00221 00222 journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE; /* start with erasing the log region */ 00223 journal->prevCommand = FLASH_JOURNAL_OPCODE_LOG_BLOB; 00224 } else { 00225 journal->log.dataBeingLogged = blob; 00226 journal->log.amountLeftToLog = size; 00227 } 00228 00229 return flashJournalStrategySequential_log_progress(); 00230 } 00231 00232 int32_t flashJournalStrategySequential_commit(FlashJournal_t *_journal) 00233 { 00234 SequentialFlashJournal_t *journal; 00235 activeJournal = journal = (SequentialFlashJournal_t *)_journal; 00236 00237 int32_t rc; 00238 if ((rc = flashJournalStrategySequential_commit_sanityChecks(journal)) != JOURNAL_STATUS_OK) { 00239 return rc; 00240 } 00241 00242 if (journal->prevCommand == FLASH_JOURNAL_OPCODE_LOG_BLOB) { 00243 journal->log.offset = journal->log.tailOffset; 00244 journal->log.dataBeingLogged = (const uint8_t *)&journal->log.tail; 00245 journal->log.amountLeftToLog = sizeof(SequentialFlashJournalLogTail_t); 00246 journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_TAIL; 00247 } else { 00248 uint32_t logBlobIndex = journal->currentBlobIndex + 1; 00249 if (logBlobIndex == SEQUENTIAL_FLASH_JOURNAL_MAX_LOGGED_BLOBS) { 00250 logBlobIndex = 0; 00251 } 00252 journal->log.eraseOffset = journal->mtdStartOffset + (logBlobIndex * journal->sequentialSkip); 00253 journal->state = SEQUENTIAL_JOURNAL_STATE_LOGGING_ERASE; 00254 } 00255 00256 journal->prevCommand = FLASH_JOURNAL_OPCODE_COMMIT; 00257 return flashJournalStrategySequential_log_progress(); 00258 } 00259 00260 int32_t flashJournalStrategySequential_reset(FlashJournal_t *_journal) 00261 { 00262 SequentialFlashJournal_t *journal; 00263 activeJournal = journal = (SequentialFlashJournal_t *)_journal; 00264 00265 journal->state = SEQUENTIAL_JOURNAL_STATE_RESETING; 00266 00267 journal->prevCommand = FLASH_JOURNAL_OPCODE_RESET; 00268 return flashJournalStrategySequential_reset_progress(); 00269 }
Generated on Tue Jul 12 2022 12:58:39 by
1.7.2