Toyomasa Watarai / Mbed OS Mbed-example-WS-W27

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_rtos.c Source File

pal_rtos.c

00001 /*
00002 * Copyright (c) 2016 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 
00018 #include "pal_rtos.h"
00019 #include "pal_plat_rtos.h"
00020 #include "pal_Crypto.h"
00021 
00022 
00023 #if PAL_UNIQUE_THREAD_PRIORITY
00024 //! Threads priorities array.
00025 uint32_t g_palThreadPriorities[PAL_NUMBER_OF_THREADS_PRIORITIES] = {0};
00026 #endif //PAL_UNIQUE_THREAD_PRIORITY
00027 
00028 palMutexID_t g_palThreadInitMutex = NULLPTR;
00029 
00030 //! static variables for Random functionality.
00031 //! CTR-DRBG context to be used for generating random numbers from given seed
00032 static palCtrDrbgCtxHandle_t s_ctrDRBGCtx = NULLPTR;
00033 
00034 
00035 static uint64_t g_palDeviceBootTimeInSec = 0;
00036 
00037 /*
00038  * Here we define const keys for RoT derivation algorithm.
00039  * Must be 16 characters or less
00040  */
00041 #define PAL_STORAGE_SIGNATURE_128_BIT_KEY  "RoTStorageSgn128"
00042 #define PAL_STORAGE_ENCRYPTION_128_BIT_KEY "RoTStorageEnc128"
00043 #define PAL_STORAGE_ENCRYPTION_256_BIT_KEY "StorageEnc256HMACSHA256SIGNATURE"
00044 
00045 static bool palRTOSInitialized = false;
00046 
00047 palStatus_t pal_RTOSInitialize(void* opaqueContext)
00048 {
00049     palStatus_t status = PAL_SUCCESS;
00050 
00051     if (palRTOSInitialized)
00052     {
00053         return PAL_SUCCESS;
00054     }
00055     memset(g_palThreadPriorities, 0, sizeof(g_palThreadPriorities));
00056     status = pal_osMutexCreate(&g_palThreadInitMutex);
00057     if(PAL_SUCCESS == status)
00058     {
00059         status = pal_plat_RTOSInitialize (opaqueContext);
00060         if(PAL_SUCCESS == status)
00061         {
00062             palRTOSInitialized = true;
00063         }
00064     }
00065 
00066     return status;
00067 }
00068 
00069 palStatus_t pal_RTOSDestroy(void)
00070 {
00071     palStatus_t status = PAL_SUCCESS;
00072     int i = 0;
00073 
00074     if(palRTOSInitialized == true)
00075     {
00076         for (i = 0; i < PAL_MAX_NUMBER_OF_THREADS; ++i)
00077         {
00078             palThreadID_t tempID = i;
00079             pal_osThreadTerminate(&tempID);
00080         }
00081         palRTOSInitialized = false;
00082 
00083         status = pal_osMutexDelete(&g_palThreadInitMutex);
00084         if ((NULLPTR != s_ctrDRBGCtx) && (PAL_SUCCESS == status))
00085         {
00086             status = pal_CtrDRBGFree(&s_ctrDRBGCtx);
00087         }
00088         if (PAL_SUCCESS == status)
00089         {
00090             status = pal_plat_RTOSDestroy ();
00091         }
00092 
00093     }
00094     else
00095     {
00096         status = PAL_ERR_NOT_INITIALIZED ;
00097     }
00098     return status;
00099 }
00100 
00101 void pal_osReboot(void)
00102 {
00103     pal_plat_osReboot ();
00104 }
00105 
00106 uint64_t pal_osKernelSysTick(void)
00107 {
00108     static uint64_t lastValue = 0;
00109     static uint64_t wraparoundsDetected = 0;
00110     const uint64_t one = 1;
00111     uint64_t tics = pal_plat_osKernelSysTick ();
00112     uint64_t tmp = tics + (wraparoundsDetected << 32);
00113 
00114     if (tmp < lastValue) //erez's "wraparound algorithm" if we detect a wrap around add 1 to the higher 32 bits
00115     {
00116         tmp = tmp + (one << 32);
00117         wraparoundsDetected++;
00118     }
00119     lastValue = tmp;
00120     return (uint64_t)tmp;
00121 }
00122 
00123 
00124 uint64_t pal_osKernelSysTickMicroSec(uint64_t microseconds)
00125 {
00126     uint64_t result;
00127     result = pal_plat_osKernelSysTickMicroSec (microseconds);
00128     return result;
00129 }
00130 
00131 uint64_t pal_osKernelSysMilliSecTick(uint64_t sysTicks)
00132 {
00133     uint64_t result = 0;
00134     uint64_t osTickFreq = pal_plat_osKernelSysTickFrequency ();
00135     if ((sysTicks) && (osTickFreq)) // > 0
00136     {
00137         result = (uint64_t)((sysTicks) / osTickFreq * PAL_TICK_TO_MILLI_FACTOR); //convert ticks per second to milliseconds
00138     }
00139 
00140     return result;
00141 }
00142 
00143 uint64_t pal_osKernelSysTickFrequency(void)
00144 {
00145     uint64_t result;
00146     result = pal_plat_osKernelSysTickFrequency ();
00147     return result;
00148 }
00149 
00150 palStatus_t pal_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, uint32_t* stackPtr, palThreadLocalStore_t* store, palThreadID_t* threadID)
00151 {
00152     palStatus_t status = PAL_SUCCESS;
00153     //! check if the priority have been used by other thread before
00154     if(PAL_osPriorityError == priority)
00155     {
00156         return PAL_ERR_INVALID_ARGUMENT ;
00157     }
00158 
00159 
00160 #if PAL_UNIQUE_THREAD_PRIORITY
00161     uint32_t incrementedPriorityNum = pal_osAtomicIncrement((int32_t*)&(g_palThreadPriorities[priority+PRIORITY_INDEX_OFFSET]),1);
00162     // if incrementedPriorityNum != 1 the cell is already occupied by other thread with the same priority.
00163     if (incrementedPriorityNum != 1)
00164     {
00165         *threadID = NULLPTR;
00166         status = PAL_ERR_RTOS_PRIORITY ;
00167     }
00168 #endif //PAL_IGNORE_UNIQUE_THREAD_PRIORITY
00169 
00170     if (PAL_SUCCESS == status)
00171     {
00172         status = pal_plat_osThreadCreate (function, funcArgument, priority, stackSize, NULL, store, threadID);
00173     #if PAL_UNIQUE_THREAD_PRIORITY
00174         if (PAL_SUCCESS != status)
00175         {
00176             g_palThreadPriorities[priority+PRIORITY_INDEX_OFFSET]= 0 ;
00177         }
00178     #endif //PAL_IGNORE_UNIQUE_THREAD_PRIORITY
00179     }
00180 
00181     return status;
00182 }
00183 
00184 palStatus_t pal_osThreadCreateWithAlloc(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadLocalStore_t* store, palThreadID_t* threadID)
00185 {
00186     palStatus_t status = PAL_SUCCESS;
00187 
00188     //! check if the priority have been used by other thread before
00189     if(PAL_osPriorityError == priority)
00190     {
00191         return PAL_ERR_INVALID_ARGUMENT ;
00192     }
00193 
00194 #if PAL_UNIQUE_THREAD_PRIORITY
00195     uint32_t incrementedPriorityNum = pal_osAtomicIncrement((int32_t*)&(g_palThreadPriorities[priority+PRIORITY_INDEX_OFFSET]),1);
00196     // if incrementedPriorityNum != 1 the cell is already occupied by other thread with the same priority.
00197     if (incrementedPriorityNum != 1)
00198     {
00199         *threadID = NULLPTR;
00200         status = PAL_ERR_RTOS_PRIORITY ;
00201     }
00202 #endif //PAL_IGNORE_UNIQUE_THREAD_PRIORITY
00203 
00204     if (PAL_SUCCESS == status)
00205     {
00206         status = pal_plat_osThreadCreate (function, funcArgument, priority, stackSize, NULL, store, threadID);
00207     #if PAL_UNIQUE_THREAD_PRIORITY
00208         if (PAL_SUCCESS != status)
00209         {
00210             g_palThreadPriorities[priority+PRIORITY_INDEX_OFFSET]= 0 ;
00211         }
00212     #endif //PAL_IGNORE_UNIQUE_THREAD_PRIORITY
00213     }
00214 
00215     return status;
00216 }
00217 
00218 
00219 palStatus_t pal_osThreadTerminate(palThreadID_t* threadID)
00220 {
00221     palStatus_t status;
00222     if ((NULL == threadID) || (PAL_INVALID_THREAD == *threadID))
00223     {
00224         return PAL_ERR_INVALID_ARGUMENT ;
00225     }
00226     status = pal_plat_osThreadTerminate (threadID);
00227     return status;
00228 }
00229 
00230 palThreadID_t pal_osThreadGetId(void)
00231 {
00232     palThreadID_t result;
00233     result = pal_plat_osThreadGetId ();
00234     return result;
00235 }
00236 
00237 palThreadLocalStore_t*  pal_osThreadGetLocalStore(void)
00238 {
00239     void* result;
00240     result = pal_plat_osThreadGetLocalStore ();
00241     return result;
00242 }
00243 
00244 palStatus_t pal_osDelay(uint32_t milliseconds)
00245 {
00246     palStatus_t status;
00247     status = pal_plat_osDelay (milliseconds);
00248     return status;
00249 }
00250 
00251 
00252 palStatus_t pal_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID)
00253 {
00254     palStatus_t status;
00255     status = pal_plat_osTimerCreate (function, funcArgument, timerType, timerID);
00256     return status;
00257 }
00258 
00259 palStatus_t pal_osTimerStart(palTimerID_t timerID, uint32_t millisec)
00260 {
00261     palStatus_t status;
00262     if (0 == millisec)
00263     {
00264         return PAL_ERR_RTOS_VALUE ;
00265     }
00266     status = pal_plat_osTimerStart (timerID, millisec);
00267     return status;
00268 }
00269 
00270 palStatus_t pal_osTimerStop(palTimerID_t timerID)
00271 {
00272     palStatus_t status;
00273     status = pal_plat_osTimerStop (timerID);
00274     return status;
00275 }
00276 
00277 palStatus_t pal_osTimerDelete(palTimerID_t* timerID)
00278 {
00279     palStatus_t status;
00280     status = pal_plat_osTimerDelete (timerID);
00281     return status;
00282 }
00283 
00284 palStatus_t pal_osMutexCreate(palMutexID_t* mutexID)
00285 {
00286     palStatus_t status;
00287     status = pal_plat_osMutexCreate (mutexID);
00288     return status;
00289 }
00290 
00291 palStatus_t pal_osMutexWait(palMutexID_t mutexID, uint32_t millisec)
00292 {
00293     palStatus_t status;
00294     status = pal_plat_osMutexWait (mutexID, millisec);
00295     return status;
00296 }
00297 
00298 palStatus_t pal_osMutexRelease(palMutexID_t mutexID)
00299 {
00300     palStatus_t status;
00301     status = pal_plat_osMutexRelease (mutexID);
00302     return status;
00303 }
00304 
00305 palStatus_t pal_osMutexDelete(palMutexID_t* mutexID)
00306 {
00307     palStatus_t status;
00308     status = pal_plat_osMutexDelete (mutexID);
00309     return status;
00310 }
00311 palStatus_t pal_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID)
00312 {
00313     palStatus_t status;
00314     status = pal_plat_osSemaphoreCreate (count, semaphoreID);
00315     return status;
00316 }
00317 
00318 palStatus_t pal_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec,  int32_t* countersAvailable)
00319 {
00320     palStatus_t status;
00321     status = pal_plat_osSemaphoreWait (semaphoreID, millisec, countersAvailable);
00322     return status;
00323 }
00324 
00325 palStatus_t pal_osSemaphoreRelease(palSemaphoreID_t semaphoreID)
00326 {
00327     palStatus_t status;
00328     status = pal_plat_osSemaphoreRelease (semaphoreID);
00329     return status;
00330 }
00331 
00332 palStatus_t pal_osSemaphoreDelete(palSemaphoreID_t* semaphoreID)
00333 {
00334     palStatus_t status;
00335     status = pal_plat_osSemaphoreDelete (semaphoreID);
00336     return status;
00337 }
00338 
00339 palStatus_t pal_osPoolCreate(uint32_t blockSize, uint32_t blockCount, palMemoryPoolID_t* memoryPoolID)
00340 {
00341     palStatus_t status;
00342     status = pal_plat_osPoolCreate (blockSize, blockCount, memoryPoolID);
00343     return status;
00344 }
00345 
00346 void* pal_osPoolAlloc(palMemoryPoolID_t memoryPoolID)
00347 {
00348     void* result;
00349     result = pal_plat_osPoolAlloc (memoryPoolID);
00350     return result;
00351 }
00352 
00353 void* pal_osPoolCAlloc(palMemoryPoolID_t memoryPoolID)
00354 {
00355     void* result;
00356     //TODO(nirson01): debug print in case of failed alloc?
00357     result = pal_plat_osPoolCAlloc (memoryPoolID);
00358     return result;
00359 }
00360 
00361 palStatus_t pal_osPoolFree(palMemoryPoolID_t memoryPoolID, void* block)
00362 {
00363     palStatus_t status;
00364     //TODO(nirson01): debug print in case of failed alloc?
00365     status = pal_plat_osPoolFree (memoryPoolID, block);
00366     return status;
00367 }
00368 
00369 palStatus_t pal_osPoolDestroy(palMemoryPoolID_t* memoryPoolID)
00370 {
00371     palStatus_t status;
00372     status = pal_plat_osPoolDestroy (memoryPoolID);  
00373     return status;
00374 }
00375 
00376 palStatus_t pal_osMessageQueueCreate(uint32_t messageQCount, palMessageQID_t* messageQID)
00377 {
00378     palStatus_t status;
00379     status = pal_plat_osMessageQueueCreate (messageQCount, messageQID);
00380     return status;
00381 }
00382 
00383 palStatus_t pal_osMessagePut(palMessageQID_t messageQID, uint32_t info, uint32_t timeout)
00384 {
00385     palStatus_t status;
00386     status = pal_plat_osMessagePut (messageQID, info, timeout);
00387     return status;
00388 }
00389 
00390 palStatus_t pal_osMessageGet(palMessageQID_t messageQID, uint32_t timeout, uint32_t* messageValue)
00391 {
00392     palStatus_t status;
00393     status = pal_plat_osMessageGet (messageQID, timeout, messageValue);
00394     return status;
00395 }
00396 
00397 palStatus_t pal_osMessageQueueDestroy(palMessageQID_t* messageQID)
00398 {
00399     palStatus_t status;
00400     status = pal_plat_osMessageQueueDestroy (messageQID);
00401     return status;
00402 }
00403 
00404 int32_t pal_osAtomicIncrement(int32_t* valuePtr, int32_t increment)
00405 {
00406     int32_t result;
00407     result = pal_plat_osAtomicIncrement (valuePtr, increment);
00408     return result;
00409 }
00410 
00411 inline PAL_PRIVATE uint64_t pal_sysTickTimeToSec()
00412 {
00413     uint64_t sysTicksFromBoot = pal_osKernelSysTick();
00414     uint64_t secFromBoot = pal_osKernelSysMilliSecTick(sysTicksFromBoot) / PAL_MILLI_PER_SECOND;
00415 
00416     return secFromBoot;
00417 }
00418 
00419 uint64_t pal_osGetTime(void)
00420 {
00421     uint64_t curSysTimeInSec = 0;
00422     if (0 < g_palDeviceBootTimeInSec) //time was previously set
00423     {
00424         uint64_t secFromBoot = pal_sysTickTimeToSec();
00425         curSysTimeInSec = g_palDeviceBootTimeInSec + secFromBoot; //boot time in sec + sec passed since boot
00426     }
00427 
00428     return curSysTimeInSec;
00429 }
00430 
00431 palStatus_t pal_osSetTime(uint64_t seconds)
00432 {
00433     palStatus_t status = PAL_SUCCESS;
00434     if (seconds < (uint64_t)PAL_MIN_SEC_FROM_EPOCH)
00435     {
00436         status = PAL_ERR_INVALID_TIME ;
00437     }
00438     else
00439     {
00440         uint64_t secFromBoot = pal_sysTickTimeToSec();
00441         g_palDeviceBootTimeInSec = seconds - secFromBoot; //update device boot time
00442     }
00443 
00444     return status;
00445 }
00446 
00447 palStatus_t pal_osRandom32bit(uint32_t *random)
00448 {
00449     palStatus_t status = PAL_SUCCESS;
00450 
00451     if (NULL == random)
00452     {
00453         return PAL_ERR_INVALID_ARGUMENT ;
00454     }
00455         
00456     status = pal_osRandomBuffer((uint8_t*)random, sizeof(uint32_t));
00457     return status;
00458 }
00459 
00460 palStatus_t pal_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes)
00461 {
00462     palStatus_t status = PAL_SUCCESS;
00463 
00464     if (NULL == randomBuf)
00465     {
00466         return PAL_ERR_INVALID_ARGUMENT ;
00467     }
00468 
00469     if (NULLPTR == s_ctrDRBGCtx)
00470     {
00471         uint8_t seed[PAL_INITIAL_RANDOM_SIZE] = {0}; //in order to get 128-bits initial seed
00472         status = pal_plat_osRandomBuffer (seed, sizeof(seed));
00473         if (PAL_SUCCESS != status)
00474         {
00475             goto finish;
00476         }
00477         status = pal_CtrDRBGInit(&s_ctrDRBGCtx, (void*)seed, sizeof(seed));
00478         if (PAL_SUCCESS != status)
00479         {
00480             goto finish;
00481         }
00482     }
00483 
00484     status = pal_CtrDRBGGenerate(s_ctrDRBGCtx, (unsigned char*)randomBuf, bufSizeBytes);
00485 
00486 finish:
00487     return status;
00488 }
00489 
00490 //As mentioned in the header file, this function ignores the upperBound parameter
00491 //in this stage, in the future it will be supported. (Erez)
00492 palStatus_t pal_osRandomUniform(uint32_t upperBound, uint32_t *random)
00493 {
00494     palStatus_t status = PAL_SUCCESS;
00495 
00496     if (NULL == random)
00497     {
00498         return PAL_ERR_INVALID_ARGUMENT ;
00499     }
00500 
00501     status = pal_osRandomBuffer((uint8_t*)random, sizeof(uint32_t));
00502     //*random = random % upperBound;
00503     return status;
00504 }
00505 
00506 palStatus_t pal_osGetDeviceKey(palDevKeyType_t keyType, uint8_t *key, size_t keyLenBytes)
00507 {
00508     palStatus_t status = PAL_SUCCESS;
00509     unsigned char rot[PAL_DEVICE_KEY_SIZE_IN_BYTES] = {0};
00510     
00511     if ((keyLenBytes < PAL_DEVICE_KEY_SIZE_IN_BYTES) || ((palOsStorageHmacSha256 == keyType) && (keyLenBytes < PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES)))
00512     {
00513         return PAL_ERR_BUFFER_TOO_SMALL ;
00514     }
00515     if (NULL == key)
00516     {
00517         return PAL_ERR_NULL_POINTER ;
00518     }
00519 
00520     status = pal_plat_osGetRoT128Bit (rot, PAL_DEVICE_KEY_SIZE_IN_BYTES);
00521     if (PAL_SUCCESS == status)
00522     {   // Logic of RoT according to key type using 128 bit strong Key Derivation Algorithm
00523         switch(keyType)
00524         {
00525             case palOsStorageEncryptionKey128Bit:
00526             {
00527                 //USE strong KDF here!
00528                 status = pal_cipherCMAC((const unsigned char*)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rot, PAL_DEVICE_KEY_SIZE_IN_BYTES, key);
00529                 break;
00530             }
00531             case palOsStorageSignatureKey128Bit:
00532             {
00533                 //USE strong KDF here!
00534                 status = pal_cipherCMAC((const unsigned char*)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rot, PAL_DEVICE_KEY_SIZE_IN_BYTES, key);
00535                 break;
00536             }
00537             case palOsStorageHmacSha256:
00538             {
00539                 size_t outputLenInBytes = 0;
00540                 status = pal_mdHmacSha256((const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char*)rot, PAL_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes);
00541                 break;
00542             }
00543             default:
00544                 status = PAL_ERR_GET_DEV_KEY ;
00545 
00546         }
00547 
00548     } // outer if
00549     else
00550     {
00551         status = PAL_ERR_GET_DEV_KEY ;
00552     }
00553     memset(rot, 0, PAL_DEVICE_KEY_SIZE_IN_BYTES);
00554 
00555     return status;
00556 
00557 }
00558