Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage-helper.cpp Source File

storage-helper.cpp

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2018 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #include "storage-helper/storage-helper.h"
00020 #include "mbed_trace.h"
00021 
00022 #define TRACE_GROUP "SMCS"
00023 
00024 StorageHelper::StorageHelper(BlockDevice *bd, FileSystem *fs)
00025     : _bd(bd), _fs(fs), fs1(NULL), fs2(NULL), part1(NULL), part2(NULL)
00026 {
00027 }
00028 
00029 int StorageHelper::init() {
00030     static bool init_done = false;
00031     int status = 0;
00032 
00033     if(!init_done) {
00034         if (_bd) {
00035             status = _bd->init();
00036 
00037             if (status != BD_ERROR_OK) {
00038                 tr_warn("bd->init() failed with %d", status);
00039                 return -1;
00040             }
00041 
00042 #if (MCC_PLATFORM_PARTITION_MODE == 1)
00043             // store partition size
00044             mcc_platform_storage_size = _bd->size();
00045             tr_debug("init() - BlockDevice init OK, bd->size() = %llu", mcc_platform_storage_size);
00046 #else
00047             tr_debug("init() - BlockDevice init OK, bd->size() = %llu", _bd->size());
00048 #endif
00049 
00050         }
00051 
00052 #if (MCC_PLATFORM_PARTITION_MODE == 1)
00053 #if (NUMBER_OF_PARTITIONS > 0)
00054         status = init_and_mount_partition(&fs1, &part1, PRIMARY_PARTITION_NUMBER, ((const char*) MOUNT_POINT_PRIMARY+1));
00055         if (status != 0) {
00056 #if (MCC_PLATFORM_AUTO_PARTITION == 1)
00057             status = create_partitions();
00058             if (status != 0) {
00059                 return status;
00060             }
00061 #else
00062             tr_warn("primary partition init failed");
00063             return status;
00064 #endif
00065         }
00066 
00067 #if (NUMBER_OF_PARTITIONS == 2)
00068         status = init_and_mount_partition(&fs2, &part2, SECONDARY_PARTITION_NUMBER, ((const char*) MOUNT_POINT_SECONDARY+1));
00069         if (status != 0) {
00070 #if (MCC_PLATFORM_AUTO_PARTITION == 1)
00071             status = create_partitions();
00072             if (status != 0) {
00073                 return status;
00074             }
00075 #else
00076             tr_warn("secondary partition init failed");
00077             return status;
00078 #endif
00079         }
00080 #endif // (NUMBER_OF_PARTITIONS == 2)
00081 #if (NUMBER_OF_PARTITIONS > 2)
00082 #error "Invalid number of partitions!!!"
00083 #endif
00084 #endif // (NUMBER_OF_PARTITIONS > 0)
00085 #else  // Else for #if (MCC_PLATFORM_PARTITION_MODE == 1)
00086 
00087     fs1 = _fs;
00088     part1 = _bd;                   /* required for mcc_platform_reformat_storage */
00089     status = test_filesystem(fs1, _bd);
00090     if (status != 0) {
00091         tr_info("Formatting...");
00092         status = reformat_partition(fs1, _bd);
00093         if (status != 0) {
00094             tr_warn("Formatting failed with 0x%X", status);
00095             return status;
00096         }
00097     }
00098 #endif // MCC_PLATFORM_PARTITION_MODE
00099         init_done = true;
00100     }
00101     else {
00102         tr_debug("init already done");
00103     }
00104 
00105     return status;
00106 }
00107 
00108 int StorageHelper::sotp_init(void)
00109 {
00110     int status = FCC_STATUS_SUCCESS;
00111 // Include this only for Developer mode and a device which doesn't have in-built TRNG support.
00112 #if MBED_CONF_DEVICE_MANAGEMENT_DEVELOPER_MODE == 1
00113 #ifdef PAL_USER_DEFINED_CONFIGURATION
00114 #if !PAL_USE_HW_TRNG
00115     status = fcc_entropy_set(MBED_CLOUD_DEV_ENTROPY, FCC_ENTROPY_SIZE);
00116 
00117     if (status != FCC_STATUS_SUCCESS && status != FCC_STATUS_ENTROPY_ERROR) {
00118         tr_error("fcc_entropy_set failed with status %d", status);
00119         fcc_finalize();
00120         return status;
00121     }
00122 #endif // PAL_USE_HW_TRNG = 0
00123 /* Include this only for Developer mode. The application will use fixed RoT to simplify user-experience with the application.
00124 * With this change the application be reflashed/SOTP can be erased safely without invalidating the application credentials.
00125 */
00126     status = fcc_rot_set(MBED_CLOUD_DEV_ROT, FCC_ROT_SIZE);
00127 
00128     if (status != FCC_STATUS_SUCCESS && status != FCC_STATUS_ROT_ERROR) {
00129         tr_error("fcc_rot_set failed with status %d", status);
00130         fcc_finalize();
00131     } else {
00132         // We can return SUCCESS here as preexisting RoT/Entropy is expected flow.
00133         tr_info("Using hardcoded Root of Trust, not suitable for production use");
00134         status = FCC_STATUS_SUCCESS;
00135     }
00136 #endif // PAL_USER_DEFINED_CONFIGURATION
00137 #endif // #if MBED_CONF_DEVICE_MANAGEMENT_DEVELOPER_MODE == 1
00138     return status;
00139 }
00140 
00141 
00142 int StorageHelper::reformat_storage(void) {
00143     int status = -1;
00144 
00145     if (_bd) {
00146 #if (NUMBER_OF_PARTITIONS > 0)
00147         status = reformat_partition(fs1, part1);
00148         if (status != 0) {
00149             tr_warn("Formatting primary partition failed with 0x%X", status);
00150             return status;
00151         }
00152 #if (NUMBER_OF_PARTITIONS == 2)
00153         status = reformat_partition(fs2, part2);
00154         if (status != 0) {
00155             tr_warn("Formatting secondary partition failed with 0x%X", status);
00156             return status;
00157         }
00158 #endif
00159 #if (NUMBER_OF_PARTITIONS > 2)
00160 #error "Invalid number of partitions!!!"
00161 #endif
00162 #endif
00163 
00164 #if NUMBER_OF_PARTITIONS == 0
00165         status = StorageHelper::format(_fs, _bd);
00166 #endif
00167     }
00168 
00169     tr_info("Storage reformatted (%d)", status);
00170 
00171     return status;
00172 }
00173 
00174 int StorageHelper::format(FileSystem *fs, BlockDevice *bd) {
00175     if (!fs || !bd) return -1;
00176 
00177     int status;
00178 
00179     status = bd->init();
00180     if (status != 0) {
00181         return status;
00182     }
00183 
00184     status = fs->mount(bd);
00185     // might fail because already mounted, so ignore
00186 
00187     status = fs->reformat(bd);
00188     if (status != 0) {
00189         if (bd->erase(0, bd->size()) == 0) {
00190             if (fs->reformat(bd) == 0) {
00191                 status = 0;
00192                 printf("The storage reformatted successfully.\n");
00193             }
00194         }
00195     }
00196 
00197     return status;
00198 }
00199 
00200 #if (MCC_PLATFORM_PARTITION_MODE == 1)
00201 // bd must be initialized before calling this function.
00202 int StorageHelper::init_and_mount_partition(FileSystem **fs, BlockDevice** part, int number_of_partition, const char* mount_point) {
00203     int status;
00204 
00205     // Init fs only once.
00206     if (&(**fs) == NULL) {
00207         if (&(**part) == NULL) {
00208             *part = new MBRBlockDevice(_bd, number_of_partition);
00209         }
00210         status = (**part).init();
00211         if (status != 0) {
00212             (**part).deinit();
00213             tr_warn("Init of partition %d fail", number_of_partition);
00214             return status;
00215         }
00216         /* This next change mean that filesystem will be FAT. */
00217         *fs = new FATFileSystem(mount_point, &(**part));  /* this also mount fs. */
00218     }
00219     // re-init and format.
00220     else {
00221         status = (**part).init();
00222         if (status != 0) {
00223             (**part).deinit();
00224             tr_warn("Init of partition %d fail", number_of_partition);
00225             return status;
00226         }
00227 
00228         tr_debug("Formatting partition %d ...", number_of_partition);
00229         status = reformat_partition(&(**fs), &(**part));
00230         if (status != 0) {
00231             tr_warn("Formatting partition %d failed with 0x%X", number_of_partition, status);
00232             return status;
00233         }
00234     }
00235 
00236     status = test_filesystem(&(**fs), &(**part));
00237     if (status != 0) {
00238         tr_debug("Formatting partition %d ...", number_of_partition);
00239         status = reformat_partition(&(**fs), &(**part));
00240         if (status != 0) {
00241             tr_warn("Formatting partition %d failed with 0x%X", number_of_partition, status);
00242             return status;
00243         }
00244     }
00245 
00246     return status;
00247 }
00248 #endif
00249 
00250 int StorageHelper::reformat_partition(FileSystem *fs, BlockDevice* part) {
00251     return fs->reformat(part);
00252 }
00253 
00254 /* help function for testing filesystem availbility by umount and
00255 * mount filesystem again.
00256 * */
00257 int StorageHelper::test_filesystem(FileSystem *fs, BlockDevice* part) {
00258     // unmount
00259     int status = fs->unmount();
00260     if (status != 0) {
00261         tr_info("test_filesystem() - unmount fail %d", status);
00262         // should be OK, maybe not mounted...
00263     }
00264     // mount again
00265     status = fs->mount(part);
00266     if (status != 0) {
00267         tr_info("test_filesystem() - mount fail %d", status);
00268         return -1;
00269     }
00270     return status;
00271 }
00272 
00273 // create partitions, initialize and mount partitions
00274 #if ((MCC_PLATFORM_PARTITION_MODE == 1) && (MCC_PLATFORM_AUTO_PARTITION == 1))
00275 int StorageHelper::create_partitions(void) {
00276     int status;
00277 
00278 #if (NUMBER_OF_PARTITIONS > 0)
00279     if (mcc_platform_storage_size < PRIMARY_PARTITION_SIZE) {
00280         tr_error("create_partitions PRIMARY_PARTITION_SIZE too large!!! Storage's size is %" PRIu64 \
00281                 " and PRIMARY_PARTITION_SIZE is %" PRIu64,
00282                 (uint64_t)mcc_platform_storage_size, (uint64_t)PRIMARY_PARTITION_SIZE);
00283         assert(0);
00284     }
00285 
00286     status = MBRBlockDevice::partition(_bd, PRIMARY_PARTITION_NUMBER, 0x83, PRIMARY_PARTITION_START, PRIMARY_PARTITION_START + PRIMARY_PARTITION_SIZE);
00287     tr_debug("Creating primary partition ...");
00288     if (status != 0) {
00289         tr_warn("Creating primary partition failed 0x%X", status);
00290         return status;
00291     }
00292     tr_debug("Created primary partition");
00293 
00294     // init and format partition 1
00295     status = init_and_mount_partition(&fs1, &part1, PRIMARY_PARTITION_NUMBER, ((const char*) MOUNT_POINT_PRIMARY+1));
00296     if (status != 0) {
00297         return status;
00298     }
00299     tr_debug("Mounted primary partition");
00300 
00301 #if (NUMBER_OF_PARTITIONS == 2)
00302     // use cast (uint64_t) for fixing compile warning.
00303     if (mcc_platform_storage_size < ((uint64_t)PRIMARY_PARTITION_SIZE + (uint64_t)SECONDARY_PARTITION_SIZE)) {
00304         tr_error("create_partitions (PRIMARY_PARTITION_SIZE+SECONDARY_PARTITION_SIZE) too large!!! Storage's size is %" PRIu64 \
00305                 " and (PRIMARY_PARTITION_SIZE+SECONDARY_PARTITION_SIZE) %" PRIu64,
00306                 (uint64_t)mcc_platform_storage_size, (uint64_t)(PRIMARY_PARTITION_SIZE+SECONDARY_PARTITION_SIZE));
00307         assert(0);
00308     }
00309 
00310     // use cast (uint64_t) for fixing compile warning.
00311     status = MBRBlockDevice::partition(_bd, SECONDARY_PARTITION_NUMBER, 0x83, SECONDARY_PARTITION_START, (uint64_t) SECONDARY_PARTITION_START + (uint64_t) SECONDARY_PARTITION_SIZE);
00312     tr_debug("Creating secondary partition ...");
00313     if (status != 0) {
00314         tr_warn("Creating secondary partition failed 0x%X", status);
00315         return status;
00316     }
00317     tr_debug("Created secondary partition");
00318 
00319     // init and format partition 2
00320     status = init_and_mount_partition(&fs2, &part2, SECONDARY_PARTITION_NUMBER, ((const char*) MOUNT_POINT_SECONDARY+1));
00321     if (status != 0) {
00322         return status;
00323     }
00324     tr_debug("Mounted secondary partition");
00325 #endif
00326 #if (NUMBER_OF_PARTITIONS > 2)
00327 #error "Invalid number of partitions!!!"
00328 #endif
00329 #endif // (NUMBER_OF_PARTITIONS > 0)
00330     return status;
00331 }
00332 #endif // ((MCC_PLATFORM_PARTITION_MODE == 1) && (MCC_PLATFORM_AUTO_PARTITION == 1))