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