mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
emummc: update for exo2
This commit is contained in:
parent
f82954e98b
commit
ff87ff2592
8 changed files with 328 additions and 49 deletions
|
@ -128,6 +128,8 @@
|
||||||
"svcUnmapDeviceAddressSpace": "0x5c",
|
"svcUnmapDeviceAddressSpace": "0x5c",
|
||||||
"svcGetSystemInfo": "0x6f",
|
"svcGetSystemInfo": "0x6f",
|
||||||
"svcSetProcessMemoryPermission": "0x73",
|
"svcSetProcessMemoryPermission": "0x73",
|
||||||
|
"svcMapProcessMemory": "0x74",
|
||||||
|
"svcUnmapProcessMemory": "0x75",
|
||||||
"svcCallSecureMonitor": "0x7f"
|
"svcCallSecureMonitor": "0x7f"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,11 @@ void hook_function(uintptr_t source, uintptr_t target);
|
||||||
|
|
||||||
void *__stack_top;
|
void *__stack_top;
|
||||||
uintptr_t text_base;
|
uintptr_t text_base;
|
||||||
|
size_t fs_code_size;
|
||||||
char inner_heap[INNER_HEAP_SIZE];
|
char inner_heap[INNER_HEAP_SIZE];
|
||||||
size_t inner_heap_size = INNER_HEAP_SIZE;
|
size_t inner_heap_size = INNER_HEAP_SIZE;
|
||||||
|
Handle self_proc_handle = 0;
|
||||||
|
u8 *fs_rw_mapping = NULL;
|
||||||
extern char _start;
|
extern char _start;
|
||||||
extern char __argdata__;
|
extern char __argdata__;
|
||||||
|
|
||||||
|
@ -148,15 +151,117 @@ void __initheap(void)
|
||||||
fake_heap_end = (char *)addr + size;
|
fake_heap_end = (char *)addr + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _receive_process_handle_thread(void *_session_handle) {
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
// Convert the argument to a handle we can use.
|
||||||
|
Handle session_handle = (Handle)(uintptr_t)_session_handle;
|
||||||
|
|
||||||
|
// Receive the request from the client thread.
|
||||||
|
memset(armGetTls(), 0, 0x10);
|
||||||
|
s32 idx = 0;
|
||||||
|
rc = svcReplyAndReceive(&idx, &session_handle, 1, INVALID_HANDLE, UINT64_MAX);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the process handle.
|
||||||
|
self_proc_handle = ((u32 *)armGetTls())[3];
|
||||||
|
|
||||||
|
// Close the session.
|
||||||
|
svcCloseHandle(session_handle);
|
||||||
|
|
||||||
|
// Terminate ourselves.
|
||||||
|
svcExitThread();
|
||||||
|
|
||||||
|
// This code will never execute.
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _init_process_handle(void) {
|
||||||
|
Result rc;
|
||||||
|
u8 temp_thread_stack[0x1000];
|
||||||
|
|
||||||
|
// Create a new session to transfer our process handle to ourself
|
||||||
|
Handle server_handle, client_handle;
|
||||||
|
rc = svcCreateSession(&server_handle, &client_handle, 0, 0);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new thread to receive our handle.
|
||||||
|
Handle thread_handle;
|
||||||
|
rc = svcCreateThread(&thread_handle, _receive_process_handle_thread, (void *)(uintptr_t)server_handle, temp_thread_stack + sizeof(temp_thread_stack), 0x20, 3);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the new thread.
|
||||||
|
rc = svcStartThread(thread_handle);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the message.
|
||||||
|
static const u32 SendProcessHandleMessage[4] = { 0x00000000, 0x80000000, 0x00000002, CUR_PROCESS_HANDLE };
|
||||||
|
memcpy(armGetTls(), SendProcessHandleMessage, sizeof(SendProcessHandleMessage));
|
||||||
|
svcSendSyncRequest(client_handle);
|
||||||
|
|
||||||
|
// Close the session handle.
|
||||||
|
svcCloseHandle(client_handle);
|
||||||
|
|
||||||
|
// Wait for the thread to be done.
|
||||||
|
rc = svcWaitSynchronizationSingle(thread_handle, UINT64_MAX);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the thread handle.
|
||||||
|
svcCloseHandle(thread_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _map_fs_rw(void) {
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fs_rw_mapping = (u8 *)(smcGenerateRandomU64() & 0xFFFFFF000ull);
|
||||||
|
rc = svcMapProcessMemory(fs_rw_mapping, self_proc_handle, INJECT_OFFSET(u64, 0), fs_code_size);
|
||||||
|
} while (rc == 0xDC01 || rc == 0xD401);
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _unmap_fs_rw(void) {
|
||||||
|
Result rc = svcUnmapProcessMemory(fs_rw_mapping, self_proc_handle, INJECT_OFFSET(u64, 0), fs_code_size);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_rw_mapping = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _write32(uintptr_t source, u32 value) {
|
||||||
|
*((u32 *)(fs_rw_mapping + (source - INJECT_OFFSET(u64, 0)))) = value;
|
||||||
|
}
|
||||||
|
|
||||||
void hook_function(uintptr_t source, uintptr_t target)
|
void hook_function(uintptr_t source, uintptr_t target)
|
||||||
{
|
{
|
||||||
u32 branch_opcode = GENERATE_BRANCH(source, target);
|
u32 branch_opcode = GENERATE_BRANCH(source, target);
|
||||||
smcWriteAddress32((void *)source, branch_opcode);
|
_write32(source, branch_opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_nop(uintptr_t source)
|
void write_nop(uintptr_t source)
|
||||||
{
|
{
|
||||||
smcWriteAddress32((void *)source, GENERATE_NOP());
|
_write32(source, GENERATE_NOP());
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_adrp_add(int reg, uintptr_t pc, uintptr_t add_rel_offset, intptr_t destination)
|
void write_adrp_add(int reg, uintptr_t pc, uintptr_t add_rel_offset, intptr_t destination)
|
||||||
|
@ -167,8 +272,8 @@ void write_adrp_add(int reg, uintptr_t pc, uintptr_t add_rel_offset, intptr_t de
|
||||||
uint32_t opcode_adrp = GENERATE_ADRP(reg, offset);
|
uint32_t opcode_adrp = GENERATE_ADRP(reg, offset);
|
||||||
uint32_t opcode_add = GENERATE_ADD(reg, reg, (destination & 0x00000FFF));
|
uint32_t opcode_add = GENERATE_ADD(reg, reg, (destination & 0x00000FFF));
|
||||||
|
|
||||||
smcWriteAddress32((void *)pc, opcode_adrp);
|
_write32(pc, opcode_adrp);
|
||||||
smcWriteAddress32((void *)add_opcode_location, opcode_add);
|
_write32(add_opcode_location, opcode_add);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_hooks(void)
|
void setup_hooks(void)
|
||||||
|
@ -306,14 +411,21 @@ void __init()
|
||||||
|
|
||||||
text_base = meminfo.addr;
|
text_base = meminfo.addr;
|
||||||
|
|
||||||
|
// Get code size
|
||||||
|
svcQueryMemory(&meminfo, &pageinfo, INJECT_OFFSET(u64, 0));
|
||||||
|
fs_code_size = meminfo.size;
|
||||||
|
|
||||||
load_emummc_ctx();
|
load_emummc_ctx();
|
||||||
|
|
||||||
fs_offsets = get_fs_offsets(emuMMC_ctx.fs_ver);
|
fs_offsets = get_fs_offsets(emuMMC_ctx.fs_ver);
|
||||||
|
|
||||||
|
_init_process_handle();
|
||||||
|
_map_fs_rw();
|
||||||
setup_hooks();
|
setup_hooks();
|
||||||
populate_function_pointers();
|
populate_function_pointers();
|
||||||
write_nops();
|
write_nops();
|
||||||
setup_nintendo_paths();
|
setup_nintendo_paths();
|
||||||
|
_unmap_fs_rw();
|
||||||
|
|
||||||
clock_enable_i2c5();
|
clock_enable_i2c5();
|
||||||
i2c_init();
|
i2c_init();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "smc.h"
|
#include "smc.h"
|
||||||
|
#include "../utils/fatal.h"
|
||||||
|
|
||||||
void smcRebootToRcm(void)
|
void smcRebootToRcm(void)
|
||||||
{
|
{
|
||||||
|
@ -117,45 +118,6 @@ Result smcReadWriteRegister(u32 phys_addr, u32 value, u32 mask)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _smcWriteAddress(void *dst_addr, u64 val, u32 size)
|
|
||||||
{
|
|
||||||
SecmonArgs args;
|
|
||||||
args.X[0] = 0xF0000003; /* smcAmsWriteAddress */
|
|
||||||
args.X[1] = (u64)dst_addr; /* DRAM address */
|
|
||||||
args.X[2] = val; /* value */
|
|
||||||
args.X[3] = size; /* Amount to write */
|
|
||||||
Result rc = svcCallSecureMonitor(&args);
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
if (args.X[0] != 0)
|
|
||||||
{
|
|
||||||
/* SPL result n = SMC result n */
|
|
||||||
rc = (26u | ((u32)args.X[0] << 9u));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result smcWriteAddress8(void *dst_addr, u8 val)
|
|
||||||
{
|
|
||||||
return _smcWriteAddress(dst_addr, val, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result smcWriteAddress16(void *dst_addr, u16 val)
|
|
||||||
{
|
|
||||||
return _smcWriteAddress(dst_addr, val, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result smcWriteAddress32(void *dst_addr, u32 val)
|
|
||||||
{
|
|
||||||
return _smcWriteAddress(dst_addr, val, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result smcWriteAddress64(void *dst_addr, u64 val)
|
|
||||||
{
|
|
||||||
return _smcWriteAddress(dst_addr, val, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg, void *out_paths)
|
Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg, void *out_paths)
|
||||||
{
|
{
|
||||||
SecmonArgs args;
|
SecmonArgs args;
|
||||||
|
@ -178,3 +140,37 @@ Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg,
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result smcGenerateRandomBytes(void *dst, u32 size)
|
||||||
|
{
|
||||||
|
SecmonArgs args;
|
||||||
|
args.X[0] = 0xC3000006; /* smcGenerateRandomBytes */
|
||||||
|
args.X[1] = size;
|
||||||
|
Result rc = svcCallSecureMonitor(&args);
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
if (args.X[0] != 0)
|
||||||
|
{
|
||||||
|
/* SPL result n = SMC result n */
|
||||||
|
rc = (26u | ((u32)args.X[0] << 9u));
|
||||||
|
}
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
memcpy(dst, &args.X[1], size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 smcGenerateRandomU64(void)
|
||||||
|
{
|
||||||
|
u64 random;
|
||||||
|
|
||||||
|
Result rc = smcGenerateRandomBytes(&random, sizeof(random));
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fatal_abort(Fatal_BadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
return random;
|
||||||
|
}
|
||||||
|
|
|
@ -78,13 +78,11 @@ Result smcCopyFromIram(void *dst_addr, uintptr_t iram_addr, u32 size);
|
||||||
|
|
||||||
Result smcReadWriteRegister(u32 phys_addr, u32 value, u32 mask);
|
Result smcReadWriteRegister(u32 phys_addr, u32 value, u32 mask);
|
||||||
|
|
||||||
Result smcWriteAddress8(void *dst_addr, u8 val);
|
|
||||||
Result smcWriteAddress16(void *dst_addr, u16 val);
|
|
||||||
Result smcWriteAddress32(void *dst_addr, u32 val);
|
|
||||||
Result smcWriteAddress64(void *dst_addr, u64 val);
|
|
||||||
|
|
||||||
Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg, void *out_paths);
|
Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg, void *out_paths);
|
||||||
|
|
||||||
|
Result smcGenerateRandomBytes(void *dst, u32 size);
|
||||||
|
u64 smcGenerateRandomU64(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -106,6 +106,104 @@ Result svcSetProcessMemoryPermission(Handle proc, u64 addr, u64 size, u32 perm);
|
||||||
*/
|
*/
|
||||||
Result svcSetMemoryPermission(void* addr, u64 size, u32 perm);
|
Result svcSetMemoryPermission(void* addr, u64 size, u32 perm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a thread.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x08.
|
||||||
|
*/
|
||||||
|
Result svcCreateThread(Handle* out, void* entry, void* arg, void* stack_top, int prio, int cpuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts a freshly created thread.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x09.
|
||||||
|
*/
|
||||||
|
Result svcStartThread(Handle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exits the current thread.
|
||||||
|
* @note Syscall number 0x0A.
|
||||||
|
*/
|
||||||
|
void __attribute__((noreturn)) svcExitThread(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes a handle, decrementing the reference count of the corresponding kernel object.
|
||||||
|
* This might result in the kernel freeing the object.
|
||||||
|
* @param handle Handle to close.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x16.
|
||||||
|
*/
|
||||||
|
Result svcCloseHandle(Handle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits on one or more synchronization objects, optionally with a timeout.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x18.
|
||||||
|
* @note \p handleCount must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation.
|
||||||
|
* @note This is the raw syscall, which can be cancelled by \ref svcCancelSynchronization or other means. \ref waitHandles or \ref waitMultiHandle should normally be used instead.
|
||||||
|
*/
|
||||||
|
Result svcWaitSynchronization(s32* index, const Handle* handles, s32 handleCount, u64 timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits on a single synchronization object, optionally with a timeout.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Wrapper for \ref svcWaitSynchronization.
|
||||||
|
* @note This is the raw syscall, which can be cancelled by \ref svcCancelSynchronization or other means. \ref waitSingleHandle should normally be used instead.
|
||||||
|
*/
|
||||||
|
static inline Result svcWaitSynchronizationSingle(Handle handle, u64 timeout) {
|
||||||
|
s32 tmp;
|
||||||
|
return svcWaitSynchronization(&tmp, &handle, 1, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an IPC session.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x40.
|
||||||
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
|
*/
|
||||||
|
Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends an IPC synchronization request to a session.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x21.
|
||||||
|
*/
|
||||||
|
Result svcSendSyncRequest(Handle session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Performs IPC input/output.
|
||||||
|
* @return Result code.
|
||||||
|
* @note Syscall number 0x43.
|
||||||
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
|
*/
|
||||||
|
Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maps the src address from the supplied process handle into the current process.
|
||||||
|
* @param[in] dst Address to which map the memory in the current process.
|
||||||
|
* @param[in] proc Process handle.
|
||||||
|
* @param[in] src Source mapping address.
|
||||||
|
* @param[in] size Size of the memory.
|
||||||
|
* @return Result code.
|
||||||
|
* @remark This allows mapping code and rodata with RW- permission.
|
||||||
|
* @note Syscall number 0x74.
|
||||||
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
|
*/
|
||||||
|
Result svcMapProcessMemory(void* dst, Handle proc, u64 src, u64 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Undoes the effects of \ref svcMapProcessMemory.
|
||||||
|
* @param[in] dst Destination mapping address
|
||||||
|
* @param[in] proc Process handle.
|
||||||
|
* @param[in] src Address of the memory in the process.
|
||||||
|
* @param[in] size Size of the memory.
|
||||||
|
* @return Result code.
|
||||||
|
* @remark This allows mapping code and rodata with RW- permission.
|
||||||
|
* @note Syscall number 0x75.
|
||||||
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
|
*/
|
||||||
|
Result svcUnmapProcessMemory(void* dst, Handle proc, u64 src, u64 size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calls a secure monitor function (TrustZone, EL3).
|
* @brief Calls a secure monitor function (TrustZone, EL3).
|
||||||
* @param regs Arguments to pass to the secure monitor.
|
* @param regs Arguments to pass to the secure monitor.
|
||||||
|
|
|
@ -56,6 +56,69 @@ SVC_BEGIN svcSetProcessMemoryPermission
|
||||||
RET
|
RET
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcCreateThread
|
||||||
|
STR X0, [SP, #-16]!
|
||||||
|
SVC 0x8
|
||||||
|
LDR X2, [SP], #16
|
||||||
|
STR W1, [X2]
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcStartThread
|
||||||
|
SVC 0x9
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcExitThread
|
||||||
|
SVC 0xA
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcCloseHandle
|
||||||
|
SVC 0x16
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcWaitSynchronization
|
||||||
|
STR X0, [SP, #-16]!
|
||||||
|
SVC 0x18
|
||||||
|
LDR X2, [SP], #16
|
||||||
|
STR W1, [X2]
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcCreateSession
|
||||||
|
STP X0, X1, [SP, #-16]!
|
||||||
|
SVC 0x40
|
||||||
|
LDP X3, X4, [SP], #16
|
||||||
|
STR W1, [X3]
|
||||||
|
STR W2, [X4]
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcSendSyncRequest
|
||||||
|
SVC 0x21
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcReplyAndReceive
|
||||||
|
STR X0, [SP, #-16]!
|
||||||
|
SVC 0x43
|
||||||
|
LDR X2, [SP], #16
|
||||||
|
STR W1, [X2]
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcMapProcessMemory
|
||||||
|
SVC 0x74
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcUnmapProcessMemory
|
||||||
|
SVC 0x75
|
||||||
|
RET
|
||||||
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcCallSecureMonitor
|
SVC_BEGIN svcCallSecureMonitor
|
||||||
STR X0, [SP, #-16]!
|
STR X0, [SP, #-16]!
|
||||||
MOV X8, X0
|
MOV X8, X0
|
||||||
|
|
|
@ -55,6 +55,10 @@ typedef volatile unsigned int vu32;
|
||||||
typedef u32 Handle; ///< Kernel object handle.
|
typedef u32 Handle; ///< Kernel object handle.
|
||||||
typedef u32 Result; ///< Function error code result type.
|
typedef u32 Result; ///< Function error code result type.
|
||||||
|
|
||||||
|
#define INVALID_HANDLE ((Handle) 0)
|
||||||
|
#define CUR_PROCESS_HANDLE ((Handle) 0xFFFF8001)
|
||||||
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
typedef int bool;
|
typedef int bool;
|
||||||
#define true 1
|
#define true 1
|
||||||
|
|
|
@ -38,6 +38,12 @@ void usleep(u64 ticks);
|
||||||
void msleep(u64 milliseconds);
|
void msleep(u64 milliseconds);
|
||||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||||
|
|
||||||
|
static inline void *armGetTls(void) {
|
||||||
|
void *ret;
|
||||||
|
__asm__ __volatile__("MRS %x[data], TPIDRRO_EL0" : [data]"=r"(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
extern volatile emuMMC_ctx_t emuMMC_ctx;
|
extern volatile emuMMC_ctx_t emuMMC_ctx;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue