Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DirectAccessDevicekey.cpp Source File

DirectAccessDevicekey.cpp

00001 /*
00002  * Copyright (c) 2018 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 // ----------------------------------------------------------- Includes -----------------------------------------------------------
00018 #if DEVICE_FLASH
00019 #include "DirectAccessDevicekey.h"
00020 #include "drivers/FlashIAP.h"
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include "mbed_error.h"
00024 #include "MbedCRC.h"
00025 #include "mbed_trace.h"
00026 #define TRACE_GROUP "DADK"
00027 
00028 using namespace mbed;
00029 
00030 // --------------------------------------------------------- Definitions ----------------------------------------------------------
00031 typedef struct {
00032     uint32_t address;
00033     size_t   size;
00034 } tdbstore_area_data_t;
00035 
00036 typedef struct {
00037     uint16_t trailer_size;
00038     uint16_t data_size;
00039     uint32_t crc;
00040 } reserved_trailer_t;
00041 
00042 #define TDBSTORE_NUMBER_OF_AREAS 2
00043 #define MAX_DEVICEKEY_DATA_SIZE 64
00044 #define RESERVED_AREA_SIZE (MAX_DEVICEKEY_DATA_SIZE+sizeof(reserved_trailer_t)) /* DeviceKey Max Data size + metadata trailer */
00045 
00046 #define STR_EXPAND(tok) #tok
00047 #define STR(tok) STR_EXPAND(tok)
00048 
00049 // -------------------------------------------------- Local Functions Declaration ----------------------------------------------------
00050 static int calc_area_params(FlashIAP *flash, uint32_t out_tdb_start_offset, uint32_t tdb_end_offset,
00051                             tdbstore_area_data_t *area_params);
00052 static int reserved_data_get(FlashIAP *flash, tdbstore_area_data_t *area_params, void *reserved_data_buf,
00053                              size_t reserved_data_buf_size, size_t *actual_data_size_ptr);
00054 static inline uint32_t align_up(uint64_t val, uint64_t size);
00055 static inline uint32_t align_down(uint64_t val, uint64_t size);
00056 static uint32_t calc_crc(uint32_t init_crc, uint32_t data_size, const void *data_buf);
00057 
00058 // -------------------------------------------------- API Functions Implementation ----------------------------------------------------
00059 int direct_access_to_devicekey(uint32_t tdb_start_offset, uint32_t tdb_end_offset, void *data_buf,
00060                                size_t data_buf_size, size_t *actual_data_size_ptr)
00061 {
00062     int status = MBED_ERROR_INVALID_ARGUMENT;
00063     FlashIAP flash;
00064     uint8_t active_area = 0;
00065     tdbstore_area_data_t area_params[TDBSTORE_NUMBER_OF_AREAS];
00066     memset(area_params, 0, sizeof(area_params));
00067     bool is_flash_init = false;
00068 
00069     if (NULL == data_buf) {
00070         tr_error("Invalid Data Buf Argument");
00071         goto exit_point;
00072     }
00073 
00074     status = flash.init();
00075     if (status != 0) {
00076         tr_error("FlashIAP init failed - err: %d", status);
00077         status = MBED_ERROR_FAILED_OPERATION;
00078         goto exit_point;
00079     }
00080 
00081     is_flash_init = true;
00082 
00083     status = calc_area_params(&flash, tdb_start_offset, tdb_end_offset, area_params);
00084     if (status != MBED_SUCCESS) {
00085         tr_error("Couldn't calulate Area Params - err: %d", status);
00086         goto exit_point;
00087     }
00088 
00089     /* DeviceKey data can be found either in first or second Flash Area */
00090     /* Loop through Areas to find valid DeviceKey data */
00091     for (active_area = 0; active_area < TDBSTORE_NUMBER_OF_AREAS; active_area++) {
00092         status = reserved_data_get(&flash, &area_params[active_area], data_buf, data_buf_size, actual_data_size_ptr);
00093         if (status == MBED_SUCCESS) {
00094             break;
00095         }
00096     }
00097 
00098     if (status != MBED_SUCCESS) {
00099         status = MBED_ERROR_ITEM_NOT_FOUND;
00100         tr_error("Couldn't find valid DeviceKey - err: %d", status);
00101     }
00102 
00103 exit_point:
00104     if (true == is_flash_init) {
00105         flash.deinit();
00106     }
00107 
00108     return status;
00109 }
00110 
00111 int  get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint32_t *out_tdb_end_offset)
00112 {
00113     uint32_t flash_end_address;
00114     uint32_t flash_start_address;
00115     uint32_t aligned_start_address;
00116     uint32_t aligned_end_address;
00117     FlashIAP flash;
00118     bool is_default_configuration = false;
00119     uint32_t tdb_size;
00120 
00121     if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "FILESYSTEM") == 0) {
00122 #ifndef MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS
00123         return MBED_ERROR_ITEM_NOT_FOUND;
00124 #else
00125         *out_tdb_start_offset =  MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS;
00126         tdb_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE;
00127 #endif
00128 
00129     } else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) {
00130 #ifndef MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS
00131         return MBED_ERROR_ITEM_NOT_FOUND;
00132 #else
00133         *out_tdb_start_offset =  MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
00134         tdb_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE;
00135 #endif
00136 
00137     } else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_INTERNAL") == 0) {
00138 #ifndef MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS
00139         return MBED_ERROR_ITEM_NOT_FOUND;
00140 #else
00141         *out_tdb_start_offset =  MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
00142         tdb_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE;
00143 #endif
00144 
00145     } else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "default") == 0) {
00146 #ifndef MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS
00147         return MBED_ERROR_ITEM_NOT_FOUND;
00148 #else
00149 #if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH
00150         *out_tdb_start_offset =  MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
00151         tdb_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE;
00152 #elif COMPONENT_SD
00153         tdb_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE;
00154 #else
00155         return MBED_ERROR_UNSUPPORTED;
00156 #endif // COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH
00157 #endif // MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS
00158     } else {
00159         return MBED_ERROR_UNSUPPORTED;
00160     }
00161 
00162     *out_tdb_end_offset = (*out_tdb_start_offset) + tdb_size;
00163 
00164     if ((*out_tdb_start_offset == 0) && (tdb_size == 0)) {
00165         is_default_configuration = true;
00166     } else if ((*out_tdb_start_offset == 0) || (tdb_size == 0)) {
00167         return MBED_ERROR_UNSUPPORTED;
00168     }
00169 
00170     int ret = flash.init();
00171     if (ret != 0) {
00172         return MBED_ERROR_FAILED_OPERATION;
00173     }
00174 
00175     uint32_t flash_first_writable_sector_address = (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR,
00176                                                                        flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)));
00177 
00178     //Get flash parameters before starting
00179     flash_start_address = flash.get_flash_start();
00180     flash_end_address = flash_start_address + flash.get_flash_size();
00181 
00182     if (!is_default_configuration) {
00183         aligned_start_address = align_down(*out_tdb_start_offset, flash.get_sector_size(*out_tdb_start_offset));
00184         aligned_end_address = align_up(*out_tdb_end_offset, flash.get_sector_size(*out_tdb_end_offset - 1));
00185         if ((*out_tdb_start_offset != aligned_start_address) || (*out_tdb_end_offset != aligned_end_address)
00186                 || (*out_tdb_end_offset > flash_end_address)) {
00187             flash.deinit();
00188             return MBED_ERROR_INVALID_OPERATION;
00189         }
00190     } else {
00191         aligned_start_address = flash_end_address - (flash.get_sector_size(flash_end_address - 1) * 2);
00192         if (aligned_start_address < flash_first_writable_sector_address) {
00193             flash.deinit();
00194             return MBED_ERROR_INVALID_OPERATION;
00195         }
00196         *out_tdb_start_offset = aligned_start_address;
00197         *out_tdb_end_offset = flash_end_address;
00198     }
00199 
00200     flash.deinit();
00201 
00202     return MBED_SUCCESS;
00203 }
00204 
00205 // -------------------------------------------------- Local Functions Implementation ----------------------------------------------------
00206 static int calc_area_params(FlashIAP *flash, uint32_t out_tdb_start_offset, uint32_t tdb_end_offset,
00207                             tdbstore_area_data_t *area_params)
00208 {
00209     uint32_t bd_size = 0;
00210     uint32_t initial_erase_size = flash->get_sector_size(out_tdb_start_offset);
00211     uint32_t erase_unit_size = initial_erase_size;
00212     size_t cur_area_size = 0;
00213 
00214     if ((tdb_end_offset < (out_tdb_start_offset + 2 * RESERVED_AREA_SIZE - 1)) ||
00215             (tdb_end_offset > (flash->get_flash_start() + flash->get_flash_size()))) {
00216         tr_error("calc_area_params failed - Invalid input addresses");
00217         return MBED_ERROR_INVALID_ARGUMENT;
00218     }
00219 
00220     // Entire TDBStore can't exceed 32 bits
00221     bd_size = (tdb_end_offset - out_tdb_start_offset + 1);
00222 
00223     while (cur_area_size < bd_size / 2) {
00224         erase_unit_size = flash->get_sector_size(out_tdb_start_offset + cur_area_size);
00225         cur_area_size += erase_unit_size;
00226     }
00227 
00228     area_params[0].address = out_tdb_start_offset;
00229     area_params[0].size = cur_area_size;
00230     area_params[1].address = out_tdb_start_offset + cur_area_size;
00231     area_params[1].size = bd_size - cur_area_size;
00232 
00233     return MBED_SUCCESS;
00234 }
00235 
00236 static int reserved_data_get(FlashIAP *flash, tdbstore_area_data_t *area_params, void *reserved_data_buf,
00237                              size_t reserved_data_buf_size, size_t *actual_data_size_ptr)
00238 {
00239     int status = MBED_SUCCESS;
00240     reserved_trailer_t trailer;
00241     uint8_t *buf;
00242     int ret = MBED_SUCCESS;
00243     bool erased = true;
00244     size_t actual_size = 0;
00245     uint32_t initial_crc = 0xFFFFFFFF;
00246     uint32_t crc = initial_crc;
00247     uint8_t blank = flash->get_erase_value();
00248 
00249     /* Read Into trailer deviceKey metadata */
00250     ret = flash->read(&trailer, area_params->address + MAX_DEVICEKEY_DATA_SIZE, sizeof(trailer));
00251     if (ret != MBED_SUCCESS) {
00252         status =  MBED_ERROR_READ_FAILED;
00253         goto exit_point;
00254     }
00255 
00256     buf = reinterpret_cast <uint8_t *>(&trailer);
00257     for (uint32_t i = 0; i < sizeof(trailer); i++) {
00258         if (buf[i] != blank) {
00259             erased = false;
00260             break;
00261         }
00262     }
00263 
00264     if (true == erased) {
00265         /* Metadata is erased , DeviceKey Data is NOT in this Area */
00266         status =  MBED_ERROR_ITEM_NOT_FOUND;
00267         goto exit_point;
00268     }
00269 
00270     actual_size = trailer.data_size;
00271     if (actual_data_size_ptr != NULL) {
00272         *actual_data_size_ptr = actual_size;
00273     }
00274     if (reserved_data_buf_size < actual_size) {
00275         status =  MBED_ERROR_INVALID_SIZE;
00276         goto exit_point;
00277     }
00278 
00279     buf = reinterpret_cast <uint8_t *>(reserved_data_buf);
00280 
00281     /* Read DeviceKey Data */
00282     ret = flash->read(buf, area_params->address, (uint32_t)actual_size);
00283     if (ret != MBED_SUCCESS) {
00284         status = MBED_ERROR_READ_FAILED;
00285         goto exit_point;
00286     }
00287 
00288     crc = calc_crc(crc, (uint32_t)actual_size, buf);
00289     if (crc != trailer.crc) {
00290         status = MBED_ERROR_INVALID_DATA_DETECTED;
00291     }
00292 
00293 exit_point:
00294 
00295     return status;
00296 }
00297 
00298 static inline uint32_t align_up(uint64_t val, uint64_t size)
00299 {
00300     return (((val - 1) / size) + 1) * size;
00301 }
00302 
00303 static inline uint32_t align_down(uint64_t val, uint64_t size)
00304 {
00305     return (((val) / size)) * size;
00306 }
00307 
00308 static uint32_t calc_crc(uint32_t init_crc, uint32_t data_size, const void *data_buf)
00309 {
00310     uint32_t crc;
00311     MbedCRC<POLY_32BIT_ANSI, 32> ct(init_crc, 0x0, true, false);
00312     ct.compute(data_buf, data_size, &crc);
00313     return crc;
00314 }
00315 #endif // DEVICE_FLASH