Add wrapper for async SMCs

This commit is contained in:
Michael Scire 2018-02-17 16:00:53 -08:00
parent 8ea1ac0ecc
commit 49e1e6f41e
2 changed files with 50 additions and 1 deletions

View file

@ -108,6 +108,8 @@ void set_se_ctr(const char *ctr);
void se_crypt_aes(unsigned int keyslot, unsigned char *dst, unsigned int dst_size, const unsigned char *src, unsigned int src_size, unsigned int config, unsigned int mode, unsigned int (*callback)(void));
void se_exp_mod(unsigned int keyslot, unsigned char *buf, unsigned int size, unsigned int (*callback)(void));
void se_generate_random(unsigned int keyslot, unsigned char *dst, unsigned int size);
/* TODO: SE context save API, consider extending AES API for secure world vs non-secure world operations. */
/* In particular, smc_crypt_aes takes in raw DMA lists, and we need to support that. */

View file

@ -2,6 +2,7 @@
#include "utils.h"
#include "smc_api.h"
#include "se.h"
#define SMC_USER_HANDLERS 0x13
#define SMC_PRIV_HANDLERS 0x9
@ -92,6 +93,29 @@ smc_table_t g_smc_tables[2] = {
};
int g_is_smc_in_progress = 0;
uint32_t (*g_smc_callback)(uint64_t, uint64_t) = NULL;
uint64_t g_smc_callback_key = 0;
uint64_t try_set_smc_callback(uint32_t (*callback)(uint64_t, uint64_t)) {
uint64_t key;
/* TODO: Atomics... */
if (g_smc_callback_key) {
return 0;
}
/* TODO: Keyslot defines. */
se_generate_random(0xB, &key, sizeof(uint64_t));
g_smc_callback_key = key;
g_smc_callback = callback;
return key;
}
void clear_smc_callback(uint64_t key) {
/* TODO: Atomics... */
if (g_smc_callback_key == key) {
g_smc_callback_key = 0;
}
}
void call_smc_handler(uint32_t handler_id, smc_args_t *args) {
unsigned char smc_id;
@ -134,4 +158,27 @@ uint32_t smc_wrapper_sync(smc_args_t *args, uint32_t (*handler)(smc_args_t *)) {
return result;
}
uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), uint32_t (*callback)(void, void));
uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), uint32_t (*callback)(uint64_t, uint64_t)) {
uint32_t result;
uint64_t key;
/* TODO: Make g_is_smc_in_progress atomic. */
if (g_is_smc_in_progress) {
return 3;
}
g_is_smc_in_progress = 1;
if ((key = try_set_smc_callback(callback)) != 0) {
result = handler(args);
if (result == 0) {
/* Pass the status check key back to userland. */
args->X[1] = key;
} else {
/* No status to check. */
clear_smc_callback(key);
}
} else {
/* smcCheckStatus needs to be called. */
result = 3;
}
g_is_smc_in_progress = 0;
return result;
}