Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 16:22:10 by
1.7.2