Lee Kai Xuan / mbed-os

Fork of mbed-os by erkin yucel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage_volume_manager.cpp Source File

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 }