1 /***************************************************************************//**
2 * @file
3 * @brief Silicon Labs Secure Engine Manager API.
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #include "sl_se_manager.h"
32
33 #if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
34 #if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
35
36 #include "sli_se_manager_internal.h"
37 #include "sli_se_manager_mailbox.h"
38 #include "sl_assert.h"
39 #if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
40 #if defined(_SILICON_LABS_32B_SERIES_3)
41 #include "sl_hal_bus.h"
42 #else
43 #include "em_bus.h"
44 #endif
45 #endif
46 #if !defined(SLI_SE_MANAGER_HOST_SYSTEM)
47 #include "sli_psec_osal.h"
48 #endif
49
50 #include <string.h>
51
52 /// @addtogroup sl_se_managers
53 /// @{
54
55 // -----------------------------------------------------------------------------
56 // Locals
57
58 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
59 #if defined(SL_SE_MANAGER_THREADING)
60 /// Priority to use for SEMBRX IRQ
61 #if defined(SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY)
62 #if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY >= (1U << __NVIC_PRIO_BITS) )
63 #error Illegal SEMBRX priority level.
64 #endif
65 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
66 #if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY < (configMAX_SYSCALL_INTERRUPT_PRIORITY >> (8U - __NVIC_PRIO_BITS) ) )
67 #error Illegal SEMBRX priority level.
68 #endif
69 #else
70 #if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY < CORE_ATOMIC_BASE_PRIORITY_LEVEL)
71 #error Illegal SEMBRX priority level.
72 #endif
73 #endif
74 #define SE_MANAGER_SEMBRX_IRQ_PRIORITY SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY
75 #else
76 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
77 #define SE_MANAGER_SEMBRX_IRQ_PRIORITY (configMAX_SYSCALL_INTERRUPT_PRIORITY >> (8U - __NVIC_PRIO_BITS) )
78 #else
79 #define SE_MANAGER_SEMBRX_IRQ_PRIORITY (CORE_ATOMIC_BASE_PRIORITY_LEVEL)
80 #endif
81 #endif
82 #else // defined(SL_SE_MANAGER_THREADING)
83 /// Priority to use for SEMBRX IRQ
84 #if defined(SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY)
85 #define SE_MANAGER_SEMBRX_IRQ_PRIORITY SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY
86 #else
87 #define SE_MANAGER_SEMBRX_IRQ_PRIORITY (0)
88 #endif
89 #endif // defined(SL_SE_MANAGER_THREADING)
90 #endif // defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
91
92 #if defined(SL_SE_MANAGER_THREADING) \
93 || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
94
95 // Flag to indicate that the SE Manager is initialized or not.
96 static volatile bool se_manager_initialized = false;
97
98 #if defined(SL_SE_MANAGER_THREADING)
99 // Lock mutex for synchronizing multiple threads calling into the
100 // SE Manager API.
101 static sli_psec_osal_lock_t se_lock = { 0 };
102
103 #endif // SL_SE_MANAGER_THREADING
104
105 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
106 // SE command completion.
107 static sli_psec_osal_completion_t se_command_completion;
108 // SE mailbox command response code. This value is read from the SEMAILBOX
109 // in ISR in order to clear the command complete interrupt condition.
110 static sli_se_mailbox_response_t se_manager_command_response = SLI_SE_RESPONSE_INTERNAL_ERROR;
111 #endif // SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
112
113 #endif // #if defined (SL_SE_MANAGER_THREADING)
114 // || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
115
116 // -----------------------------------------------------------------------------
117 // Global functions
118
119 /***************************************************************************//**
120 * Initialize the SE Manager.
121 ******************************************************************************/
sl_se_init(void)122 sl_status_t sl_se_init(void)
123 {
124 sl_status_t ret = SL_STATUS_OK;
125 #if defined (SL_SE_MANAGER_THREADING) \
126 || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
127
128 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
129 (void)se_manager_command_response;
130 #endif
131
132 #if defined(SL_SE_MANAGER_THREADING)
133 SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_START
134 #endif
135
136 if ( !se_manager_initialized ) {
137 #if defined(SL_SE_MANAGER_THREADING)
138 // Initialize SE lock
139 ret = sli_psec_osal_init_lock(&se_lock);
140 #endif
141 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
142 if (ret == SL_STATUS_OK) {
143 // Initialize command completion object.
144 ret = sli_psec_osal_init_completion(&se_command_completion);
145 if (ret == SL_STATUS_OK) {
146 // Enable SE RX mailbox interrupt in NVIC, but not in SEMAILBOX
147 // which will be enabled if the yield parameter in
148 // sli_se_execute_and_wait is true.
149 NVIC_SetPriority(SEMBRX_IRQn, SE_MANAGER_SEMBRX_IRQ_PRIORITY);
150 NVIC_EnableIRQ(SEMBRX_IRQn);
151 }
152 }
153 #endif // SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
154 if (ret == SL_STATUS_OK) {
155 se_manager_initialized = true;
156 }
157 }
158
159 #if defined(SL_SE_MANAGER_THREADING)
160 SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END
161 #endif
162
163 #endif // #if defined (SL_SE_MANAGER_THREADING)
164 // || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
165
166 return ret;
167 }
168
169 /***************************************************************************//**
170 * Denitialize the SE Manager.
171 ******************************************************************************/
sl_se_deinit(void)172 sl_status_t sl_se_deinit(void)
173 {
174 sl_status_t ret = SL_STATUS_OK;
175
176 #if defined (SL_SE_MANAGER_THREADING) \
177 || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
178
179 #if defined(SL_SE_MANAGER_THREADING)
180 SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_START
181 #endif
182
183 if ( se_manager_initialized ) {
184 // We need to exit the critical section in case the SE lock is held by a
185 // thread, and we want to take it before de-initializing.
186 #if defined(SL_SE_MANAGER_THREADING)
187 SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END
188 #endif
189
190 // Acquire the SE lock to make sure no thread is executing SE commands
191 // when we de-initialize.
192 ret = sli_se_lock_acquire();
193 if (ret != SL_STATUS_OK) {
194 return ret;
195 }
196
197 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
198 // Disable SE RX mailbox interrupt in NVIC.
199 NVIC_ClearPendingIRQ(SEMBRX_IRQn);
200 NVIC_DisableIRQ(SEMBRX_IRQn);
201 // Free command completion object.
202 ret = sli_psec_osal_free_completion(&se_command_completion);
203 #endif // SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
204
205 #if defined(SL_SE_MANAGER_THREADING)
206 if (ret == SL_STATUS_OK) {
207 // Free the SE lock mutex
208 ret = sli_psec_osal_free_lock(&se_lock);
209 }
210 #endif
211
212 // Mark the SE Manager as un-initialized.
213 se_manager_initialized = false;
214 }
215 #if defined(SL_SE_MANAGER_THREADING)
216 else {
217 SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END
218 }
219 #endif
220
221 #endif // #if defined (SL_SE_MANAGER_THREADING)
222 // || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
223
224 return ret;
225 }
226
227 /***************************************************************************//**
228 * @brief
229 * Translate SE response codes to sl_status_t codes.
230 *
231 * @return
232 * Converted status code, their meaning is documented here @ref sl_status.h,
233 * Asserts and returns @c SL_STATUS_FAIL on unexpected response.
234 ******************************************************************************/
sli_se_to_sl_status(sli_se_mailbox_response_t res)235 sl_status_t sli_se_to_sl_status(sli_se_mailbox_response_t res)
236 {
237 switch (res) {
238 case SLI_SE_RESPONSE_OK:
239 return SL_STATUS_OK;
240 case SLI_SE_RESPONSE_INVALID_COMMAND:
241 return SL_STATUS_COMMAND_IS_INVALID;
242 case SLI_SE_RESPONSE_AUTHORIZATION_ERROR:
243 return SL_STATUS_INVALID_CREDENTIALS;
244 case SLI_SE_RESPONSE_INVALID_SIGNATURE:
245 return SL_STATUS_INVALID_SIGNATURE;
246 case SLI_SE_RESPONSE_BUS_ERROR:
247 return SL_STATUS_BUS_ERROR;
248 case SLI_SE_RESPONSE_INTERNAL_ERROR:
249 return SL_STATUS_FAIL;
250 case SLI_SE_RESPONSE_CRYPTO_ERROR:
251 return SL_STATUS_FAIL;
252 case SLI_SE_RESPONSE_INVALID_PARAMETER:
253 return SL_STATUS_INVALID_PARAMETER;
254 case SLI_SE_RESPONSE_ABORT:
255 return SL_STATUS_ABORT;
256 case SLI_SE_RESPONSE_SELFTEST_ERROR:
257 return SL_STATUS_INITIALIZATION;
258 case SLI_SE_RESPONSE_NOT_INITIALIZED:
259 return SL_STATUS_NOT_INITIALIZED;
260 #if defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
261 case SLI_SE_RESPONSE_MAILBOX_INVALID:
262 return SL_STATUS_COMMAND_IS_INVALID;
263 #endif
264 default:
265 // Assert we do not get a bad SE response code.
266 EFM_ASSERT(false);
267 return SL_STATUS_FAIL;
268 }
269 }
270
271 /***************************************************************************//**
272 * Acquire the SE lock for exclusive access if necessary (thread mode).
273 * Enable the SEMAILBOX clock if necessary.
274 ******************************************************************************/
sli_se_lock_acquire(void)275 sl_status_t sli_se_lock_acquire(void)
276 {
277 #if defined(SL_SE_MANAGER_THREADING)
278 sl_status_t status = sli_psec_osal_take_lock(&se_lock);
279 #else
280 sl_status_t status = SL_STATUS_OK;
281 #endif
282 #if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
283 if (status == SL_STATUS_OK) {
284 #if defined(_SILICON_LABS_32B_SERIES_3)
285 sl_hal_bus_reg_write_bit(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 1);
286 #else
287 BUS_RegBitWrite(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 1);
288 #endif
289 // Make sure the write to CMU->CLKEN1 is finished.
290 __DSB();
291 }
292 #endif
293 return status;
294 }
295
296 /***************************************************************************//**
297 * Release the SE lock if necessary (thread mode).
298 * Disable the SEMAILBOX clock if necessary.
299 ******************************************************************************/
sli_se_lock_release(void)300 sl_status_t sli_se_lock_release(void)
301 {
302 #if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
303 #if defined(_SILICON_LABS_32B_SERIES_3)
304 sl_hal_bus_reg_write_bit(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 0);
305 #else
306 BUS_RegBitWrite(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 0);
307 #endif
308 #endif
309 #if defined(SL_SE_MANAGER_THREADING)
310 return sli_psec_osal_give_lock(&se_lock);
311 #else
312 return SL_STATUS_OK;
313 #endif
314 }
315
316 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
317
318 /***************************************************************************//**
319 * @brief
320 * SE Mailbox Interrupt Service Routine
321 ******************************************************************************/
SEMBRX_IRQHandler(void)322 void SEMBRX_IRQHandler(void)
323 {
324 sl_status_t status;
325 // Check if the SE mailbox is the source of the interrupt.
326 if (SEMAILBOX_HOST->RX_STATUS & SEMAILBOX_RX_STATUS_RXINT) {
327 // Signal SE mailbox completion.
328 status = sli_psec_osal_complete(&se_command_completion);
329 EFM_ASSERT(status == SL_STATUS_OK);
330 }
331 // Get command response (clears interrupt condition in SEMAILBOX)
332 se_manager_command_response = sli_se_mailbox_read_response();
333 // Clear interrupt condition in NVIC
334 NVIC_ClearPendingIRQ(SEMBRX_IRQn);
335 }
336
337 #endif // #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
338
339 /***************************************************************************//**
340 * Set the yield attribute of the SE command context object.
341 ******************************************************************************/
sl_se_set_yield(sl_se_command_context_t * cmd_ctx,bool yield)342 sl_status_t sl_se_set_yield(sl_se_command_context_t *cmd_ctx,
343 bool yield)
344 {
345 if (cmd_ctx == NULL) {
346 return SL_STATUS_INVALID_PARAMETER;
347 }
348
349 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
350 cmd_ctx->yield = yield;
351 return SL_STATUS_OK;
352 #else
353 if (yield) {
354 return SL_STATUS_NOT_AVAILABLE;
355 } else {
356 (void) cmd_ctx;
357 return SL_STATUS_OK;
358 }
359 #endif
360 }
361
362 /***************************************************************************//**
363 * @brief
364 * Execute and wait for SE mailbox command to complete.
365 *
366 * @return
367 * One of the following status code, any other status codes relates to internal
368 * function errors see @ref sl_status.h for their meaning.
369 * - @c SL_STATUS_OK
370 * - @c SL_STATUS_INVALID_PARAMETER
371 ******************************************************************************/
372 #if defined(SLI_MAILBOX_COMMAND_SUPPORTED) && !defined(SLI_SE_MANAGER_HOST_SYSTEM)
sli_se_execute_and_wait(sl_se_command_context_t * cmd_ctx)373 sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
374 {
375 sl_status_t status = SL_STATUS_FAIL;
376 sli_se_mailbox_response_t command_response = SLI_SE_RESPONSE_INTERNAL_ERROR;
377
378 if (cmd_ctx == NULL) {
379 return SL_STATUS_INVALID_PARAMETER;
380 }
381
382 // Try to acquire SE lock
383 status = sli_se_lock_acquire();
384 if (status != SL_STATUS_OK) {
385 return status;
386 }
387
388 // Execute SE mailbox command
389 sli_se_mailbox_execute_command(&cmd_ctx->command);
390
391 #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION) \
392 && !defined(_SILICON_LABS_32B_SERIES_3)
393 if (cmd_ctx->yield) {
394 // Enable SEMAILBOX RXINT interrupt
395 sli_se_mailbox_enable_interrupt(SEMAILBOX_CONFIGURATION_RXINTEN);
396
397 // Yield and Wait for the command completion signal
398 status = sli_psec_osal_wait_completion(&se_command_completion,
399 SLI_PSEC_OSAL_WAIT_FOREVER);
400
401 // Disable SEMAILBOX RXINT interrupt.
402 sli_se_mailbox_disable_interrupt(SEMAILBOX_CONFIGURATION_RXINTEN);
403
404 if (status != SL_STATUS_OK) {
405 #if (_SILICON_LABS_32B_SERIES == 3)
406 // Read the command handle word ( not used ) from the SEMAILBOX FIFO
407 SEMAILBOX_HOST->FIFO;
408 #endif // #if (_SILICON_LABS_32B_SERIES == 3)
409 sli_se_lock_release();
410 return status;
411 }
412
413 // Get response which is read in the ISR to clear interrupt condition.
414 command_response = se_manager_command_response;
415 // Default to an error.
416 se_manager_command_response = SLI_SE_RESPONSE_INTERNAL_ERROR;
417 } else {
418 // Wait for command completion and get command response
419 command_response = sli_se_mailbox_read_response();
420 }
421
422 #else // #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
423
424 #if defined(_SILICON_LABS_32B_SERIES_3)
425 CORE_DECLARE_IRQ_STATE;
426 CORE_ENTER_ATOMIC();
427 #endif
428
429 // Wait for command completion and get command response
430 command_response = sli_se_mailbox_read_response();
431
432 #if defined(_SILICON_LABS_32B_SERIES_3)
433 CORE_EXIT_ATOMIC();
434 #endif
435
436 #endif // #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
437
438 #if (_SILICON_LABS_32B_SERIES == 3)
439 // Read the command handle word ( not used ) from the SEMAILBOX FIFO
440 SEMAILBOX_HOST->FIFO;
441 #endif // #if (_SILICON_LABS_32B_SERIES == 3)
442
443 // Release SE lock
444 status = sli_se_lock_release();
445
446 // Return sl_status_t code.
447 if (command_response == SLI_SE_RESPONSE_OK) {
448 return status;
449 } else {
450 // Convert from sli_se_mailbox_response_t to sl_status_t code and return.
451 return sli_se_to_sl_status(command_response);
452 }
453 }
454
455 #elif defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED) // SLI_MAILBOX_COMMAND_SUPPORTED
456
sli_se_execute_and_wait(sl_se_command_context_t * cmd_ctx)457 sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
458 {
459 sl_status_t status;
460
461 if (cmd_ctx == NULL) {
462 return SL_STATUS_INVALID_PARAMETER;
463 }
464
465 // Try to acquire SE lock
466 status = sli_se_lock_acquire();
467 if (status != SL_STATUS_OK) {
468 return status;
469 }
470
471 // Execute SE mailbox command
472 sli_se_mailbox_execute_command(&cmd_ctx->command);
473
474 return SL_STATUS_FAIL; // Should never get to this point
475 }
476
477 /***************************************************************************//**
478 * From VSE mailbox read which command, if any, was executed.
479 ******************************************************************************/
sl_se_read_executed_command(sl_se_command_context_t * cmd_ctx)480 sl_status_t sl_se_read_executed_command(sl_se_command_context_t *cmd_ctx)
481 {
482 sl_status_t status;
483
484 if (cmd_ctx == NULL) {
485 return SL_STATUS_INVALID_PARAMETER;
486 }
487
488 // Try to acquire SE lock
489 status = sli_se_lock_acquire();
490 if (status != SL_STATUS_OK) {
491 return status;
492 }
493
494 // Read command
495 cmd_ctx->command.command = sli_vse_mailbox_read_executed_command();
496
497 // Release SE lock
498 status = sli_se_lock_release();
499
500 // Return sl_status_t code.
501 if (cmd_ctx->command.command == SLI_SE_RESPONSE_MAILBOX_INVALID) {
502 // Convert from sli_se_mailbox_response_t to sl_status_t code and return.
503 return sli_se_to_sl_status(SLI_SE_RESPONSE_MAILBOX_INVALID);
504 } else {
505 return status;
506 }
507 }
508
509 /***************************************************************************//**
510 * Acknowledge and get status and output data of a completed command.
511 ******************************************************************************/
sl_se_ack_command(sl_se_command_context_t * cmd_ctx)512 sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx)
513 {
514 sl_status_t status;
515 sl_status_t command_response;
516
517 if (cmd_ctx == NULL) {
518 return SL_STATUS_INVALID_PARAMETER;
519 }
520
521 // Try to acquire SE lock
522 status = sli_se_lock_acquire();
523 if (status != SL_STATUS_OK) {
524 return status;
525 }
526
527 // Acknowledge VSE mailbox command
528 command_response = sli_vse_mailbox_ack_command(&cmd_ctx->command);
529
530 // Release SE lock
531 status = sli_se_lock_release();
532
533 // Return sl_status_t code.
534 if (command_response == SLI_SE_RESPONSE_OK) {
535 return status;
536 } else {
537 // Convert from SE_Response_t to sl_status_t code and return.
538 return sli_se_to_sl_status(command_response);
539 }
540 }
541
542 #endif // SLI_VSE_MAILBOX_COMMAND_SUPPORTED
543
544 #endif // !SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT
545
546 /***************************************************************************//**
547 * Initialize an SE command context object
548 ******************************************************************************/
sl_se_init_command_context(sl_se_command_context_t * cmd_ctx)549 sl_status_t sl_se_init_command_context(sl_se_command_context_t *cmd_ctx)
550 {
551 sl_se_command_context_t v = SL_SE_COMMAND_CONTEXT_INIT;
552
553 if (cmd_ctx == NULL) {
554 return SL_STATUS_INVALID_PARAMETER;
555 }
556
557 *cmd_ctx = v;
558 return SL_STATUS_OK;
559 }
560
561 /***************************************************************************//**
562 * De-initialize an SE command context object
563 ******************************************************************************/
sl_se_deinit_command_context(sl_se_command_context_t * cmd_ctx)564 sl_status_t sl_se_deinit_command_context(sl_se_command_context_t *cmd_ctx)
565 {
566 if (cmd_ctx == NULL) {
567 return SL_STATUS_INVALID_PARAMETER;
568 }
569
570 return sl_se_init_command_context(cmd_ctx);
571 }
572
573 /** @} (end addtogroup sl_se) */
574
575 #endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
576