mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-06 04:01:44 +00:00
exo: add extension smc to write to user address
This commit is contained in:
parent
79d96bbdfd
commit
40b838c896
3 changed files with 73 additions and 0 deletions
|
@ -155,3 +155,69 @@ uint32_t ams_iram_copy(smc_args_t *args) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t ams_write_address(smc_args_t *args) {
|
||||||
|
/* Implements a write to a DRAM page. */
|
||||||
|
/* This operation can be used to write to read-only pages. */
|
||||||
|
/* args->X[1] = DRAM address (translated by kernel), must be size-bytes aligned. */
|
||||||
|
/* args->X[2] = Value. */
|
||||||
|
/* args->X[3] = size (must be 1, 2, 4, or 8). */
|
||||||
|
|
||||||
|
const uintptr_t dram_address = (uintptr_t)args->X[1];
|
||||||
|
const uintptr_t dram_page_offset = (dram_address & 0xFFFULL);
|
||||||
|
const size_t size = (size_t)(args->X[3]);
|
||||||
|
|
||||||
|
/* Validate addresses. */
|
||||||
|
if (!ams_is_user_addr_valid(dram_address)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate size. */
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
if ((size + dram_page_offset) > 0x1000) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate alignment. */
|
||||||
|
if (dram_page_offset % size) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map pages. */
|
||||||
|
ams_map_userpage(dram_address);
|
||||||
|
|
||||||
|
/* Write data. */
|
||||||
|
uintptr_t dram_ptr = (uintptr_t)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset);
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
*((volatile uint8_t *)dram_ptr) = (uint8_t)(args->X[2]);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*((volatile uint16_t *)dram_ptr) = (uint16_t)(args->X[2]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
*((volatile uint32_t *)dram_ptr) = (uint32_t)(args->X[2]);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
*((volatile uint64_t *)dram_ptr) = args->X[2];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush! */
|
||||||
|
flush_dcache_range((void *)dram_ptr, (void *)(dram_ptr + size));
|
||||||
|
|
||||||
|
/* Unmap pages. */
|
||||||
|
ams_unmap_userpage();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "smc_api.h"
|
#include "smc_api.h"
|
||||||
|
|
||||||
uint32_t ams_iram_copy(smc_args_t *args);
|
uint32_t ams_iram_copy(smc_args_t *args);
|
||||||
|
uint32_t ams_write_address(smc_args_t *args);
|
||||||
|
|
||||||
void ams_map_irampage(uintptr_t iram_address);
|
void ams_map_irampage(uintptr_t iram_address);
|
||||||
void ams_unmap_irampage(void);
|
void ams_unmap_irampage(void);
|
||||||
|
|
|
@ -77,6 +77,7 @@ uint32_t smc_read_write_register(smc_args_t *args);
|
||||||
|
|
||||||
/* Atmosphere SMC prototypes */
|
/* Atmosphere SMC prototypes */
|
||||||
uint32_t smc_ams_iram_copy(smc_args_t *args);
|
uint32_t smc_ams_iram_copy(smc_args_t *args);
|
||||||
|
uint32_t smc_ams_write_address(smc_args_t *args);
|
||||||
|
|
||||||
/* TODO: Provide a way to set this. It's 0 on non-recovery boot anyway... */
|
/* TODO: Provide a way to set this. It's 0 on non-recovery boot anyway... */
|
||||||
static uint32_t g_smc_blacklist_mask = 0;
|
static uint32_t g_smc_blacklist_mask = 0;
|
||||||
|
@ -133,6 +134,7 @@ static smc_table_entry_t g_smc_ams_table[] = {
|
||||||
{0, 4, NULL},
|
{0, 4, NULL},
|
||||||
{0xF0000201, 0, smc_ams_iram_copy},
|
{0xF0000201, 0, smc_ams_iram_copy},
|
||||||
{0xF0000002, 0, smc_read_write_register},
|
{0xF0000002, 0, smc_read_write_register},
|
||||||
|
{0xF0000203, 0, smc_ams_write_address},
|
||||||
};
|
};
|
||||||
#define SMC_AMS_HANDLERS (sizeof(g_smc_ams_table) / sizeof(g_smc_ams_table[0]))
|
#define SMC_AMS_HANDLERS (sizeof(g_smc_ams_table) / sizeof(g_smc_ams_table[0]))
|
||||||
|
|
||||||
|
@ -718,3 +720,7 @@ uint32_t smc_panic(smc_args_t *args) {
|
||||||
uint32_t smc_ams_iram_copy(smc_args_t *args) {
|
uint32_t smc_ams_iram_copy(smc_args_t *args) {
|
||||||
return smc_wrapper_sync(args, ams_iram_copy);
|
return smc_wrapper_sync(args, ams_iram_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t smc_ams_write_address(smc_args_t *args) {
|
||||||
|
return smc_wrapper_sync(args, ams_write_address);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue