Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fcc_sotp.c Source File

fcc_sotp.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //  
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may 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,
00012 // WITHOUT 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 #include <string.h>
00018 #include "fcc_sotp.h"
00019 #include "pv_error_handling.h"
00020 
00021 
00022 static bool get_sotp_type(fcc_sotp_type_e sotp_type, size_t *required_size_out)
00023 {
00024     size_t required_size;
00025 
00026     switch (sotp_type) {
00027         case FCC_SOTP_TYPE_ROT:
00028             required_size = FCC_ROT_SIZE;
00029             break;
00030         case FCC_SOTP_TYPE_FACTORY_DISABLE:
00031             required_size = FCC_FACTORY_DISABLE_FLAG_SIZE;
00032             break;
00033         case FCC_SOTP_TYPE_ENTROPY:
00034             required_size = FCC_ENTROPY_SIZE;
00035             break;
00036         default:
00037             SA_PV_LOG_ERR("Non existant sotp_type provided");
00038             return false;
00039     }
00040 
00041     // Success
00042     *required_size_out = required_size;
00043 
00044     return true;
00045 }
00046 
00047 fcc_status_e fcc_sotp_data_store(const uint8_t *data, size_t data_size, fcc_sotp_type_e sotp_type)
00048 {
00049     bool success;
00050     size_t required_size = 0;
00051     int64_t aligned_8_bytes_buffer[MAX_SOTP_BUFFER_SIZE / 8];
00052 
00053     SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " sotp_type = %d", (uint32_t)data_size, (int)sotp_type);
00054 
00055     SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid param data");
00056 
00057     success = get_sotp_type(sotp_type, &required_size);
00058     SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), FCC_STATUS_ERROR, "Failed for get_sotp_type()");
00059 
00060     // Assert that buffer provided is of correct size
00061     SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size != required_size), FCC_STATUS_ERROR, "Wrong buf_size provided. Must be size of exactly %" PRIu32 " bytes", (uint32_t)required_size);
00062 
00063     // Write buf to SOTP. Cast is OK since size must be divisible by 8
00064     
00065     /*
00066     * Copy from data (uint8_t*) to aligned_8_bytes_buffer (uint64_t*) to make sure that data is 8 byte aligned.
00067     * Since SOTP_Set() gets a pointer to int64_t, if it is not aligned, and we just cast it to uint8_t*,
00068     * ARMCC functions like memcpy will assume 8 byte alignment resulting in possible access of unallocated memory. 
00069     */
00070     memcpy(aligned_8_bytes_buffer, data, data_size);
00071 
00072     success = SOTP_Set((uint8_t)sotp_type, (data_size >> 3), aligned_8_bytes_buffer);
00073 
00074     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00075 
00076     // FIXME: When SOTP returns real status - we must translate the error
00077     return success ? FCC_STATUS_SUCCESS : FCC_STATUS_ERROR;
00078 }
00079 
00080 fcc_status_e fcc_sotp_data_retrieve(uint8_t *data_out, size_t data_size_max, size_t *data_actual_size_out, fcc_sotp_type_e sotp_type)
00081 {
00082     bool success;
00083     size_t required_size = 0;
00084     int64_t aligned_8_bytes_buffer[MAX_SOTP_BUFFER_SIZE / 8];
00085 
00086     uint8_t data_size_as_array_of_int64; /* store as array of int64_t */
00087 
00088     SA_PV_LOG_INFO_FUNC_ENTER("data_out = %" PRIu32 " sotp_type = %d", (uint32_t)data_size_max, (int)sotp_type);
00089 
00090     SA_PV_ERR_RECOVERABLE_RETURN_IF((data_out == NULL), FCC_STATUS_INVALID_PARAMETER, "invalid param data_out");
00091 
00092     success = get_sotp_type(sotp_type, &required_size);
00093     SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), FCC_STATUS_ERROR, "Failed for get_sotp_type()");
00094 
00095     // Assert that buffer provided is of correct size
00096     SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size_max < required_size), FCC_STATUS_ERROR, "Wrong data_size provided. Must be size of exactly %" PRIu32 " bytes", (uint32_t)required_size);
00097 
00098     // Retrieve buf from SOTP. Cast is OK since size must be multiple of 8
00099     // FIXME: When SOTP returns real status - we must translate the error
00100     success = SOTP_Get((uint8_t)sotp_type, aligned_8_bytes_buffer, &data_size_as_array_of_int64);
00101     SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), FCC_STATUS_ERROR, "SOTP_Get failed");
00102 
00103     // Copy from aligned buffer to callers uint8_t* buffer
00104     memcpy(data_out, aligned_8_bytes_buffer, data_size_as_array_of_int64 * sizeof(int64_t));
00105 
00106     // Convert back to bytes
00107     *data_actual_size_out = (size_t)(data_size_as_array_of_int64 << 3);
00108     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00109 
00110     // FIXME: When SOTP returns real status - we must translate the error
00111     return FCC_STATUS_SUCCESS;
00112 }
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00121 // FIXME: All code from here on should be removed once SOTP APIs are implemented
00122 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00123 
00124 /*
00125 * These globals mock the SOTP storage.
00126 * Should be removed once SOTP is implemented.
00127 */
00128 sotp_entree_s g_sotp_rot = { 0 };
00129 sotp_entree_s g_sotp_factory_disabled = { 0 };
00130 sotp_entree_s g_sotp_entropy = { 0 };
00131 
00132 // API that mocks future SOTP_Set()
00133 bool SOTP_Set(uint8_t type, uint8_t size, const int64_t *data)
00134 {
00135     sotp_entree_s entree;
00136 
00137     entree.data_size_in_bytes = (size << 3);
00138     memcpy(entree.data, data, entree.data_size_in_bytes);
00139     entree.type = type;
00140     entree.write_disabled = true;
00141 
00142     switch (type) {
00143         case FCC_SOTP_TYPE_ENTROPY:
00144             if (!g_sotp_entropy.write_disabled) {
00145                 g_sotp_entropy = entree;
00146             } else {
00147                 return false;
00148             }
00149             break;
00150         case FCC_SOTP_TYPE_ROT:
00151             if (!g_sotp_rot.write_disabled) {
00152                 g_sotp_rot = entree;
00153             } else {
00154                 return false;
00155             }
00156             break;
00157         case FCC_SOTP_TYPE_FACTORY_DISABLE:
00158             if (!g_sotp_factory_disabled.write_disabled) {
00159                 g_sotp_factory_disabled = entree;
00160             } else {
00161                 return false;
00162             }
00163             break;
00164         default:
00165             return false;
00166     }
00167 
00168     return true;
00169 }
00170 
00171 // API that mocks future SOTP_Get()
00172 bool SOTP_Get(uint8_t type, int64_t *data_out, uint8_t *data_size_out)
00173 {
00174     switch (type) {
00175         case FCC_SOTP_TYPE_ENTROPY:
00176             *data_size_out = g_sotp_entropy.data_size_in_bytes >> 3;
00177             memcpy(data_out, g_sotp_entropy.data, g_sotp_entropy.data_size_in_bytes);
00178             break;
00179         case FCC_SOTP_TYPE_ROT:
00180             *data_size_out = g_sotp_rot.data_size_in_bytes >> 3;
00181             memcpy(data_out, g_sotp_rot.data, g_sotp_rot.data_size_in_bytes);
00182             break;
00183         case FCC_SOTP_TYPE_FACTORY_DISABLE:
00184             *data_size_out = g_sotp_factory_disabled.data_size_in_bytes >> 3;
00185             memcpy(data_out, g_sotp_factory_disabled.data, g_sotp_factory_disabled.data_size_in_bytes);
00186             break;
00187         default:
00188             return false;
00189     }
00190 
00191     return true;
00192 }
00193 
00194 void SOTP_TestOnly_reset()
00195 {
00196     memset(&g_sotp_entropy, 0, sizeof(g_sotp_entropy));
00197     memset(&g_sotp_rot, 0, sizeof(g_sotp_rot));
00198     memset(&g_sotp_factory_disabled, 0, sizeof(g_sotp_factory_disabled));
00199 }