1/*
2 * Copyright (c) 2007-2015 Freescale Semiconductor, Inc.
3 * Copyright 2018-2021 NXP
4 *
5 * License: NXP LA_OPT_NXP_Software_License
6 *
7 * NXP Confidential. This software is owned or controlled by NXP and may
8 * only be used strictly in accordance with the applicable license terms.
9 * By expressly accepting such terms or by downloading, installing,
10 * activating and/or otherwise using the software, you are agreeing that
11 * you have read, and that you agree to comply with and are bound by,
12 * such license terms. If you do not agree to be bound by the applicable
13 * license terms, then you may not retain, install, activate or otherwise
14 * use the software. This code may only be used in a microprocessor,
15 * microcontroller, sensor or digital signal processor ("NXP Product")
16 * supplied directly or indirectly from NXP. See the full NXP Software
17 * License Agreement in license/LA_OPT_NXP_Software_License.pdf
18 *
19 * FreeMASTER Communication Driver - protocol implementation
20 */
21
22#include "freemaster.h"
23#include "freemaster_private.h"
24#include "freemaster_protocol.h"
25#include "freemaster_utils.h"
26
27#if FMSTR_DISABLE == 0
28
29/* When using sessions, calculate number of instances of each lockable feature as U8 type */
30#if FMSTR_SESSION_COUNT > 1
31
32#if FMSTR_USE_SCOPE > 0
33#define _FMSTR_SC ((FMSTR_U8)(FMSTR_USE_SCOPE))
34#else
35#define _FMSTR_SC 0U
36#endif
37
38#if FMSTR_USE_RECORDER > 0
39#define _FMSTR_RC ((FMSTR_U8)(FMSTR_USE_RECORDER))
40#else
41#define _FMSTR_RC 0U
42#endif
43
44#if FMSTR_USE_PIPES > 0
45#define _FMSTR_PC ((FMSTR_U8)(FMSTR_USE_PIPES))
46#else
47#define _FMSTR_PC 0U
48#endif
49
50#if FMSTR_USE_APPCMD > 0
51#define _FMSTR_AC 1U /* All app commands make up one instance, if enabled */
52#else
53#define _FMSTR_AC 0U
54#endif
55
56#define _FMSTR_FPG 1U /* Flash programmer is a lockable software feature. Always enabled */
57
58/* Macros to convert instance to an index in one large fature locking array */
59
60#define FMSTR_FEATURE_SCOPE_INSTANCE(n) ((FMSTR_U8)(n))
61#define FMSTR_FEATURE_REC_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + (FMSTR_U8)(n)))
62#define FMSTR_FEATURE_APPCMD_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + 0U))
63#define FMSTR_FEATURE_FLASHPROG_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + _FMSTR_AC + 0U))
64#define FMSTR_FEATURE_PIPE_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + _FMSTR_AC + _FMSTR_FPG + (FMSTR_U8)(n)))
65#define FMSTR_FEATURE_LOCK_COUNT ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + _FMSTR_AC + _FMSTR_FPG + _FMSTR_PC))
66
67typedef struct
68{
69 FMSTR_SESSION *owner; /* Session which locks feature */
70 FMSTR_S32 lockCount; /* Locked count */
71} FMSTR_FEATURE_LOCK;
72#endif
73
74/******************************************************************************
75 * Local Functions
76 ******************************************************************************/
77
78/* The functions are local, but not declared "static" to prevent linker warnings
79 when features are excluded from protocol. */
80const FMSTR_CHAR *_FMSTR_GetAccessPassword(FMSTR_U8 requiredAccess);
81FMSTR_BPTR _FMSTR_GetBoardConfig(FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
82FMSTR_BPTR _FMSTR_AuthenticationStep1(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
83FMSTR_BPTR _FMSTR_AuthenticationStep2(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
84FMSTR_BPTR _FMSTR_ReadMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
85FMSTR_BPTR _FMSTR_ReadMemBaseAddress(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
86FMSTR_BPTR _FMSTR_WriteMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
87
88static FMSTR_SESSION *_FMSTR_FindSession(void *identification, FMSTR_BOOL create);
89
90#if FMSTR_SESSION_COUNT > 1
91static FMSTR_BPTR _FMSTR_FeatureLock(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus);
92#endif
93/******************************************************************************
94 * Local variables
95 ******************************************************************************/
96
97/* Protocol sessions */
98static FMSTR_SESSION fmstr_sessions[FMSTR_SESSION_COUNT];
99
100#if FMSTR_SESSION_COUNT > 1
101/* Features */
102static FMSTR_FEATURE_LOCK fmstr_features[FMSTR_FEATURE_LOCK_COUNT];
103#endif
104
105#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
106/* To save stack usage, we have the following SHA context variables static, although
107 * they could be local in Auth2 function. */
108static FMSTR_SHA1_CTX fmstr_sha1Ctx;
109/* Currently granted access (one of FMSTR_RESTRICTED_ACCESS_xxx). */
110static FMSTR_U8 fmstr_dfltGrantedAccess;
111#endif /* FMSTR_CFG_F1_RESTRICTED_ACCESS */
112
113#if FMSTR_DEBUG_TX > 0
114/* This warning is for you not to forget to disable the DEBUG_TX mode once the
115 * communication line works fine. You can ignore this warning if it is okay
116 * that the application will be periodically sending test frames to the world. */
117#warning FMSTR_DEBUG_TX is enabled. Test frames will be transmitted periodically.
118/* When communication debugging mode is requested, this global variable is used to
119 turn the debugging off once a valid connection is detected */
120FMSTR_BOOL fmstr_doDebugTx;
121#endif
122
123/******************************************************************************
124 *
125 * @brief FreeMASTER driver initialization
126 *
127 ******************************************************************************/
128
129FMSTR_BOOL FMSTR_Init(void)
130{
131 FMSTR_BOOL ok = FMSTR_TRUE;
132
133 FMSTR_MemSet(&fmstr_sessions, 0, sizeof(fmstr_sessions));
134
135#if FMSTR_SESSION_COUNT > 1
136 FMSTR_MemSet(&fmstr_features, 0, sizeof(fmstr_features));
137#endif
138
139#if FMSTR_DEBUG_LEVEL >= 1
140 FMSTR_DEBUG_PRINTF("FMSTR Init begins\n");
141#endif
142
143 /* Check the transport interface validity */
144 FMSTR_ASSERT_RETURN(FMSTR_TRANSPORT.Init != NULL, FMSTR_FALSE);
145 FMSTR_ASSERT_RETURN(FMSTR_TRANSPORT.Poll != NULL, FMSTR_FALSE);
146 FMSTR_ASSERT_RETURN(FMSTR_TRANSPORT.SendResponse != NULL, FMSTR_FALSE);
147
148#if FMSTR_USE_TSA > 0
149 /* initialize TSA */
150 if (FMSTR_InitTsa() == FMSTR_FALSE)
151 {
152 ok = FMSTR_FALSE;
153 }
154#endif
155
156#if FMSTR_USE_SCOPE > 0
157 /* initialize Scope */
158 if (FMSTR_InitScope() == FMSTR_FALSE)
159 {
160 ok = FMSTR_FALSE;
161 }
162#endif
163
164#if FMSTR_USE_RECORDER > 0
165 /* initialize Recorder */
166 if (FMSTR_InitRec() == FMSTR_FALSE)
167 {
168 ok = FMSTR_FALSE;
169 }
170#endif
171
172#if FMSTR_USE_APPCMD > 0
173 /* initialize application commands */
174 if (FMSTR_InitAppCmds() == FMSTR_FALSE)
175 {
176 ok = FMSTR_FALSE;
177 }
178#endif
179
180#if FMSTR_USE_PIPES > 0
181 /* initialize PIPES interface */
182 if (FMSTR_InitPipes() == FMSTR_FALSE)
183 {
184 ok = FMSTR_FALSE;
185 }
186#endif
187
188 /* initialize communication layer and start listening for commands */
189 if (FMSTR_TRANSPORT.Init() == FMSTR_FALSE)
190 {
191 ok = FMSTR_FALSE;
192 }
193
194#if FMSTR_DEBUG_TX > 0
195 /* start in the debugging mode, we will be sending test frames periodically */
196 fmstr_doDebugTx = FMSTR_TRUE;
197#endif
198
199#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
200 fmstr_dfltGrantedAccess = FMSTR_RESTRICTED_ACCESS_NO;
201 /* set the access level to the highest "open" level (the one without a password) */
202 for (FMSTR_U8 access = FMSTR_RESTRICTED_ACCESS_R; access <= FMSTR_RESTRICTED_ACCESS_RWF; access++)
203 {
204 if (_FMSTR_GetAccessPassword(access) != NULL)
205 {
206 break; /* this level (and all levels above) are protected by a password */
207 }
208 else
209 {
210 fmstr_dfltGrantedAccess = access;
211 }
212 }
213#endif
214
215#if FMSTR_DEBUG_LEVEL >= 1
216 FMSTR_DEBUG_PRINTF("FMSTR Init finished, ok=%d\n", (int)ok);
217#endif
218
219 return ok;
220}
221
222/*******************************************************************************
223 *
224 * @brief API: Main "Polling" call from the application main loop
225 *
226 * This function either handles all the communication (polling-only mode =
227 * FMSTR_POLL_DRIVEN) or decodes messages received on the background by SCI interrupt
228 * (short-interrupt mode = FMSTR_SHORT_INTR).
229 *
230 *
231 *******************************************************************************/
232
233void FMSTR_Poll(void)
234{
235 /* Increase entropy in each poll round */
236#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
237 static FMSTR_U8 e = 0x7U;
238 FMSTR_Randomize(e);
239 e += 13U;
240#endif
241
242 FMSTR_TRANSPORT.Poll();
243}
244
245/******************************************************************************
246 *
247 * @brief Finalize transmit buffer before transmitting
248 *
249 * @param length - response length
250 *
251 *
252 * This Function takes the data already prepared in the transmit buffer
253 * (inlcuding the status byte). It computes the check sum and kicks on tx.
254 *
255 ******************************************************************************/
256
257void FMSTR_SendResponse(FMSTR_BPTR response, FMSTR_SIZE length, FMSTR_U8 statusCode, FMSTR_SESSION *session)
258{
259 /* Allow NULL session only if sessions count is 1, use the first (single) session as default. */
260 if (session == NULL)
261 {
262#if FMSTR_SESSION_COUNT == 1
263 session = &fmstr_sessions[0];
264#else
265 /* You must specify session when multiple sessions are supported */
266 FMSTR_ASSERT(FMSTR_FALSE);
267 return;
268#endif
269 }
270
271#if FMSTR_DEBUG_LEVEL >= 2
272 FMSTR_DEBUG_PRINTF("FMSTR SendResponse Status: 0x%x, Len: 0x%x\n", statusCode, length);
273#endif
274
275 FMSTR_TRANSPORT.SendResponse(response, length, statusCode, session->identification);
276}
277
278/******************************************************************************
279 *
280 * @brief Decodes the FreeMASTER protocol and calls appropriate handlers
281 *
282 * @param msgBuffIO - message in/out buffer
283 * @param identification - transport identification
284 *
285 * @return TRUE if frame was valid and any output was generated to IO buffer
286 *
287 * This Function decodes given message and invokes proper command handler
288 * which fills in the response. The response transmission is initiated
289 * in this call as well.
290 *
291 ******************************************************************************/
292
293FMSTR_BOOL FMSTR_ProtocolDecoder(FMSTR_BPTR msgBuffIO, FMSTR_SIZE msgSize, FMSTR_U8 cmdCode, void *identification)
294{
295 FMSTR_BPTR responseEnd = msgBuffIO;
296 FMSTR_U8 statusCode = FMSTR_STS_INVALID;
297 FMSTR_SESSION *activeSession = NULL;
298
299#if FMSTR_DEBUG_LEVEL >= 2
300 FMSTR_DEBUG_PRINTF("FMSTR ProtocolDecoder Cmd: 0x%x, Len: 0x%x\n", cmdCode, msgSize);
301#endif
302
303 /* Find session (or free) and create it for this identification */
304 activeSession = _FMSTR_FindSession(identification, FMSTR_TRUE);
305
306 FMSTR_ASSERT_RETURN(activeSession != NULL, FMSTR_FALSE);
307
308 /* process command */
309 switch (cmdCode)
310 {
311 /* retrieve board configuration value*/
312 case FMSTR_CMD_GETCONFIG:
313 responseEnd = _FMSTR_GetBoardConfig(msgBuffIO, &statusCode);
314 break;
315
316#if FMSTR_USE_READMEM > 0
317 /* read a block of memory */
318 case FMSTR_CMD_READMEM:
319 responseEnd = _FMSTR_ReadMem(activeSession, msgBuffIO, &statusCode);
320 break;
321
322#ifdef FMSTR_PLATFORM_BASE_ADDRESS
323 /* read a block of memory with base address*/
324 case FMSTR_CMD_READMEM_BA:
325 responseEnd = _FMSTR_ReadMemBaseAddress(activeSession, msgBuffIO, &statusCode);
326 break;
327#endif
328
329#endif /* FMSTR_USE_READMEM */
330
331#if FMSTR_USE_WRITEMEM > 0
332 /* write a block of memory */
333 case FMSTR_CMD_WRITEMEM:
334 responseEnd = _FMSTR_WriteMem(activeSession, msgBuffIO, &statusCode);
335 break;
336#endif /* FMSTR_USE_WRITEMEM */
337
338#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
339 /* Initiate password authentication, request authentication challenge */
340 case FMSTR_CMD_AUTH1:
341 responseEnd = _FMSTR_AuthenticationStep1(activeSession, msgBuffIO, &statusCode);
342 break;
343
344 /* Initiate password authentication, request authentication challenge */
345 case FMSTR_CMD_AUTH2:
346 responseEnd = _FMSTR_AuthenticationStep2(activeSession, msgBuffIO, &statusCode);
347 break;
348#endif
349
350#if FMSTR_USE_PIPES > 0
351 case FMSTR_CMD_GETPIPE:
352 responseEnd = FMSTR_GetPipe(activeSession, msgBuffIO, msgSize, &statusCode);
353 break;
354 case FMSTR_CMD_PIPE:
355 responseEnd = FMSTR_PipeFrame(activeSession, msgBuffIO, msgSize, &statusCode);
356 break;
357#endif /* FMSTR_USE_PIPES */
358
359#if FMSTR_USE_TSA > 0
360 /* get TSA table (force EX instead of non-EX) */
361 case FMSTR_CMD_GETTSAINFO:
362 responseEnd = FMSTR_GetTsaInfo(msgBuffIO, &statusCode);
363 break;
364
365 case FMSTR_CMD_GETSTRLEN:
366 responseEnd = FMSTR_GetStringLen(msgBuffIO, &statusCode);
367 break;
368
369 case FMSTR_CMD_URESRWI:
370 responseEnd = FMSTR_UresControl(msgBuffIO, msgSize, &statusCode);
371 break;
372#endif /* FMSTR_USE_TSA */
373
374#if FMSTR_USE_APPCMD > 0
375 /* accept the application command */
376 case FMSTR_CMD_SENDAPPCMD:
377 responseEnd = FMSTR_StoreAppCmd(activeSession, msgBuffIO, msgSize, &statusCode);
378 break;
379
380 /* get the application command status */
381 case FMSTR_CMD_GETAPPCMDSTS:
382 responseEnd = FMSTR_GetAppCmdStatus(activeSession, msgBuffIO, &statusCode);
383 break;
384
385 /* get the application command data */
386 case FMSTR_CMD_GETAPPCMDDATA:
387 responseEnd = FMSTR_GetAppCmdRespData(activeSession, msgBuffIO, &statusCode);
388 break;
389#endif /* FMSTR_USE_APPCMD */
390
391#if FMSTR_USE_RECORDER > 0
392 /* get recorder data */
393 case FMSTR_CMD_GETREC:
394 responseEnd = FMSTR_GetRecCmd(activeSession, msgBuffIO, &statusCode);
395 break;
396
397 /* setup recorder */
398 case FMSTR_CMD_SETREC:
399 responseEnd = FMSTR_SetRecCmd(activeSession, msgBuffIO, msgSize, &statusCode);
400 break;
401#endif /* FMSTR_USE_RECORDER */
402
403#if FMSTR_USE_SCOPE > 0
404 /* prepare scope variables */
405 case FMSTR_CMD_SETSCOPE:
406 responseEnd = FMSTR_SetScope(activeSession, msgBuffIO, msgSize, &statusCode);
407 break;
408
409 case FMSTR_CMD_READSCOPE:
410 responseEnd = FMSTR_ReadScope(activeSession, msgBuffIO, &statusCode, FMSTR_COMM_BUFFER_SIZE);
411 break;
412#endif /* FMSTR_USE_SCOPE */
413
414#if FMSTR_SESSION_COUNT > 1
415 /* Lock or unlock feature in a multi-session configuration */
416 case FMSTR_CMD_FEATLOCK:
417 responseEnd = _FMSTR_FeatureLock(activeSession, msgBuffIO, &statusCode);
418 break;
419#endif /* FMSTR_SESSION_COUNT > 1 */
420
421 /* unknown command */
422 default:
423 statusCode = FMSTR_STC_INVCMD;
424 break;
425 }
426
427 /* anything to send back? */
428 if (statusCode != FMSTR_STS_INVALID)
429 {
430 /*lint -e{946,960} subtracting pointers is appropriate here */
431 FMSTR_INDEX ptrDiff = (FMSTR_INDEX)(responseEnd - msgBuffIO);
432 FMSTR_SIZE respSize = (FMSTR_SIZE)ptrDiff;
433
434 /* Non-variable length error responses are forced to 0 length */
435 if ((statusCode & (FMSTR_STSF_VARLEN | FMSTR_STSF_ERROR)) == FMSTR_STSF_ERROR)
436 {
437 respSize = 0;
438 }
439
440#if FMSTR_DEBUG_TX > 0
441 /* the first sane frame received from PC Host ends test frame sending */
442 fmstr_doDebugTx = FMSTR_FALSE;
443#endif
444 FMSTR_SendResponse(msgBuffIO, respSize, statusCode, activeSession);
445 return FMSTR_TRUE;
446 }
447 else
448 {
449 /* nothing sent out */
450 return FMSTR_FALSE;
451 }
452}
453
454/******************************************************************************
455 *
456 * @brief Sending debug test frame
457 *
458 * @param msgBuffIO - outut frame buffer
459 * @param session - transport session
460 *
461 * @return True if successful (always in current implementation)
462 *
463 ******************************************************************************/
464
465FMSTR_BOOL FMSTR_SendTestFrame(FMSTR_BPTR msgBuffIO, FMSTR_SESSION *session)
466{
467 FMSTR_SendResponse(msgBuffIO, 0, FMSTR_STC_DEBUGTX_TEST, session);
468 return FMSTR_TRUE;
469}
470
471/******************************************************************************
472 *
473 * @brief Handling GETINFO or GETINFO_BRIEF
474 *
475 * @param msgBuffIO - original command (in) and response buffer (out)
476 * @param retStatus - response status
477 *
478 * @return As all command handlers, the return value should be the buffer
479 * pointer where the response data payload is finished
480 *
481 ******************************************************************************/
482
483FMSTR_BPTR _FMSTR_GetBoardConfig(FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
484{
485 static const FMSTR_CHAR *const fmstr_cfgParamNames[] = {
486 "MTU", "VS", "NM", "DS", "BD", "F1", "BA", "RC", "SC", "PV", "PC",
487 };
488
489 FMSTR_BPTR response = msgBuffIO;
490 FMSTR_U8 respCode = FMSTR_STS_INVALID;
491 FMSTR_CHAR str[4];
492 FMSTR_INDEX ix = 0;
493
494 /* Get the IX from incomming buffer */
495 msgBuffIO = FMSTR_IndexFromBuffer(&ix, msgBuffIO);
496
497 if (ix == 0)
498 {
499 FMSTR_INDEX i;
500 /* Get the configuration name from incomming buffer */
501 msgBuffIO = FMSTR_StringFromBuffer(msgBuffIO, str, sizeof(str));
502
503 /* Try to find the Index of the config item */
504 for (i = 0; i < (FMSTR_INDEX)FMSTR_COUNTOF(fmstr_cfgParamNames); i++)
505 {
506 if (FMSTR_StrCmp(fmstr_cfgParamNames[i], str) == 0)
507 {
508 ix = i + 1;
509 break;
510 }
511 }
512
513 if (ix == 0)
514 {
515 respCode = FMSTR_STC_EACCESS;
516 goto FMSTR_GetConfig_exit;
517 }
518 }
519
520 respCode = FMSTR_STS_OK | FMSTR_STSF_VARLEN;
521 response = FMSTR_StringCopyToBuffer(response, fmstr_cfgParamNames[ix - 1]);
522
523 /* The ix must corresponded to table fmstr_cfgParamNames incremented by one */
524 switch (ix)
525 {
526 case 1: /* MTU */
527 response = FMSTR_SizeToBuffer(response, FMSTR_COMM_BUFFER_SIZE);
528 break;
529 case 2: /* VS */
530 response = FMSTR_StringCopyToBuffer(response, FMSTR_VERSION_STR);
531 break;
532 case 3: /* NM */
533 response = FMSTR_StringCopyToBuffer(response, FMSTR_APPLICATION_STR);
534 break;
535 case 4: /* DS */
536 response = FMSTR_StringCopyToBuffer(response, FMSTR_DESCRIPTION_STR);
537 break;
538 case 5: /* BD */
539 response = FMSTR_StringCopyToBuffer(response, FMSTR_BUILDTIME_STR);
540 break;
541 case 6: /* F1 */
542 response = FMSTR_ValueToBuffer8(response, FMSTR_CFG_F1);
543 break;
544#ifdef FMSTR_PLATFORM_BASE_ADDRESS
545 case 7: /* BA */
546 response = FMSTR_SizeToBuffer(response, FMSTR_PLATFORM_BASE_ADDRESS);
547 break;
548#endif
549 case 8: /* RC */
550 response = FMSTR_ValueToBuffer8(response, FMSTR_USE_RECORDER);
551 break;
552 case 9: /* SC */
553 response = FMSTR_ValueToBuffer8(response, FMSTR_USE_SCOPE);
554 break;
555 case 10: /* PV */
556 response = FMSTR_ValueToBuffer8(response, FMSTR_PRCTL_VER);
557 break;
558 case 11: /* PC */
559 response = FMSTR_ValueToBuffer8(response, FMSTR_USE_PIPES);
560 break;
561 default:
562 respCode = FMSTR_STC_EACCESS;
563 break;
564 }
565
566FMSTR_GetConfig_exit:
567 *retStatus = respCode;
568
569 return response;
570}
571
572/* Helper call to obtain password required for certain access level. */
573
574const FMSTR_CHAR *_FMSTR_GetAccessPassword(FMSTR_U8 requiredAccess)
575{
576 const FMSTR_CHAR *password = NULL;
577
578#if defined(FMSTR_RESTRICTED_ACCESS_R_PASSWORD)
579 if (requiredAccess >= FMSTR_RESTRICTED_ACCESS_R)
580 {
581 password = (FMSTR_CHAR *)FMSTR_RESTRICTED_ACCESS_R_PASSWORD;
582 }
583#endif
584
585#if defined(FMSTR_RESTRICTED_ACCESS_RW_PASSWORD)
586 if (requiredAccess >= FMSTR_RESTRICTED_ACCESS_RW)
587 {
588 password = (FMSTR_CHAR *)FMSTR_RESTRICTED_ACCESS_RW_PASSWORD;
589 }
590#endif
591
592#if defined(FMSTR_RESTRICTED_ACCESS_RWF_PASSWORD)
593 if (requiredAccess >= FMSTR_RESTRICTED_ACCESS_RWF)
594 {
595 password = (FMSTR_CHAR *)FMSTR_RESTRICTED_ACCESS_RWF_PASSWORD;
596 }
597#endif
598
599 /* password remains NULL if requested level and any lower level are unprotected */
600 return password;
601}
602
603/******************************************************************************
604 *
605 * @brief Handling FMSTR_CMD_AUTH1 command
606 *
607 * @param session - transport session
608 * @param msgBuffIO - original command (in) and response buffer (out)
609 * @param retStatus - response status
610 *
611 * @return As all command handlers, the return value should be the buffer
612 * pointer where the response data payload is finished
613 *
614 ******************************************************************************/
615
616#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
617
618FMSTR_BPTR _FMSTR_AuthenticationStep1(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
619{
620 FMSTR_BPTR response = msgBuffIO;
621 FMSTR_U8 reqAccess = 0;
622
623 FMSTR_ASSERT(session != NULL);
624
625 /* Get the Required access from incomming buffer */
626 msgBuffIO = FMSTR_ValueFromBuffer8(&reqAccess, msgBuffIO);
627
628 /* success */
629 *retStatus = FMSTR_STS_OK | FMSTR_STSF_VARLEN;
630
631 /* Check if password is needed for requested access. When logging-out, the client sends 0 as requested level. */
632 if (reqAccess == 0U || _FMSTR_GetAccessPassword(reqAccess) == NULL)
633 {
634 /* no password is required, access is granted, we do not require the step 2 */
635 session->restr.grantedAccess = reqAccess;
636
637 FMSTR_FreeSession(session);
638
639 return FMSTR_ValueToBuffer8(response, 0U);
640 }
641
642 /* ULEB-encoded algorithm ID */
643 response = FMSTR_SizeToBuffer(response, FMSTR_AUTHENT_PRTCL_SHA1);
644
645 /* Generate random salt and store it to local buffer for later use with FMSTR_AuthenticationM2 handler. */
646 (void)FMSTR_RandomNumbersToBuffer(session->restr.authSalt, sizeof(session->restr.authSalt));
647 return FMSTR_CopyToBuffer(response, session->restr.authSalt, sizeof(session->restr.authSalt));
648}
649
650#endif /* FMSTR_CFG_F1_RESTRICTED_ACCESS */
651
652/******************************************************************************
653 *
654 * @brief Handling FMSTR_CMD_AUTH2 command
655 *
656 * @param session - transport session
657 * @param msgBuffIO - original command (in) and response buffer (out)
658 * @param retStatus - response status
659 *
660 * @return As all command handlers, the return value should be the buffer
661 * pointer where the response data payload is finished
662 *
663 ******************************************************************************/
664
665#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
666
667FMSTR_BPTR _FMSTR_AuthenticationStep2(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
668{
669 FMSTR_BPTR response = msgBuffIO;
670 FMSTR_U8 reqAccess = 0;
671 FMSTR_U8 access;
672 const FMSTR_CHAR *pass;
673
674 /* Get the Required access from incomming buffer */
675 msgBuffIO = FMSTR_ValueFromBuffer8(&reqAccess, msgBuffIO);
676
677 /* Get access key provided by client */
678 msgBuffIO = FMSTR_CopyFromBuffer(session->restr.accessKey, msgBuffIO, sizeof(session->restr.accessKey));
679 FMSTR_UNUSED(msgBuffIO);
680
681 /* Evaluate all levels (from 3..1) */
682 for (access = FMSTR_RESTRICTED_ACCESS_RWF; access >= FMSTR_RESTRICTED_ACCESS_R; access--)
683 {
684 if ((pass = _FMSTR_GetAccessPassword(access)) == NULL)
685 {
686 break; /* this access level and all lower levels are open (can be granted) */
687 }
688
689#if FMSTR_USE_HASHED_PASSWORDS > 0
690 /* Password is already hashed */
691 FMSTR_MemCpyFrom(fmstr_localKey, (FMSTR_ADDR)pass, sizeof(fmstr_localKey));
692#else
693 /* Password was provided as a string, compute SHA1 hash now */
694 FMSTR_MemSet(session->restr.localKey, 0, sizeof(session->restr.localKey));
695 FMSTR_Sha1Init(&fmstr_sha1Ctx);
696 FMSTR_Sha1Update(&fmstr_sha1Ctx, (const FMSTR_U8 *)pass, FMSTR_StrLen(pass));
697 FMSTR_Sha1Final(&fmstr_sha1Ctx, session->restr.localKey);
698#endif
699
700 /* compute correct key as SHA1(salt + SHA1(password) + salt) */
701 FMSTR_Sha1Init(&fmstr_sha1Ctx);
702 FMSTR_Sha1Update(&fmstr_sha1Ctx, session->restr.authSalt, sizeof(session->restr.authSalt));
703 FMSTR_Sha1Update(&fmstr_sha1Ctx, session->restr.localKey, sizeof(session->restr.localKey));
704 FMSTR_Sha1Update(&fmstr_sha1Ctx, session->restr.authSalt, sizeof(session->restr.authSalt));
705 FMSTR_Sha1Final(&fmstr_sha1Ctx, session->restr.localKey);
706
707 /* is access key valid? (i.e. is client's password valid?) */
708 if (FMSTR_MemCmp(session->restr.localKey, session->restr.accessKey, sizeof(session->restr.localKey)) == 0)
709 {
710 break;
711 }
712 }
713
714 /* Here, the access is the maximum level which is possible to grant with the password provided */
715
716 /* Do not grant higher level than requested */
717 session->restr.grantedAccess = access <= reqAccess ? access : reqAccess;
718
719 /* Return success if at least some access level has been granted. Or when user was only validating the password with
720 * level=0. */
721 if (access != 0U || reqAccess == 0U)
722 {
723 *retStatus = FMSTR_STS_OK;
724 response = FMSTR_ValueToBuffer8(response, session->restr.grantedAccess);
725 }
726 else
727 {
728 *retStatus = FMSTR_STC_EPASS;
729 }
730
731 return response;
732}
733
734#endif /* FMSTR_CFG_F1_RESTRICTED_ACCESS */
735
736/******************************************************************************
737 *
738 * @brief Handling READMEM command
739 *
740 * @param session - transport session
741 * @param msgBuffIO - original command (in) and response buffer (out)
742 * @param retStatus - response status
743 *
744 * @return As all command handlers, the return value should be the buffer
745 * pointer where the response data payload is finished
746 *
747 ******************************************************************************/
748
749FMSTR_BPTR _FMSTR_ReadMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
750{
751 FMSTR_BPTR response = msgBuffIO;
752 FMSTR_ADDR addr;
753 FMSTR_SIZE size;
754
755#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
756 if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_R)
757 {
758 *retStatus = FMSTR_STC_EAUTH;
759 return response;
760 }
761#endif
762
763 /* Get the Address from incomming buffer */
764 msgBuffIO = FMSTR_AddressFromBuffer(&addr, msgBuffIO);
765 /* Get the Size from incomming buffer */
766 msgBuffIO = FMSTR_SizeFromBuffer(&size, msgBuffIO);
767
768#if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY
769 if (FMSTR_CheckTsaSpace(addr, size, FMSTR_FALSE) == FMSTR_FALSE)
770 {
771 *retStatus = FMSTR_STC_EACCESS;
772 return response;
773 }
774#endif
775
776 /* check the response will safely fit into comm buffer */
777 if (size > (FMSTR_U16)FMSTR_COMM_BUFFER_SIZE)
778 {
779 *retStatus = FMSTR_STC_RSPBUFFOVF;
780 return response;
781 }
782
783 /* success */
784 *retStatus = FMSTR_STS_OK;
785 return FMSTR_CopyToBuffer(response, addr, size);
786}
787
788/******************************************************************************
789 *
790 * @brief Handling READMEM command with base address
791 *
792 * @param session - transport session
793 * @param msgBuffIO - original command (in) and response buffer (out)
794 * @param retStatus - response status
795 *
796 * @return As all command handlers, the return value should be the buffer
797 * pointer where the response data payload is finished
798 *
799 ******************************************************************************/
800
801#ifdef FMSTR_PLATFORM_BASE_ADDRESS
802
803FMSTR_BPTR _FMSTR_ReadMemBaseAddress(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
804{
805 FMSTR_BPTR response = msgBuffIO;
806 FMSTR_ADDR addr;
807 FMSTR_SIZE size;
808 FMSTR_INDEX index;
809
810#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
811 if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_R)
812 {
813 *retStatus = FMSTR_STC_EAUTH;
814 return response;
815 }
816#endif
817
818 /* Get the Relative address to base from incoming buffer */
819 msgBuffIO = FMSTR_IndexFromBuffer(&index, msgBuffIO);
820 /* Get the Size from incomming buffer */
821 msgBuffIO = FMSTR_SizeFromBuffer(&size, msgBuffIO);
822
823 addr = (FMSTR_ADDR)(FMSTR_PLATFORM_BASE_ADDRESS + index);
824
825#if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY
826 if (FMSTR_CheckTsaSpace(addr, size, FMSTR_FALSE) == FMSTR_FALSE)
827 {
828 *retStatus = FMSTR_STC_EACCESS;
829 return response;
830 }
831#endif
832
833 /* check the response will safely fit into comm buffer */
834 if (size > (FMSTR_U16)FMSTR_COMM_BUFFER_SIZE)
835 {
836 *retStatus = FMSTR_STC_RSPBUFFOVF;
837 return response;
838 }
839
840 /* success */
841 *retStatus = FMSTR_STS_OK;
842 return FMSTR_CopyToBuffer(response, addr, size);
843}
844#endif /* FMSTR_PLATFORM_BASE_ADDRESS */
845
846/******************************************************************************
847 *
848 * @brief Handling WRITEMEM and WRITEMEM_EX commands
849 *
850 * @param session - transport session
851 * @param msgBuffIO - original command (in) and response buffer (out)
852 * @param retStatus - response status
853 *
854 * @return As all command handlers, the return value should be the buffer
855 * pointer where the response data payload is finished
856 *
857 ******************************************************************************/
858
859FMSTR_BPTR _FMSTR_WriteMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
860{
861 FMSTR_BPTR response = msgBuffIO;
862 FMSTR_ADDR addr;
863 FMSTR_SIZE size;
864 FMSTR_U8 respCode, flags;
865
866#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
867 if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_RW)
868 {
869 *retStatus = FMSTR_STC_EAUTH;
870 return response;
871 }
872#endif
873
874 /* Get the Flags from incomming buffer */
875 msgBuffIO = FMSTR_ValueFromBuffer8(&flags, msgBuffIO);
876 /* Get the Address from incomming buffer */
877 msgBuffIO = FMSTR_AddressFromBuffer(&addr, msgBuffIO);
878 /* Get the Size from incomming buffer */
879 msgBuffIO = FMSTR_SizeFromBuffer(&size, msgBuffIO);
880
881#if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY
882 if (FMSTR_CheckTsaSpace(addr, size, FMSTR_TRUE) == FMSTR_FALSE)
883 {
884 respCode = FMSTR_STC_EACCESS;
885 goto FMSTR_WriteMem_exit;
886 }
887#endif
888
889 // TODO Add flash write support FLAG FMSTR_WRMFLAG_WRFLASH
890
891 /*lint -e{534} ignoring function return value */
892 if ((flags & FMSTR_WRMFLAG_WITHMASK) != 0U)
893 {
894 FMSTR_CopyFromBufferWithMask(addr, msgBuffIO, size);
895 }
896 else
897 {
898 msgBuffIO = FMSTR_CopyFromBuffer(addr, msgBuffIO, size);
899 FMSTR_UNUSED(msgBuffIO);
900 }
901
902 respCode = FMSTR_STS_OK;
903
904#if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY
905FMSTR_WriteMem_exit:
906#endif
907
908 *retStatus = respCode;
909
910 return response;
911}
912
913#if FMSTR_SESSION_COUNT > 1
914/******************************************************************************
915 *
916 * @brief Get feature structure from the static array of features
917 *
918 * @param featureType - feature type
919 * @param instance - instance number of the selected feature
920 *
921 * @return Selected feature struct
922 *
923 ******************************************************************************/
924
925static FMSTR_FEATURE_LOCK *_FMSTR_FeatureGet(FMSTR_U8 featureType, FMSTR_U8 instance)
926{
927 FMSTR_INDEX index = -1;
928
929 switch (featureType)
930 {
931#if FMSTR_USE_SCOPE > 0
932 case FMSTR_FEATURE_SCOPE:
933 if (instance < _FMSTR_SC)
934 {
935 index = (FMSTR_INDEX)FMSTR_FEATURE_SCOPE_INSTANCE(instance);
936 }
937 break;
938#endif
939
940#if FMSTR_USE_RECORDER > 0
941 case FMSTR_FEATURE_REC:
942 if (instance < _FMSTR_RC)
943 {
944 index = (FMSTR_INDEX)FMSTR_FEATURE_REC_INSTANCE(instance);
945 }
946 break;
947#endif
948
949#if FMSTR_USE_APPCMD > 0
950 case FMSTR_FEATURE_APPCMD:
951 if (instance < _FMSTR_AC)
952 {
953 index = (FMSTR_INDEX)FMSTR_FEATURE_APPCMD_INSTANCE(instance);
954 }
955 break;
956#endif
957
958 case FMSTR_FEATURE_FLASHPROG:
959 if (instance < _FMSTR_FPG)
960 {
961 index = (FMSTR_INDEX)FMSTR_FEATURE_FLASHPROG_INSTANCE(instance);
962 }
963 break;
964
965#if FMSTR_USE_PIPES > 0
966 case FMSTR_FEATURE_PIPE:
967 {
968 FMSTR_INDEX pipeIndex = FMSTR_FindPipeIndex(instance);
969 if (pipeIndex < (FMSTR_INDEX)_FMSTR_PC)
970 {
971 index = (FMSTR_INDEX)FMSTR_FEATURE_PIPE_INSTANCE(pipeIndex);
972 }
973 }
974 break;
975#endif
976
977 default:
978 index = -1;
979 break;
980 }
981
982 /* Check max size */
983 if (index < 0 || index > (FMSTR_INDEX)FMSTR_FEATURE_LOCK_COUNT)
984 {
985 return NULL;
986 }
987
988 return &fmstr_features[index];
989}
990
991/******************************************************************************
992 *
993 * @brief Lock or unlock feature in a multi-session configuration
994 *
995 * @param session - transport session
996 * @param msgBuffIO - original command (in) and response buffer (out)
997 * @param retStatus - response status
998 *
999 * @return As all command handlers, the return value should be the buffer
1000 * pointer where the response data payload is finished
1001 *
1002 ******************************************************************************/
1003
1004static FMSTR_BPTR _FMSTR_FeatureLock(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus)
1005{
1006 FMSTR_BPTR response = msgBuffIO;
1007 FMSTR_FEATURE_LOCK *feature = NULL;
1008 FMSTR_U8 featType = 0;
1009 FMSTR_U8 instance = 0;
1010 FMSTR_U8 lock = 0;
1011
1012#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
1013 if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_R)
1014 {
1015 *retStatus = FMSTR_STC_EAUTH;
1016 return response;
1017 }
1018#endif
1019
1020 /* Get the Feature Type from incomming buffer */
1021 msgBuffIO = FMSTR_ValueFromBuffer8(&featType, msgBuffIO);
1022 /* Get the Instance from incomming buffer */
1023 msgBuffIO = FMSTR_ValueFromBuffer8(&instance, msgBuffIO);
1024 /* Get the Lock/Unlock from incomming buffer */
1025 msgBuffIO = FMSTR_ValueFromBuffer8(&lock, msgBuffIO);
1026
1027 /* Get feature struct */
1028 feature = _FMSTR_FeatureGet(featType, instance);
1029 if (feature == NULL)
1030 {
1031 /* Invalid instance */
1032 *retStatus = FMSTR_STC_EINSTANCE;
1033 return response;
1034 }
1035
1036 /* Check locked session */
1037 if (feature->lockCount > 0 && feature->owner != session)
1038 {
1039 /* Feature is locked by another session */
1040 *retStatus = FMSTR_STC_SERVBUSY;
1041 return response;
1042 }
1043
1044 /* Lock */
1045 if (lock != 0U)
1046 {
1047 feature->lockCount++;
1048 feature->owner = session;
1049 }
1050 /* Unlock */
1051 else
1052 {
1053 if (feature->lockCount > 0)
1054 {
1055 feature->lockCount--;
1056 }
1057 if (feature->lockCount == 0)
1058 {
1059 feature->owner = NULL;
1060 }
1061 }
1062
1063 *retStatus = FMSTR_STS_OK;
1064
1065 return response;
1066}
1067
1068/******************************************************************************
1069 *
1070 * @brief Unlock all features, which is owned by session
1071 *
1072 * @param session - transport session
1073 *
1074 ******************************************************************************/
1075
1076static void _FMSTR_UnlockFeatures(FMSTR_SESSION *session)
1077{
1078 FMSTR_FEATURE_LOCK *feature = NULL;
1079 FMSTR_U8 i;
1080
1081 for (i = 0; i < FMSTR_FEATURE_LOCK_COUNT; i++)
1082 {
1083 feature = &fmstr_features[i];
1084 if (feature->owner == session)
1085 {
1086 feature->lockCount = 0;
1087 feature->owner = NULL;
1088 }
1089 }
1090}
1091
1092/******************************************************************************
1093 *
1094 * @brief Check if feature is locked for the owner (session)
1095 *
1096 * @param session - transport session
1097 * @param featureType - feature type
1098 * @param instance - instance number of the selected feature
1099 *
1100 * @return locked state
1101 *
1102 ******************************************************************************/
1103
1104FMSTR_BOOL FMSTR_IsFeatureOwned(FMSTR_SESSION *session, FMSTR_U8 featureType, FMSTR_U8 instance)
1105{
1106 FMSTR_FEATURE_LOCK *feature = NULL;
1107
1108 /* Get feature struct */
1109 feature = _FMSTR_FeatureGet(featureType, instance);
1110 if (feature == NULL)
1111 {
1112 return FMSTR_FALSE;
1113 }
1114
1115 if (feature->owner == session && feature->lockCount > 0)
1116 {
1117 return FMSTR_TRUE;
1118 }
1119
1120 return FMSTR_FALSE;
1121}
1122#endif /* FMSTR_SESSION_COUNT > 1 */
1123
1124/******************************************************************************
1125 *
1126 * @brief Free transport session
1127 *
1128 * @param identification - transport identification
1129 *
1130 ******************************************************************************/
1131
1132void FMSTR_FreeSession(void *identification)
1133{
1134 FMSTR_SESSION *ses = _FMSTR_FindSession(identification, FMSTR_FALSE);
1135 if (ses != NULL && ses->identification == identification)
1136 {
1137#if FMSTR_SESSION_COUNT > 1
1138 /* Unlock all features, which is owned by session */
1139 _FMSTR_UnlockFeatures(ses);
1140#endif
1141
1142 FMSTR_MemSet(ses, 0, sizeof(FMSTR_SESSION));
1143 }
1144}
1145
1146/******************************************************************************
1147 *
1148 * @brief Find transport session by transport identification
1149 *
1150 * @param identification - transport identification
1151 * @param create - when true, creates session with transport identification
1152 *
1153 * @return Found/created session.
1154 *
1155 ******************************************************************************/
1156
1157static FMSTR_SESSION *_FMSTR_FindSession(void *identification, FMSTR_BOOL create)
1158{
1159 FMSTR_SESSION *ses;
1160 FMSTR_SESSION *freeSession = NULL;
1161 FMSTR_INDEX i;
1162
1163 for (i = 0; i < FMSTR_SESSION_COUNT; i++)
1164 {
1165 ses = &fmstr_sessions[i];
1166
1167 /* Find session by identification */
1168 if (ses->identification == identification)
1169 {
1170 return ses;
1171 }
1172
1173 /* Find free session */
1174 if (freeSession == NULL && ses->identification == NULL)
1175 {
1176 freeSession = ses;
1177 }
1178 }
1179
1180 /* Set identification to session */
1181 if (freeSession != NULL && create != FMSTR_FALSE)
1182 {
1183 freeSession->identification = identification;
1184
1185#if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0
1186 /* Initialize the access protection variables */
1187 FMSTR_MemSet(freeSession->restr.authSalt, 0xaa, sizeof(freeSession->restr.authSalt));
1188 freeSession->restr.grantedAccess = fmstr_dfltGrantedAccess;
1189#endif
1190 }
1191
1192 return freeSession;
1193}
1194
1195#else /* !FMSTR_DISABLE */
1196
1197/******************************************************************************
1198 *
1199 * @brief FreeMASTER driver initialization is disabled
1200 *
1201 ******************************************************************************/
1202
1203FMSTR_BOOL FMSTR_Init(void)
1204{
1205 return FMSTR_FALSE;
1206}
1207
1208/*******************************************************************************
1209 *
1210 * @brief API: Main "Polling" call from the application main loop
1211 *
1212 *******************************************************************************/
1213
1214void FMSTR_Poll(void)
1215{
1216}
1217
1218#endif /* !FMSTR_DISABLE */
1219