/******************************************************************************* | |
* (c) Copyright 2012 Microsemi SoC Products Group. All rights reserved. | |
* | |
* SmartFusion2 system services. | |
* | |
* SVN $Revision: 5615 $ | |
* SVN $Date: 2013-04-05 14:48:10 +0100 (Fri, 05 Apr 2013) $ | |
*/ | |
#include "mss_sys_services.h" | |
#include "mss_comblk.h" | |
#include "../../CMSIS/mss_assert.h" | |
#include <string.h> | |
/*============================================================================== | |
* | |
*/ | |
/* | |
* Service request command opcodes: | |
*/ | |
#define DEVICE_CERTIFICATE_REQUEST_CMD 0u | |
#define SERIAL_NUMBER_REQUEST_CMD 1u | |
#define FLASH_FREEZE_REQUEST_CMD 2u | |
#define AES128_REQUEST_CMD 3u | |
#define USERCODE_REQUEST_CMD 4u | |
#define DESIGNVER_REQUEST_CMD 5u | |
#define AES256_REQUEST_CMD 6u | |
#define KEYTREE_REQUEST_CMD 9u | |
#define SHA256_REQUEST_CMD 10u | |
#define HMAC_REQUEST_CMD 12u | |
#define PPUF_CHALLENGE_RESP_REQUEST_CMD 14u | |
#define ISP_PROGRAMMING_REQUEST_CMD 21u | |
#define DIGEST_CHECK_REQUEST_CMD 23u | |
#define NRBG_SELF_TEST_REQUEST_CMD 40u | |
#define NRBG_INSTANTIATE_REQUEST_CMD 41u | |
#define NRBG_GENERATE_REQUEST_CMD 42u | |
#define NRBG_RESEED_REQUEST_CMD 43u | |
#define NRBG_UNINSTANTIATE_REQUEST_CMD 44u | |
#define NRBG_RESET_REQUEST_CMD 45u | |
#define FLASHFREEZE_SHUTDOWN_CMD 224u | |
#define ZEROIZATION_REQUEST_CMD 240u | |
#define POWER_ON_RESET_DIGEST_ERROR_CMD 241u | |
/* | |
* System Services requests length: | |
*/ | |
#define FLASH_FREEZE_REQUEST_LENGTH 2u | |
/* | |
* Service response lengths: | |
*/ | |
#define STANDARD_SERV_RESP_LENGTH 6u | |
#define SERIAL_NUMBER_SERV_RESP_LENGTH 6u | |
#define USERCODE_SERV_RESP_LENGTH 6u | |
#define DESIGNVER_SERV_RESP_LENGTH 6u | |
#define DEVICE_CERT_SERV_RESP_LENGTH 6u | |
#define ISP_PROG_SERV_RESP_LENGTH 2u | |
#define NRBG_RESET_SERV_RESP_LENGTH 2u | |
#define NRBG_SELF_TEST_SERV_RESP_LENGTH 2u | |
#define NRBG_UNINST_SERV_RESP_LENGTH 3u | |
#define DIGEST_CHECK_SERV_RESP_LENGTH 2u | |
#define FLASH_FREEZE_SERV_RESP_LENGTH 2u | |
/* | |
* Non Deterministic Random Bit Generator defines: | |
*/ | |
#define INVALID_NRBG_HANDLE 0xFFu | |
/* | |
* RTC_WAKEUP_CR system register bit masks: | |
*/ | |
#define RTC_WAKEUP_G4C_EN_MASK 0x00000004u | |
#define RTC_WAKEUP_FAB_EN_MASK 0x00000002u | |
/*============================================================================== | |
* Local functions. | |
*/ | |
static void request_completion_handler(uint8_t * p_response, uint16_t response_size); | |
static void signal_request_start(void); | |
static uint16_t wait_for_request_completion(void); | |
static uint8_t execute_service | |
( | |
uint8_t cmd_opcode, | |
uint8_t * cmd_params_ptr, | |
uint8_t * response, | |
uint16_t response_length | |
); | |
static void asynchronous_event_handler(uint8_t event_opcode); | |
static void write_ptr_value_into_array | |
( | |
const uint8_t * pointer, | |
uint8_t target_array[], | |
uint32_t array_index | |
); | |
/*============================================================================== | |
* Global variables | |
*/ | |
static volatile uint8_t g_request_in_progress = 0u; | |
static volatile uint16_t g_last_response_length = 0u; | |
static sys_serv_async_event_handler_t g_event_handler = 0; | |
/*============================================================================== | |
* | |
*/ | |
void MSS_SYS_init(sys_serv_async_event_handler_t event_handler) | |
{ | |
MSS_COMBLK_init(asynchronous_event_handler); | |
g_event_handler = event_handler; | |
g_request_in_progress = 0u; | |
g_last_response_length = 0u; | |
} | |
/*============================================================================== | |
* | |
*/ | |
static void asynchronous_event_handler(uint8_t event_opcode) | |
{ | |
if(g_event_handler != 0) | |
{ | |
switch(event_opcode) | |
{ | |
case FLASH_FREEZE_SHUTDOWN_OPCODE: | |
case FLASH_FREEZE_EXIT_OPCODE: | |
g_event_handler(event_opcode); | |
break; | |
default: | |
/* Ignore all other events. */ | |
break; | |
} | |
} | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_get_serial_number | |
( | |
uint8_t * p_serial_number | |
) | |
{ | |
uint8_t response[SERIAL_NUMBER_SERV_RESP_LENGTH]; | |
uint8_t status; | |
status = execute_service(SERIAL_NUMBER_REQUEST_CMD, | |
p_serial_number, | |
response, | |
SERIAL_NUMBER_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_get_user_code | |
( | |
uint8_t * p_user_code | |
) | |
{ | |
uint8_t response[USERCODE_SERV_RESP_LENGTH]; | |
uint8_t status; | |
status = execute_service(USERCODE_REQUEST_CMD, | |
p_user_code, | |
response, | |
USERCODE_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_get_design_version | |
( | |
uint8_t * p_design_version | |
) | |
{ | |
uint8_t response[DESIGNVER_SERV_RESP_LENGTH]; | |
uint8_t status; | |
status = execute_service(DESIGNVER_REQUEST_CMD, | |
p_design_version, | |
response, | |
DESIGNVER_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_get_device_certificate | |
( | |
uint8_t * p_device_certificate | |
) | |
{ | |
uint8_t response[DEVICE_CERT_SERV_RESP_LENGTH]; | |
uint8_t status; | |
status = execute_service(DEVICE_CERTIFICATE_REQUEST_CMD, | |
p_device_certificate, | |
response, | |
DEVICE_CERT_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_flash_freeze(uint8_t options) | |
{ | |
uint8_t status; | |
uint16_t actual_response_length; | |
uint8_t flash_freeze_req[FLASH_FREEZE_REQUEST_LENGTH]; | |
uint8_t response[FLASH_FREEZE_SERV_RESP_LENGTH]; | |
/* | |
* The Flash Freeze system service is not available on M2S050 rev A and rev B. | |
*/ | |
ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION); | |
ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION); | |
/* | |
* Enable RTC wake-up interrupt to System Controller and FPGA fabric. | |
*/ | |
SYSREG->RTC_WAKEUP_CR |= (RTC_WAKEUP_G4C_EN_MASK | RTC_WAKEUP_FAB_EN_MASK); | |
signal_request_start(); | |
flash_freeze_req[0] = FLASH_FREEZE_REQUEST_CMD; | |
flash_freeze_req[1] = options; | |
MSS_COMBLK_send_cmd(flash_freeze_req, /* p_cmd */ | |
FLASH_FREEZE_REQUEST_LENGTH, /* cmd_size */ | |
0, /* p_data */ | |
0u, /* data_size */ | |
response, /* p_response */ | |
FLASH_FREEZE_SERV_RESP_LENGTH, /* response_size */ | |
request_completion_handler); /* completion_handler */ | |
actual_response_length = wait_for_request_completion(); | |
if((FLASH_FREEZE_SERV_RESP_LENGTH == actual_response_length) && | |
(FLASH_FREEZE_REQUEST_CMD == response[0])) | |
{ | |
status = response[1]; | |
} | |
else | |
{ | |
status = MSS_SYS_UNEXPECTED_ERROR; | |
} | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
#define AES128_KEY_LENGTH 16u | |
#define IV_LENGTH 16u | |
#define AES256_KEY_LENGTH 32u | |
#define HMAC_KEY_LENGTH 32u | |
uint8_t MSS_SYS_128bit_aes | |
( | |
const uint8_t * key, | |
const uint8_t * iv, | |
uint16_t nb_blocks, | |
uint8_t mode, | |
uint8_t * dest_addr, | |
const uint8_t * src_addr) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t params[44]; | |
uint8_t status; | |
memcpy(¶ms[0], key, AES128_KEY_LENGTH); | |
memcpy(¶ms[16], iv, IV_LENGTH); | |
params[32] = (uint8_t)nb_blocks; | |
params[33] = (uint8_t)(nb_blocks >> 8u); | |
params[34] = mode; | |
params[35] = 0u; | |
#if 1 | |
write_ptr_value_into_array(dest_addr, params, 36u); | |
write_ptr_value_into_array(src_addr, params, 40u); | |
#else | |
params[36] = (uint8_t)((uint32_t)dest_addr); | |
params[37] = (uint8_t)((uint32_t)dest_addr >> 8u); | |
params[38] = (uint8_t)((uint32_t)dest_addr >> 16u); | |
params[39] = (uint8_t)((uint32_t)dest_addr >> 24u); | |
params[40] = (uint8_t)((uint32_t)src_addr); | |
params[41] = (uint8_t)((uint32_t)src_addr >> 8u); | |
params[42] = (uint8_t)((uint32_t)src_addr >> 16u); | |
params[43] = (uint8_t)((uint32_t)src_addr >> 24u); | |
#endif | |
status = execute_service(AES128_REQUEST_CMD, | |
params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_256bit_aes | |
( | |
const uint8_t * key, | |
const uint8_t * iv, | |
uint16_t nb_blocks, | |
uint8_t mode, | |
uint8_t * dest_addr, | |
const uint8_t * src_addr | |
) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t params[60]; | |
uint8_t status; | |
memcpy(¶ms[0], key, AES256_KEY_LENGTH); | |
memcpy(¶ms[32], iv, IV_LENGTH); | |
params[48] = (uint8_t)nb_blocks; | |
params[49] = (uint8_t)(nb_blocks >> 8u); | |
params[50] = mode; | |
params[51] = 0u; | |
#if 1 | |
write_ptr_value_into_array(dest_addr, params, 52u); | |
write_ptr_value_into_array(src_addr, params, 56u); | |
#else | |
params[52] = (uint8_t)((uint32_t)dest_addr); | |
params[53] = (uint8_t)((uint32_t)dest_addr >> 8u); | |
params[54] = (uint8_t)((uint32_t)dest_addr >> 16u); | |
params[55] = (uint8_t)((uint32_t)dest_addr >> 24u); | |
params[56] = (uint8_t)((uint32_t)src_addr); | |
params[57] = (uint8_t)((uint32_t)src_addr >> 8u); | |
params[58] = (uint8_t)((uint32_t)src_addr >> 16u); | |
params[59] = (uint8_t)((uint32_t)src_addr >> 24u); | |
#endif | |
status = execute_service(AES256_REQUEST_CMD, | |
params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_sha256 | |
( | |
const uint8_t * p_data_in, | |
uint32_t length, | |
uint8_t * result | |
) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t params[12]; | |
uint8_t status; | |
params[0] = (uint8_t)((uint32_t)length); | |
params[1] = (uint8_t)((uint32_t)length >> 8u); | |
params[2] = (uint8_t)((uint32_t)length >> 16u); | |
params[3] = (uint8_t)((uint32_t)length >> 24u); | |
#if 1 | |
write_ptr_value_into_array(result, params, 4u); | |
write_ptr_value_into_array(p_data_in, params, 8u); | |
#else | |
params[4] = (uint8_t)((uint32_t)result); | |
params[5] = (uint8_t)((uint32_t)result >> 8u); | |
params[6] = (uint8_t)((uint32_t)result >> 16u); | |
params[7] = (uint8_t)((uint32_t)result >> 24u); | |
params[8] = (uint8_t)((uint32_t)p_data_in); | |
params[9] = (uint8_t)((uint32_t)p_data_in >> 8u); | |
params[10] = (uint8_t)((uint32_t)p_data_in >> 16u); | |
params[11] = (uint8_t)((uint32_t)p_data_in >> 24u); | |
#endif | |
status = execute_service(SHA256_REQUEST_CMD, | |
params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_hmac | |
( | |
const uint8_t * key, | |
const uint8_t * p_data_in, | |
uint32_t length, | |
uint8_t * p_result | |
) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t params[58]; | |
uint8_t status; | |
memcpy(¶ms[0], key, HMAC_KEY_LENGTH); | |
params[32] = (uint8_t)((uint32_t)length); | |
params[33] = (uint8_t)((uint32_t)length >> 8u); | |
params[34] = (uint8_t)((uint32_t)length >> 16u); | |
params[35] = (uint8_t)((uint32_t)length >> 24u); | |
#if 1 | |
write_ptr_value_into_array(p_data_in, params, 36u); | |
write_ptr_value_into_array(p_result, params, 40u); | |
#else | |
params[36] = (uint8_t)((uint32_t)p_data_in); | |
params[37] = (uint8_t)((uint32_t)p_data_in >> 8u); | |
params[38] = (uint8_t)((uint32_t)p_data_in >> 16u); | |
params[39] = (uint8_t)((uint32_t)p_data_in >> 24u); | |
params[40] = (uint8_t)((uint32_t)p_result); | |
params[41] = (uint8_t)((uint32_t)p_result >> 8u); | |
params[42] = (uint8_t)((uint32_t)p_result >> 16u); | |
params[43] = (uint8_t)((uint32_t)p_result >> 24u); | |
#endif | |
status = execute_service(HMAC_REQUEST_CMD, | |
params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_nrbg_self_test(void) | |
{ | |
uint8_t status; | |
uint16_t actual_response_length; | |
uint8_t self_test; | |
uint8_t response[NRBG_SELF_TEST_SERV_RESP_LENGTH]; | |
signal_request_start(); | |
self_test = NRBG_SELF_TEST_REQUEST_CMD; | |
MSS_COMBLK_send_cmd(&self_test, /* p_cmd */ | |
sizeof(self_test), /* cmd_size */ | |
0, /* p_data */ | |
0, /* data_size */ | |
response, /* p_response */ | |
NRBG_SELF_TEST_SERV_RESP_LENGTH, /* response_size */ | |
request_completion_handler); /* completion_handler */ | |
actual_response_length = wait_for_request_completion(); | |
if((NRBG_SELF_TEST_SERV_RESP_LENGTH == actual_response_length) && | |
(NRBG_SELF_TEST_REQUEST_CMD == response[0])) | |
{ | |
status = response[1]; | |
} | |
else | |
{ | |
status = MSS_SYS_UNEXPECTED_ERROR; | |
} | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_nrbg_instantiate | |
( | |
const uint8_t * personalization_str, | |
uint16_t personalization_str_length, | |
uint8_t * p_nrbg_handle | |
) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t intantiate_params[7]; | |
uint8_t status; | |
#if 1 | |
write_ptr_value_into_array(personalization_str, intantiate_params, 0u); | |
#else | |
intantiate_params[0] = (uint8_t)((uint32_t)personalization_str); | |
intantiate_params[1] = (uint8_t)((uint32_t)personalization_str >> 8u); | |
intantiate_params[2] = (uint8_t)((uint32_t)personalization_str >> 16u); | |
intantiate_params[3] = (uint8_t)((uint32_t)personalization_str >> 24u); | |
#endif | |
intantiate_params[4] = (uint8_t)personalization_str_length; | |
intantiate_params[5] = (uint8_t)(personalization_str_length >> 8u); | |
intantiate_params[6] = INVALID_NRBG_HANDLE; | |
status = execute_service(NRBG_INSTANTIATE_REQUEST_CMD, | |
intantiate_params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
if(MSS_SYS_SUCCESS == status) | |
{ | |
*p_nrbg_handle = intantiate_params[6]; | |
} | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_nrbg_generate | |
( | |
const uint8_t * p_requested_data, | |
const uint8_t * p_additional_input, | |
uint8_t requested_length, | |
uint8_t additional_input_length, | |
uint8_t pr_req, | |
uint8_t nrbg_handle | |
) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t generate_params[12]; | |
uint8_t status; | |
#if 1 | |
write_ptr_value_into_array(p_requested_data, generate_params, 0u); | |
write_ptr_value_into_array(p_additional_input, generate_params, 4u); | |
#else | |
generate_params[0] = (uint8_t)((uint32_t)p_requested_data); | |
generate_params[1] = (uint8_t)((uint32_t)p_requested_data >> 8u); | |
generate_params[2] = (uint8_t)((uint32_t)p_requested_data >> 16u); | |
generate_params[3] = (uint8_t)((uint32_t)p_requested_data >> 24u); | |
generate_params[4] = (uint8_t)((uint32_t)p_additional_input); | |
generate_params[5] = (uint8_t)((uint32_t)p_additional_input >> 8u); | |
generate_params[6] = (uint8_t)((uint32_t)p_additional_input >> 16u); | |
generate_params[7] = (uint8_t)((uint32_t)p_additional_input >> 24u); | |
#endif | |
generate_params[8] = requested_length; | |
generate_params[9] = additional_input_length; | |
generate_params[10] = pr_req; | |
generate_params[11] = nrbg_handle; | |
status = execute_service(NRBG_GENERATE_REQUEST_CMD, | |
generate_params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_nrbg_reseed | |
( | |
const uint8_t * p_additional_input, | |
uint8_t additional_input_length, | |
uint8_t nrbg_handle | |
) | |
{ | |
uint8_t response[STANDARD_SERV_RESP_LENGTH]; | |
uint8_t params[6]; | |
uint8_t status; | |
#if 1 | |
write_ptr_value_into_array(p_additional_input, params, 0u); | |
#else | |
params[0] = (uint8_t)((uint32_t)p_additional_input); | |
params[1] = (uint8_t)((uint32_t)p_additional_input >> 8u); | |
params[2] = (uint8_t)((uint32_t)p_additional_input >> 16u); | |
params[3] = (uint8_t)((uint32_t)p_additional_input >> 24u); | |
#endif | |
params[4] = (uint8_t)additional_input_length; | |
params[5] = nrbg_handle; | |
status = execute_service(NRBG_RESEED_REQUEST_CMD, | |
params, | |
response, | |
STANDARD_SERV_RESP_LENGTH); | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_nrbg_uninstantiate | |
( | |
uint8_t nrbg_handle | |
) | |
{ | |
uint8_t status; | |
uint16_t actual_response_length; | |
uint8_t uninstantiate_req[2]; | |
uint8_t response[NRBG_UNINST_SERV_RESP_LENGTH]; | |
signal_request_start(); | |
uninstantiate_req[0] = NRBG_UNINSTANTIATE_REQUEST_CMD; | |
uninstantiate_req[1] = nrbg_handle; | |
MSS_COMBLK_send_cmd(uninstantiate_req, /* p_cmd */ | |
sizeof(uninstantiate_req), /* cmd_size */ | |
0, /* p_data */ | |
0, /* data_size */ | |
response, /* p_response */ | |
NRBG_UNINST_SERV_RESP_LENGTH, /* response_size */ | |
request_completion_handler); /* completion_handler */ | |
actual_response_length = wait_for_request_completion(); | |
if((NRBG_UNINST_SERV_RESP_LENGTH == actual_response_length) && | |
(NRBG_UNINSTANTIATE_REQUEST_CMD == response[0])) | |
{ | |
status = response[1]; | |
} | |
else | |
{ | |
status = MSS_SYS_UNEXPECTED_ERROR; | |
} | |
return status; | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
static uint8_t g_isp_response[ISP_PROG_SERV_RESP_LENGTH]; | |
void (*g_isp_completion_handler)(uint32_t) = 0; | |
static void isp_sys_completion_handler | |
( | |
uint8_t * p_response, | |
uint16_t length | |
) | |
{ | |
if(g_isp_completion_handler != 0) | |
{ | |
g_isp_completion_handler(p_response[1]); | |
} | |
} | |
void MSS_SYS_start_isp | |
( | |
uint8_t mode, | |
uint32_t (*page_read_handler)(uint8_t const **), | |
void (*isp_completion_handler)(uint32_t) | |
) | |
{ | |
uint8_t isp_prog_request[2]; | |
signal_request_start(); | |
isp_prog_request[0] = ISP_PROGRAMMING_REQUEST_CMD; | |
isp_prog_request[1] = mode; | |
g_isp_completion_handler = isp_completion_handler; | |
MSS_COMBLK_send_paged_cmd(isp_prog_request, /* p_cmd */ | |
sizeof(isp_prog_request), /* cmd_size */ | |
g_isp_response, /* p_response */ | |
ISP_PROG_SERV_RESP_LENGTH, /* response_size */ | |
page_read_handler, /* page_handler */ | |
isp_sys_completion_handler); /* completion_handler */ | |
} | |
/*============================================================================== | |
* See mss_sys_services.h for details. | |
*/ | |
uint8_t MSS_SYS_check_digest | |
( | |
uint8_t options | |
) | |
{ | |
uint8_t status; | |
uint16_t actual_response_length; | |
uint8_t digest_check_req[2]; | |
uint8_t response[DIGEST_CHECK_SERV_RESP_LENGTH]; | |
signal_request_start(); | |
digest_check_req[0] = DIGEST_CHECK_REQUEST_CMD; | |
digest_check_req[1] = options; | |
MSS_COMBLK_send_cmd(digest_check_req, /* p_cmd */ | |
sizeof(digest_check_req), /* cmd_size */ | |
0, /* p_data */ | |
0u, /* data_size */ | |
response, /* p_response */ | |
DIGEST_CHECK_SERV_RESP_LENGTH, /* response_size */ | |
request_completion_handler); /* completion_handler */ | |
actual_response_length = wait_for_request_completion(); | |
if((DIGEST_CHECK_SERV_RESP_LENGTH == actual_response_length) && | |
(DIGEST_CHECK_REQUEST_CMD == response[0])) | |
{ | |
status = response[1]; | |
} | |
else | |
{ | |
status = MSS_SYS_UNEXPECTED_ERROR; | |
} | |
return status; | |
} | |
/*============================================================================== | |
* | |
*/ | |
static uint8_t execute_service | |
( | |
uint8_t cmd_opcode, | |
uint8_t * cmd_params_ptr, | |
uint8_t * response, | |
uint16_t response_length | |
) | |
{ | |
uint8_t status; | |
uint16_t actual_response_length; | |
signal_request_start(); | |
MSS_COMBLK_send_cmd_with_ptr(cmd_opcode, /* cmd_opcode */ | |
(uint32_t)cmd_params_ptr, /* cmd_params_ptr */ | |
response, /* p_response */ | |
response_length, /* response_size */ | |
request_completion_handler); /* completion_handler */ | |
actual_response_length = wait_for_request_completion(); | |
if((response_length == actual_response_length) && (cmd_opcode == response[0])) | |
{ | |
status = response[1]; | |
} | |
else | |
{ | |
status = MSS_SYS_UNEXPECTED_ERROR; | |
} | |
return status; | |
} | |
/*============================================================================== | |
* | |
*/ | |
static void request_completion_handler | |
( | |
uint8_t * p_response, | |
uint16_t response_size | |
) | |
{ | |
g_request_in_progress = 0u; | |
g_last_response_length = response_size; | |
} | |
/*============================================================================== | |
* | |
*/ | |
static void signal_request_start(void) | |
{ | |
/* Wait for current request to complete. */ | |
while(g_request_in_progress) | |
{ | |
; | |
} | |
g_request_in_progress = 1u; | |
g_last_response_length = 0u; | |
} | |
/*============================================================================== | |
* | |
*/ | |
static uint16_t wait_for_request_completion(void) | |
{ | |
while(g_request_in_progress) | |
{ | |
; | |
} | |
return g_last_response_length; | |
} | |
/*============================================================================== | |
* | |
*/ | |
static void write_ptr_value_into_array | |
( | |
const uint8_t * pointer, | |
uint8_t target_array[], | |
uint32_t array_index | |
) | |
{ | |
target_array[array_index] = (uint8_t)((uint32_t)pointer); | |
target_array[array_index + 1] = (uint8_t)((uint32_t)pointer >> 8u); | |
target_array[array_index + 2] = (uint8_t)((uint32_t)pointer >> 16u); | |
target_array[array_index + 3] = (uint8_t)((uint32_t)pointer >> 24u); | |
} | |