git subrepo pull --force emummc
subrepo: subdir: "emummc" merged: "2fc47cbb8" upstream: origin: "https://github.com/lulle2007200/emuMMC.git" branch: "develop" commit: "2fc47cbb8" git-subrepo: version: "0.4.9" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "30db3b8"
This commit is contained in:
95
emummc/source/nx/smc.c
vendored
95
emummc/source/nx/smc.c
vendored
@@ -22,6 +22,7 @@ void smcRebootToIramPayload(void)
|
||||
SecmonArgs args;
|
||||
args.X[0] = 0xC3000401; /* smcSetConfig */
|
||||
args.X[1] = SplConfigItem_NeedsReboot; /* Exosphere reboot */
|
||||
args.X[2] = 0;
|
||||
args.X[3] = 2; /* Perform reboot to payload at 0x40010000 in IRAM. */
|
||||
svcCallSecureMonitor(&args);
|
||||
}
|
||||
@@ -40,22 +41,20 @@ Result smcGetConfig(SplConfigItem config_item, u64 *out_config)
|
||||
SecmonArgs args;
|
||||
args.X[0] = 0xC3000002; /* smcGetConfig */
|
||||
args.X[1] = (u64)config_item; /* config item */
|
||||
Result rc = svcCallSecureMonitor(&args);
|
||||
if (rc == 0)
|
||||
svcCallSecureMonitor(&args);
|
||||
Result rc = 0;
|
||||
if (args.X[0] == 0)
|
||||
{
|
||||
if (args.X[0] == 0)
|
||||
if (out_config)
|
||||
{
|
||||
if (out_config)
|
||||
{
|
||||
*out_config = args.X[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
*out_config = args.X[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -108,14 +107,12 @@ Result smcCopyToIram(uintptr_t iram_addr, const void *src_addr, u32 size)
|
||||
args.X[2] = (u64)iram_addr; /* IRAM address */
|
||||
args.X[3] = size; /* Amount to copy */
|
||||
args.X[4] = 1; /* 1 = Write */
|
||||
Result rc = svcCallSecureMonitor(&args);
|
||||
if (rc == 0)
|
||||
svcCallSecureMonitor(&args);
|
||||
Result rc = 0;
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -128,14 +125,12 @@ Result smcCopyFromIram(void *dst_addr, uintptr_t iram_addr, u32 size)
|
||||
args.X[2] = (u64)iram_addr; /* IRAM address */
|
||||
args.X[3] = size; /* Amount to copy */
|
||||
args.X[4] = 0; /* 0 = Read */
|
||||
Result rc = svcCallSecureMonitor(&args);
|
||||
if (rc == 0)
|
||||
svcCallSecureMonitor(&args);
|
||||
Result rc = 0;
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -147,14 +142,12 @@ Result smcReadWriteRegister(u32 phys_addr, u32 value, u32 mask)
|
||||
args.X[1] = phys_addr; /* MMIO address */
|
||||
args.X[2] = mask; /* mask */
|
||||
args.X[3] = value; /* value */
|
||||
Result rc = svcCallSecureMonitor(&args);
|
||||
if (rc == 0)
|
||||
svcCallSecureMonitor(&args);
|
||||
Result rc = 0;
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -165,18 +158,16 @@ Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg,
|
||||
args.X[0] = 0xF0000404; /* smcAmsGetEmunandConfig */
|
||||
args.X[1] = mmc_id;
|
||||
args.X[2] = (u64)out_paths; /* out path */
|
||||
Result rc = svcCallSecureMonitor(&args);
|
||||
svcCallSecureMonitor(&args);
|
||||
Result rc = 0;
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
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(out_cfg, &args.X[1], sizeof(*out_cfg));
|
||||
}
|
||||
memcpy(out_cfg, &args.X[1], sizeof(*out_cfg));
|
||||
}
|
||||
return rc;
|
||||
|
||||
@@ -187,18 +178,16 @@ Result smcGenerateRandomBytes(void *dst, u32 size)
|
||||
SecmonArgs args;
|
||||
args.X[0] = 0xC3000006; /* smcGenerateRandomBytes */
|
||||
args.X[1] = size;
|
||||
Result rc = svcCallSecureMonitor(&args);
|
||||
svcCallSecureMonitor(&args);
|
||||
Result rc = 0;
|
||||
if (args.X[0] != 0)
|
||||
{
|
||||
/* SPL result n = SMC result n */
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
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);
|
||||
}
|
||||
memcpy(dst, &args.X[1], size);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
16
emummc/source/nx/smc.h
vendored
16
emummc/source/nx/smc.h
vendored
@@ -4,8 +4,7 @@
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../utils/types.h"
|
||||
#include "svc.h"
|
||||
#include <switch/kernel/svc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -81,6 +80,18 @@ typedef struct {
|
||||
};
|
||||
} exo_emummc_config_t;
|
||||
|
||||
typedef char exo_emummc_path_t[0x80];
|
||||
|
||||
typedef struct {
|
||||
union{
|
||||
exo_emummc_path_t paths[2];
|
||||
struct{
|
||||
exo_emummc_path_t storage_path;
|
||||
exo_emummc_path_t nintendo_path;
|
||||
};
|
||||
};
|
||||
}exo_emummc_paths_t;
|
||||
|
||||
Result smcGetConfig(SplConfigItem config_item, u64 *out_config);
|
||||
|
||||
SplHardwareType splGetHardwareType(void);
|
||||
@@ -88,6 +99,7 @@ SplSocType splGetSocType(void);
|
||||
|
||||
void smcRebootToRcm(void);
|
||||
void smcRebootToIramPayload(void);
|
||||
void smcRebootToFatalError(void);
|
||||
void smcPerformShutdown(void);
|
||||
|
||||
Result smcCopyToIram(uintptr_t iram_addr, const void *src_addr, u32 size);
|
||||
|
||||
220
emummc/source/nx/svc.h
vendored
220
emummc/source/nx/svc.h
vendored
@@ -1,220 +0,0 @@
|
||||
/**
|
||||
* @file svc.h
|
||||
* @brief Wrappers for kernel syscalls.
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../utils/types.h"
|
||||
|
||||
/// Memory information structure.
|
||||
typedef struct {
|
||||
u64 addr; ///< Base address.
|
||||
u64 size; ///< Size.
|
||||
u32 type; ///< Memory type (see lower 8 bits of \ref MemoryState).
|
||||
u32 attr; ///< Memory attributes (see \ref MemoryAttribute).
|
||||
u32 perm; ///< Memory permissions (see \ref Permission).
|
||||
u32 device_refcount; ///< Device reference count.
|
||||
u32 ipc_refcount; ///< IPC reference count.
|
||||
u32 padding; ///< Padding.
|
||||
} MemoryInfo;
|
||||
|
||||
/// Memory permission bitmasks.
|
||||
typedef enum {
|
||||
Perm_None = 0, ///< No permissions.
|
||||
Perm_R = BIT(0), ///< Read permission.
|
||||
Perm_W = BIT(1), ///< Write permission.
|
||||
Perm_X = BIT(2), ///< Execute permission.
|
||||
Perm_Rw = Perm_R | Perm_W, ///< Read/write permissions.
|
||||
Perm_Rx = Perm_R | Perm_X, ///< Read/execute permissions.
|
||||
Perm_DontCare = BIT(28), ///< Don't care
|
||||
} Permission;
|
||||
|
||||
/// Secure monitor arguments.
|
||||
typedef struct {
|
||||
u64 X[8]; ///< Values of X0 through X7.
|
||||
} SecmonArgs;
|
||||
|
||||
_Static_assert(sizeof(SecmonArgs) == 0x40, "SecmonArgs definition");
|
||||
|
||||
#define DeviceName_SDMMC1A 19
|
||||
#define DeviceName_SDMMC2A 20
|
||||
#define DeviceName_SDMMC3A 21
|
||||
#define DeviceName_SDMMC4A 22
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Returns a virtual address mapped to a given IO range.
|
||||
* @return Result code.
|
||||
* @note Syscall number 0x55.
|
||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||
* @warning Only exists on [10.0.0+]. For older versions use \ref svcLegacyQueryIoMapping.
|
||||
*/
|
||||
Result svcQueryIoMapping(u64* virtaddr, u64* out_size, u64 physaddr, u64 size);
|
||||
|
||||
/**
|
||||
* @brief Returns a virtual address mapped to a given IO range.
|
||||
* @return Result code.
|
||||
* @note Syscall number 0x55.
|
||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||
* @warning Only exists on [1.0.0-9.2.0]. For newer versions use \ref svcQueryIoMapping.
|
||||
*/
|
||||
Result svcLegacyQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
|
||||
|
||||
/**
|
||||
* @brief Attaches a device address space to a device.
|
||||
* @return Result code.
|
||||
* @note Syscall number 0x57.
|
||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||
*/
|
||||
Result svcAttachDeviceAddressSpace(u64 device, Handle handle);
|
||||
|
||||
/**
|
||||
* @brief Query information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address.
|
||||
* @param[out] meminfo_ptr \ref MemoryInfo structure which will be filled in.
|
||||
* @param[out] pageinfo Page information which will be filled in.
|
||||
* @param[in] addr Address to query.
|
||||
* @return Result code.
|
||||
* @note Syscall number 0x06.
|
||||
*/
|
||||
Result svcQueryMemory(MemoryInfo* meminfo_ptr, u32 *pageinfo, u64 addr);
|
||||
|
||||
/**
|
||||
* @brief Sets the memory permissions for the specified memory with the supplied process handle.
|
||||
* @param[in] proc Process handle.
|
||||
* @param[in] addr Address of the memory.
|
||||
* @param[in] size Size of the memory.
|
||||
* @param[in] perm Permissions (see \ref Permission).
|
||||
* @return Result code.
|
||||
* @remark This returns an error (0xD801) when \p perm is >0x5, hence -WX and RWX are not allowed.
|
||||
* @note Syscall number 0x73.
|
||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||
*/
|
||||
Result svcSetProcessMemoryPermission(Handle proc, u64 addr, u64 size, u32 perm);
|
||||
|
||||
/**
|
||||
* @brief Set the memory permissions of a (page-aligned) range of memory.
|
||||
* @param[in] addr Start address of the range.
|
||||
* @param[in] size Size of the range, in bytes.
|
||||
* @param[in] perm Permissions (see \ref Permission).
|
||||
* @return Result code.
|
||||
* @remark Perm_X is not allowed. Setting write-only is not allowed either (Perm_W).
|
||||
* This can be used to move back and forth between Perm_None, Perm_R and Perm_Rw.
|
||||
* @note Syscall number 0x01.
|
||||
*/
|
||||
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).
|
||||
* @param regs Arguments to pass to the secure monitor.
|
||||
* @return Return value from the secure monitor.
|
||||
* @note Syscall number 0x7F.
|
||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||
*/
|
||||
u64 svcCallSecureMonitor(SecmonArgs* regs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
///@}
|
||||
136
emummc/source/nx/svc.s
vendored
136
emummc/source/nx/svc.s
vendored
@@ -1,136 +0,0 @@
|
||||
/**
|
||||
* @file svc.s
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
|
||||
.macro SVC_BEGIN name
|
||||
.section .text.\name, "ax", %progbits
|
||||
.global \name
|
||||
.type \name, %function
|
||||
.align 2
|
||||
.cfi_startproc
|
||||
\name:
|
||||
.endm
|
||||
|
||||
.macro SVC_END
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
SVC_BEGIN svcQueryIoMapping
|
||||
STP X0, X1, [SP, #-16]!
|
||||
SVC 0x55
|
||||
LDP X3, X4, [SP], #16
|
||||
STR X1, [X3]
|
||||
STR X2, [X4]
|
||||
RET
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcLegacyQueryIoMapping
|
||||
STR X0, [SP, #-16]!
|
||||
SVC 0x55
|
||||
LDR X2, [SP], #16
|
||||
STR X1, [X2]
|
||||
RET
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcAttachDeviceAddressSpace
|
||||
SVC 0x57
|
||||
RET
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcQueryMemory
|
||||
STR X1, [SP, #-16]!
|
||||
SVC 0x6
|
||||
LDR X2, [SP], #16
|
||||
STR W1, [X2]
|
||||
RET
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcSetMemoryPermission
|
||||
SVC 0x2
|
||||
RET
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcSetProcessMemoryPermission
|
||||
SVC 0x73
|
||||
RET
|
||||
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
|
||||
STR X0, [SP, #-16]!
|
||||
MOV X8, X0
|
||||
LDP X0, X1, [X8]
|
||||
LDP X2, X3, [X8, #0x10]
|
||||
LDP X4, X5, [X8, #0x20]
|
||||
LDP X6, X7, [X8, #0x30]
|
||||
SVC 0x7F
|
||||
LDR X8, [SP], #16
|
||||
STP X0, X1, [X8]
|
||||
STP X2, X3, [X8, #0x10]
|
||||
STP X4, X5, [X8, #0x20]
|
||||
STP X6, X7, [X8, #0x30]
|
||||
RET
|
||||
SVC_END
|
||||
Reference in New Issue
Block a user