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