blob: 4226767bbcbc815b03d2e4b8d5c7b4317e22899d [file] [log] [blame]
/*
* Copyright (c) 2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <debug.h>
#include <mm_svc.h>
#include <secure_partition.h>
#include <sp_helpers.h>
#include <spm_svc.h>
#include <string.h>
/*
* Handle a fast secure service request, i.e. one made through an MM_COMMUNICATE
* call.
*
* cc
* Calling convention. If MM_COMMUNICATE has been invoked using the SMC32
* calling convention, this argument must be 32, else 64.
*
* sps
* Communication buffer attached to the secure partition service request.
*/
static int32_t cactus_handle_fast_request(int cc,
secure_partition_request_info_t *sps)
{
assert(cc == 32 || cc == 64);
/* No SMC32 is supported at the moment. Just ignore them. */
if (cc == 32) {
INFO("Ignoring MM_COMMUNICATE_AARCH32 call\n");
return SPM_SUCCESS;
}
/* See secure_partition.h for possible ID values. */
switch (sps->id) {
case SPS_TIMER_SLEEP: {
if (sps->data_size != 1) {
ERROR("Invalid payload size for SPM_SPS_TIMER_SLEEP request (%llu)\n",
sps->data_size);
return SPM_INVALID_PARAMETER;
}
uint32_t duration_sec = sps->data[0];
sp_sleep(duration_sec * 1000);
/*
* Write back to the communication buffer to acknowledge the
* request has been successfully handled.
*/
uint32_t response = CACTUS_FAST_REQUEST_SUCCESS;
memcpy(sps->data, &response, sizeof(response));
return SPM_SUCCESS;
}
case SPS_CHECK_ALIVE:
return SPM_SUCCESS;
default:
INFO("Unsupported MM_COMMUNICATE_AARCH64 call with service ID 0x%x, ignoring it\n",
sps->id);
return SPM_INVALID_PARAMETER;
}
}
__dead2 void secure_services_loop(void)
{
int32_t event_status_code;
svc_args svc_values = { 0 };
/*
* The first time this loop is executed corresponds to when Cactus has
* finished initialising its run time environment and is ready to handle
* secure service requests.
*/
NOTICE("Cactus: Signal end of init to SPM\n");
event_status_code = SPM_SUCCESS;
while (1) {
svc_values.fid = SP_EVENT_COMPLETE_AARCH64;
svc_values.arg1 = event_status_code;
int32_t event_id = sp_svc(&svc_values);
switch (event_id) {
case MM_COMMUNICATE_AARCH64:
{
uint64_t ctx_addr = svc_values.arg1;
uint32_t ctx_size = svc_values.arg2;
uint64_t cookie = svc_values.arg3;
(void) cookie;
(void) ctx_size;
VERBOSE("Cactus: Received MM_COMMUNICATE_AARCH64 call\n");
VERBOSE("Cactus: Context address: 0x%llx\n", ctx_addr);
VERBOSE("Cactus: Context size : %u\n", ctx_size);
VERBOSE("Cactus: Cookie : 0x%llx\n", cookie);
if (ctx_addr == 0) {
ERROR("Context address is invalid\n");
event_status_code = SPM_INVALID_PARAMETER;
continue;
}
secure_partition_request_info_t *sps = (void *)(uintptr_t) ctx_addr;
INFO("Received fast secure service request with ID #%u\n",
sps->id);
event_status_code = cactus_handle_fast_request(64, sps);
break;
}
case MM_COMMUNICATE_AARCH32:
{
uint32_t ctx_addr = svc_values.arg1;
uint32_t ctx_size = svc_values.arg2;
uint32_t cookie = svc_values.arg3;
(void) cookie;
(void) ctx_size;
VERBOSE("Cactus: Received MM_COMMUNICATE_AARCH32 call\n");
VERBOSE("Cactus: Context address: 0x%x\n", ctx_addr);
VERBOSE("Cactus: Context size : %u\n", ctx_size);
VERBOSE("Cactus: Cookie : 0x%x\n", cookie);
if (ctx_addr == 0) {
ERROR("Context address is invalid\n");
event_status_code = SPM_INVALID_PARAMETER;
continue;
}
secure_partition_request_info_t *sps = (void *)(uintptr_t) ctx_addr;
INFO("Received fast secure service request with ID #%u\n",
sps->id);
event_status_code = cactus_handle_fast_request(32, sps);
break;
}
default:
NOTICE("Unhandled Service ID 0x%x\n", event_id);
event_status_code = SPM_NOT_SUPPORTED;
break;
}
}
}