Skeleton for smcGetConfig and smcSetConfig

This commit is contained in:
Michael Scire 2018-02-19 00:41:19 -08:00
parent f629a629d1
commit f77cae48d0
4 changed files with 114 additions and 1 deletions

67
exosphere/configitem.c Normal file
View file

@ -0,0 +1,67 @@
#include <stdint.h>
#include "utils.h"
#include "configitem.h"
int g_battery_profile = 0;
uint32_t configitem_set(enum ConfigItem item, uint64_t value) {
if (item != CONFIGITEM_BATTERYPROFILE) {
return 2;
}
g_battery_profile = ((int)(value != 0)) & 1;
}
uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue) {
uint32_t result = 0;
switch (item) {
case CONFIGITEM_DISABLEPROGRAMVERIFICATION:
/* TODO: This is loaded from BootConfig on dev units, always zero on retail. How should we support? */
*p_outvalue = 0;
break;
case CONFIGITEM_MEMORYCONFIGURATION:
/* TODO: Fuse driver */
break;
case CONFIGITEM_SECURITYENGINEIRQ:
/* SE is interrupt #44. */
*p_outvalue = 0x2C;
break;
case CONFIGITEM_UNK04:
/* Always returns 2 on hardware. */
*p_outvalue = 2;
break;
case CONFIGITEM_HARDWARETYPE:
/* TODO: Fuse driver */
break;
case CONFIGITEM_ISRETAIL:
/* TODO: Fuse driver */
break;
case CONFIGITEM_ISRECOVERYBOOT:
/* TODO: This is just a constant, hardcoded into TZ on retail. How should we support? */
*p_outvalue = 0;
break;
case CONFIGITEM_DEVICEID:
/* TODO: Fuse driver */
break;
case CONFIGITEM_BOOTREASON:
/* TODO: This requires reading values passed to crt0 via NX_Bootloader. TBD pending crt0 implementation. */
break;
case CONFIGITEM_MEMORYARRANGE:
/* TODO: More BootConfig stuff. */
break;
case CONFIGITEM_ISDEBUGMODE:
/* TODO: More BootConfig stuff. */
break;
case CONFIGITEM_KERNELMEMORYCONFIGURATION:
/* TODO: More BootConfig stuff. */
break;
case CONFIGITEM_BATTERYPROFILE:
*p_outvalue = g_battery_profile;
break;
default:
result = 2;
break;
}
return result;
}

26
exosphere/configitem.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef EXOSPHERE_CFG_ITEM_H
#define EXOSPHERE_CFG_ITEM_H
#include <stdint.h>
enum ConfigItem {
CONFIGITEM_DISABLEPROGRAMVERIFICATION = 1,
CONFIGITEM_MEMORYCONFIGURATION = 2,
CONFIGITEM_SECURITYENGINEIRQ = 3,
CONFIGITEM_UNK04 = 4,
CONFIGITEM_HARDWARETYPE = 5,
CONFIGITEM_ISRETAIL = 6,
CONFIGITEM_ISRECOVERYBOOT = 7,
CONFIGITEM_DEVICEID = 8,
CONFIGITEM_BOOTREASON = 9,
CONFIGITEM_MEMORYARRANGE = 10,
CONFIGITEM_ISDEBUGMODE = 11,
CONFIGITEM_KERNELMEMORYCONFIGURATION = 12,
CONFIGITEM_BATTERYPROFILE = 13
};
uint32_t configitem_set(enum ConfigItem item, uint64_t value);
uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue);
#endif

View file

@ -1,6 +1,7 @@
#include <stdint.h>
#include "utils.h"
#include "configitem.h"
#include "cpu_context.h"
#include "smc_api.h"
#include "smc_user.h"
@ -129,6 +130,12 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) {
panic();
}
/* Validate core is appropriate for handler. */
if (handler_id == SMC_HANDLER_USER && get_core_id() != 3) {
/* USER SMCs must be called via svcCallSecureMonitor on core 3 (where spl runs) */
panic();
}
/* Validate sub-handler index */
if ((smc_id = (unsigned char)args->X[0]) >= g_smc_tables[handler_id].num_handlers) {
panic();
@ -185,6 +192,19 @@ uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *),
return result;
}
uint32_t smc_set_config(smc_args_t *args) {
/* Actual value presumed in X3 on hardware. */
return configitem_set((enum ConfigItem)args->X[1], args->X[3]);
}
uint32_t smc_get_config(smc_args_t *args) {
uint64_t out_item = 0;
uint32_t result;
result = configitem_get((enum ConfigItem)args->X[1], &out_item);
args->X[1] = out_item;
return result;
}
uint32_t smc_check_status(smc_args_t *args) {
if (g_smc_callback_key == 0) {
return 4;

View file

@ -17,7 +17,7 @@ static inline uint32_t read32be(const unsigned char *dword, size_t offset) {
static inline unsigned int get_core_id(void) {
unsigned int core_id;
__asm__ __volatile__ ("mrs %0, MPIDR_EL1" : "=r"(core_id));
return core_id;
return core_id & 3;
}
#endif