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.
Dependents: blinky_max32630fthr
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 14:21:21 by
1.7.2
