1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * PolarFire SoC Microprocessor Subsystem(MSS) System Services bare metal driver
7  * implementation.
8  */
9 
10 #include "mpfs_hal/mss_hal.h"
11 #include "mss_sys_services_regs.h"
12 #include "mss_sys_services.h"
13 
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /*******************************************************************************
20  * Null buffer constant definition
21  */
22 #define NULL_BUFFER                      (( uint8_t* ) 0)
23 
24 /*-------------------------------------------------------------------------*//**
25   System service response offset
26   ============================
27   The following constants are used to specify the offset in the mailbox where
28   the service response is written by the system controller after service
29   execution.
30 */
31 #define MSS_SYS_COMMON_RET_OFFSET                               0u
32 #define MSS_SYS_DIGITAL_SIG_RET_OFFSET                          48u
33 #define MSS_SYS_SECURE_NVM_READ_RET_OFFSET                      16u
34 #define MSS_SYS_PUF_EMULATION_RET_OFFSET                        20u
35 #define MSS_SYS_DIGEST_CHECK_RET_OFFSET                         4u
36 #define MSS_SYS_GENERATE_OTP_RET_OFFSET                         20u
37 
38 /*******************************************************************************
39  * Global variables declarations
40  */
41 volatile uint8_t g_message_received = 0u;
42 uint8_t g_service_mode = 0u;
43 
44 uint8_t* gp_int_service_response;
45 uint16_t g_int_service_response_size;
46 uint16_t g_int_service_response_offset;
47 
48 volatile uint8_t g_message_interrupt_counter = 0u;
49 
50 /*******************************************************************************
51  * Callback handler function declaration
52  */
53 mss_sys_service_handler_t mss_sys_interrupt_handler;
54 
55 /*******************************************************************************
56  * Local function declarations.
57  */
58 static uint16_t execute_ss_polling_mode
59 (
60     uint8_t cmd_opcode,
61     uint8_t* cmd_data,
62     uint16_t cmd_data_size,
63     uint8_t* p_response,
64     uint16_t response_size,
65     uint16_t mb_offset,
66     uint16_t response_offset
67 );
68 
69 static uint16_t execute_ss_interrupt_mode
70 (
71     uint8_t cmd_opcode,
72     uint8_t* cmd_data,
73     uint16_t cmd_data_size,
74     uint8_t* p_response,
75     uint16_t response_size,
76     uint16_t mb_offset,
77     uint16_t response_offset
78 );
79 
80 static uint16_t request_system_service
81 (
82     uint8_t cmd_opcode,
83     uint8_t* cmd_data,
84     uint16_t cmd_data_size,
85     uint8_t* p_response,
86     uint16_t response_size,
87     uint16_t mb_offset,
88     uint16_t response_offset
89 );
90 
91 /*-----------------------------------------------------------------------------
92                              Public Functions
93  -----------------------------------------------------------------------------*/
94 
95 /***************************************************************************//**
96  * MSS_SYS_get_serial_number()
97  * See "mss_sysservices.h" for details of how to use this function.
98  */
99 void
MSS_SYS_select_service_mode(uint8_t sys_service_mode,mss_sys_service_handler_t mss_sys_service_interrupt_handler)100 MSS_SYS_select_service_mode
101 (
102     uint8_t sys_service_mode,
103     mss_sys_service_handler_t mss_sys_service_interrupt_handler
104 )
105 {
106     g_service_mode = sys_service_mode;
107     mss_sys_interrupt_handler = mss_sys_service_interrupt_handler;
108 }
109 
110 
111 /***************************************************************************//**
112  * MSS_SYS_get_serial_number()
113  * See "mss_sysservices.h" for details of how to use this function.
114  */
115 uint16_t
MSS_SYS_get_serial_number(uint8_t * p_serial_number,uint16_t mb_offset)116 MSS_SYS_get_serial_number
117 (
118     uint8_t * p_serial_number,
119     uint16_t mb_offset
120 )
121 {
122     uint16_t status = MSS_SYS_PARAM_ERR;
123 
124     if (p_serial_number == NULL_BUFFER)
125     {
126         return status;
127     }
128 
129     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
130     {
131         status = execute_ss_interrupt_mode(
132                 (uint8_t)MSS_SYS_SERIAL_NUMBER_REQUEST_CMD,
133                 NULL_BUFFER,
134                 MSS_SYS_WITHOUT_CMD_DATA,
135                 p_serial_number,
136                 (uint16_t)MSS_SYS_SERIAL_NUMBER_RESP_LEN,
137                 mb_offset,
138                 MSS_SYS_COMMON_RET_OFFSET);
139     }
140     else
141     {
142         status = execute_ss_polling_mode(
143                 (uint8_t)MSS_SYS_SERIAL_NUMBER_REQUEST_CMD,
144                 NULL_BUFFER,
145                 MSS_SYS_WITHOUT_CMD_DATA,
146                 p_serial_number,
147                 (uint16_t)MSS_SYS_SERIAL_NUMBER_RESP_LEN,
148                 mb_offset,
149                 MSS_SYS_COMMON_RET_OFFSET);
150     }
151 
152     return status;
153 }
154 
155 /***************************************************************************//**
156  * SYS_get_user_code()
157  * See "mss_sysservices.h" for details of how to use this function.
158  */
159 uint16_t
MSS_SYS_get_user_code(uint8_t * p_user_code,uint16_t mb_offset)160 MSS_SYS_get_user_code
161 (
162     uint8_t * p_user_code,
163     uint16_t mb_offset
164 )
165 {
166     uint16_t status = MSS_SYS_PARAM_ERR;
167 
168     if (p_user_code == NULL_BUFFER)
169     {
170         return status;
171     }
172 
173     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
174     {
175         status = execute_ss_interrupt_mode(
176                 (uint8_t)MSS_SYS_USERCODE_REQUEST_CMD,
177                 NULL_BUFFER,
178                 MSS_SYS_WITHOUT_CMD_DATA,
179                 p_user_code,
180                 (uint16_t)MSS_SYS_USERCODE_RESP_LEN,
181                 mb_offset,
182                 MSS_SYS_COMMON_RET_OFFSET);
183     }
184     else
185     {
186         status = execute_ss_polling_mode(
187                 (uint8_t)MSS_SYS_USERCODE_REQUEST_CMD,
188                 NULL_BUFFER,
189                 MSS_SYS_WITHOUT_CMD_DATA,
190                 p_user_code,
191                 (uint16_t)MSS_SYS_USERCODE_RESP_LEN,
192                 mb_offset,
193                 MSS_SYS_COMMON_RET_OFFSET);
194     }
195 
196     return status;
197 }
198 
199 /***************************************************************************//**
200  * SYS_get_design_info()
201  * See "mss_sysservices.h" for details of how to use this function.
202  */
203 uint16_t
MSS_SYS_get_design_info(uint8_t * p_design_info,uint16_t mb_offset)204 MSS_SYS_get_design_info
205 (
206     uint8_t * p_design_info,
207     uint16_t mb_offset
208 )
209 {
210     uint16_t status = MSS_SYS_PARAM_ERR;
211 
212     if (p_design_info  == NULL_BUFFER)
213     {
214         return status;
215     }
216 
217     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
218     {
219         status = execute_ss_interrupt_mode(
220                 (uint8_t)MSS_SYS_DESIGN_INFO_REQUEST_CMD,
221                 NULL_BUFFER,
222                 MSS_SYS_WITHOUT_CMD_DATA,
223                 p_design_info,
224                 (uint16_t)MSS_SYS_DESIGN_INFO_RESP_LEN,
225                 mb_offset,
226                 MSS_SYS_COMMON_RET_OFFSET);
227     }
228     else
229     {
230         status = execute_ss_polling_mode(
231                  (uint8_t)MSS_SYS_DESIGN_INFO_REQUEST_CMD,
232                  NULL_BUFFER,
233                  MSS_SYS_WITHOUT_CMD_DATA,
234                  p_design_info,
235                  (uint16_t)MSS_SYS_DESIGN_INFO_RESP_LEN,
236                  mb_offset,
237                  MSS_SYS_COMMON_RET_OFFSET);
238     }
239 
240     return status;
241 }
242 
243 /***************************************************************************//**
244  * SYS_get_device_certificate()
245  * See "mss_sysservices.h" for details of how to use this function.
246  */
247 uint16_t
MSS_SYS_get_device_certificate(uint8_t * p_device_certificate,uint16_t mb_offset)248 MSS_SYS_get_device_certificate
249 (
250     uint8_t * p_device_certificate,
251     uint16_t mb_offset
252 )
253 {
254     uint16_t status = MSS_SYS_PARAM_ERR;
255 
256     if (p_device_certificate  == NULL_BUFFER)
257     {
258         return status;
259     }
260 
261     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
262     {
263         status = execute_ss_interrupt_mode(
264                  (uint8_t)MSS_SYS_DEVICE_CERTIFICATE_REQUEST_CMD,
265                  NULL_BUFFER,
266                  MSS_SYS_WITHOUT_CMD_DATA,
267                  p_device_certificate,
268                  (uint16_t)MSS_SYS_DEVICE_CERTIFICATE_RESP_LEN,
269                  mb_offset,
270                  MSS_SYS_COMMON_RET_OFFSET);
271     }
272     else
273     {
274         status = execute_ss_polling_mode(
275                  (uint8_t)MSS_SYS_DEVICE_CERTIFICATE_REQUEST_CMD,
276                  NULL_BUFFER,
277                  MSS_SYS_WITHOUT_CMD_DATA,
278                  p_device_certificate,
279                  (uint16_t)MSS_SYS_DEVICE_CERTIFICATE_RESP_LEN,
280                  mb_offset,
281                  MSS_SYS_COMMON_RET_OFFSET);
282     }
283 
284     return status;
285 }
286 
287 /***************************************************************************//**
288  * SYS_read_digest()
289  * See "mss_sysservices.h" for details of how to use this function.
290  */
291 uint16_t
MSS_SYS_read_digest(uint8_t * p_digest,uint16_t mb_offset)292 MSS_SYS_read_digest
293 (
294    uint8_t * p_digest,
295    uint16_t mb_offset
296 )
297 {
298     uint16_t status = MSS_SYS_PARAM_ERR;
299 
300     if (p_digest  == NULL_BUFFER)
301     {
302         return status;
303     }
304 
305     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
306     {
307         status = execute_ss_interrupt_mode(
308                  (uint8_t)MSS_SYS_READ_DIGEST_REQUEST_CMD,
309                  NULL_BUFFER,
310                  MSS_SYS_WITHOUT_CMD_DATA,
311                  p_digest,
312                  (uint16_t)MSS_SYS_READ_DIGEST_RESP_LEN,
313                  mb_offset,
314                  MSS_SYS_COMMON_RET_OFFSET);
315     }
316     else
317     {
318         status = execute_ss_polling_mode(
319                  (uint8_t)MSS_SYS_READ_DIGEST_REQUEST_CMD,
320                  NULL_BUFFER,
321                  MSS_SYS_WITHOUT_CMD_DATA,
322                  p_digest,
323                  (uint16_t)MSS_SYS_READ_DIGEST_RESP_LEN,
324                  mb_offset,
325                  MSS_SYS_COMMON_RET_OFFSET);
326     }
327 
328     return status;
329 }
330 
331 /***************************************************************************//**
332  * SYS_query_security()
333  * See "mss_sysservices.h" for details of how to use this function.
334  */
335 uint16_t
MSS_SYS_query_security(uint8_t * p_security_locks,uint16_t mb_offset)336 MSS_SYS_query_security
337 (
338     uint8_t * p_security_locks,
339     uint16_t mb_offset
340 )
341 {
342     uint16_t status = MSS_SYS_PARAM_ERR;
343     uint8_t idx=0;
344     uint8_t buf[36] = {0};
345 
346     if (p_security_locks  == NULL_BUFFER)
347     {
348         return status;
349     }
350 
351     /* Actual QUERY_SECURITY_RESP_LEN is 9 but CoreSysService_PF IP needs number
352      * of words instead of number of bytes to be written to or read from
353      * MailBox */
354     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
355     {
356         status = execute_ss_interrupt_mode(
357                  (uint8_t)MSS_SYS_QUERY_SECURITY_REQUEST_CMD,
358                  NULL_BUFFER,
359                  MSS_SYS_WITHOUT_CMD_DATA,
360                  buf,
361                  (uint16_t)(MSS_SYS_QUERY_SECURITY_RESP_LEN + 3u),
362                  mb_offset,
363                  MSS_SYS_COMMON_RET_OFFSET);
364     }
365     else
366     {
367         status = execute_ss_polling_mode(
368                  (uint8_t)MSS_SYS_QUERY_SECURITY_REQUEST_CMD,
369                  NULL_BUFFER,
370                  MSS_SYS_WITHOUT_CMD_DATA,
371                  buf,
372                  (uint16_t)(MSS_SYS_QUERY_SECURITY_RESP_LEN + 3u),
373                  mb_offset,
374                  MSS_SYS_COMMON_RET_OFFSET);
375     }
376 
377     for (idx = 0u; idx < MSS_SYS_QUERY_SECURITY_RESP_LEN; idx++)
378     {
379         *(p_security_locks + idx) = buf[idx];
380     }
381 
382     return status;
383 }
384 
385 /***************************************************************************//**
386  * SYS_read_debug_info()
387  * See "mss_sysservices.h" for details of how to use this function.
388  */
389 uint16_t
MSS_SYS_read_debug_info(uint8_t * p_debug_info,uint16_t mb_offset)390 MSS_SYS_read_debug_info
391 (
392     uint8_t * p_debug_info,
393     uint16_t mb_offset
394 )
395 {
396 
397     uint16_t status = MSS_SYS_PARAM_ERR;
398 
399     if (p_debug_info  == NULL_BUFFER)
400     {
401         return status;
402     }
403 
404     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
405     {
406         status = execute_ss_interrupt_mode(
407                  (uint8_t)MSS_SYS_READ_DEBUG_INFO_REQUEST_CMD,
408                  NULL_BUFFER,
409                  MSS_SYS_WITHOUT_CMD_DATA,
410                  p_debug_info,
411                  (uint16_t)MSS_SYS_READ_DEBUG_INFO_RESP_LEN,
412                  mb_offset,
413                  MSS_SYS_COMMON_RET_OFFSET);
414     }
415     else
416     {
417         status = execute_ss_polling_mode(
418                  (uint8_t)MSS_SYS_READ_DEBUG_INFO_REQUEST_CMD,
419                  NULL_BUFFER,
420                  MSS_SYS_WITHOUT_CMD_DATA,
421                  p_debug_info,
422                  (uint16_t)MSS_SYS_READ_DEBUG_INFO_RESP_LEN,
423                  mb_offset,
424                  MSS_SYS_COMMON_RET_OFFSET);
425     }
426 
427     return status;
428 }
429 
430 /**************************************************************************//**
431  * SYS_read_envm_param()
432  * See "mss_sysservices.h" for details of how to use this function.
433  */
434 
435 uint16_t
MSS_SYS_read_envm_parameter(uint8_t * p_envm_param,uint16_t mb_offset)436 MSS_SYS_read_envm_parameter
437 (
438     uint8_t * p_envm_param,
439     uint16_t mb_offset
440 )
441 {
442     uint16_t status = MSS_SYS_PARAM_ERR;
443 
444     if (p_envm_param  == NULL_BUFFER)
445     {
446         return status;
447     }
448 
449     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
450     {
451         status = execute_ss_interrupt_mode(
452                  (uint8_t)MSS_SYS_READ_ENVM_PARAM_REQUEST_CMD,
453                  NULL_BUFFER,
454                  MSS_SYS_WITHOUT_CMD_DATA,
455                  p_envm_param,
456                  (uint16_t)MSS_SYS_READ_ENVM_PARAM_RESP_LEN,
457                  mb_offset,
458                  MSS_SYS_COMMON_RET_OFFSET);
459     }
460     else
461     {
462         status = execute_ss_polling_mode(
463                  (uint8_t)MSS_SYS_READ_ENVM_PARAM_REQUEST_CMD,
464                  NULL_BUFFER,
465                  MSS_SYS_WITHOUT_CMD_DATA,
466                  p_envm_param,
467                  (uint16_t)MSS_SYS_READ_ENVM_PARAM_RESP_LEN,
468                  mb_offset,
469                  MSS_SYS_COMMON_RET_OFFSET);
470     }
471 
472     return status;
473 }
474 
475 /***************************************************************************//**
476  * SYS_puf_emulation_service()
477  * See "mss_sysservices.h" for details of how to use this function.
478  */
479 uint16_t
MSS_SYS_puf_emulation_service(uint8_t * p_challenge,uint8_t op_type,uint8_t * p_response,uint16_t mb_offset)480 MSS_SYS_puf_emulation_service
481 (
482     uint8_t * p_challenge,
483     uint8_t op_type,
484     uint8_t* p_response,
485     uint16_t mb_offset
486 )
487 {
488     uint16_t status = MSS_SYS_PARAM_ERR;
489     uint8_t mb_format[20] = {0x00};
490     uint8_t index = 0u;
491 
492     if((p_response  == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
493     {
494         return status;
495     }
496 
497     /* Frame the data required for mailbox */
498     mb_format[index] = op_type;
499 
500     for (index = 4u; index < 20u; index++)
501     {
502         mb_format[index] = p_challenge[index - 4u];
503     }
504 
505     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
506     {
507         status = execute_ss_interrupt_mode(
508                  (uint8_t)MSS_SYS_PUF_EMULATION_SERVICE_REQUEST_CMD,
509                  mb_format,
510                  (uint16_t)MSS_SYS_PUF_EMULATION_SERVICE_CMD_LEN,
511                  p_response,
512                  (uint16_t)MSS_SYS_PUF_EMULATION_SERVICE_RESP_LEN,
513                  mb_offset,
514                  (uint16_t)MSS_SYS_PUF_EMULATION_RET_OFFSET);
515     }
516     else
517     {
518         status = execute_ss_polling_mode(
519                  (uint8_t)MSS_SYS_PUF_EMULATION_SERVICE_REQUEST_CMD,
520                  mb_format,
521                  (uint16_t)MSS_SYS_PUF_EMULATION_SERVICE_CMD_LEN,
522                  p_response,
523                  (uint16_t)MSS_SYS_PUF_EMULATION_SERVICE_RESP_LEN,
524                  mb_offset,
525                  (uint16_t)MSS_SYS_PUF_EMULATION_RET_OFFSET);
526     }
527 
528     return status;
529 }
530 
531 /***************************************************************************//**
532  * SYS_digital_signature_service()
533  * See "mss_sysservices.h" for details of how to use this function.
534  */
535 uint16_t
MSS_SYS_digital_signature_service(uint8_t * p_hash,uint8_t format,uint8_t * p_response,uint16_t mb_offset)536 MSS_SYS_digital_signature_service
537 (
538     uint8_t* p_hash,
539     uint8_t format,
540     uint8_t* p_response,
541     uint16_t mb_offset
542 )
543 {
544     uint16_t status = MSS_SYS_PARAM_ERR;
545 
546     if((p_hash  == NULL_BUFFER) || (p_response == NULL_BUFFER))
547     {
548         return status;
549     }
550 
551     if (format == MSS_SYS_DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
552     {
553         if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
554         {
555             status = execute_ss_interrupt_mode
556                      ((uint8_t)MSS_SYS_DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
557                      p_hash,
558                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_HASH_DATA_LEN,
559                      p_response,
560                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
561                      mb_offset,
562                      (uint16_t)MSS_SYS_DIGITAL_SIG_RET_OFFSET);
563         }
564         else
565         {
566             status = execute_ss_polling_mode
567                      ((uint8_t)MSS_SYS_DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
568                      p_hash,
569                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_HASH_DATA_LEN,
570                      p_response,
571                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
572                      mb_offset,
573                      (uint16_t)MSS_SYS_DIGITAL_SIG_RET_OFFSET);
574         }
575     }
576 
577     else
578     {
579         if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
580         {
581             status = execute_ss_interrupt_mode
582                      ((uint8_t)MSS_SYS_DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
583                      p_hash,
584                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_HASH_DATA_LEN,
585                      p_response,
586                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
587                      mb_offset,
588                      (uint16_t)MSS_SYS_DIGITAL_SIG_RET_OFFSET);
589         }
590         else
591         {
592             status = execute_ss_polling_mode
593                      ((uint8_t)MSS_SYS_DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
594                      p_hash,
595                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_HASH_DATA_LEN,
596                      p_response,
597                      (uint16_t)MSS_SYS_DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
598                      mb_offset,
599                      (uint16_t)MSS_SYS_DIGITAL_SIG_RET_OFFSET);
600         }
601     }
602 
603     return status;
604 }
605 
606 /***************************************************************************//**
607  * SYS_secure_nvm_write()
608  * See "mss_sysservices.h" for details of how to use this function.
609  */
610 uint16_t
MSS_SYS_secure_nvm_write(uint8_t format,uint8_t snvm_module,uint8_t * p_data,uint8_t * p_user_key,uint16_t mb_offset)611 MSS_SYS_secure_nvm_write
612 (
613     uint8_t format,
614     uint8_t snvm_module,
615     uint8_t* p_data,
616     uint8_t* p_user_key,
617     uint16_t mb_offset
618 )
619 {
620     uint8_t frame[256] = {0x00};
621     uint8_t* p_frame = &frame[0];
622     uint16_t index = 0;
623     uint16_t status = MSS_SYS_PARAM_ERR;
624 
625     ASSERT(!(NULL_BUFFER == p_data));
626     ASSERT(!(NULL_BUFFER == p_user_key));
627     ASSERT(!(snvm_module >= 221u));
628 
629     if((p_data  == NULL_BUFFER) || (p_user_key == NULL_BUFFER)
630                                 || (snvm_module >= 221))
631     {
632         return status;
633     }
634 
635     if ((format != MSS_SYS_SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
636       || (format !=  MSS_SYS_SNVM_AUTHEN_TEXT_REQUEST_CMD)
637       || (format != MSS_SYS_SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
638     {
639         return status;
640     }
641 
642     *p_frame = snvm_module; /* SNVMADDR - SNVM module */
643     p_frame += 4; /* Next 3 bytes RESERVED - For alignment */
644 
645     /* Copy user key and send the command/data to mailbox. */
646     if ((format == MSS_SYS_SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
647        (format == MSS_SYS_SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
648     {
649         /* Copy user data */
650         for (index = 0u; index < (MSS_SYS_AUTHENTICATED_TEXT_DATA_LEN
651                 - MSS_SYS_USER_SECRET_KEY_LEN - 4u); index++)
652         {
653             *p_frame = p_data[index];
654             p_frame++;
655         }
656 
657         /* Copy user key */
658         for (index = 0u; index < MSS_SYS_USER_SECRET_KEY_LEN; index++)
659         {
660             *p_frame = p_user_key[index];
661             p_frame++;
662         }
663 
664         if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
665         {
666             status = execute_ss_interrupt_mode(
667                      format,
668                      &frame[0],
669                      (uint16_t)MSS_SYS_AUTHENTICATED_TEXT_DATA_LEN,
670                      NULL_BUFFER,
671                      MSS_SYS_NO_RESPONSE_LEN,
672                      mb_offset,
673                      MSS_SYS_COMMON_RET_OFFSET);
674         }
675         else
676         {
677             status = execute_ss_polling_mode(
678                      format,
679                      &frame[0],
680                      (uint16_t)MSS_SYS_AUTHENTICATED_TEXT_DATA_LEN,
681                      NULL_BUFFER,
682                      MSS_SYS_NO_RESPONSE_LEN,
683                      mb_offset,
684                      MSS_SYS_COMMON_RET_OFFSET);
685         }
686     }
687     else
688     {
689         /* Copy user data */
690         for (index = 0u; index < (MSS_SYS_NON_AUTHENTICATED_TEXT_DATA_LEN - 4u);
691                 index++)
692         {
693             *(p_frame+index) = p_data[index];
694         }
695 
696         if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
697         {
698             status = execute_ss_interrupt_mode(
699                      format,
700                      &frame[0],
701                      (uint16_t)MSS_SYS_NON_AUTHENTICATED_TEXT_DATA_LEN,
702                      NULL_BUFFER,
703                      MSS_SYS_NO_RESPONSE_LEN,
704                      mb_offset,
705                      MSS_SYS_COMMON_RET_OFFSET);
706         }
707         else
708         {
709             status = execute_ss_polling_mode(
710                     format,
711                     &frame[0],
712                     (uint16_t)MSS_SYS_NON_AUTHENTICATED_TEXT_DATA_LEN,
713                     NULL_BUFFER,
714                     MSS_SYS_NO_RESPONSE_LEN,
715                     mb_offset,
716                     MSS_SYS_COMMON_RET_OFFSET);
717         }
718     }
719 
720     return status;
721 }
722 
723 /***************************************************************************//**
724  * SYS_secure_nvm_read()
725  * See "mss_sysservices.h" for details of how to use this function.
726  */
727 uint16_t
MSS_SYS_secure_nvm_read(uint8_t snvm_module,uint8_t * p_user_key,uint8_t * p_admin,uint8_t * p_data,uint16_t data_len,uint16_t mb_offset)728 MSS_SYS_secure_nvm_read
729 (
730     uint8_t snvm_module,
731     uint8_t* p_user_key,
732     uint8_t* p_admin,
733     uint8_t* p_data,
734     uint16_t data_len,
735     uint16_t mb_offset
736 )
737 {
738     /* Frame the message. */
739     uint8_t frame[16] = {0x00u};
740     uint8_t* p_frame = &frame[0];
741     uint16_t index = 0u;
742     uint16_t status = MSS_SYS_PARAM_ERR;
743     uint8_t response[256] = {0x00};
744 
745     ASSERT(!(NULL_BUFFER == p_data));
746     ASSERT(!(NULL_BUFFER == p_admin));
747     ASSERT(!(snvm_module > 221u));
748 
749     ASSERT((data_len == 236u) || (data_len == 252u));
750 
751     if((p_data  == NULL_BUFFER) || (snvm_module >= 221) ||
752        (p_admin == NULL_BUFFER))
753     {
754         return status;
755     }
756 
757 
758     *p_frame = snvm_module; /* SNVMADDR - SNVM module */
759     p_frame += 4u; /* RESERVED - For alignment */
760 
761     /* Copy user key */
762     if (236u == data_len)
763     {
764         for (index = 0u; index < 12u; index++)
765         {
766             ASSERT(p_user_key !=  NULL_BUFFER);
767             *p_frame = p_user_key[index];
768             p_frame++;
769         }
770     }
771     else
772     {
773         p_frame += 12u;
774     }
775 
776     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
777     {
778         status = execute_ss_interrupt_mode(
779                  (uint8_t)MSS_SYS_SNVM_READ_REQUEST_CMD,
780                  &frame[0],
781                  (uint16_t)MSS_SYS_SECURE_NVM_READ_DATA_LEN,
782                  response,
783                  (data_len + 4u),
784                  mb_offset,
785                  (uint16_t)MSS_SYS_SECURE_NVM_READ_RET_OFFSET);
786         }
787     else
788     {
789         status = execute_ss_polling_mode(
790                  (uint8_t)MSS_SYS_SNVM_READ_REQUEST_CMD,
791                  &frame[0],
792                  (uint16_t)MSS_SYS_SECURE_NVM_READ_DATA_LEN,
793                  response,
794                  (data_len + 4u),
795                  mb_offset,
796                  (uint16_t)MSS_SYS_SECURE_NVM_READ_RET_OFFSET);
797     }
798 
799     if (MSS_SYS_SUCCESS == status)
800     {
801         for (index = 0u; index < 4u; index++)
802         {
803             *(p_admin+index) = (uint32_t)response[index];
804         }
805 
806        /* Copy data into user buffer. */
807         for (index = 4u; index < (data_len + 4u); index++)
808         {
809             *(p_data + (index - 4u)) = response[index];
810         }
811     }
812     else
813     {
814         ;
815     }
816 
817     return status;
818 }
819 
820 /***************************************************************************//**
821  * SYS_nonce_service()
822  * See "mss_sysservices.h" for details of how to use this function.
823  */
824 uint16_t
MSS_SYS_nonce_service(uint8_t * p_nonce,uint16_t mb_offset)825 MSS_SYS_nonce_service
826 (
827     uint8_t * p_nonce,
828     uint16_t mb_offset
829 )
830 {
831     uint16_t status = MSS_SYS_PARAM_ERR;
832 
833     if (p_nonce  == NULL_BUFFER)
834     {
835         return status;
836     }
837 
838     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
839     {
840         status = execute_ss_interrupt_mode(
841                  (uint8_t)MSS_SYS_NONCE_SERVICE_REQUEST_CMD,
842                  NULL_BUFFER,
843                  MSS_SYS_WITHOUT_CMD_DATA,
844                  p_nonce,
845                  (uint16_t)MSS_SYS_NONCE_SERVICE_RESP_LEN,
846                  mb_offset,
847                  MSS_SYS_COMMON_RET_OFFSET);
848     }
849     else
850     {
851         status = execute_ss_polling_mode(
852                 (uint8_t)MSS_SYS_NONCE_SERVICE_REQUEST_CMD,
853                 NULL_BUFFER,
854                 MSS_SYS_WITHOUT_CMD_DATA,
855                 p_nonce,
856                 (uint16_t)MSS_SYS_NONCE_SERVICE_RESP_LEN,
857                 mb_offset,
858                 MSS_SYS_COMMON_RET_OFFSET);
859     }
860 
861     return status;
862 }
863 
864 /***************************************************************************//**
865  * MSS_SYS_authenticate_bitstream()
866  * See "mss_sysservices.h" for details of how to use this function.
867  */
868 uint16_t
MSS_SYS_authenticate_bitstream(uint32_t spi_flash_address,uint16_t mb_offset)869 MSS_SYS_authenticate_bitstream
870 (
871     uint32_t spi_flash_address,
872     uint16_t mb_offset
873 )
874 {
875     uint16_t status = MSS_SYS_PARAM_ERR;
876     uint32_t l_spi_flash_address = spi_flash_address;
877 
878     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
879     {
880         status = execute_ss_interrupt_mode(
881                  (uint8_t)MSS_SYS_BITSTREAM_AUTHENTICATE_CMD,
882                  (uint8_t* )&l_spi_flash_address,
883                  (uint16_t)MSS_SYS_BITSTREAM_AUTHENTICATE_DATA_LEN,
884                  NULL_BUFFER,
885                  MSS_SYS_NO_RESPONSE_LEN,
886                  mb_offset,
887                  MSS_SYS_COMMON_RET_OFFSET);
888     }
889     else
890     {
891         status = execute_ss_polling_mode(
892                  (uint8_t)MSS_SYS_BITSTREAM_AUTHENTICATE_CMD,
893                  (uint8_t* )&l_spi_flash_address,
894                  (uint16_t)MSS_SYS_BITSTREAM_AUTHENTICATE_DATA_LEN,
895                  NULL_BUFFER,
896                  MSS_SYS_NO_RESPONSE_LEN,
897                  mb_offset,
898                  MSS_SYS_COMMON_RET_OFFSET);
899     }
900 
901     return status;
902 }
903 
904 /***************************************************************************//**
905  * MSS_SYS_authenticate_iap_image()
906  * See "mss_sysservices.h" for details of how to use this function.
907  */
908 uint16_t
MSS_SYS_authenticate_iap_image(uint32_t spi_idx)909 MSS_SYS_authenticate_iap_image
910 (
911     uint32_t spi_idx
912 )
913 {
914     uint16_t status = MSS_SYS_PARAM_ERR;
915 
916     ASSERT(!(spi_idx == 1u));
917 
918     if (spi_idx == 1u)
919     {
920         return status;
921     }
922 
923     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
924     {
925         status = execute_ss_interrupt_mode(
926                 (uint8_t)MSS_SYS_IAP_BITSTREAM_AUTHENTICATE_CMD,
927                 NULL_BUFFER,
928                 MSS_SYS_WITHOUT_CMD_DATA,
929                 NULL_BUFFER,
930                 MSS_SYS_NO_RESPONSE_LEN,
931                 (uint16_t)spi_idx,
932                 MSS_SYS_COMMON_RET_OFFSET);
933     }
934     else
935     {
936         status = execute_ss_polling_mode(
937                 (uint8_t)MSS_SYS_IAP_BITSTREAM_AUTHENTICATE_CMD,
938                 NULL_BUFFER,
939                 MSS_SYS_WITHOUT_CMD_DATA,
940                 NULL_BUFFER,
941                 MSS_SYS_NO_RESPONSE_LEN,
942                 (uint16_t)spi_idx,
943                 MSS_SYS_COMMON_RET_OFFSET);
944     }
945 
946     return status;
947 }
948 
949 /***************************************************************************//**
950  * MSS_SYS_digest_check()
951  * See "mss_sysservices.h" for details of how to use this function.
952  */
953 uint16_t
MSS_SYS_digest_check(uint32_t options,uint8_t * digesterr,uint16_t mb_offset)954 MSS_SYS_digest_check
955 (
956     uint32_t options,
957     uint8_t* digesterr,
958     uint16_t mb_offset
959 )
960 {
961     uint16_t status = MSS_SYS_PARAM_ERR;
962     uint32_t l_options = options;
963 
964     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
965     {
966         status = execute_ss_interrupt_mode(
967                 (uint8_t)MSS_SYS_DIGEST_CHECK_CMD,
968                 (uint8_t* )&l_options,
969                 (uint16_t)MSS_SYS_DIGEST_CHECK_DATA_LEN,
970                 digesterr,
971                 (uint16_t)MSS_SYS_DIGEST_CHECK_SERVICE_RESP_LEN,
972                 mb_offset,
973                 MSS_SYS_DIGEST_CHECK_RET_OFFSET);
974     }
975     else
976     {
977         status = execute_ss_polling_mode(
978                  (uint8_t)MSS_SYS_DIGEST_CHECK_CMD,
979                  (uint8_t* )&l_options,
980                  (uint16_t)MSS_SYS_DIGEST_CHECK_DATA_LEN,
981                  digesterr,
982                  (uint16_t)MSS_SYS_DIGEST_CHECK_SERVICE_RESP_LEN,
983                  mb_offset,
984                  MSS_SYS_DIGEST_CHECK_RET_OFFSET);
985     }
986 
987     return status;
988 }
989 
990 /***************************************************************************//**
991  * MSS_SYS_execute_iap()
992  * See "mss_sysservices.h" for details of how to use this function.
993  */
994 uint16_t
MSS_SYS_execute_iap(uint8_t iap_cmd,uint32_t spiaddr)995 MSS_SYS_execute_iap
996 (
997     uint8_t iap_cmd,
998     uint32_t spiaddr
999 )
1000 {
1001     uint16_t status = MSS_SYS_PARAM_ERR;
1002     uint32_t l_spiaddr = spiaddr;
1003 
1004     if ((MSS_SYS_IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
1005     || (MSS_SYS_IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
1006     {
1007         return status;
1008     }
1009 
1010     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1011     {
1012         status = execute_ss_interrupt_mode(
1013                  (uint8_t)iap_cmd,
1014                  (uint8_t*)&l_spiaddr,
1015                  MSS_SYS_IAP_SERVICE_DATA_LEN,
1016                  NULL_BUFFER,
1017                  MSS_SYS_NO_RESPONSE_LEN,
1018                  (uint16_t)spiaddr,
1019                  MSS_SYS_COMMON_RET_OFFSET);
1020     }
1021     else
1022     {
1023         status = execute_ss_polling_mode(
1024                  (uint8_t)iap_cmd,
1025                  (uint8_t*)&l_spiaddr,
1026                  MSS_SYS_IAP_SERVICE_DATA_LEN,
1027                  NULL_BUFFER,
1028                  MSS_SYS_NO_RESPONSE_LEN,
1029                  (uint16_t)spiaddr,
1030                  MSS_SYS_COMMON_RET_OFFSET);
1031     }
1032 
1033     return status;
1034 }
1035 
1036 /***************************************************************************//**
1037  * MSS_SYS_spi_copy()
1038  * See "mss_sysservices.h" for details of how to use this function.
1039  */
1040 uint16_t
MSS_SYS_spi_copy(uint64_t mss_dest_addr,uint32_t mss_spi_flash,uint32_t n_bytes,uint8_t options,uint16_t mb_offset)1041 MSS_SYS_spi_copy
1042 (
1043     uint64_t mss_dest_addr,
1044     uint32_t mss_spi_flash,
1045     uint32_t n_bytes,
1046     uint8_t options,
1047     uint16_t mb_offset
1048 )
1049 {
1050      uint16_t status = MSS_SYS_PARAM_ERR;
1051      uint8_t mb_format[17];
1052 
1053      if ((options < 1U) || (options > 3U))
1054      {
1055          return MSS_SYS_PARAM_ERR;
1056      }
1057 
1058      *(uint64_t *)mb_format         = mss_dest_addr;
1059      *(uint32_t *)(mb_format + 8u)  = mss_spi_flash;
1060      *(uint32_t *)(mb_format + 12u) = n_bytes;
1061      mb_format[16] = options;
1062 
1063 
1064      if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1065      {
1066          status = execute_ss_interrupt_mode(
1067                  (uint8_t)MSS_SYS_SPI_COPY_CMD,
1068                  mb_format,
1069                  (uint16_t)MSS_SYS_SPI_COPY_MAILBOX_DATA_LEN,
1070                  NULL_BUFFER,
1071                  MSS_SYS_NO_RESPONSE_LEN,
1072                  mb_offset,
1073                  MSS_SYS_COMMON_RET_OFFSET);
1074      }
1075      else
1076      {
1077          status = execute_ss_polling_mode(
1078                  (uint8_t)MSS_SYS_SPI_COPY_CMD,
1079                  mb_format,
1080                  (uint16_t)MSS_SYS_SPI_COPY_MAILBOX_DATA_LEN,
1081                  NULL_BUFFER,
1082                  MSS_SYS_NO_RESPONSE_LEN,
1083                  mb_offset,
1084                  MSS_SYS_COMMON_RET_OFFSET);
1085      }
1086 
1087      return status;
1088 }
1089 
1090 /***************************************************************************//**
1091  * MSS_SYS_debug_read_probe()
1092  * See "mss_sysservices.h" for details of how to use this function.
1093  */
1094  uint16_t
MSS_SYS_debug_read_probe(uint8_t ipseg_addr,uint8_t iprow_addr,uint8_t * prdata,uint16_t mb_offset,uint8_t resp_offset)1095  MSS_SYS_debug_read_probe
1096 (
1097     uint8_t ipseg_addr,
1098     uint8_t iprow_addr,
1099     uint8_t *prdata,
1100     uint16_t mb_offset,
1101     uint8_t resp_offset
1102 )
1103 {
1104      uint16_t status = MSS_SYS_PARAM_ERR;
1105      uint8_t mb_format[2];
1106      uint16_t service_data = 0u;
1107      uint8_t l_resp_offset = resp_offset;
1108 
1109      if (prdata == NULL_BUFFER)
1110      {
1111          return status;
1112      }
1113 
1114      service_data = iprow_addr;
1115      service_data = service_data << 6u;
1116 
1117      service_data = service_data + ipseg_addr;
1118 
1119      *(uint16_t*)mb_format = service_data;
1120 
1121      l_resp_offset = (4u + (4u * l_resp_offset));
1122 
1123      if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1124      {
1125          status = execute_ss_interrupt_mode(
1126                   (uint8_t)MSS_SYS_PROBE_READ_DEBUG_CMD,
1127                   mb_format,
1128                   (uint16_t)MSS_SYS_PROBE_READ_SERVICE_DATA_LEN,
1129                   prdata,
1130                   (uint16_t)MSS_SYS_PROBE_READ_SERVICE_RESP_LEN,
1131                   mb_offset,
1132                   (uint16_t)l_resp_offset);
1133      }
1134      else
1135      {
1136          status = execute_ss_polling_mode(
1137                   (uint8_t)MSS_SYS_PROBE_READ_DEBUG_CMD,
1138                   mb_format,
1139                   (uint16_t)MSS_SYS_PROBE_READ_SERVICE_DATA_LEN,
1140                   prdata,
1141                   (uint16_t)MSS_SYS_PROBE_READ_SERVICE_RESP_LEN,
1142                   mb_offset,
1143                   (uint16_t)l_resp_offset);
1144      }
1145 
1146      return status;
1147  }
1148 
1149 /***************************************************************************//**
1150  * MSS_SYS_debug_write_probe()
1151  * See "mss_sysservices.h" for details of how to use this function.
1152  */
1153 uint16_t
MSS_SYS_debug_write_probe(uint8_t prb_addr,uint8_t ipseg_addr,uint8_t iprow_addr,uint32_t pwmask,uint32_t pwdata,uint16_t mb_offset)1154 MSS_SYS_debug_write_probe
1155 (
1156     uint8_t prb_addr,
1157     uint8_t ipseg_addr,
1158     uint8_t iprow_addr,
1159     uint32_t pwmask,
1160     uint32_t pwdata,
1161     uint16_t mb_offset
1162 )
1163 {
1164      uint16_t status = MSS_SYS_PARAM_ERR;
1165      uint8_t mb_format[12] = {0};
1166 
1167      /* Local variable to store the combination of iprow_addr, ipseg_addr and
1168       * prb_addr */
1169      uint32_t service_data = 0u;
1170 
1171      uint16_t ip_addr = iprow_addr;
1172      ip_addr = ip_addr << 6u;
1173      ip_addr += ipseg_addr;/* ip_addr is ipseg_addr + iprow_addr */
1174 
1175      service_data = ip_addr;
1176      service_data = service_data << 16; /* 2 bytes space for prb_addr */
1177      service_data += prb_addr;
1178 
1179      *(uint32_t *)mb_format       = service_data;
1180      *(uint32_t *)(mb_format + 4u) = pwmask;
1181      *(uint32_t *)(mb_format + 8u) = pwdata;
1182 
1183      if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1184      {
1185          status = execute_ss_interrupt_mode(
1186                   (uint8_t)MSS_SYS_PROBE_WRITE_DEBUG_CMD,
1187                   mb_format,
1188                   (uint16_t)MSS_SYS_PROBE_WRITE_SERVICE_DATA_LEN,
1189                   NULL_BUFFER,
1190                   MSS_SYS_NO_RESPONSE_LEN,
1191                   mb_offset,
1192                   MSS_SYS_COMMON_RET_OFFSET);
1193      }
1194      else
1195      {
1196          status = execute_ss_polling_mode(
1197                   (uint8_t)MSS_SYS_PROBE_WRITE_DEBUG_CMD,
1198                   mb_format,
1199                   (uint16_t)MSS_SYS_PROBE_WRITE_SERVICE_DATA_LEN,
1200                   NULL_BUFFER,
1201                   MSS_SYS_NO_RESPONSE_LEN,
1202                   mb_offset,
1203                   MSS_SYS_COMMON_RET_OFFSET);
1204      }
1205 
1206     return status;
1207 }
1208 
1209 /***************************************************************************//**
1210  * MSS_SYS_debug_live_probe()
1211  * See "mss_sysservices.h" for details of how to use this function.
1212  */
1213 uint16_t
MSS_SYS_debug_live_probe(uint8_t x_addr,uint8_t y_addr,uint8_t ipseg_addr,uint8_t iprow_addr,uint8_t clear,uint8_t ioen,uint16_t mb_offset,uint8_t service_cmd)1214 MSS_SYS_debug_live_probe
1215 (
1216     uint8_t x_addr,
1217     uint8_t y_addr,
1218     uint8_t ipseg_addr,
1219     uint8_t iprow_addr,
1220     uint8_t clear,
1221     uint8_t ioen,
1222     uint16_t mb_offset,
1223     uint8_t service_cmd
1224 )
1225 {
1226     uint16_t status = MSS_SYS_PARAM_ERR;
1227     uint8_t mb_format[6] = {0};
1228     uint32_t service_data = 0u;
1229 
1230     uint16_t channel_addr = 0u;
1231     uint16_t probe_addr = 0u;
1232 
1233     channel_addr = y_addr;
1234     channel_addr = (channel_addr << 5u) + x_addr;
1235 
1236     probe_addr = iprow_addr;
1237     probe_addr = (probe_addr << 6u) + ipseg_addr;
1238 
1239     service_data = probe_addr;
1240     service_data = (service_data << 16u) + channel_addr;
1241 
1242     *(uint32_t*)mb_format = service_data;
1243     mb_format[4] = clear & 0x01u;
1244     mb_format[5] = ioen & 0x01u;
1245 
1246     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1247     {
1248         status = execute_ss_interrupt_mode(
1249                  service_cmd,
1250                  mb_format,
1251                  (uint16_t)MSS_SYS_LIVE_PROBE_DEBUG_SERVICE_DATA_LEN,
1252                  NULL_BUFFER,
1253                  MSS_SYS_NO_RESPONSE_LEN,
1254                  mb_offset,
1255                  MSS_SYS_COMMON_RET_OFFSET);
1256     }
1257     else
1258     {
1259         status = execute_ss_polling_mode(
1260                  service_cmd,
1261                  mb_format,
1262                  (uint16_t)MSS_SYS_LIVE_PROBE_DEBUG_SERVICE_DATA_LEN,
1263                  NULL_BUFFER,
1264                  MSS_SYS_NO_RESPONSE_LEN,
1265                  mb_offset,
1266                  MSS_SYS_COMMON_RET_OFFSET);
1267     }
1268 
1269     return status;
1270 }
1271 
1272 /***************************************************************************//**
1273  * MSS_SYS_debug_select_mem()
1274  * See "mss_sysservices.h" for details of how to use this function.
1275  */
1276 uint16_t
MSS_SYS_debug_select_mem(uint8_t ipblk_addr,uint8_t ipseg_addr,uint8_t iprow_addr,uint8_t memtype,uint8_t memlock_mode,uint16_t timeout,uint16_t mb_offset)1277 MSS_SYS_debug_select_mem
1278 (
1279     uint8_t ipblk_addr,
1280     uint8_t ipseg_addr,
1281     uint8_t iprow_addr,
1282     uint8_t memtype,
1283     uint8_t memlock_mode,
1284     uint16_t timeout,
1285     uint16_t mb_offset
1286 )
1287 {
1288     uint16_t status = MSS_SYS_PARAM_ERR;
1289     uint8_t mb_format[6] = {0};
1290     uint16_t service_data = 0u;
1291 
1292     if ((memlock_mode >= 4u) || (timeout > 8193u))
1293     {
1294         return status;
1295     }
1296 
1297     service_data = ipblk_addr;
1298 
1299     uint16_t temp = iprow_addr;
1300     temp = ((temp << 6u) + ipseg_addr);
1301     service_data = ((temp << 3u) + service_data);
1302 
1303     *(uint16_t *)mb_format = service_data;
1304     mb_format[2] = memtype;
1305     mb_format[3] = memlock_mode;
1306     *(uint16_t*)(mb_format + 4u) = timeout;
1307 
1308     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1309     {
1310         status = execute_ss_interrupt_mode(
1311                  (uint8_t)MSS_SYS_MEM_SELECT_DEBUG_CMD,
1312                  mb_format,
1313                  (uint16_t)MSS_SYS_MEM_SELECT_DATA_LEN,
1314                  NULL_BUFFER,
1315                  MSS_SYS_NO_RESPONSE_LEN,
1316                  mb_offset,
1317                  MSS_SYS_COMMON_RET_OFFSET);
1318     }
1319     else
1320     {
1321         status = execute_ss_polling_mode(
1322                  (uint8_t)MSS_SYS_MEM_SELECT_DEBUG_CMD,
1323                  mb_format,
1324                  (uint16_t)MSS_SYS_MEM_SELECT_DATA_LEN,
1325                  NULL_BUFFER,
1326                  MSS_SYS_NO_RESPONSE_LEN,
1327                  mb_offset,
1328                  MSS_SYS_COMMON_RET_OFFSET);
1329     }
1330 
1331     return status;
1332 }
1333 
1334 /***************************************************************************//**
1335  * MSS_SYS_debug_read_mem()
1336  * See "mss_sysservices.h" for details of how to use this function.
1337  */
1338 uint16_t
MSS_SYS_debug_read_mem(uint16_t mem_addr,uint16_t n_words,uint64_t mss_addr,uint16_t mb_offset)1339 MSS_SYS_debug_read_mem
1340 (
1341     uint16_t mem_addr,
1342     uint16_t n_words,
1343     uint64_t mss_addr,
1344     uint16_t mb_offset
1345 )
1346 {
1347     uint16_t status = MSS_SYS_PARAM_ERR;
1348     uint8_t mb_format[12] = {0};
1349 
1350     *(uint16_t*)(mb_format)     = mem_addr;
1351     *(uint16_t*)(mb_format + 2u) = n_words;
1352 
1353     for (uint8_t index  = 4u; index < 12u; index++)
1354     {
1355         mb_format[index] = (mss_addr >> (8u * (index - 4u)));
1356     }
1357 
1358     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1359     {
1360         status = execute_ss_interrupt_mode(
1361                  (uint8_t)MSS_SYS_MEM_READ_DEBUG_CMD,
1362                  mb_format,
1363                  (uint16_t)MSS_SYS_MEM_READ_WRITE_DATA_LEN,
1364                  NULL_BUFFER,
1365                  MSS_SYS_NO_RESPONSE_LEN,
1366                  mb_offset,
1367                  MSS_SYS_COMMON_RET_OFFSET);
1368     }
1369     else
1370     {
1371         status = execute_ss_polling_mode(
1372                  (uint8_t)MSS_SYS_MEM_READ_DEBUG_CMD,
1373                  mb_format,
1374                  (uint16_t)MSS_SYS_MEM_READ_WRITE_DATA_LEN,
1375                  NULL_BUFFER,
1376                  MSS_SYS_NO_RESPONSE_LEN,
1377                  mb_offset,
1378                  MSS_SYS_COMMON_RET_OFFSET);
1379     }
1380 
1381     return status;
1382  }
1383 
1384 
1385 /***************************************************************************//**
1386  * MSS_SYS_debug_write_mem()
1387  * See "mss_sysservices.h" for details of how to use this function.
1388  */
1389 uint16_t
MSS_SYS_debug_write_mem(uint16_t mem_addr,uint16_t n_words,uint64_t mss_addr,uint16_t mb_offset)1390 MSS_SYS_debug_write_mem
1391 (
1392     uint16_t mem_addr,
1393     uint16_t n_words,
1394     uint64_t mss_addr,
1395     uint16_t mb_offset
1396 )
1397 {
1398     uint16_t status = MSS_SYS_PARAM_ERR;
1399     uint8_t mb_format[12] = {0};
1400 
1401     *(uint16_t*)(mb_format)     = mem_addr;
1402     *(uint16_t*)(mb_format + 2u) = n_words;
1403 
1404     for (uint8_t index  = 4u; index < 12u; index++)
1405     {
1406         mb_format[index] = (mss_addr >> (8u * (index - 4u)));
1407     }
1408 
1409     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1410     {
1411         status = execute_ss_interrupt_mode(
1412                 (uint8_t)MSS_SYS_MEM_WRITE_DEBUG_CMD,
1413                 mb_format,
1414                 (uint16_t)MSS_SYS_MEM_READ_WRITE_DATA_LEN,
1415                 NULL_BUFFER,
1416                 MSS_SYS_NO_RESPONSE_LEN,
1417                 mb_offset,
1418                 MSS_SYS_COMMON_RET_OFFSET);
1419     }
1420     else
1421     {
1422         status = execute_ss_polling_mode(
1423                  (uint8_t)MSS_SYS_MEM_WRITE_DEBUG_CMD,
1424                  mb_format,
1425                  (uint16_t)MSS_SYS_MEM_READ_WRITE_DATA_LEN,
1426                  NULL_BUFFER,
1427                  MSS_SYS_NO_RESPONSE_LEN,
1428                  mb_offset,
1429                  MSS_SYS_COMMON_RET_OFFSET);
1430     }
1431 
1432     return status;
1433 }
1434 
1435 /***************************************************************************//**
1436  * MSS_SYS_debug_read_apb()
1437  * See "mss_sysservices.h" for details of how to use this function.
1438  */
1439 uint16_t
MSS_SYS_debug_read_apb(uint32_t apb_addr,uint8_t apb_wsize,uint16_t max_bytes,uint64_t mss_addr,uint16_t mb_offset)1440 MSS_SYS_debug_read_apb
1441 (
1442     uint32_t apb_addr,
1443     uint8_t  apb_wsize,
1444     uint16_t max_bytes,
1445     uint64_t mss_addr,
1446     uint16_t mb_offset
1447 )
1448 {
1449     uint16_t status = MSS_SYS_PARAM_ERR;
1450     uint8_t mb_format[24] = {0};
1451     *(uint32_t *)mb_format = apb_addr;
1452 
1453     mb_format[4] = apb_wsize;
1454     *(uint16_t *)(mb_format + 8u)  = max_bytes;
1455 
1456     for (uint8_t index  = 12u; index < 20u; index++)
1457     {
1458         mb_format[index] = (mss_addr >> (8u * (index - 12u)));
1459     }
1460 
1461     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1462     {
1463         status = execute_ss_interrupt_mode(
1464                  (uint8_t)MSS_SYS_APB_READ_DEBUG_CMD,
1465                  mb_format,
1466                  (uint16_t)MSS_SYS_APB_SERVICE_DATA_LEN,
1467                  NULL_BUFFER,
1468                  MSS_SYS_NO_RESPONSE_LEN,
1469                  mb_offset,
1470                  MSS_SYS_COMMON_RET_OFFSET);
1471     }
1472     else
1473     {
1474         status = execute_ss_polling_mode(
1475                  (uint8_t)MSS_SYS_APB_READ_DEBUG_CMD,
1476                  mb_format,
1477                  (uint16_t)MSS_SYS_APB_SERVICE_DATA_LEN,
1478                  NULL_BUFFER,
1479                  MSS_SYS_NO_RESPONSE_LEN,
1480                  mb_offset,
1481                  MSS_SYS_COMMON_RET_OFFSET);
1482     }
1483 
1484     return status;
1485 }
1486 
1487 /***************************************************************************//**
1488  * MSS_SYS_debug_write_apb()
1489  * See "mss_sysservices.h" for details of how to use this function.
1490  */
1491 uint16_t
MSS_SYS_debug_write_apb(uint32_t apb_addr,uint8_t apb_wsize,uint16_t max_bytes,uint64_t mss_addr,uint16_t mb_offset)1492 MSS_SYS_debug_write_apb
1493 (
1494     uint32_t apb_addr,
1495     uint8_t  apb_wsize,
1496     uint16_t max_bytes,
1497     uint64_t mss_addr,
1498     uint16_t mb_offset
1499 )
1500 {
1501     uint16_t status = MSS_SYS_PARAM_ERR;
1502     uint8_t mb_format[20] = {0};
1503 
1504     *(uint32_t *)mb_format = apb_addr;
1505     mb_format[4] = apb_wsize;
1506     *(uint16_t *)(mb_format + 8u)  = max_bytes;
1507 
1508     for (uint8_t index  = 12u; index < 20u; index++)
1509     {
1510         mb_format[index] = (mss_addr >> (8u * (index - 12u)));
1511     }
1512 
1513     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1514     {
1515         status = execute_ss_interrupt_mode(
1516                  (uint8_t)MSS_SYS_APB_WRITE_DEBUG_CMD,
1517                  mb_format,
1518                  (uint16_t)MSS_SYS_APB_SERVICE_DATA_LEN,
1519                  NULL_BUFFER,
1520                  MSS_SYS_NO_RESPONSE_LEN,
1521                  mb_offset,
1522                  MSS_SYS_COMMON_RET_OFFSET);
1523     }
1524     else
1525     {
1526         status = execute_ss_polling_mode(
1527                  (uint8_t)MSS_SYS_APB_WRITE_DEBUG_CMD,
1528                  mb_format,
1529                  (uint16_t)MSS_SYS_APB_SERVICE_DATA_LEN,
1530                  NULL_BUFFER,
1531                  MSS_SYS_NO_RESPONSE_LEN,
1532                  mb_offset,
1533                  MSS_SYS_COMMON_RET_OFFSET);
1534     }
1535 
1536     return status;
1537 }
1538 
1539 /***************************************************************************//**
1540  * MSS_SYS_debug_fabric_snapshot()
1541  * See "mss_sysservices.h" for details of how to use this function.
1542  */
1543 uint16_t
MSS_SYS_debug_fabric_snapshot(uint32_t port_addr,uint8_t apb_fast_write,uint16_t mb_offset)1544 MSS_SYS_debug_fabric_snapshot
1545 (
1546     uint32_t port_addr,
1547     uint8_t apb_fast_write,
1548     uint16_t mb_offset
1549 )
1550 {
1551     uint16_t status = MSS_SYS_PARAM_ERR;
1552     uint8_t mb_format[5]={0};
1553 
1554     *(uint32_t *)mb_format = port_addr;
1555     mb_format[4] = apb_fast_write;
1556 
1557     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1558     {
1559         status = execute_ss_interrupt_mode(
1560                  (uint8_t)MSS_SYS_DEBUG_SNAPSHOT_CMD,
1561                  mb_format,
1562                  (uint16_t)MSS_SYS_DEBUG_SNAPSHOT_DATA_LEN,
1563                  NULL_BUFFER,
1564                  MSS_SYS_NO_RESPONSE_LEN,
1565                  mb_offset,
1566                  MSS_SYS_COMMON_RET_OFFSET);
1567     }
1568     else
1569     {
1570         status = execute_ss_polling_mode(
1571                  (uint8_t)MSS_SYS_DEBUG_SNAPSHOT_CMD,
1572                  mb_format,
1573                  (uint16_t)MSS_SYS_DEBUG_SNAPSHOT_DATA_LEN,
1574                  NULL_BUFFER,
1575                  MSS_SYS_NO_RESPONSE_LEN,
1576                  mb_offset,
1577                  MSS_SYS_COMMON_RET_OFFSET);
1578     }
1579 
1580     return status;
1581 }
1582 
1583 /***************************************************************************//**
1584  * MSS_SYS_otp_generate()
1585  * See "mss_sysservices.h" for details of how to use this function.
1586  */
1587 uint16_t
MSS_SYS_otp_generate(uint8_t keymode,uint8_t * n_user,uint8_t * n_fpga,uint16_t mb_offset,uint16_t resp_offset)1588 MSS_SYS_otp_generate
1589 (
1590     uint8_t keymode,
1591     uint8_t* n_user,
1592     uint8_t* n_fpga,
1593     uint16_t mb_offset,
1594     uint16_t resp_offset
1595 )
1596 {
1597     uint16_t status = MSS_SYS_PARAM_ERR;
1598     uint8_t mb_format[20] = {0};
1599     uint8_t index = 0u;
1600 
1601     if ((n_user = NULL_BUFFER) || (n_fpga == NULL_BUFFER))
1602     {
1603         return status;
1604     }
1605 
1606     mb_format[index] = keymode;
1607 
1608     for (index = 0u; index < 16u; index++ )
1609     {
1610         mb_format[index + 4u] = *(n_user + index);
1611     }
1612 
1613     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1614     {
1615         status = execute_ss_interrupt_mode(
1616                  (uint8_t)MSS_SYS_GENERATE_OTP_CMD,
1617                  mb_format,
1618                  (uint16_t)MSS_SYS_GENERATE_OTP_DATA_LEN,
1619                  n_fpga,
1620                  (uint16_t)MSS_SYS_GENERATE_OTP_RESP_LEN,
1621                  mb_offset,
1622                  resp_offset);
1623     }
1624     else
1625     {
1626         status = execute_ss_polling_mode(
1627                  (uint8_t)MSS_SYS_GENERATE_OTP_CMD,
1628                  mb_format,
1629                  (uint16_t)MSS_SYS_GENERATE_OTP_DATA_LEN,
1630                  n_fpga,
1631                  (uint16_t)MSS_SYS_GENERATE_OTP_RESP_LEN,
1632                  mb_offset,
1633                  resp_offset);
1634     }
1635 
1636     return status;
1637 }
1638 
1639 /***************************************************************************//**
1640  * MSS_SYS_otp_match()
1641  * See "mss_sysservices.h" for details of how to use this function.
1642  */
MSS_SYS_otp_match(uint8_t * user_id,uint8_t * validator,uint8_t * otp,uint16_t mb_offset,uint16_t resp_offset)1643 uint16_t MSS_SYS_otp_match
1644 (
1645     uint8_t * user_id,
1646     uint8_t * validator,
1647     uint8_t * otp,
1648     uint16_t mb_offset,
1649     uint16_t resp_offset
1650 )
1651 {
1652     uint16_t status = MSS_SYS_PARAM_ERR;
1653     uint8_t mb_format[80] = {0};
1654     uint8_t index = 0u;
1655 
1656     if ((user_id == NULL_BUFFER) || (validator == NULL_BUFFER))
1657     {
1658         return status;
1659     }
1660 
1661     for (index = 0u; index < 80u; index++)
1662     {
1663         if (index < 16u)
1664         {
1665             mb_format[index] = user_id[index];
1666         }
1667         if ((index > 15u) && (index < 48u))
1668         {
1669             mb_format[index] = validator[index - 16u];
1670         }
1671         if (index > 47u)
1672         {
1673             mb_format[index] = otp[index - 48u];
1674         }
1675     }
1676 
1677     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1678     {
1679         status = execute_ss_interrupt_mode(
1680                  (uint8_t)MSS_SYS_MATCH_OTP_CMD,
1681                  mb_format,
1682                  (uint16_t)MSS_SYS_MATCH_OTP_DATA_LEN,
1683                  NULL_BUFFER,
1684                  MSS_SYS_NO_RESPONSE_LEN,
1685                  mb_offset,
1686                  resp_offset);
1687     }
1688     else
1689     {
1690         status = execute_ss_polling_mode(
1691                  (uint8_t)MSS_SYS_MATCH_OTP_CMD,
1692                  mb_format,
1693                  (uint16_t)MSS_SYS_MATCH_OTP_DATA_LEN,
1694                  NULL_BUFFER,
1695                  MSS_SYS_NO_RESPONSE_LEN,
1696                  mb_offset,
1697                  resp_offset);
1698     }
1699 
1700     return status;
1701 }
1702 
1703 /***************************************************************************//**
1704  * MSS_SYS_unlock_debug_passcode()
1705  * See "mss_sysservices.h" for details of how to use this function.
1706  */
1707 uint16_t
MSS_SYS_unlock_debug_passcode(uint8_t * cmd_data,uint16_t mb_offset,uint16_t resp_offset)1708 MSS_SYS_unlock_debug_passcode
1709 (
1710     uint8_t* cmd_data,
1711     uint16_t mb_offset,
1712     uint16_t resp_offset
1713 )
1714 {
1715     uint16_t status = MSS_SYS_PARAM_ERR;
1716     uint8_t mb_format[32] = {0};
1717     uint8_t index = 0u;
1718 
1719     if (cmd_data == NULL_BUFFER)
1720     {
1721         return status;
1722     }
1723 
1724     for (index = 0u; index < 32u; index++)
1725     {
1726         mb_format[index] = cmd_data[index];
1727     }
1728 
1729     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1730     {
1731         status = execute_ss_interrupt_mode(
1732                  (uint8_t)MSS_SYS_UNLOCK_DEBUG_PASSCODE,
1733                  cmd_data,
1734                  (uint16_t)MSS_SYS_UNLOCK_DEBUG_PASSCODE_DATA_LEN,
1735                  NULL_BUFFER,
1736                  MSS_SYS_NO_RESPONSE_LEN,
1737                  mb_offset,
1738                  resp_offset);
1739     }
1740     else
1741     {
1742         status = execute_ss_polling_mode(
1743                  (uint8_t)MSS_SYS_UNLOCK_DEBUG_PASSCODE,
1744                  cmd_data,
1745                  (uint16_t)MSS_SYS_UNLOCK_DEBUG_PASSCODE_DATA_LEN,
1746                  NULL_BUFFER,
1747                  MSS_SYS_NO_RESPONSE_LEN,
1748                  mb_offset,
1749                  resp_offset);
1750     }
1751 
1752     return status;
1753 }
1754 
1755 /***************************************************************************//**
1756  * MSS_SYS_one_way_passcode()
1757  * See "mss_sysservices.h" for details of how to use this function.
1758  */
1759 uint16_t
MSS_SYS_one_way_passcode(uint8_t * msg_id,uint8_t * validator,uint8_t keymode,uint8_t * dsn,uint8_t * hash,uint8_t * plaintext_passcode,uint8_t * hwm,uint16_t mb_offset,uint16_t resp_offset)1760 MSS_SYS_one_way_passcode
1761 (
1762     uint8_t* msg_id,
1763     uint8_t* validator,
1764     uint8_t keymode,
1765     uint8_t* dsn,
1766     uint8_t* hash,
1767     uint8_t* plaintext_passcode,
1768     uint8_t* hwm,
1769     uint16_t mb_offset,
1770     uint16_t resp_offset
1771 )
1772 {
1773     uint16_t status = MSS_SYS_PARAM_ERR;
1774     uint8_t mb_format[480] = {0};
1775     uint16_t index = 0;
1776     for (index = 0u; index < 480u; index++)
1777     {
1778         if ( index < 16u)
1779         {
1780             mb_format[index] = msg_id[index];
1781         }
1782         if ((index > 15u) && (index < 48u))
1783         {
1784             mb_format[index] = validator[index - 16];
1785         }
1786         if ( index == 51u)
1787         {
1788             mb_format[index] = keymode;
1789         }
1790         if ((index > 67u) && (index < 84u))
1791         {
1792             mb_format[index] = dsn[index - 68];
1793         }
1794         if ((index > 351u) && (index < 384u))
1795         {
1796             mb_format[index] = hash[index - 352];
1797         }
1798         if ((index > 383u) && (index < 416u))
1799         {
1800             mb_format[index] = plaintext_passcode[index - 384];
1801         }
1802         if ((index > 415u) && (index < 432u))
1803         {
1804             mb_format[index] = hwm[index];
1805         }
1806     }
1807 
1808     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1809     {
1810         status = execute_ss_interrupt_mode(
1811                  (uint8_t)MSS_SYS_ONE_WAY_PASSCODE_CMD,
1812                  mb_format,
1813                  (uint16_t)MSS_SYS_ONE_WAY_PASSCODE_DATA_LEN,
1814                  NULL_BUFFER,
1815                  MSS_SYS_NO_RESPONSE_LEN,
1816                  mb_offset,
1817                  resp_offset);
1818     }
1819     else
1820     {
1821         status = execute_ss_polling_mode(
1822                  (uint8_t)MSS_SYS_ONE_WAY_PASSCODE_CMD,
1823                  mb_format,
1824                  (uint16_t)MSS_SYS_ONE_WAY_PASSCODE_DATA_LEN,
1825                  NULL_BUFFER,
1826                  MSS_SYS_NO_RESPONSE_LEN,
1827                  mb_offset,
1828                  resp_offset);
1829     }
1830 
1831     return status;
1832 }
1833 
1834 /***************************************************************************//**
1835  * MSS_SYS_debug_terminate()
1836  * See "mss_sysservices.h" for details of how to use this function.
1837  */
1838 uint16_t
MSS_SYS_debug_terminate(uint16_t mb_offset,uint16_t resp_offset)1839 MSS_SYS_debug_terminate
1840 (
1841     uint16_t mb_offset,
1842     uint16_t resp_offset
1843 )
1844 {
1845     uint16_t status = MSS_SYS_PARAM_ERR;
1846 
1847     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1848     {
1849         status = execute_ss_interrupt_mode(
1850                  (uint8_t)MSS_SYS_TERMINATE_DEBUG_CMD,
1851                  NULL_BUFFER,
1852                  MSS_SYS_WITHOUT_CMD_DATA,
1853                  NULL_BUFFER,
1854                  MSS_SYS_NO_RESPONSE_LEN,
1855                  mb_offset,
1856                  resp_offset);
1857     }
1858     else
1859     {
1860         status = execute_ss_polling_mode(
1861                  (uint8_t)MSS_SYS_TERMINATE_DEBUG_CMD,
1862                  NULL_BUFFER,
1863                  MSS_SYS_WITHOUT_CMD_DATA,
1864                  NULL_BUFFER,
1865                  MSS_SYS_NO_RESPONSE_LEN,
1866                  mb_offset,
1867                  resp_offset);
1868     }
1869 
1870     return status;
1871 }
1872 
1873 /***************************************************************************//**
1874  * MSS_SYS_read_response()
1875  * See "mss_sysservices.h" for details of how to use this function.
1876  */
MSS_SYS_read_response(void)1877 uint16_t MSS_SYS_read_response
1878 (
1879     void
1880 )
1881 {
1882     uint16_t response_limit = 0u;
1883     uint32_t idx;
1884     uint16_t status = MSS_SYS_PARAM_ERR;
1885 
1886     if (g_message_interrupt_counter > 0u)
1887     {
1888         g_message_interrupt_counter = 0u;
1889 
1890         if (g_int_service_response_size > 0u)
1891         {
1892             response_limit = g_int_service_response_size +
1893                              g_int_service_response_offset;
1894 
1895             for (idx = g_int_service_response_offset; idx < response_limit; idx++)
1896             {
1897                 gp_int_service_response[idx - g_int_service_response_offset] =
1898                         *((uint8_t *)MSS_SCBMAILBOX + idx);
1899             }
1900         }
1901 
1902         /* Read the status returned by System Controller*/
1903         status = ((MSS_SCBCTRL->SERVICES_SR & SCBCTRL_SERVICESSR_STATUS_MASK) >>
1904                 SCBCTRL_SERVICESSR_STATUS);
1905     }
1906 
1907     return status;
1908 }
1909 
1910 /***************************************************************************//**
1911  Internal functions.
1912 */
1913 
1914 /*
1915  * This function requests the system service to the system controller. It will
1916  * first write the Mailbox input data to the mailbox from the cmd_data if
1917  * required for that service.
1918  *
1919  */
request_system_service(uint8_t cmd_opcode,uint8_t * cmd_data,uint16_t cmd_data_size,uint8_t * p_response,uint16_t response_size,uint16_t mb_offset,uint16_t response_offset)1920 static uint16_t request_system_service
1921 (
1922     uint8_t cmd_opcode,
1923     uint8_t* cmd_data,
1924     uint16_t cmd_data_size,
1925     uint8_t* p_response,
1926     uint16_t response_size,
1927     uint16_t mb_offset,
1928     uint16_t response_offset
1929 
1930 )
1931 {
1932     uint32_t idx;
1933     uint16_t ss_command = 0u;
1934     uint32_t* word_buf ;
1935     uint8_t* byte_buf ;
1936     uint8_t byte_off;
1937     uint8_t byte_index;
1938     uint32_t * mailbox_reg;
1939     uint32_t mailbox_val = 0u;
1940 
1941     if (MSS_SCBCTRL->SERVICES_SR & SCBCTRL_SERVICESSR_BUSY_MASK)
1942     {
1943         /* System controller is busy with executing service */
1944         return MSS_SYS_BUSY;
1945     }
1946 
1947     /* Code for MSS_SYS_PARAM_ERR is not implemented with this version of
1948        driver. */
1949 
1950     *MSS_SCBMESSAGE_INT = 0x0u; /* clear message_int reg */
1951 
1952     if (g_service_mode == MSS_SYS_SERVICE_INTERRUPT_MODE)
1953     {
1954         gp_int_service_response = (uint8_t*)p_response;
1955         g_int_service_response_offset = response_offset;
1956         g_int_service_response_size = response_size;
1957     }
1958 
1959     if (cmd_data_size > 0u)
1960     {
1961         word_buf = (uint32_t*)cmd_data;
1962 
1963         /* Write the user data into mail box. */
1964         for (idx = 0u; idx < (cmd_data_size / 4u); idx++)
1965         {
1966             *(MSS_SCBMAILBOX + idx) = word_buf[idx];
1967         }
1968 
1969         if ((cmd_data_size % 4u) > 0u)
1970         {
1971              byte_off = (((cmd_data_size / 4u) * 4u));
1972              byte_buf = (uint8_t*)(cmd_data + byte_off);
1973 
1974              mailbox_reg = (MSS_SCBMAILBOX + idx);
1975              mailbox_val = *mailbox_reg;
1976 
1977              for (byte_index = 0u; byte_index < (cmd_data_size % 4u);
1978                   byte_index++)
1979              {
1980                  mailbox_val &= ~(0xffu << (byte_index * 8u));
1981                  mailbox_val |= (byte_buf[byte_index] << (byte_index * 8u));
1982              }
1983              *mailbox_reg = mailbox_val;
1984         }
1985     }
1986 
1987     /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox
1988      * offset For some services this field has another meaning.
1989      * (e.g. for IAP bit-stream auth. it means spi_idx) */
1990     ss_command = ((mb_offset << 7u) |  (cmd_opcode & 0x7Fu));
1991 
1992     /* Interrupt based implementation of services */
1993     if (MSS_SYS_SERVICE_INTERRUPT_MODE == g_service_mode)
1994     {
1995         MSS_SCBCTRL->SERVICES_CR = (((ss_command << SCBCTRL_SERVICESCR_COMMAND)
1996                 & SCBCTRL_SERVICESCR_COMMAND_MASK) |
1997                 SCBCTRL_SERVICESCR_REQ_MASK |
1998                 SCBCTRL_SERVICESSR_NOTIFY_MASK);
1999     }
2000     else
2001     {
2002         MSS_SCBCTRL->SERVICES_CR = (((ss_command << SCBCTRL_SERVICESCR_COMMAND)
2003                 & SCBCTRL_SERVICESCR_COMMAND_MASK) |
2004                 SCBCTRL_SERVICESCR_REQ_MASK);
2005 
2006     }
2007 
2008     /* Service requested successfully */
2009     return MSS_SYS_SUCCESS;
2010 }
2011 
2012 /* This function executes the SS command in interrupt mode. If Mailbox input data
2013  * is required by the service, the call to request_system_service() function will
2014  * first load it from cmd_data into the Mailbox. The response of the service is
2015  * not read by this function as it depends on message interrupt. Application
2016  * will have to read the response of service by calling MSS_SYS_read_response(),
2017  * only after interrupt occurs. */
execute_ss_interrupt_mode(uint8_t cmd_opcode,uint8_t * cmd_data,uint16_t cmd_data_size,uint8_t * p_response,uint16_t response_size,uint16_t mb_offset,uint16_t response_offset)2018 static uint16_t execute_ss_interrupt_mode
2019 (
2020     uint8_t cmd_opcode,
2021     uint8_t* cmd_data,
2022     uint16_t cmd_data_size,
2023     uint8_t* p_response,
2024     uint16_t response_size,
2025     uint16_t mb_offset,
2026     uint16_t response_offset
2027 )
2028 {
2029 
2030     uint16_t status;
2031     status = request_system_service(cmd_opcode, cmd_data, cmd_data_size,
2032                                     p_response, response_size, mb_offset,
2033                                     response_offset);
2034 
2035     return status;
2036  }
2037 
2038 /* This function executes the SS command in polling mode. If Mailbox input data
2039  * is required by the it will first load it from cmd_data into the Mailbox.
2040  * After requesting the service it will poll the request and busy bit. If the
2041  * service requires the response data to be read from mailbox, it will read the
2042  * mailbox contents and store it in p_response buffer.
2043  */
execute_ss_polling_mode(uint8_t cmd_opcode,uint8_t * cmd_data,uint16_t cmd_data_size,uint8_t * p_response,uint16_t response_size,uint16_t mb_offset,uint16_t response_offset)2044 static uint16_t execute_ss_polling_mode
2045 (
2046     uint8_t cmd_opcode,
2047     uint8_t* cmd_data,
2048     uint16_t cmd_data_size,
2049     uint8_t* p_response,
2050     uint16_t response_size,
2051     uint16_t mb_offset,
2052     uint16_t response_offset
2053 )
2054 {
2055     uint32_t idx;
2056     uint16_t status = 0u;
2057     uint16_t response_limit = 0u;
2058     uint8_t* response_buf;
2059 
2060     status = request_system_service(cmd_opcode, cmd_data, cmd_data_size,
2061                                    p_response,response_size, mb_offset,
2062                                    response_offset);
2063 
2064     if (status == MSS_SYS_SUCCESS)
2065     {
2066         /* REQ bit will remain set till the system controller starts
2067          * processing command. Since DRI is slow interface, we are waiting
2068          * here to make sure System controller has started processing
2069          * command*/
2070         while (SCBCTRL_SERVICESCR_REQ_MASK == (MSS_SCBCTRL->SERVICES_CR &
2071                 SCBCTRL_SERVICESCR_REQ_MASK))
2072         {
2073             ;
2074         }
2075 
2076         /* Once system controller starts processing command The busy bit will
2077          * go 1. Make sure that service is complete i.e. BUSY bit is gone 0 */
2078         while (SCBCTRL_SERVICESSR_BUSY_MASK == (MSS_SCBCTRL->SERVICES_SR &
2079                 SCBCTRL_SERVICESSR_BUSY_MASK))
2080         {
2081             ;
2082         }
2083 
2084         if (response_size > 0u)
2085         {
2086             response_limit = response_size + response_offset;
2087             response_buf = (uint8_t*)p_response;
2088 
2089             for (idx = response_offset; idx < response_limit; idx++)
2090             {
2091                 response_buf[idx - response_offset] =
2092                         *((uint8_t *)MSS_SCBMAILBOX + idx);
2093             }
2094         }
2095 
2096         /* Read the status returned by System Controller */
2097         status = ((MSS_SCBCTRL->SERVICES_SR & SCBCTRL_SERVICESSR_STATUS_MASK) >>
2098                 SCBCTRL_SERVICESSR_STATUS);
2099     }
2100     else
2101     {
2102         status = MSS_SYS_BUSY;
2103     }
2104 
2105     return status;
2106 }
2107 
2108 /***************************************************************************//**
2109  * Interrupt service routine triggered by message interrupt.
2110  * This routine will call handler function which will read the service response
2111  * in interrupt mode of operation.
2112  */
2113 uint8_t
g5c_message_plic_IRQHandler(void)2114 g5c_message_plic_IRQHandler
2115 (
2116     void
2117 )
2118 {
2119     g_message_interrupt_counter++;
2120 
2121     volatile uint32_t reg = *MSS_SCBMESSAGE; /* read message reg. */
2122     reg = *MSS_SCBMESSAGE_INT;
2123     *MSS_SCBMESSAGE_INT = 0x0u; /* clear message_int reg */
2124     reg = *MSS_SCBMESSAGE_INT;
2125 
2126     mss_sys_interrupt_handler();
2127 
2128     return 0;
2129 }
2130 
2131 #ifdef __cplusplus
2132 }
2133 #endif
2134