mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-09 21:51:45 +00:00
Basic API for SMC handlers.
This commit is contained in:
parent
049553aa91
commit
8ea1ac0ecc
2 changed files with 152 additions and 0 deletions
137
exosphere/smc_api.c
Normal file
137
exosphere/smc_api.c
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "smc_api.h"
|
||||
|
||||
#define SMC_USER_HANDLERS 0x13
|
||||
#define SMC_PRIV_HANDLERS 0x9
|
||||
|
||||
/* User SMC prototypes */
|
||||
uint32_t smc_set_config(smc_args_t *args);
|
||||
uint32_t smc_get_config(smc_args_t *args);
|
||||
uint32_t smc_check_status(smc_args_t *args);
|
||||
uint32_t smc_get_result(smc_args_t *args);
|
||||
uint32_t smc_exp_mod(smc_args_t *args);
|
||||
uint32_t smc_get_random_bytes_for_user(smc_args_t *args);
|
||||
uint32_t smc_generate_aes_kek(smc_args_t *args);
|
||||
uint32_t smc_load_aes_key(smc_args_t *args);
|
||||
uint32_t smc_crypt_aes(smc_args_t *args);
|
||||
uint32_t smc_generate_specific_aes_key(smc_args_t *args);
|
||||
uint32_t smc_compute_cmac(smc_args_t *args);
|
||||
uint32_t smc_load_rsa_private_key(smc_args_t *args);
|
||||
uint32_t smc_decrypt_rsa_private_key(smc_args_t *args);
|
||||
uint32_t smc_load_rsa_oaep_key(smc_args_t *args);
|
||||
uint32_t smc_rsa_oaep(smc_args_t *args);
|
||||
uint32_t smc_unwrap_rsa_wrapped_titlekey(smc_args_t *args);
|
||||
uint32_t smc_load_titlekey(smc_args_t *args);
|
||||
uint32_t smc_unwrap_aes_wrapped_titlekey(smc_args_t *args);
|
||||
|
||||
/* Privileged SMC prototypes */
|
||||
uint32_t smc_cpu_suspend(smc_args_t *args);
|
||||
uint32_t smc_cpu_off(smc_args_t *args);
|
||||
uint32_t smc_cpu_on(smc_args_t *args);
|
||||
/* uint32_t smc_get_config(smc_args_t *args); */
|
||||
uint32_t smc_get_random_bytes_for_priv(smc_args_t *args);
|
||||
uint32_t smc_panic(smc_args_t *args);
|
||||
uint32_t smc_configure_carveout(smc_args_t *args);
|
||||
uint32_t smc_read_write_register(smc_args_t *args);
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t (*handler)(smc_args_t *args);
|
||||
} smc_table_entry_t;
|
||||
|
||||
typedef struct {
|
||||
smc_table_entry_t *handlers;
|
||||
uint32_t num_handlers;
|
||||
} smc_table_t;
|
||||
|
||||
smc_table_entry_t g_smc_user_table[SMC_USER_HANDLERS] = {
|
||||
{0, NULL},
|
||||
{0xC3000401, smc_set_config},
|
||||
{0xC3000002, smc_get_config},
|
||||
{0xC3000003, smc_check_status},
|
||||
{0xC3000404, smc_get_result},
|
||||
{0xC3000E05, smc_exp_mod},
|
||||
{0xC3000006, smc_get_random_bytes_for_user},
|
||||
{0xC3000007, smc_generate_aes_kek},
|
||||
{0xC3000008, smc_load_aes_key},
|
||||
{0xC3000009, smc_crypt_aes},
|
||||
{0xC300000A, smc_generate_specific_aes_key},
|
||||
{0xC300040B, smc_compute_cmac},
|
||||
{0xC300100C, smc_load_rsa_private_key},
|
||||
{0xC300100D, smc_decrypt_rsa_private_key},
|
||||
{0xC300100E, smc_load_rsa_oaep_key},
|
||||
{0xC300060F, smc_rsa_oaep},
|
||||
{0xC3000610, smc_unwrap_rsa_wrapped_titlekey},
|
||||
{0xC3000011, smc_load_titlekey},
|
||||
{0xC3000012, smc_unwrap_aes_wrapped_titlekey}
|
||||
};
|
||||
|
||||
smc_table_entry_t g_smc_priv_table[SMC_PRIV_HANDLERS] = {
|
||||
{0, NULL},
|
||||
{0xC4000001, smc_cpu_suspend},
|
||||
{0x84000002, smc_cpu_off},
|
||||
{0xC4000003, smc_cpu_on},
|
||||
{0xC3000004, smc_get_config}, /* NOTE: Same function as for USER */
|
||||
{0xC3000005, smc_get_random_bytes_for_priv},
|
||||
{0xC3000006, smc_panic},
|
||||
{0xC3000007, smc_configure_carveout},
|
||||
{0xC3000008, smc_read_write_register}
|
||||
};
|
||||
|
||||
smc_table_t g_smc_tables[2] = {
|
||||
{ /* SMC_HANDLER_USER */
|
||||
g_smc_user_table,
|
||||
SMC_USER_HANDLERS
|
||||
},
|
||||
{ /* SMC_HANDLER_PRIV */
|
||||
g_smc_priv_table,
|
||||
SMC_PRIV_HANDLERS
|
||||
}
|
||||
};
|
||||
|
||||
int g_is_smc_in_progress = 0;
|
||||
|
||||
void call_smc_handler(uint32_t handler_id, smc_args_t *args) {
|
||||
unsigned char smc_id;
|
||||
unsigned int result;
|
||||
unsigned int (*smc_handler)(smc_args_t *args);
|
||||
|
||||
/* Validate top-level handler. */
|
||||
if (handler_id != SMC_HANDLER_USER && handler_id != SMC_HANDLER_PRIV) {
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Validate sub-handler index */
|
||||
if ((smc_id = (unsigned char)args->X[0]) >= g_smc_tables[handler_id].num_handlers) {
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Validate sub-handler */
|
||||
if (g_smc_tables[handler_id].handlers[smc_id].id != args->X[0]) {
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Validate handler. */
|
||||
if ((smc_handler = g_smc_tables[handler_id].handlers[smc_id].handler) == NULL) {
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Call function. */
|
||||
args->X[0] = smc_handler(args);
|
||||
}
|
||||
|
||||
uint32_t smc_wrapper_sync(smc_args_t *args, uint32_t (*handler)(smc_args_t *)) {
|
||||
uint32_t result;
|
||||
/* TODO: Make g_is_smc_in_progress atomic. */
|
||||
if (g_is_smc_in_progress) {
|
||||
return 3;
|
||||
}
|
||||
g_is_smc_in_progress = 1;
|
||||
result = handler(args);
|
||||
g_is_smc_in_progress = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), uint32_t (*callback)(void, void));
|
15
exosphere/smc_api.h
Normal file
15
exosphere/smc_api.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef EXOSPHERE_SMC_API_H
|
||||
#define EXOSPHERE_SMC_API_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SMC_HANDLER_USER 0
|
||||
#define SMC_HANDLER_PRIV 1
|
||||
|
||||
typedef struct {
|
||||
uint64_t X[8];
|
||||
} smc_args_t;
|
||||
|
||||
void call_smc_handler(unsigned int handler_id, smc_args_t *args);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue