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.
storage_volume_manager.cpp
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 // This file is deprecated so deprecation warnings when building it are silenced 00019 #if defined ( __CC_ARM ) 00020 #pragma diag_suppress 1361 // Deprecated declaration 00021 #elif defined ( __GNUC__ ) 00022 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 00023 #endif 00024 00025 #include "storage-volume-manager/storage_volume_manager.h" 00026 #include <string.h> 00027 #include <inttypes.h> 00028 00029 /* redefine these macros to a printf() equivalent to emit trace */ 00030 #define tr_debug(...) 00031 #define tr_error(...) 00032 00033 /* 00034 * The following variable records the volume-manager instance which last setup 00035 * StorageVolumeManager::storageCallback() as a callback for a storage driver. 00036 * We use this value in the callback handler to de-multiplex the callback into a 00037 * volume-manager. 00038 */ 00039 static StorageVolumeManager *activeVolumeManager; 00040 00041 InitializeCallback_t initializeCallback; 00042 00043 #define STORAGE_API_DEFINITIONS_FOR_VOLUME(N) \ 00044 extern "C" ARM_DRIVER_VERSION GetVersion_ ## N(void) { \ 00045 return activeVolumeManager->volumes[(N)].GetVersion(); \ 00046 } \ 00047 ARM_STORAGE_CAPABILITIES GetCapabilities_ ## N(void) { \ 00048 return activeVolumeManager->volumes[(N)].GetCapabilities(); \ 00049 } \ 00050 int32_t Initialize_ ## N(ARM_Storage_Callback_t callback) { \ 00051 return activeVolumeManager->volumes[(N)].Initialize(callback); \ 00052 } \ 00053 int32_t Uninitialize_ ## N(void) { \ 00054 return activeVolumeManager->volumes[(N)].Uninitialize(); \ 00055 } \ 00056 int32_t PowerControl_ ## N(ARM_POWER_STATE state) { \ 00057 return activeVolumeManager->volumes[(N)].PowerControl(state); \ 00058 } \ 00059 int32_t ReadData_ ## N(uint64_t addr, void *data, uint32_t size) { \ 00060 return activeVolumeManager->volumes[(N)].ReadData(addr, data, size); \ 00061 } \ 00062 int32_t ProgramData_ ## N(uint64_t addr, const void *data, uint32_t size) { \ 00063 return activeVolumeManager->volumes[(N)].ProgramData(addr, data, size); \ 00064 } \ 00065 int32_t Erase_ ## N(uint64_t addr, uint32_t size) { \ 00066 return activeVolumeManager->volumes[(N)].Erase(addr, size); \ 00067 } \ 00068 int32_t EraseAll_ ## N(void) { \ 00069 return activeVolumeManager->volumes[(N)].EraseAll(); \ 00070 } \ 00071 ARM_STORAGE_STATUS GetStatus_ ## N(void) { \ 00072 return activeVolumeManager->volumes[(N)].GetStatus(); \ 00073 } \ 00074 int32_t GetInfo_ ## N(ARM_STORAGE_INFO *infoP) { \ 00075 return activeVolumeManager->volumes[(N)].GetInfo(infoP); \ 00076 } \ 00077 uint32_t ResolveAddress_ ## N(uint64_t addr) { \ 00078 return activeVolumeManager->volumes[(N)].ResolveAddress(addr); \ 00079 } \ 00080 int32_t GetNextBlock_ ## N(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP) { \ 00081 return activeVolumeManager->volumes[(N)].GetNextBlock(prevP, nextP); \ 00082 } \ 00083 int32_t GetBlock_ ## N(uint64_t addr, ARM_STORAGE_BLOCK *blockP) { \ 00084 return activeVolumeManager->volumes[(N)].GetBlock(addr, blockP); \ 00085 } \ 00086 ARM_DRIVER_STORAGE VIRTUAL_MTD_ ## N = { \ 00087 .GetVersion = GetVersion_ ## N, \ 00088 .GetCapabilities = GetCapabilities_ ## N, \ 00089 .Initialize = Initialize_ ## N, \ 00090 .Uninitialize = Uninitialize_ ## N, \ 00091 .PowerControl = PowerControl_ ## N, \ 00092 .ReadData = ReadData_ ## N, \ 00093 .ProgramData = ProgramData_ ## N, \ 00094 .Erase = Erase_ ## N, \ 00095 .EraseAll = EraseAll_ ## N, \ 00096 .GetStatus = GetStatus_ ## N, \ 00097 .GetInfo = GetInfo_ ## N, \ 00098 .ResolveAddress = ResolveAddress_ ## N, \ 00099 .GetNextBlock = GetNextBlock_ ## N, \ 00100 .GetBlock = GetBlock_ ## N, \ 00101 }; 00102 00103 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_1 STORAGE_API_DEFINITIONS_FOR_VOLUME(0) 00104 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_2 STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_1 STORAGE_API_DEFINITIONS_FOR_VOLUME(1) 00105 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_3 STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_2 STORAGE_API_DEFINITIONS_FOR_VOLUME(2) 00106 #define STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_4 STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_3 STORAGE_API_DEFINITIONS_FOR_VOLUME(3) 00107 /* ... add more of the above if ever needed */ 00108 00109 #define STORAGE_API_DEFINITIONS_FOR_VOLUMES(N) EXPAND(CONCATENATE(STORAGE_API_DEFINITIONS_LIST_FOR_VOLUME_, N)) 00110 00111 STORAGE_API_DEFINITIONS_FOR_VOLUMES(MAX_VOLUMES); 00112 00113 int32_t StorageVolumeManager::initialize(ARM_DRIVER_STORAGE *mtd, InitializeCallback_t callback) 00114 { 00115 activeVolume = NULL; 00116 initializeCallback = callback; 00117 00118 storage = mtd; 00119 storageCapabilities = mtd->GetCapabilities(); 00120 00121 int32_t rc = mtd->GetInfo(&storageInfo); 00122 if (rc != ARM_DRIVER_OK) { 00123 tr_error("StorageVolumeManager::initialize: call to GetInfo() failed with %" PRId32, rc); 00124 return ARM_DRIVER_ERROR; 00125 } 00126 00127 rc = mtd->Initialize(storageCallback); 00128 if (rc < ARM_DRIVER_OK) { 00129 tr_error("Initialize() failed with error %" PRId32, rc); 00130 return ARM_DRIVER_ERROR; 00131 } 00132 00133 activeVolumeManager = this; 00134 if (rc == ARM_DRIVER_OK) { 00135 /* there is pending asynchronous activity which will result in a callback later */ 00136 return ARM_DRIVER_OK; 00137 } 00138 00139 /* Clear previously allocated volumes */ 00140 for (size_t i = 0; i < MAX_VOLUMES; i++) { 00141 if (volumes[i].isAllocated()) { 00142 volumes[i].deallocate(); 00143 } 00144 } 00145 00146 /* synchronous completion */ 00147 initialized = true; 00148 return 1; 00149 } 00150 00151 int32_t StorageVolumeManager::addVolume(uint64_t addr, uint64_t size, StorageVolume **volumePP) 00152 { 00153 tr_debug("StorageVolumeManager_addVolume: addr = %" PRIu32 ", size = %" PRIu32, (uint32_t)addr, (uint32_t)size); 00154 00155 *volumePP = NULL; 00156 00157 /* 00158 * sanity checks for arguments 00159 */ 00160 ARM_STORAGE_INFO info; 00161 int32_t rc; 00162 rc = storage->GetInfo(&info); 00163 if (rc != ARM_DRIVER_OK) { 00164 tr_error("StorageVolumeManager_addVolume: storage->GetInfo() failed with %" PRId32, rc); 00165 return ARM_DRIVER_ERROR; 00166 } 00167 if (size > info.total_storage) { 00168 tr_error("StorageVolumeManager_addVolume: 'size' parameter too large: %" PRIu32, (uint32_t)size); 00169 return ARM_DRIVER_ERROR; 00170 } 00171 ARM_STORAGE_BLOCK firstBlock; 00172 rc = storage->GetNextBlock(NULL, &firstBlock); 00173 if (rc != ARM_DRIVER_OK) { 00174 tr_error("StorageVolumeManager_addVolume: storage->GetNextBlock() failed with %" PRId32, rc); 00175 return ARM_DRIVER_ERROR; 00176 } 00177 if ((addr < firstBlock.addr) || ((addr + size) > (firstBlock.addr + info.total_storage))) { 00178 tr_error("StorageVolumeManager_addVolume: given range [%" PRIu32 ", %" PRIu32 ") isn't entirely contained within available storage range [%" PRIu32 ", %" PRIu32 ")", 00179 (uint32_t)addr, (uint32_t)(addr + size), (uint32_t)firstBlock.addr, (uint32_t)(firstBlock.addr + info.total_storage)); 00180 return ARM_DRIVER_ERROR; 00181 } 00182 00183 /* Find an unused volume. */ 00184 uint32_t index = findIndexOfUnusedVolume(); 00185 if (index == MAX_VOLUMES) { 00186 return STORAGE_VOLUME_MANAGER_STATUS_ERROR_EXHASTED_VOLUMES; 00187 } 00188 00189 /* setup volume */ 00190 StorageVolume *volumeP = &volumes[index]; 00191 volumeP->setup(addr, size, this); 00192 *volumePP = volumeP; 00193 tr_debug("StorageVolumeManager_addVolume: setup volume at index %" PRIu32, index); 00194 00195 return ARM_DRIVER_OK; 00196 } 00197 00198 int32_t StorageVolumeManager::addVolume_C(uint64_t addr, uint64_t size, _ARM_DRIVER_STORAGE *mtd) 00199 { 00200 int32_t rc; 00201 StorageVolume *volumeP; 00202 if ((rc = addVolume(addr, size, &volumeP)) < ARM_DRIVER_OK) { 00203 return rc; 00204 } 00205 00206 /* locate index of the allocated volume */ 00207 size_t index; 00208 for (index = 0; index < MAX_VOLUMES; index++) { 00209 if (volumes[index].isAllocated() && (&volumes[index] == volumeP)) { 00210 break; 00211 } 00212 } 00213 if (index == MAX_VOLUMES) { 00214 return STORAGE_VOLUME_MANAGER_STATUS_ERROR_EXHASTED_VOLUMES; 00215 } 00216 00217 if (index == 0) { 00218 *mtd = VIRTUAL_MTD_0; 00219 } else if (index == 1) { 00220 *mtd = VIRTUAL_MTD_1; 00221 } else if (index == 2) { 00222 *mtd = VIRTUAL_MTD_2; 00223 } else if (index == 3) { 00224 *mtd = VIRTUAL_MTD_3; 00225 } else { 00226 return ARM_DRIVER_ERROR; 00227 } 00228 00229 return ARM_DRIVER_OK; 00230 } 00231 00232 int32_t StorageVolumeManager::lookupVolume(uint64_t addr, StorageVolume **volumePP) 00233 { 00234 /* 00235 * Traverse the volumes in reverse order of creation; this allows newly created volumes to supersede the older ones. 00236 */ 00237 for (size_t index = MAX_VOLUMES - 1; index > 0; --index) { 00238 StorageVolume *volume = &volumes[index]; 00239 if ((addr >= volume->getVolumeOffset()) && (addr < (volume->getVolumeOffset() + volume->getVolumeSize()))) { 00240 *volumePP = volume; 00241 return ARM_DRIVER_OK; 00242 } 00243 } 00244 00245 return ARM_DRIVER_ERROR; 00246 } 00247 00248 void StorageVolumeManager::storageCallback(int32_t status, ARM_STORAGE_OPERATION operation) 00249 { 00250 tr_debug("StorageVolumeManager_callback: operation = %u", operation); 00251 StorageVolumeManager *volumeManager = activeVolumeManager; 00252 00253 switch (operation) { 00254 case ARM_STORAGE_OPERATION_INITIALIZE: 00255 volumeManager->initialized = true; 00256 if (initializeCallback != NULL) { 00257 initializeCallback(status); 00258 } 00259 break; 00260 00261 case ARM_STORAGE_OPERATION_POWER_CONTROL: 00262 case ARM_STORAGE_OPERATION_READ_DATA: 00263 case ARM_STORAGE_OPERATION_PROGRAM_DATA: 00264 case ARM_STORAGE_OPERATION_ERASE: 00265 case ARM_STORAGE_OPERATION_ERASE_ALL: 00266 if (volumeManager->activeVolume != NULL) { 00267 /* Reset activeVolume and invoke callback. We reset activeVolume before the 00268 * callback because the callback may attempt to launch another asynchronous 00269 * operation, which requires 'activeVolume' to be NULL. */ 00270 StorageVolume *callbackVolume = volumeManager->activeVolume; /* remember the volume which will receive the callback. */ 00271 volumeManager->activeVolume = NULL; 00272 00273 if (callbackVolume->isAllocated() && callbackVolume->getCallback()) { 00274 (callbackVolume->getCallback())(status, operation); 00275 } 00276 } 00277 break; 00278 00279 default: 00280 tr_error("StorageVolumeManager_callback: unknown operation %u", operation); 00281 break; 00282 } 00283 } 00284 00285 size_t StorageVolumeManager::findIndexOfUnusedVolume(void) const { 00286 size_t index; 00287 for (index = 0; index < MAX_VOLUMES; index++) { 00288 if (!volumes[index].isAllocated()) { 00289 break; 00290 } 00291 } 00292 return index; 00293 }
Generated on Tue Jul 12 2022 14:24:39 by
