Simon Cooksey / mbed-os
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage_volume.cpp Source File

storage_volume.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 tr_debug() to a printf() equivalent to emit trace */
00023 #define tr_debug(...)
00024 
00025 
00026 void StorageVolume::setup(uint64_t _addr, uint64_t _size, StorageVolumeManager *_volumeManager)
00027 {
00028     volumeOffset  = _addr;
00029     volumeSize    = _size;
00030     volumeManager = _volumeManager;
00031     allocated     = true;
00032 }
00033 
00034 ARM_DRIVER_VERSION StorageVolume::GetVersion(void)
00035 {
00036     ARM_DRIVER_VERSION bad_ver = {0, 0};
00037 
00038     if (!allocated) {
00039         return bad_ver;
00040     }
00041     return volumeManager->getStorage()->GetVersion();
00042 }
00043 
00044 ARM_STORAGE_CAPABILITIES StorageVolume::GetCapabilities(void)
00045 {
00046     ARM_STORAGE_CAPABILITIES bad_cap;
00047 
00048     if (!allocated) {
00049         memset(&bad_cap, 0, sizeof(ARM_STORAGE_CAPABILITIES));
00050         return bad_cap;
00051     }
00052     return volumeManager->getStorage()->GetCapabilities();
00053 }
00054 
00055 int32_t StorageVolume::Initialize(ARM_Storage_Callback_t _callback)
00056 {
00057     if (!allocated) {
00058         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00059     }
00060 
00061     callback = _callback; /* nothing else to do since we've already initialized the storage */
00062     return 1; /* synchronous completion. */
00063 }
00064 
00065 int32_t StorageVolume::Uninitialize(void)
00066 {
00067     if (!allocated) {
00068         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00069     }
00070 
00071     return 1; /* synchronous completion. */
00072 }
00073 
00074 int32_t StorageVolume::PowerControl(ARM_POWER_STATE state)
00075 {
00076     tr_debug("called powerControl(%u)", state);
00077     if (!allocated) {
00078         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00079     }
00080     if (volumeManager->activeVolume != NULL) {
00081         return ARM_DRIVER_ERROR_BUSY;
00082     }
00083 
00084     volumeManager->activeVolume = this;
00085     int32_t rc = volumeManager->getStorage()->PowerControl(state);
00086     if (rc != ARM_DRIVER_OK) {
00087         volumeManager->activeVolume = NULL; /* we're certain that there is no more pending asynch. activity */
00088     }
00089     return rc;
00090 }
00091 
00092 int32_t StorageVolume::ReadData(uint64_t addr, void *data, uint32_t size)
00093 {
00094     tr_debug("called ReadData(%" PRIu32 ", %" PRIu32 ")", (uint32_t)addr, size);
00095     if (!allocated) {
00096         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00097     }
00098     if (volumeManager->activeVolume != NULL) {
00099         return ARM_DRIVER_ERROR_BUSY;
00100     }
00101     if ((size > volumeSize) || ((addr + size) > volumeSize)) {
00102         return ARM_DRIVER_ERROR_PARAMETER;
00103     }
00104 
00105     volumeManager->activeVolume = this;
00106     int32_t rc = volumeManager->getStorage()->ReadData(volumeOffset + addr, data, size);
00107     if (rc != ARM_DRIVER_OK) {
00108         volumeManager->activeVolume = NULL; /* we're certain that there is no more pending asynch. activity */
00109     }
00110     return rc;
00111 }
00112 
00113 int32_t StorageVolume::ProgramData(uint64_t addr, const void *data, uint32_t size)
00114 {
00115     tr_debug("called ProgramData(%" PRIu32 ", %" PRIu32 ")", (uint32_t)addr, size);
00116     if (!allocated) {
00117         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00118     }
00119     if (volumeManager->activeVolume != NULL) {
00120         return ARM_DRIVER_ERROR_BUSY;
00121     }
00122     if ((size > volumeSize) || ((addr + size) > volumeSize)) {
00123         return ARM_DRIVER_ERROR_PARAMETER;
00124     }
00125 
00126     volumeManager->activeVolume = this;
00127     int32_t rc = volumeManager->getStorage()->ProgramData(volumeOffset + addr, data, size);
00128     if (rc != ARM_DRIVER_OK) {
00129         volumeManager->activeVolume = NULL; /* we're certain that there is no more pending asynch. activity */
00130     }
00131     return rc;
00132 }
00133 
00134 int32_t StorageVolume::Erase(uint64_t addr, uint32_t size)
00135 {
00136     tr_debug("called erase(%" PRIu32 ", %" PRIu32 ")", (uint32_t)addr, size);
00137     if (!allocated) {
00138         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00139     }
00140     if (volumeManager->activeVolume != NULL) {
00141         return ARM_DRIVER_ERROR_BUSY;
00142     }
00143     if ((size > volumeSize) || ((addr + size) > volumeSize)) {
00144         return ARM_DRIVER_ERROR_PARAMETER;
00145     }
00146 
00147     volumeManager->activeVolume = this;
00148     int32_t rc = volumeManager->getStorage()->Erase(volumeOffset + addr, size);
00149     if (rc != ARM_DRIVER_OK) {
00150         volumeManager->activeVolume = NULL; /* we're certain that there is no more pending asynch. activity */
00151     }
00152     return rc;
00153 }
00154 
00155 int32_t StorageVolume::EraseAll(void)
00156 {
00157     tr_debug("called eraseAll");
00158     if (!allocated) {
00159         return STORAGE_VOLUME_MANAGER_STATUS_ERROR_VOLUME_NOT_ALLOCATED;
00160     }
00161     if (volumeManager->activeVolume != NULL) {
00162         return ARM_DRIVER_ERROR_BUSY;
00163     }
00164 
00165     int32_t rc;
00166 
00167     /* Allow EraseAll() only if the volume spans the entire storage. */
00168     {
00169         ARM_STORAGE_INFO info;
00170         rc = volumeManager->getStorage()->GetInfo(&info);
00171         if (rc != ARM_DRIVER_OK) {
00172             return ARM_DRIVER_ERROR;
00173         }
00174 
00175         if ((volumeOffset != 0) || (volumeSize != info.total_storage)) {
00176             return ARM_DRIVER_ERROR_UNSUPPORTED;
00177         }
00178     }
00179 
00180     volumeManager->activeVolume = this;
00181     rc = volumeManager->getStorage()->EraseAll();
00182     if (rc != ARM_DRIVER_OK) {
00183         volumeManager->activeVolume = NULL; /* we're certain that there is no more pending asynch. activity */
00184     }
00185     return rc;
00186 }
00187 
00188 ARM_STORAGE_STATUS StorageVolume::GetStatus(void)
00189 {
00190     const uint32_t busy = ((volumeManager->activeVolume != NULL) ? (uint32_t)1 : (uint32_t)0);
00191     ARM_STORAGE_STATUS status = {0, 0};
00192     status.busy = busy;
00193     return status;
00194 }
00195 
00196 int32_t StorageVolume::GetInfo(ARM_STORAGE_INFO *infoP)
00197 {
00198     int32_t rc;
00199     rc = volumeManager->getStorage()->GetInfo(infoP);
00200     if (rc != ARM_DRIVER_OK) {
00201         return ARM_DRIVER_ERROR;
00202     }
00203 
00204     infoP->total_storage = volumeSize;
00205     return ARM_DRIVER_OK;
00206 }
00207 
00208 uint32_t StorageVolume::ResolveAddress(uint64_t addr) {
00209     return (uint32_t)(volumeOffset + addr);
00210 }
00211 
00212 int32_t StorageVolume::GetNextBlock(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP)
00213 {
00214     int32_t rc;
00215     ARM_STORAGE_BLOCK tmpBlock;
00216     do {
00217         /* iterate forward */
00218         rc = volumeManager->getStorage()->GetNextBlock(prevP, &tmpBlock);
00219         if (rc != ARM_DRIVER_OK) {
00220             return rc;
00221         }
00222 
00223         /* Stop iteration if we have progressed past the boundary of this volume. */
00224         if (tmpBlock.addr >= (volumeOffset + volumeSize)) {
00225             return ARM_DRIVER_ERROR;
00226         }
00227     } while (!this->overlapsWithBlock(&tmpBlock));
00228 
00229     if (nextP) {
00230         memcpy(nextP, &tmpBlock, sizeof(ARM_STORAGE_BLOCK));
00231         transformBlockToVolume(nextP);
00232     }
00233     return ARM_DRIVER_OK;
00234 }
00235 
00236 int32_t StorageVolume::GetBlock(uint64_t addr, ARM_STORAGE_BLOCK *blockP)
00237 {
00238     ARM_STORAGE_BLOCK tmpBlock;
00239     int32_t rc = volumeManager->getStorage()->GetBlock(ResolveAddress(addr), &tmpBlock);
00240     if (rc != ARM_DRIVER_OK) {
00241         return rc;
00242     }
00243     if (!this->overlapsWithBlock(&tmpBlock)) {
00244         return ARM_DRIVER_ERROR;
00245     }
00246 
00247     if (blockP) {
00248         memcpy(blockP, &tmpBlock, sizeof(ARM_STORAGE_BLOCK));
00249         transformBlockToVolume(blockP);
00250     }
00251     return ARM_DRIVER_OK;
00252 }