Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
pal_rtos.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 00018 #include "pal.h" 00019 #include "pal_plat_rtos.h" 00020 #include "sotp.h" 00021 00022 #if PAL_UNIQUE_THREAD_PRIORITY 00023 // An array of PAL thread priorities. 00024 // This array holds a boolean for each thread priority. 00025 // If the value is true then it means that the priority is in use. 00026 // The mapping between the priorities and the index in the array is as follow: 00027 // g_palThreadPriorities[0] --> PAL_osPriorityIdle 00028 // g_palThreadPriorities[1] --> PAL_osPriorityLow 00029 // g_palThreadPriorities[2] --> PAL_osPriorityReservedTRNG 00030 // g_palThreadPriorities[3] --> PAL_osPriorityBelowNormal 00031 // g_palThreadPriorities[4] --> PAL_osPriorityNormal 00032 // g_palThreadPriorities[5] --> PAL_osPriorityAboveNormal 00033 // g_palThreadPriorities[6] --> PAL_osPriorityReservedDNS 00034 // g_palThreadPriorities[7] --> PAL_osPriorityReservedSockets 00035 // g_palThreadPriorities[8] --> PAL_osPriorityHigh 00036 // g_palThreadPriorities[9] --> PAL_osPriorityReservedHighResTimer 00037 // g_palThreadPriorities[10] --> PAL_osPriorityRealtime 00038 PAL_PRIVATE bool g_threadPriorities[PAL_NUMBER_OF_THREAD_PRIORITIES]; 00039 #endif //PAL_UNIQUE_THREAD_PRIORITY 00040 00041 // thread structure (used by service layer) 00042 typedef struct palThreadWrapper 00043 { 00044 palThreadData_t threadData; // structure containing information about the thread 00045 palThreadServiceBridge_t bridge; // structure containing a function pointer which should always point to threadBridgeFunction & a pointer to palThreadData_t 00046 } palThreadWrapper_t; 00047 00048 PAL_PRIVATE palMutexID_t g_threadsMutex = NULLPTR; // threads mutex 00049 PAL_PRIVATE uint32_t g_threadIdCounter = 0; // threads counter used for palThreadID generation 00050 PAL_PRIVATE palThreadWrapper_t g_threadsArray[(PAL_MAX_NUMBER_OF_THREADS + 1)] = {{{ 0 }}}; // threads array (+1 for the current thread) 00051 PAL_PRIVATE void threadSetDefaultValues(palThreadData_t* threadData); // forward declaration 00052 PAL_PRIVATE palThreadID_t generatePALthreadID(uint32_t threadWrapperIndex); // forward declaration 00053 00054 //! Store the last saved time in SOTP (ram) for quick access 00055 PAL_PRIVATE uint64_t g_lastSavedTimeInSec = 0; 00056 00057 //! static variables for Random functionality. 00058 //! CTR-DRBG context to be used for generating random numbers from given seed 00059 static palCtrDrbgCtxHandle_t s_ctrDRBGCtx = NULLPTR; 00060 00061 PAL_PRIVATE palStatus_t pal_setWeakTimeForward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime); 00062 PAL_PRIVATE palStatus_t pal_setWeakTimeBackward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime); 00063 00064 static uint64_t g_palDeviceBootTimeInSec = 0; 00065 00066 /* 00067 * Here we define const keys for RoT derivation algorithm. 00068 * Must be 16 characters or less 00069 */ 00070 #define PAL_STORAGE_SIGNATURE_128_BIT_KEY "RoTStorageSgn128" 00071 #define PAL_STORAGE_ENCRYPTION_128_BIT_KEY "RoTStorageEnc128" 00072 #define PAL_STORAGE_ENCRYPTION_256_BIT_KEY "StorageEnc256HMACSHA256SIGNATURE" 00073 00074 PAL_PRIVATE bool palRTOSInitialized = false; 00075 00076 #if (PAL_SIMULATE_RTOS_REBOOT == 1) 00077 #include <unistd.h> 00078 extern char *program_invocation_name; 00079 #endif 00080 00081 #define PAL_NOISE_WAIT_FOR_WRITERS_DELAY_MILLI_SEC 1 00082 #define PAL_NOISE_BITS_TO_BYTES(x) (x / CHAR_BIT) 00083 00084 typedef struct palNoise 00085 { 00086 int32_t buffer[PAL_NOISE_BUFFER_LEN]; 00087 volatile uint16_t bitCountAllocated; 00088 volatile uint16_t bitCountActual; 00089 volatile uint8_t numWriters; 00090 volatile bool isReading; 00091 } palNoise_t; 00092 00093 PAL_PRIVATE palNoise_t g_noise; 00094 00095 palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten); // forward declaration 00096 palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead); // forward declaration 00097 00098 extern palStatus_t pal_plat_CtrDRBGGenerateWithAdditional(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len, unsigned char* additional, size_t additionalLen); 00099 00100 //Error Translation from SOTP module to PAL 00101 PAL_PRIVATE palStatus_t pal_osSotpErrorTranslation(sotp_result_e err) 00102 { 00103 palStatus_t ret; 00104 switch(err) 00105 { 00106 case SOTP_BAD_VALUE: 00107 ret = PAL_ERR_INVALID_ARGUMENT ; 00108 break; 00109 00110 case SOTP_BUFF_TOO_SMALL: 00111 ret = PAL_ERR_BUFFER_TOO_SMALL ; 00112 break; 00113 00114 case SOTP_BUFF_NOT_ALIGNED: 00115 ret = PAL_ERR_RTOS_BUFFER_NOT_ALIGNED ; 00116 break; 00117 00118 case SOTP_READ_ERROR: 00119 case SOTP_DATA_CORRUPT: 00120 case SOTP_OS_ERROR: 00121 default: 00122 ret = PAL_ERR_GENERIC_FAILURE; 00123 break; 00124 } 00125 return ret; 00126 } 00127 00128 palStatus_t pal_RTOSInitialize(void* opaqueContext) 00129 { 00130 palStatus_t status = PAL_SUCCESS; 00131 if (palRTOSInitialized) 00132 { 00133 return status; 00134 } 00135 00136 status = pal_osMutexCreate(&g_threadsMutex); 00137 if(PAL_SUCCESS == status) 00138 { 00139 status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00140 if (PAL_SUCCESS == status) 00141 { 00142 #if PAL_UNIQUE_THREAD_PRIORITY 00143 memset(g_threadPriorities, 0, sizeof(g_threadPriorities)); // mark all priorities as available 00144 #endif // PAL_UNIQUE_THREAD_PRIORITY 00145 for (uint32_t i = 0; i <= PAL_MAX_NUMBER_OF_THREADS; ++i) // note the '<=' since g_threadsArray has PAL_MAX_NUMBER_OF_THREADS + 1 for the implicit thread 00146 { 00147 threadSetDefaultValues(&(g_threadsArray[i].threadData)); 00148 } 00149 // add the currently running thread 00150 g_threadsArray[0].threadData.palThreadID = generatePALthreadID(0); 00151 g_threadsArray[0].threadData.osThreadID = pal_plat_osThreadGetId (); 00152 00153 status = pal_osMutexRelease(g_threadsMutex); 00154 if (PAL_SUCCESS == status) 00155 { 00156 status = pal_plat_RTOSInitialize (opaqueContext); 00157 if (PAL_SUCCESS == status) 00158 { 00159 memset(g_noise.buffer, 0, PAL_NOISE_SIZE_BYTES); 00160 g_noise.bitCountActual = g_noise.bitCountAllocated = 0; 00161 g_noise.numWriters = 0; 00162 g_noise.isReading = false; 00163 palRTOSInitialized = true; 00164 } 00165 } 00166 } 00167 } 00168 return status; 00169 } 00170 00171 palStatus_t pal_RTOSDestroy(void) 00172 { 00173 palStatus_t status = PAL_SUCCESS; 00174 uint32_t i; 00175 if (palRTOSInitialized) 00176 { 00177 palStatus_t status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00178 if (PAL_SUCCESS == status) 00179 { 00180 for (i = 1; i <= PAL_MAX_NUMBER_OF_THREADS; ++i) // terminate running threads, note skipping the (1st) thread 00181 { // note the '<=' since g_threadsArray has PAL_MAX_NUMBER_OF_THREADS + 1 for the implicit thread 00182 if (NULLPTR != g_threadsArray[i].threadData.palThreadID) 00183 { 00184 pal_osThreadTerminate(&(g_threadsArray[i].threadData.palThreadID)); 00185 } 00186 } 00187 status = pal_osMutexRelease(g_threadsMutex); 00188 if (PAL_SUCCESS != status) 00189 { 00190 PAL_LOG(ERR, "pal_RTOSDestroy: mutex release failed\n"); 00191 } 00192 } 00193 else 00194 { 00195 PAL_LOG(ERR, "pal_RTOSDestroy: mutex wait failed\n"); 00196 } 00197 00198 status = pal_osMutexDelete(&g_threadsMutex); 00199 if (PAL_SUCCESS != status) 00200 { 00201 PAL_LOG(ERR, "pal_RTOSDestroy: mutex delete failed\n"); 00202 } 00203 00204 if (NULLPTR != s_ctrDRBGCtx) 00205 { 00206 status = pal_CtrDRBGFree(&s_ctrDRBGCtx); 00207 if (PAL_SUCCESS != status) 00208 { 00209 PAL_LOG(ERR, "pal_RTOSDestroy: pal_CtrDRBGFree failed\n"); 00210 } 00211 } 00212 00213 status = pal_plat_RTOSDestroy (); 00214 if (PAL_SUCCESS != status) 00215 { 00216 PAL_LOG(ERR, "pal_RTOSDestroy: pal_plat_RTOSDestroy failed\n"); 00217 } 00218 palRTOSInitialized = false; 00219 } 00220 else 00221 { 00222 status = PAL_ERR_NOT_INITIALIZED ; 00223 } 00224 return status; 00225 } 00226 00227 00228 void pal_osReboot(void) 00229 { 00230 //Simulator is currently for Linux only 00231 #if (PAL_SIMULATE_RTOS_REBOOT == 1) 00232 const char *argv[] = {"0" , 0}; 00233 char *const envp[] = { 0 }; 00234 argv[0] = program_invocation_name; 00235 if (-1 == execve(argv[0], (char **)argv , envp)) 00236 { 00237 PAL_LOG(ERR,"child process execve failed [%s]",argv[0]); 00238 } 00239 #else 00240 pal_plat_osReboot (); 00241 #endif 00242 } 00243 00244 uint64_t pal_osKernelSysTick(void) 00245 { 00246 static uint64_t lastValue = 0; 00247 static uint64_t wraparoundsDetected = 0; 00248 const uint64_t one = 1; 00249 uint64_t tics = pal_plat_osKernelSysTick (); 00250 uint64_t tmp = tics + (wraparoundsDetected << 32); 00251 00252 if (tmp < lastValue) //erez's "wraparound algorithm" if we detect a wrap around add 1 to the higher 32 bits 00253 { 00254 tmp = tmp + (one << 32); 00255 wraparoundsDetected++; 00256 } 00257 lastValue = tmp; 00258 return (uint64_t)tmp; 00259 } 00260 00261 uint64_t pal_osKernelSysTickMicroSec(uint64_t microseconds) 00262 { 00263 uint64_t result; 00264 result = pal_plat_osKernelSysTickMicroSec (microseconds); 00265 return result; 00266 } 00267 00268 uint64_t pal_osKernelSysMilliSecTick(uint64_t sysTicks) 00269 { 00270 uint64_t result = 0; 00271 uint64_t osTickFreq = pal_plat_osKernelSysTickFrequency (); 00272 if ((sysTicks) && (osTickFreq)) // > 0 00273 { 00274 result = (uint64_t)((sysTicks) / osTickFreq * PAL_TICK_TO_MILLI_FACTOR); //convert ticks per second to milliseconds 00275 } 00276 00277 return result; 00278 } 00279 00280 uint64_t pal_osKernelSysTickFrequency(void) 00281 { 00282 uint64_t result; 00283 result = pal_plat_osKernelSysTickFrequency (); 00284 return result; 00285 } 00286 00287 inline PAL_PRIVATE void threadSetDefaultValues(palThreadData_t* threadData) 00288 { 00289 threadData->palThreadID = NULLPTR; 00290 threadData->osThreadID = NULLPTR; 00291 threadData->store = NULL; 00292 threadData->palPriority = PAL_osPriorityError; 00293 threadData->osPriority = 0; 00294 threadData->stackSize = 0; 00295 threadData->userFunction = NULL; 00296 threadData->userFunctionArg = NULL; 00297 threadData->portData = NULL; 00298 } 00299 00300 PAL_PRIVATE void threadCleanup(palThreadData_t* threadData) 00301 { 00302 #if PAL_UNIQUE_THREAD_PRIORITY 00303 g_threadPriorities[(threadData->palPriority )] = false; // mark the priority as available 00304 #endif // PAL_UNIQUE_THREAD_PRIORITY 00305 threadSetDefaultValues(threadData); 00306 } 00307 00308 PAL_PRIVATE palStatus_t findThreadData(palThreadID_t* threadID, palThreadData_t** threadData) 00309 { 00310 palStatus_t status = PAL_ERR_RTOS_ERROR_BASE ; 00311 uint32_t index; 00312 PAL_VALIDATE_ARGUMENTS((NULLPTR == threadID) || (PAL_INVALID_THREAD == *threadID)); 00313 00314 index = PAL_GET_THREAD_INDEX(*threadID); 00315 if ((PAL_MAX_NUMBER_OF_THREADS >= index) && (g_threadsArray[index].threadData.palThreadID == *threadID)) 00316 { 00317 *threadData = &(g_threadsArray[index].threadData); 00318 status = PAL_SUCCESS; 00319 } 00320 return status; 00321 } 00322 00323 PAL_PRIVATE void threadBridgeFunction(palThreadData_t* threadData) 00324 { 00325 palThreadData_t* tempThreadData = NULL; 00326 palThreadID_t localPalThreadID = NULLPTR; // local copy - will be used after mutex release 00327 palThreadFuncPtr localUserFunction = NULL; // local copy - will be used after mutex release 00328 void* localUserFunctionArg = NULL; // local copy - will be used after mutex release 00329 palStatus_t status; 00330 00331 status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); // enter critical section 00332 if (PAL_SUCCESS != status) 00333 { 00334 goto mutex_wait_err; 00335 } 00336 00337 status = findThreadData(&(threadData->palThreadID), &tempThreadData); 00338 if (PAL_SUCCESS == status) // thread still exists, i.e. it has NOT been terminated by API call 00339 { 00340 if (NULLPTR == tempThreadData->osThreadID ) // may happen (on some systems) when the created thread has higher priority than the current thread & is immediately executed 00341 { 00342 tempThreadData->osThreadID = pal_plat_osThreadGetId (); 00343 } 00344 localPalThreadID = tempThreadData->palThreadID; 00345 localUserFunction = tempThreadData->userFunction ; 00346 localUserFunctionArg = tempThreadData->userFunctionArg ; 00347 } 00348 00349 status = pal_osMutexRelease(g_threadsMutex); // exit critical section 00350 if (PAL_SUCCESS != status) 00351 { 00352 goto mutex_release_err; 00353 } 00354 00355 if (NULLPTR == localPalThreadID) 00356 { 00357 // thread has been requested for termination, note that some operating systems don't terminate the thread immediately 00358 goto finish; 00359 } 00360 00361 localUserFunction(localUserFunctionArg); // invoke user function with user function argument (local copies since we're not under mutex lock anymore) 00362 00363 status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); // enter critical section 00364 if (PAL_SUCCESS != status) 00365 { 00366 goto mutex_wait_err; 00367 } 00368 00369 tempThreadData = NULL; 00370 status = findThreadData(&localPalThreadID, &tempThreadData); 00371 if (PAL_SUCCESS == status) // thread still exists, i.e. it has NOT been terminated by API call 00372 { 00373 status = pal_plat_osThreadDataCleanup (tempThreadData); // platform clean up 00374 threadCleanup(tempThreadData); 00375 if (PAL_SUCCESS != status) 00376 { 00377 PAL_LOG(ERR, "threadBridgeFunction: pal_plat_osThreadDataCleanup failed\n"); 00378 } 00379 } 00380 00381 status = pal_osMutexRelease(g_threadsMutex); // exit critical section 00382 if (PAL_SUCCESS != status) 00383 { 00384 goto mutex_release_err; 00385 } 00386 goto finish; 00387 00388 mutex_wait_err: 00389 { 00390 PAL_LOG(ERR, "threadBridgeFunction: mutex wait failed\n"); 00391 goto finish; 00392 } 00393 mutex_release_err: 00394 { 00395 PAL_LOG(ERR, "threadBridgeFunction: mutex release failed\n"); 00396 goto finish; 00397 } 00398 finish: 00399 return; 00400 } 00401 00402 PAL_PRIVATE palStatus_t allocateThreadWrapper(palThreadWrapper_t** threadWrapper, uint32_t* threadWrapperIndex) 00403 { 00404 palStatus_t status = PAL_ERR_RTOS_RESOURCE ; 00405 for (uint32_t i = 1; i <= PAL_MAX_NUMBER_OF_THREADS; ++i) // note skipping 1st index since it's being used for the implicit thread set in pal_RTOSInitialize 00406 { // note the '<=' since g_threadsArray has PAL_MAX_NUMBER_OF_THREADS + 1 for the implicit thread 00407 if (NULLPTR == g_threadsArray[i].threadData.palThreadID) 00408 { 00409 *threadWrapper = &g_threadsArray[i]; 00410 *threadWrapperIndex = i; 00411 status = PAL_SUCCESS; 00412 break; 00413 } 00414 } 00415 return status; 00416 } 00417 00418 inline PAL_PRIVATE palThreadID_t generatePALthreadID(uint32_t threadWrapperIndex) 00419 { 00420 // 24 bits for thread counter + lower 8 bits for thread index 00421 ++g_threadIdCounter; 00422 palThreadID_t threadID = (palThreadID_t)((threadWrapperIndex + (g_threadIdCounter << 8))); 00423 return threadID; 00424 } 00425 00426 PAL_PRIVATE palStatus_t threadCreate(palThreadFuncPtr function, void* functionArg, palThreadPriority_t priority, uint32_t stackSize, palThreadLocalStore_t* store, 00427 palThreadID_t* threadID) 00428 { 00429 palStatus_t status, tempStatus; 00430 palThreadWrapper_t* threadWrapper = NULL; 00431 uint32_t threadWrapperIndex; 00432 palThreadID_t localPalThreadID; 00433 palThreadID_t localOsThreadID = NULLPTR; 00434 palThreadData_t* tempThreadData = NULL; 00435 int16_t translatedPriority; 00436 00437 PAL_VALIDATE_ARGUMENTS((NULL == function) || (PAL_osPriorityRealtime < priority) || (PAL_osPriorityError == priority) || (0 == stackSize) || (NULL == threadID)); 00438 00439 *threadID = PAL_INVALID_THREAD; 00440 translatedPriority = pal_plat_osThreadTranslatePriority (priority); 00441 tempStatus = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00442 if (PAL_SUCCESS != tempStatus) 00443 { 00444 goto mutex_wait_err; 00445 } 00446 00447 #if PAL_UNIQUE_THREAD_PRIORITY 00448 if (g_threadPriorities[priority]) // requested thread priority already occupied 00449 { 00450 status = PAL_ERR_RTOS_PRIORITY ; 00451 tempStatus = pal_osMutexRelease(g_threadsMutex); 00452 if (PAL_SUCCESS != tempStatus) 00453 { 00454 goto mutex_release_err; 00455 } 00456 goto finish; 00457 } 00458 g_threadPriorities[priority] = true; 00459 #endif // PAL_UNIQUE_THREAD_PRIORITY 00460 00461 status = allocateThreadWrapper(&threadWrapper, &threadWrapperIndex); 00462 if (PAL_SUCCESS != status) 00463 { 00464 PAL_LOG(ERR, "threadCreate: thread wrapper allocation failed\n"); 00465 tempStatus = pal_osMutexRelease(g_threadsMutex); 00466 if (PAL_SUCCESS != tempStatus) 00467 { 00468 goto mutex_release_err; 00469 } 00470 goto finish; 00471 } 00472 00473 localPalThreadID = generatePALthreadID(threadWrapperIndex); 00474 threadWrapper->bridge.function = threadBridgeFunction; // this is the (service layer) thread function invoked by the port via the bridge 00475 threadWrapper->bridge.threadData = &(threadWrapper->threadData); 00476 threadWrapper->threadData.palThreadID = localPalThreadID; 00477 threadWrapper->threadData.store = store; 00478 threadWrapper->threadData.palPriority = priority; 00479 threadWrapper->threadData.osPriority = translatedPriority; 00480 threadWrapper->threadData.stackSize = stackSize; 00481 threadWrapper->threadData.userFunction = function; 00482 threadWrapper->threadData.userFunctionArg = functionArg; 00483 status = pal_plat_osThreadDataInitialize (&(threadWrapper->threadData.portData), threadWrapper->threadData.osPriority, threadWrapper->threadData.stackSize); 00484 if (PAL_SUCCESS != status) 00485 { 00486 threadCleanup(&(threadWrapper->threadData)); 00487 PAL_LOG(ERR, "threadCreate: pal_plat_osThreadDataInitialize failed\n"); 00488 tempStatus = pal_osMutexRelease(g_threadsMutex); 00489 if (PAL_SUCCESS != tempStatus) 00490 { 00491 goto mutex_release_err; 00492 } 00493 goto finish; 00494 } 00495 00496 tempStatus = pal_osMutexRelease(g_threadsMutex); 00497 if (PAL_SUCCESS != tempStatus) 00498 { 00499 goto mutex_release_err; 00500 } 00501 00502 status = pal_plat_osThreadRun (&(threadWrapper->bridge), &localOsThreadID); // note that we're not under a mutex lock anymore 00503 00504 tempStatus = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00505 if (PAL_SUCCESS != tempStatus) 00506 { 00507 goto mutex_wait_err; 00508 } 00509 00510 tempStatus = findThreadData(&localPalThreadID, &tempThreadData); 00511 if ((PAL_SUCCESS == tempStatus) && (PAL_SUCCESS == status)) // thread still exists & pal_plat_osThreadRun was successful 00512 { 00513 if (NULLPTR == tempThreadData->osThreadID ) 00514 { 00515 tempThreadData->osThreadID = localOsThreadID; 00516 } 00517 *threadID = localPalThreadID; 00518 } 00519 else if ((PAL_SUCCESS == tempStatus) && (PAL_SUCCESS != status)) // thread still exists & pal_plat_osThreadRun was not successful 00520 { 00521 threadCleanup(tempThreadData); 00522 } 00523 else if ((PAL_SUCCESS != tempStatus) && (PAL_SUCCESS == status)) // thread does not exist (either finished or terminated) & pal_plat_osThreadRun was successful 00524 { 00525 *threadID = localPalThreadID; 00526 } 00527 else 00528 { 00529 // note: this should never happen because if we're here then it means that pal_plat_osThreadRun was not successful and also that the thread data does not exist any more 00530 // meaning it has been cleaned up already, this should not be possible since the thread was not supposed to run (pal_plat_osThreadRun failed) and pal_osThreadTerminate 00531 // is not possible since the user does not have the palThreadID yet which is an output parameter of this function 00532 PAL_LOG(ERR, "threadCreate: pal_plat_osThreadRun was not successful but the thread was not found"); 00533 } 00534 00535 tempStatus = pal_osMutexRelease(g_threadsMutex); 00536 if (PAL_SUCCESS != tempStatus) 00537 { 00538 goto mutex_release_err; 00539 } 00540 goto finish; 00541 00542 mutex_wait_err: 00543 { 00544 status = tempStatus; 00545 PAL_LOG(ERR, "threadCreate: mutex wait failed\n"); 00546 goto finish; 00547 } 00548 mutex_release_err: 00549 { 00550 status = tempStatus; 00551 PAL_LOG(ERR, "threadCreate: mutex release failed\n"); 00552 goto finish; 00553 } 00554 finish: 00555 return status; 00556 } 00557 00558 00559 palStatus_t pal_osThreadCreateWithAlloc(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadLocalStore_t* store, palThreadID_t* threadID) 00560 { 00561 palStatus_t status = threadCreate(function, funcArgument, priority, stackSize, store, threadID); 00562 return status; 00563 } 00564 00565 palStatus_t pal_osThreadTerminate(palThreadID_t* threadID) 00566 { 00567 PAL_VALIDATE_ARGUMENTS ((NULL == threadID) || (PAL_INVALID_THREAD == *threadID)); 00568 00569 palThreadData_t* threadData = NULL; 00570 palStatus_t status; 00571 palStatus_t mutexStatus = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00572 if (PAL_SUCCESS == mutexStatus) 00573 { 00574 status = findThreadData(threadID, &threadData); 00575 if (PAL_SUCCESS == status) // thread has not finished yet 00576 { 00577 status = pal_plat_osThreadTerminate (threadData); 00578 if (PAL_SUCCESS == status) 00579 { 00580 threadCleanup(threadData); 00581 } 00582 else 00583 { 00584 PAL_LOG(ERR, "pal_osThreadTerminate: pal_plat_osThreadTerminate failed\n"); 00585 } 00586 } 00587 else // thread was not found, it either never existed or already finished 00588 { 00589 status = PAL_SUCCESS; 00590 } 00591 00592 mutexStatus = pal_osMutexRelease(g_threadsMutex); 00593 if (PAL_SUCCESS != mutexStatus) 00594 { 00595 status = mutexStatus; 00596 PAL_LOG(ERR, "pal_osThreadTerminate: mutex release failed\n"); 00597 } 00598 } 00599 else 00600 { 00601 status = mutexStatus; 00602 PAL_LOG(ERR, "pal_osThreadTerminate: mutex wait failed\n"); 00603 } 00604 return status; 00605 } 00606 00607 palThreadID_t pal_osThreadGetId(void) 00608 { 00609 palThreadID_t palThreadID = PAL_INVALID_THREAD; 00610 palThreadID_t osThreadID; 00611 uint32_t i; 00612 palStatus_t status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00613 if (PAL_SUCCESS == status) 00614 { 00615 osThreadID = pal_plat_osThreadGetId (); 00616 for (i = 0; i <= PAL_MAX_NUMBER_OF_THREADS; ++i) // search the threads array, note the '<=' since g_threadsArray has PAL_MAX_NUMBER_OF_THREADS + 1 for the implicit thread 00617 { 00618 if ((NULLPTR != g_threadsArray[i].threadData.palThreadID) && (g_threadsArray[i].threadData.osThreadID == osThreadID)) 00619 { 00620 palThreadID = g_threadsArray[i].threadData.palThreadID; 00621 break; 00622 } 00623 } 00624 status = pal_osMutexRelease(g_threadsMutex); 00625 if (PAL_SUCCESS != status) 00626 { 00627 PAL_LOG(ERR, "pal_osThreadGetId: mutex release failed\n"); 00628 } 00629 } 00630 else 00631 { 00632 PAL_LOG(ERR, "pal_osThreadGetId: mutex wait failed\n"); 00633 } 00634 return palThreadID; 00635 } 00636 00637 palThreadLocalStore_t* pal_osThreadGetLocalStore(void) 00638 { 00639 palThreadID_t palThreadID; 00640 palThreadData_t* threadData = NULL; 00641 palThreadLocalStore_t* store = NULL; 00642 palStatus_t status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); 00643 if (PAL_SUCCESS == status) 00644 { 00645 palThreadID = pal_osThreadGetId(); // find the palThreadID for the current thread 00646 if (PAL_INVALID_THREAD != palThreadID) 00647 { 00648 status = findThreadData(&palThreadID, &threadData); 00649 if (PAL_SUCCESS == status) 00650 { 00651 store = threadData->store ; 00652 } 00653 } 00654 status = pal_osMutexRelease(g_threadsMutex); 00655 if (PAL_SUCCESS != status) 00656 { 00657 PAL_LOG(ERR, "pal_osThreadGetLocalStore: mutex release failed\n"); 00658 } 00659 } 00660 else 00661 { 00662 PAL_LOG(ERR, "pal_osThreadGetLocalStore: mutex wait failed\n"); 00663 } 00664 return store; 00665 } 00666 00667 palStatus_t pal_osDelay(uint32_t milliseconds) 00668 { 00669 palStatus_t status; 00670 status = pal_plat_osDelay (milliseconds); 00671 return status; 00672 } 00673 00674 palStatus_t pal_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID) 00675 { 00676 PAL_VALIDATE_ARGUMENTS(NULL == timerID || NULL == function); 00677 palStatus_t status; 00678 status = pal_plat_osTimerCreate (function, funcArgument, timerType, timerID); 00679 return status; 00680 } 00681 00682 palStatus_t pal_osTimerStart(palTimerID_t timerID, uint32_t millisec) 00683 { 00684 PAL_VALIDATE_ARGUMENTS (NULLPTR == timerID); 00685 palStatus_t status; 00686 if (0 == millisec) 00687 { 00688 return PAL_ERR_RTOS_VALUE ; 00689 } 00690 status = pal_plat_osTimerStart (timerID, millisec); 00691 return status; 00692 } 00693 00694 palStatus_t pal_osTimerStop(palTimerID_t timerID) 00695 { 00696 PAL_VALIDATE_ARGUMENTS(NULLPTR == timerID); 00697 palStatus_t status; 00698 status = pal_plat_osTimerStop (timerID); 00699 return status; 00700 } 00701 00702 palStatus_t pal_osTimerDelete(palTimerID_t* timerID) 00703 { 00704 PAL_VALIDATE_ARGUMENTS(NULL == timerID || NULLPTR == *timerID); 00705 palStatus_t status; 00706 status = pal_plat_osTimerDelete (timerID); 00707 return status; 00708 } 00709 00710 palStatus_t pal_osMutexCreate(palMutexID_t* mutexID) 00711 { 00712 PAL_VALIDATE_ARGUMENTS(NULL == mutexID); 00713 palStatus_t status; 00714 status = pal_plat_osMutexCreate (mutexID); 00715 return status; 00716 } 00717 00718 palStatus_t pal_osMutexWait(palMutexID_t mutexID, uint32_t millisec) 00719 { 00720 PAL_VALIDATE_ARGUMENTS((NULLPTR == mutexID)); 00721 palStatus_t status; 00722 status = pal_plat_osMutexWait (mutexID, millisec); 00723 return status; 00724 } 00725 00726 palStatus_t pal_osMutexRelease(palMutexID_t mutexID) 00727 { 00728 PAL_VALIDATE_ARGUMENTS(NULLPTR == mutexID); 00729 palStatus_t status; 00730 status = pal_plat_osMutexRelease (mutexID); 00731 return status; 00732 } 00733 00734 palStatus_t pal_osMutexDelete(palMutexID_t* mutexID) 00735 { 00736 PAL_VALIDATE_ARGUMENTS(NULL == mutexID || NULLPTR == *mutexID); 00737 palStatus_t status; 00738 status = pal_plat_osMutexDelete (mutexID); 00739 return status; 00740 } 00741 00742 palStatus_t pal_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID) 00743 { 00744 PAL_VALIDATE_ARGUMENTS(NULL == semaphoreID); 00745 palStatus_t status; 00746 status = pal_plat_osSemaphoreCreate (count, semaphoreID); 00747 return status; 00748 } 00749 00750 palStatus_t pal_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable) 00751 { 00752 PAL_VALIDATE_ARGUMENTS(NULLPTR == semaphoreID); 00753 palStatus_t status; 00754 status = pal_plat_osSemaphoreWait (semaphoreID, millisec, countersAvailable); 00755 return status; 00756 } 00757 00758 palStatus_t pal_osSemaphoreRelease(palSemaphoreID_t semaphoreID) 00759 { 00760 PAL_VALIDATE_ARGUMENTS(NULLPTR == semaphoreID); 00761 palStatus_t status; 00762 status = pal_plat_osSemaphoreRelease (semaphoreID); 00763 return status; 00764 } 00765 00766 palStatus_t pal_osSemaphoreDelete(palSemaphoreID_t* semaphoreID) 00767 { 00768 PAL_VALIDATE_ARGUMENTS(NULL == semaphoreID || NULLPTR == *semaphoreID); 00769 palStatus_t status; 00770 status = pal_plat_osSemaphoreDelete (semaphoreID); 00771 return status; 00772 } 00773 00774 00775 int32_t pal_osAtomicIncrement(int32_t* valuePtr, int32_t increment) 00776 { 00777 PAL_VALIDATE_ARGUMENTS(NULL == valuePtr); 00778 int32_t result; 00779 result = pal_plat_osAtomicIncrement (valuePtr, increment); 00780 return result; 00781 } 00782 00783 00784 PAL_PRIVATE uint64_t pal_sysTickTimeToSec() 00785 { 00786 uint64_t sysTicksFromBoot = pal_osKernelSysTick(); 00787 uint64_t secFromBoot = pal_osKernelSysMilliSecTick(sysTicksFromBoot) / PAL_MILLI_PER_SECOND; 00788 00789 return secFromBoot; 00790 } 00791 00792 uint64_t pal_osGetTime(void) 00793 { 00794 uint64_t curSysTimeInSec = 0; 00795 if (0 < g_palDeviceBootTimeInSec) //time was previously set 00796 { 00797 uint64_t secFromBoot = pal_sysTickTimeToSec(); 00798 curSysTimeInSec = g_palDeviceBootTimeInSec + secFromBoot; //boot time in sec + sec passed since boot 00799 00800 if((curSysTimeInSec > g_lastSavedTimeInSec) && (curSysTimeInSec - g_lastSavedTimeInSec > PAL_LAST_SAVED_TIME_LATENCY_SEC)) 00801 { 00802 sotp_result_e status = SOTP_SUCCESS; 00803 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&curSysTimeInSec); 00804 if (SOTP_SUCCESS != status) 00805 { 00806 PAL_LOG(ERR,"SOTP set time failed \n"); 00807 } 00808 else 00809 { 00810 g_lastSavedTimeInSec = curSysTimeInSec; 00811 } 00812 00813 } 00814 } 00815 00816 return curSysTimeInSec; 00817 } 00818 00819 palStatus_t pal_osSetTime(uint64_t seconds) 00820 { 00821 palStatus_t status = PAL_SUCCESS; 00822 if(0 == seconds) 00823 { 00824 g_palDeviceBootTimeInSec = 0; 00825 } 00826 else if (seconds < (uint64_t)PAL_MIN_SEC_FROM_EPOCH) 00827 { 00828 status = PAL_ERR_INVALID_TIME ; 00829 } 00830 else 00831 { 00832 uint64_t secFromBoot = pal_sysTickTimeToSec(); 00833 g_palDeviceBootTimeInSec = seconds - secFromBoot; //update device boot time 00834 } 00835 00836 return status; 00837 } 00838 00839 00840 00841 #if PAL_USE_HW_TRNG 00842 PAL_PRIVATE void pal_trngNoiseThreadFunc(void const* arg) 00843 { 00844 uint8_t buf[PAL_NOISE_SIZE_BYTES] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 }; 00845 size_t trngBytesRead = 0; 00846 uint16_t noiseBitsWritten = 0; 00847 palStatus_t status; 00848 while (true) 00849 { 00850 status = pal_plat_osRandomBuffer (buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead); 00851 if ((0 < trngBytesRead) && ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status))) 00852 { 00853 noiseBitsWritten = 0; 00854 status = pal_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWritten); 00855 PAL_LOG(DBG, "noise trng thread wrote %" PRIu16 " bits, status=%" PRIx32 "\n", noiseBitsWritten, status); 00856 } 00857 pal_osDelay(PAL_NOISE_TRNG_THREAD_DELAY_MILLI_SEC); 00858 } 00859 } 00860 #endif // PAL_USE_HW_TRNG 00861 00862 00863 // this function generates drbg with the possibility of adding noise as additional input to the drbg function. 00864 PAL_PRIVATE palStatus_t pal_generateDrbgWithNoiseAttempt(palCtrDrbgCtxHandle_t drbgContext, uint8_t* outBuffer, bool partial, size_t numBytesToGenerate) 00865 { 00866 uint16_t bitsRead = 0; 00867 int32_t buffer[PAL_NOISE_BUFFER_LEN] = { 0 }; 00868 palStatus_t status = pal_noiseRead(buffer, partial, &bitsRead); 00869 if (PAL_SUCCESS == status) 00870 { 00871 status = pal_plat_CtrDRBGGenerateWithAdditional(drbgContext, (unsigned char*)outBuffer, numBytesToGenerate, (unsigned char*)buffer, (size_t)PAL_NOISE_BITS_TO_BYTES(bitsRead)); 00872 } 00873 else 00874 { 00875 status = pal_CtrDRBGGenerate(drbgContext, (unsigned char*)outBuffer, numBytesToGenerate); 00876 } 00877 return status; 00878 } 00879 00880 palStatus_t pal_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes) 00881 { 00882 PAL_VALIDATE_ARGUMENTS (NULL == randomBuf); 00883 00884 palStatus_t status = PAL_ERR_GENERIC_FAILURE; 00885 if (palRTOSInitialized == true) 00886 { 00887 if (NULLPTR == s_ctrDRBGCtx) 00888 { 00889 uint32_t sotpCounter = 0; 00890 uint8_t buf[(PAL_INITIAL_RANDOM_SIZE * 2 + sizeof(sotpCounter))] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 }; // space for 48 bytes short term + 48 bytes long term + 4 counter bytes (note this buffer will also be used to collect TRNG noise) 00891 const uint16_t sotpLenBytes = PAL_INITIAL_RANDOM_SIZE + sizeof(sotpCounter); // the max number of bytes expected to be read/written form/to sotp, note that sotpCounter will probably be empty the 1st time data is read from sotp 00892 uint32_t* ptrSotpRead = (uint32_t*)&buf; // pointer to the memory address in buf which will point to the data that will be read from sotp 00893 uint32_t* ptrSotpWrite = (uint32_t*)&buf[PAL_INITIAL_RANDOM_SIZE]; // pointer to the memory address in buf which will point to the data which needs to be written back to sotp 00894 uint32_t* ptrSotpCounterRead = ptrSotpWrite; // pointer to the memory address in buf which will point to the counter read from sotp 00895 uint32_t* ptrSotpCounterWrite = (uint32_t*)&buf[PAL_INITIAL_RANDOM_SIZE * 2]; // pointer to the memory address in buf which will point to the incremented counter which will be written back to sotp 00896 uint16_t sotpBytesRead = 0, noiseBitsWrittern = 0; 00897 size_t trngBytesRead = 0; 00898 palCtrDrbgCtxHandle_t longCtrDRBGCtx = NULLPTR; // long term drbg context 00899 palStatus_t tmpStatus; 00900 sotp_result_e sotpResult = sotp_get(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpRead, &sotpBytesRead); // read 48 drbg bytes + 4 counter bytes 00901 if (SOTP_SUCCESS == sotpResult) 00902 { 00903 if ((PAL_INITIAL_RANDOM_SIZE != sotpBytesRead) && (sotpLenBytes != sotpBytesRead)) 00904 { 00905 status = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00906 PAL_LOG(ERR, "Invalid number of bytes read from sotp, bytes read=%" PRIu16, sotpBytesRead); 00907 goto finish; 00908 } 00909 status = pal_CtrDRBGInit(&longCtrDRBGCtx, ptrSotpRead, PAL_INITIAL_RANDOM_SIZE); // initialize long term drbg with the seed that was read from sotp 00910 if (PAL_SUCCESS != status) 00911 { 00912 PAL_LOG(ERR, "Failed to initialize long term drbg context, status=%" PRIx32 "\n", status); 00913 goto finish; 00914 } 00915 memcpy((void*)&sotpCounter, (void*)ptrSotpCounterRead, sizeof(sotpCounter)); // read the counter from the buffer (sotp data) to local var 00916 #if PAL_USE_HW_TRNG 00917 memset((void*)buf, 0, sizeof(buf)); 00918 status = pal_plat_osRandomBuffer (buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead); 00919 if ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status)) 00920 { 00921 if (0 < trngBytesRead) 00922 { 00923 tmpStatus = pal_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWrittern); // write whatever was collected from trng to the noise buffer 00924 PAL_LOG(DBG, "Write trng to noise buffer, status=%" PRIx32 ", bits writtern=%" PRIu16 "\n", tmpStatus, noiseBitsWrittern); 00925 } 00926 } 00927 else 00928 { 00929 PAL_LOG(ERR, "Read from TRNG failed, status=%" PRIx32 "\n", status); 00930 } 00931 #endif // PAL_USE_HW_TRNG 00932 memset((void*)buf, 0, sizeof(buf)); 00933 status = pal_generateDrbgWithNoiseAttempt(longCtrDRBGCtx, buf, true, (PAL_INITIAL_RANDOM_SIZE * 2)); // generate 96 bytes, the 1st 48 bytes will be used for short term drbg and the other 48 bytes will be used for long term drbg 00934 if (PAL_SUCCESS != status) 00935 { 00936 PAL_LOG(ERR, "Failed to gererate drbg long term and short term seeds, status=%" PRIx32 "\n", status); 00937 goto drbg_cleanup; 00938 } 00939 sotpCounter++; // increment counter before writting it back to sotp 00940 memcpy((void*)ptrSotpCounterWrite, (void*)&sotpCounter, sizeof(sotpCounter)); // copy the incremented counter to the last 4 bytes of the buffer 00941 sotpResult = sotp_set(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpWrite); // write 48 long term drbg bytes + 4 counter bytes 00942 if (SOTP_SUCCESS != sotpResult) 00943 { 00944 PAL_LOG(ERR, "Failed to write to sotp, sotp result=%d", sotpResult); 00945 status = PAL_ERR_GENERIC_FAILURE; 00946 } 00947 drbg_cleanup: 00948 { 00949 tmpStatus = pal_CtrDRBGFree(&longCtrDRBGCtx); 00950 if (PAL_SUCCESS != tmpStatus) 00951 { 00952 PAL_LOG(ERR, "Failed to free long term drbg context, status=%" PRIx32 "\n", tmpStatus); 00953 } 00954 longCtrDRBGCtx = NULLPTR; 00955 if (PAL_SUCCESS != status) 00956 { 00957 goto finish; 00958 } 00959 #if PAL_USE_HW_TRNG 00960 palThreadID_t trngThreadId = NULLPTR; 00961 tmpStatus = pal_osThreadCreateWithAlloc(pal_trngNoiseThreadFunc, NULL, PAL_osPriorityReservedTRNG, PAL_NOISE_TRNG_THREAD_STACK_SIZE, NULL, &trngThreadId); 00962 if (PAL_SUCCESS != tmpStatus) 00963 { 00964 PAL_LOG(ERR, "Failed to create noise trng thread, status=%" PRIx32 "\n", tmpStatus); 00965 } 00966 #endif // PAL_USE_HW_TRNG 00967 } 00968 } 00969 else if (SOTP_NOT_FOUND == sotpResult) 00970 { 00971 #if PAL_USE_HW_TRNG 00972 memset((void*)buf, 0, sizeof(buf)); 00973 uint8_t* seedPtr = buf; 00974 size_t randomCounterBytes = 0; 00975 do 00976 { 00977 status = pal_plat_osRandomBuffer (seedPtr, PAL_INITIAL_RANDOM_SIZE - randomCounterBytes, &trngBytesRead); 00978 if (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status) 00979 { 00980 pal_osDelay(PAL_TRNG_COLLECT_DELAY_MILLI_SEC); // sleep to let the device to collect random data. 00981 randomCounterBytes += trngBytesRead; 00982 seedPtr += trngBytesRead; 00983 } 00984 } while (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status); 00985 #endif // PAL_USE_HW_TRNG 00986 } 00987 if (PAL_SUCCESS != status) 00988 { 00989 goto finish; 00990 } 00991 status = pal_CtrDRBGInit(&s_ctrDRBGCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE); 00992 if (PAL_SUCCESS != status) 00993 { 00994 PAL_LOG(ERR, "Failed to initialize short term drbg context, status=%" PRIx32 "\n", status); 00995 goto finish; 00996 } 00997 } 00998 status = pal_generateDrbgWithNoiseAttempt(s_ctrDRBGCtx, randomBuf, false, bufSizeBytes); 00999 if (PAL_SUCCESS != status) 01000 { 01001 PAL_LOG(ERR, "Failed to gererate random, status=%" PRIx32 "\n", status); 01002 } 01003 } 01004 else 01005 { 01006 return PAL_ERR_NOT_INITIALIZED ; 01007 } 01008 finish: 01009 return status; 01010 } 01011 01012 palStatus_t pal_osRandom32bit(uint32_t *random) 01013 { 01014 palStatus_t status = PAL_SUCCESS; 01015 01016 PAL_VALIDATE_ARGUMENTS(NULL == random); 01017 01018 status = pal_osRandomBuffer((uint8_t*)random, sizeof(uint32_t)); 01019 return status; 01020 } 01021 01022 01023 PAL_PRIVATE palStatus_t pal_osGetRoT(uint8_t * key,size_t keyLenBytes) 01024 { 01025 palStatus_t palStatus = PAL_SUCCESS; 01026 #if (PAL_USE_HW_ROT) 01027 palStatus = pal_plat_osGetRoTFromHW (key, keyLenBytes); 01028 #else 01029 sotp_result_e sotpStatus = SOTP_SUCCESS; 01030 uint16_t actual_size; 01031 sotpStatus = sotp_get(SOTP_TYPE_ROT, keyLenBytes, (uint32_t *)key, &actual_size); 01032 if (SOTP_NOT_FOUND == sotpStatus) 01033 { 01034 palStatus = pal_osRandomBuffer(key , keyLenBytes); 01035 if (PAL_SUCCESS == palStatus) 01036 { 01037 sotpStatus = sotp_set(SOTP_TYPE_ROT,keyLenBytes, (uint32_t *)key); 01038 } 01039 } 01040 if (SOTP_SUCCESS != sotpStatus) 01041 { 01042 palStatus = pal_osSotpErrorTranslation(sotpStatus); 01043 } 01044 #endif 01045 return palStatus; 01046 } 01047 01048 palStatus_t pal_osGetDeviceKey(palDevKeyType_t keyType, uint8_t *key, size_t keyLenBytes) 01049 { 01050 palStatus_t status = PAL_SUCCESS; 01051 uint8_t rotBuffer[PAL_DEVICE_KEY_SIZE_IN_BYTES] __attribute__ ((aligned(4))) = {0}; 01052 01053 01054 PAL_VALIDATE_CONDITION_WITH_ERROR(((keyLenBytes < PAL_DEVICE_KEY_SIZE_IN_BYTES) || ((palOsStorageHmacSha256 == keyType) && (keyLenBytes < PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES))),PAL_ERR_BUFFER_TOO_SMALL ) 01055 01056 PAL_VALIDATE_CONDITION_WITH_ERROR ((NULL == key),PAL_ERR_NULL_POINTER ) 01057 01058 status = pal_osGetRoT(rotBuffer, keyLenBytes); 01059 if (PAL_SUCCESS == status) 01060 { // Logic of RoT according to key type using 128 bit strong Key Derivation Algorithm 01061 01062 #if (PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC == 1) //calculate the key derivation in an old way 01063 switch(keyType) 01064 { 01065 case palOsStorageEncryptionKey128Bit: 01066 { 01067 //USE strong KDF here! 01068 status = pal_cipherCMAC((const unsigned char*)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 01069 break; 01070 } 01071 case palOsStorageSignatureKey128Bit : 01072 { 01073 //USE strong KDF here! 01074 status = pal_cipherCMAC((const unsigned char *)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 01075 break; 01076 } 01077 case palOsStorageHmacSha256 : 01078 { 01079 size_t outputLenInBytes = 0; 01080 status = pal_mdHmacSha256((const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes); 01081 break; 01082 } 01083 default: 01084 status = PAL_ERR_GET_DEV_KEY ; 01085 } //switch end 01086 #else //calculate the key derivation in a new way 01087 switch(keyType) 01088 { 01089 case palOsStorageEncryptionKey128Bit: 01090 { 01091 //USE strong KDF here! 01092 status = pal_cipherCMAC((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 01093 break; 01094 } 01095 case palOsStorageSignatureKey128Bit : 01096 { 01097 //USE strong KDF here! 01098 status = pal_cipherCMAC((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 01099 break; 01100 } 01101 case palOsStorageHmacSha256 : 01102 { 01103 size_t outputLenInBytes = 0; 01104 status = pal_mdHmacSha256((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes); 01105 break; 01106 } 01107 default: 01108 status = PAL_ERR_GET_DEV_KEY ; 01109 } //switch end 01110 #endif 01111 01112 } // outer if 01113 else 01114 { 01115 status = PAL_ERR_GET_DEV_KEY ; 01116 } 01117 01118 return status; 01119 01120 } 01121 01122 palStatus_t pal_initTime(void) 01123 { 01124 uint64_t rtcTime = 0; 01125 uint64_t sotpGetTime = 0, sotpLastTimeBack = 0; 01126 palStatus_t ret = PAL_SUCCESS; 01127 sotp_result_e status = SOTP_SUCCESS; 01128 uint16_t actualLenBytes = 0; 01129 01130 status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes); 01131 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 01132 { 01133 ret = pal_osSotpErrorTranslation(status); 01134 } 01135 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 01136 { 01137 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 01138 } 01139 01140 status = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpLastTimeBack, &actualLenBytes); 01141 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 01142 { 01143 ret = pal_osSotpErrorTranslation(status); 01144 } 01145 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 01146 { 01147 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 01148 } 01149 01150 if (sotpLastTimeBack > sotpGetTime) 01151 {//Enter here only when reset occurs during set weak or strong time 01152 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&sotpLastTimeBack); 01153 if (SOTP_SUCCESS != status) 01154 { 01155 ret = pal_osSotpErrorTranslation(status); 01156 } 01157 sotpGetTime = sotpLastTimeBack; 01158 } 01159 g_lastSavedTimeInSec = sotpGetTime; 01160 01161 #if (PAL_USE_HW_RTC) 01162 if (PAL_SUCCESS == ret) 01163 { 01164 ret = pal_plat_osGetRtcTime(&rtcTime); 01165 } 01166 #endif 01167 01168 if (PAL_SUCCESS == ret) 01169 {//set the max time as boot time of the device 01170 pal_osSetTime(PAL_MAX(rtcTime, sotpGetTime)); 01171 } 01172 return ret; 01173 } 01174 01175 01176 palStatus_t pal_osSetStrongTime(uint64_t setNewTimeInSeconds) 01177 { 01178 palStatus_t ret = PAL_SUCCESS; 01179 01180 uint64_t getSotpTimeValue = 0; 01181 uint16_t actualLenBytes = 0; 01182 sotp_result_e status = SOTP_SUCCESS; 01183 01184 #if (PAL_USE_HW_RTC) 01185 //RTC Time Latency 01186 if (PAL_SUCCESS == ret) 01187 { 01188 uint64_t getRtcTimeValue = 0; 01189 ret = pal_plat_osGetRtcTime(&getRtcTimeValue); 01190 if (PAL_SUCCESS == ret) 01191 { 01192 if(llabs(setNewTimeInSeconds - getRtcTimeValue) > PAL_MINIMUM_RTC_LATENCY_SEC) 01193 { 01194 ret = pal_plat_osSetRtcTime(setNewTimeInSeconds); 01195 } 01196 } 01197 } 01198 #endif 01199 01200 status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes); 01201 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 01202 { 01203 ret = pal_osSotpErrorTranslation(status); 01204 } 01205 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 01206 { 01207 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 01208 } 01209 else if (((setNewTimeInSeconds > getSotpTimeValue) && (setNewTimeInSeconds - getSotpTimeValue > PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC)) //Forward Time 01210 || ((setNewTimeInSeconds < getSotpTimeValue) && (getSotpTimeValue - setNewTimeInSeconds > PAL_MINIMUM_SOTP_BACKWARD_LATENCY_SEC))) //Backward Time 01211 { 01212 status = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 01213 if (SOTP_SUCCESS != status) 01214 { 01215 ret = pal_osSotpErrorTranslation(status); 01216 } 01217 else 01218 { 01219 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 01220 if (SOTP_SUCCESS != status) 01221 { 01222 ret = pal_osSotpErrorTranslation(status); 01223 } 01224 g_lastSavedTimeInSec = setNewTimeInSeconds; 01225 } 01226 } 01227 01228 if(PAL_SUCCESS == ret) 01229 { 01230 ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM 01231 } 01232 01233 return ret; 01234 } 01235 01236 PAL_PRIVATE palStatus_t pal_setWeakTimeForward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime) 01237 { 01238 sotp_result_e status = SOTP_SUCCESS; 01239 palStatus_t ret = PAL_SUCCESS; 01240 01241 ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM 01242 #if (PAL_USE_HW_RTC) 01243 //RTC Time Forward 01244 if (PAL_SUCCESS == ret) 01245 { 01246 uint64_t getRtcTimeValue = 0; 01247 ret = pal_plat_osGetRtcTime(&getRtcTimeValue); 01248 if (PAL_SUCCESS == ret) 01249 { 01250 if((setNewTimeInSeconds > getRtcTimeValue) && (setNewTimeInSeconds - getRtcTimeValue > PAL_MINIMUM_RTC_LATENCY_SEC)) 01251 { 01252 ret = pal_plat_osSetRtcTime(setNewTimeInSeconds); 01253 } 01254 } 01255 } 01256 #endif// (PAL_USE_HW_RTC) 01257 01258 if ((setNewTimeInSeconds - currentOsTime > PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC) && (PAL_SUCCESS == ret)) 01259 {//SOTP time forward 01260 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 01261 if (SOTP_SUCCESS != status) 01262 { 01263 ret = pal_osSotpErrorTranslation(status); 01264 } 01265 else 01266 { 01267 g_lastSavedTimeInSec = setNewTimeInSeconds; 01268 } 01269 } 01270 return ret; 01271 } 01272 01273 PAL_PRIVATE palStatus_t pal_setWeakTimeBackward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime) 01274 { 01275 uint64_t getSotpTimeValue = 0; 01276 uint16_t actualLenBytes = 0; 01277 sotp_result_e status = SOTP_SUCCESS; 01278 palStatus_t ret = PAL_SUCCESS; 01279 01280 status = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes); 01281 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 01282 { 01283 ret = pal_osSotpErrorTranslation(status); 01284 } 01285 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 01286 { 01287 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 01288 } 01289 else if (setNewTimeInSeconds > getSotpTimeValue) 01290 { 01291 if ((setNewTimeInSeconds - getSotpTimeValue) / PAL_RATIO_SECONDS_PER_DAY > (currentOsTime - setNewTimeInSeconds)) 01292 { 01293 status = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 01294 if (SOTP_SUCCESS != status) 01295 { 01296 ret = pal_osSotpErrorTranslation(status); 01297 } 01298 else 01299 { 01300 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 01301 if (SOTP_SUCCESS != status) 01302 { 01303 ret = pal_osSotpErrorTranslation(status); 01304 } 01305 else 01306 { 01307 g_lastSavedTimeInSec = setNewTimeInSeconds; 01308 ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM 01309 } 01310 } 01311 } 01312 } 01313 01314 return ret; 01315 } 01316 01317 palStatus_t pal_osSetWeakTime(uint64_t setNewTimeInSeconds) 01318 { 01319 uint64_t getSotpTimeValue = 0; 01320 uint16_t actualLenBytes = 0; 01321 sotp_result_e status = SOTP_SUCCESS; 01322 palStatus_t ret = PAL_SUCCESS; 01323 uint64_t getOsTimeValue = 0; 01324 01325 getOsTimeValue = pal_osGetTime(); //get current system time 01326 01327 if (setNewTimeInSeconds > getOsTimeValue) 01328 {//Time Forward 01329 ret = pal_setWeakTimeForward(setNewTimeInSeconds, getOsTimeValue); 01330 } 01331 else if (getOsTimeValue > setNewTimeInSeconds) 01332 {//Time Backward 01333 ret = pal_setWeakTimeBackward(setNewTimeInSeconds, getOsTimeValue); 01334 } 01335 01336 if(PAL_SUCCESS == ret) 01337 { 01338 getSotpTimeValue = 0; 01339 status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes); 01340 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 01341 { 01342 ret = pal_osSotpErrorTranslation(status); 01343 } 01344 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 01345 { 01346 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 01347 } 01348 else if ((setNewTimeInSeconds > getSotpTimeValue) && (setNewTimeInSeconds - getSotpTimeValue > PAL_MINIMUM_STORAGE_LATENCY_SEC)) 01349 { 01350 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 01351 if (SOTP_SUCCESS != status) 01352 { 01353 ret = pal_osSotpErrorTranslation(status); 01354 } 01355 else 01356 { 01357 g_lastSavedTimeInSec = setNewTimeInSeconds; 01358 } 01359 } 01360 } 01361 return ret; 01362 } 01363 01364 /*! Write a value (either all or specific bits) to the global noise buffer 01365 * 01366 * @param[in] data The value containing the bits to be written. 01367 * @param[in] startBit The index of the first bit to be written, valid values are 0-31. 01368 * @param[in] lenBits The number of bits that should be written (startBit+lenBits must be less than 32). 01369 * @param[out] bitsWritten The number of bits that were actually written. 01370 * 01371 * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. 01372 */ 01373 palStatus_t pal_noiseWriteValue(const int32_t* data, uint8_t startBit, uint8_t lenBits, uint8_t* bitsWritten) 01374 { 01375 PAL_VALIDATE_ARGUMENTS((NULL == data) || (PAL_INT32_BITS - 1 < startBit) || (PAL_INT32_BITS < lenBits + startBit) || (NULL == bitsWritten)); 01376 01377 palStatus_t status = PAL_SUCCESS; 01378 uint16_t incrementedBitCount; 01379 uint8_t currentIndex, occupiedBitsInCurrentIndex, availableBitsInCurrentIndex; 01380 uint32_t mask, value; 01381 01382 *bitsWritten = 0; 01383 if (PAL_NOISE_SIZE_BITS == g_noise.bitCountActual) 01384 { 01385 return PAL_ERR_RTOS_NOISE_BUFFER_FULL ; 01386 } 01387 01388 pal_osAtomicIncrement((int32_t*)(&g_noise.numWriters), 1); // increment number of writers 01389 if (g_noise.isReading) // if we're in read mode then discard & exit 01390 { 01391 status = PAL_ERR_RTOS_NOISE_BUFFER_IS_READING ; 01392 goto finish; 01393 } 01394 01395 incrementedBitCount = (uint16_t)pal_osAtomicIncrement((int32_t*)(&g_noise.bitCountAllocated), lenBits); // reserve space in the array 01396 if (PAL_NOISE_SIZE_BITS < incrementedBitCount) // we want to write more bits than are available in the (entire) buffer 01397 { 01398 lenBits -= incrementedBitCount - PAL_NOISE_SIZE_BITS; // max number of bits that are avialable for writing 01399 if ((int8_t)lenBits <= 0) // we don't have any available bits for writing 01400 { 01401 status = PAL_ERR_RTOS_NOISE_BUFFER_FULL ; 01402 goto finish; 01403 } 01404 incrementedBitCount = PAL_NOISE_SIZE_BITS; 01405 } 01406 01407 currentIndex = (incrementedBitCount - lenBits) / PAL_INT32_BITS; // the current index in the array 01408 occupiedBitsInCurrentIndex = (incrementedBitCount - lenBits) % PAL_INT32_BITS; // how many bits are already occupied (with either 0 or 1) in the current index 01409 availableBitsInCurrentIndex = PAL_INT32_BITS - occupiedBitsInCurrentIndex; // how many bits are available in the current index 01410 01411 if (lenBits > availableBitsInCurrentIndex) // we want to write more bits than are available in the current index so we need to split the bits 01412 { 01413 mask = ((((int32_t)1) << availableBitsInCurrentIndex) - 1) << startBit; // mask to isolate the wanted bits 01414 value = *data & mask; 01415 if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) > 0) 01416 { 01417 value = value >> (startBit - occupiedBitsInCurrentIndex); 01418 } 01419 else if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) < 0) 01420 { 01421 value = value << (occupiedBitsInCurrentIndex - startBit); 01422 } 01423 pal_osAtomicIncrement(&g_noise.buffer[currentIndex], value); // write the 1st part of the splitted bits to the current index of the noise buffer 01424 *bitsWritten = availableBitsInCurrentIndex; 01425 lenBits -= availableBitsInCurrentIndex; // how many bits remain to be written 01426 startBit += availableBitsInCurrentIndex; 01427 mask = ((((int32_t)1) << lenBits) - 1) << startBit; // mask for the remaining bits that have not been written yet 01428 value = *data & mask; 01429 value = value >> startBit; // since we're writting to the next index we start at bit 0 01430 pal_osAtomicIncrement(&g_noise.buffer[currentIndex + 1], value); // write the 2nd part of the splitted bits to the next index of the noise buffer 01431 *bitsWritten += lenBits; 01432 } 01433 else // we have enough available bits for the current index (no need to split the bits) 01434 { 01435 mask = ((((int64_t)1) << lenBits) - 1) << startBit; // int64_t in case we want all the 32 bits 01436 value = *data & mask; 01437 if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) > 0) 01438 { 01439 value = value >> (startBit - occupiedBitsInCurrentIndex); 01440 } 01441 else if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) < 0) 01442 { 01443 value = value << (occupiedBitsInCurrentIndex - startBit); 01444 } 01445 pal_osAtomicIncrement(&g_noise.buffer[currentIndex], value); // write the bits to the current index of the noise buffer 01446 *bitsWritten = lenBits; 01447 } 01448 pal_osAtomicIncrement((int32_t*)(&g_noise.bitCountActual), *bitsWritten); // increment how many bits were actually written 01449 PAL_LOG(DBG, "noise added %" PRIu8 " bits\n", *bitsWritten); 01450 finish: 01451 pal_osAtomicIncrement((int32_t*)(&g_noise.numWriters), -1); // decrement number of writers 01452 return status; 01453 } 01454 01455 /*! Write values to the global noise buffer 01456 * 01457 * @param[in] buffer The buffer which contains the values to be written. 01458 * @param[in] lenBits The number of bits that should be written. 01459 * @param[out] bitsWritten The number of bits that were actually written. 01460 * 01461 * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. 01462 */ 01463 palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten) 01464 { 01465 PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (PAL_NOISE_SIZE_BITS < lenBits) || (NULL == bitsWritten)); 01466 01467 palStatus_t status; 01468 uint8_t idx, bitsToWrite; 01469 uint16_t totalBitsWritten; 01470 01471 idx = 0; 01472 totalBitsWritten = 0; 01473 do 01474 { 01475 bitsToWrite = (lenBits > PAL_INT32_BITS) ? PAL_INT32_BITS : lenBits; // we can write a max number of 32 bits at a time 01476 status = pal_noiseWriteValue(&buffer[idx], 0, bitsToWrite, (uint8_t*)bitsWritten); 01477 lenBits -= bitsToWrite; 01478 idx++; 01479 totalBitsWritten += *bitsWritten; 01480 } while ((PAL_SUCCESS == status) && (bitsToWrite == *bitsWritten) && lenBits); // exit if there was an error, or the noise buffer has no more space, or all bits were written 01481 01482 *bitsWritten = totalBitsWritten; 01483 if (0 < totalBitsWritten) 01484 { 01485 status = PAL_SUCCESS; 01486 } 01487 return status; 01488 } 01489 01490 /*! Read values from the global noise buffer 01491 * 01492 * @param[out] buffer The output buffer which will contain the noise data collected. 01493 * @param[in] partial When true read what was collected so far, otherwise read only if the noise buffer is full. 01494 * @param[out] bitsRead he number of bits that were actually read. 01495 * 01496 * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. 01497 */ 01498 palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead) 01499 { 01500 PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (NULL == bitsRead)); 01501 01502 static uint8_t numOfNoiseReaders = 0; // allow only one reader at a time (no concurrent reads) 01503 palStatus_t status = PAL_SUCCESS; 01504 uint8_t numBytesToRead, numReadersLocal; 01505 uint16_t bitCountActual = g_noise.bitCountActual; 01506 numReadersLocal = (uint8_t)pal_osAtomicIncrement((int32_t*)(&numOfNoiseReaders), 1); // increment number of readers 01507 *bitsRead = 0; 01508 if (1 != numReadersLocal) // single reader 01509 { 01510 PAL_LOG(DBG, "noise cannot read by multiple readers\n"); 01511 status = PAL_ERR_RTOS_NOISE_BUFFER_EMPTY ; 01512 goto finish; 01513 } 01514 01515 if ((CHAR_BIT > bitCountActual) || (!partial && (PAL_NOISE_SIZE_BITS != bitCountActual))) // exit if less than 1 byte was written or if we want a full read and not all bits were written 01516 { 01517 status = (CHAR_BIT > bitCountActual) ? PAL_ERR_RTOS_NOISE_BUFFER_EMPTY : PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL ; 01518 goto finish; 01519 } 01520 01521 g_noise.isReading = true; // set mode to reading so that no more writes will be allowed 01522 while (g_noise.numWriters) // wait for currently executing writers to finish (relevant only for partial read) 01523 { 01524 pal_osDelay(PAL_NOISE_WAIT_FOR_WRITERS_DELAY_MILLI_SEC); 01525 } 01526 bitCountActual = g_noise.bitCountActual; // this may occur if we waited for the writers to finish writing, meaning we might have a few more bits (relevant only for partial read) 01527 numBytesToRead = (uint8_t)PAL_NOISE_BITS_TO_BYTES(bitCountActual); 01528 memcpy((void*)buffer, (void*)g_noise.buffer, numBytesToRead); // copy noise buffer to output buffer 01529 *bitsRead = (numBytesToRead * CHAR_BIT); // set out param of how many bits were actually read 01530 memset((void*)g_noise.buffer, 0, PAL_NOISE_SIZE_BYTES); // reset the noise buffer 01531 g_noise.bitCountActual = g_noise.bitCountAllocated = 0; // reset counters 01532 g_noise.isReading = false; // exit read mode so that writters will be able to continue writting 01533 PAL_LOG(DBG, "noise read %" PRIu8 " bits\n", *bitsRead); 01534 finish: 01535 pal_osAtomicIncrement((int32_t*)(&numOfNoiseReaders), -1); // decrement number of readers 01536 return status; 01537 }
Generated on Tue Jul 12 2022 19:01:36 by 1.7.2