mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Minor changes
* Refactored system/* * Implemented all of tmem * Introduced virtmem
This commit is contained in:
parent
bfc15bb4e1
commit
3926969ebc
@ -31,11 +31,11 @@ bss_loop:
|
||||
|
||||
// initialize system
|
||||
mov x0, x28
|
||||
bl __nx_init
|
||||
bl __libnx_init
|
||||
|
||||
// call entrypoint
|
||||
mov x0, #0 // argc
|
||||
mov x1, #0 // argv
|
||||
adrp x30, __nx_exit
|
||||
add x30, x30, #:lo12:__nx_exit
|
||||
adrp x30, __libnx_exit
|
||||
add x30, x30, #:lo12:__libnx_exit
|
||||
b main
|
||||
|
@ -16,6 +16,7 @@ extern "C" {
|
||||
|
||||
#include <switch/kernel/tmem.h>
|
||||
#include <switch/kernel/mutex.h>
|
||||
#include <switch/kernel/virtmem.h>
|
||||
|
||||
#include <switch/services/sm.h>
|
||||
#include <switch/services/bsd.h>
|
||||
|
@ -1,14 +1,16 @@
|
||||
typedef struct {
|
||||
Handle MemHandle;
|
||||
size_t Size;
|
||||
Handle MemHandle;
|
||||
size_t Size;
|
||||
Permission Perm;
|
||||
void* SourceAddr;
|
||||
void* MappedAddr;
|
||||
} TransferMemory;
|
||||
|
||||
typedef enum {
|
||||
PERM_NONE = 0,
|
||||
PERM_R = 1,
|
||||
PERM_RW = 3
|
||||
} Permission;
|
||||
|
||||
Result tmemCreate(TransferMemory* t, size_t size, Permission perm);
|
||||
Result tmemClose(TransferMemory* t);
|
||||
void tmemLoadRemote(TransferMemory* t, Handle handle, size_t size, Permission perm);
|
||||
|
||||
Result tmemMap(TransferMemory* t);
|
||||
Result tmemUnmap(TransferMemory* t);
|
||||
void* tmemGetAddr(TransferMemory* t);
|
||||
|
||||
Result tmemClose(TransferMemory* t);
|
||||
|
2
nx/include/switch/kernel/virtmem.h
Normal file
2
nx/include/switch/kernel/virtmem.h
Normal file
@ -0,0 +1,2 @@
|
||||
void* virtmemReserve(size_t size);
|
||||
void virtmemFree(void* addr, size_t size);
|
@ -18,5 +18,7 @@
|
||||
#define MAKERESULT(module,description) \
|
||||
((((module)&0x1FF)) | ((description)&0x1FFF)<<9)
|
||||
|
||||
#define MODULE_LIBNX 345
|
||||
#define MODULE_BADRELOC 1
|
||||
#define MODULE_LIBNX 345
|
||||
#define LIBNX_BADRELOC 1
|
||||
#define LIBNX_OUTOFMEM 2
|
||||
#define LIBNX_ALREADYMAPPED 3
|
||||
|
@ -29,8 +29,7 @@ typedef struct {
|
||||
u32 padding;
|
||||
} MemInfo;
|
||||
|
||||
typedef struct _regs_t
|
||||
{
|
||||
typedef struct {
|
||||
u64 X0;
|
||||
u64 X1;
|
||||
u64 X2;
|
||||
@ -39,11 +38,11 @@ typedef struct _regs_t
|
||||
u64 X5;
|
||||
u64 X6;
|
||||
u64 X7;
|
||||
} __attribute__((packed)) regs_t;
|
||||
} __attribute__((packed)) SecmonArgs;
|
||||
|
||||
Result svcSetHeapSize(void** out_addr, u64 size);
|
||||
Result svcQueryMemory(MemInfo* meminfo_ptr, u32 *pageinfo, u64 addr);
|
||||
void svcExitProcess() __attribute__((noreturn));
|
||||
void NORETURN svcExitProcess();
|
||||
Result svcSleepThread(u64 nano);
|
||||
Result svcCloseHandle(Handle handle);
|
||||
Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm);
|
||||
@ -57,6 +56,8 @@ Result svcGetInfo(u64* out, u64 id0, Handle handle, u64 id1);
|
||||
Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0?
|
||||
Result svcAcceptSession(Handle *session_handle, Handle port_handle);
|
||||
Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout);
|
||||
Result svcMapTransferMemory(Handle tmem_handle, void* addr, size_t size, u32 perm);
|
||||
Result svcUnmapTransferMemory(Handle tmem_handle, void* addr, size_t size);
|
||||
Result svcQueryPhysicalAddress(u64 out[3], u64 virtaddr);
|
||||
Result svcQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
|
||||
Result svcCreateDeviceAddressSpace(Handle *handle, u64 dev_addr, u64 dev_size);
|
||||
@ -69,4 +70,4 @@ Result svcContinueDebugEvent(Handle debug, u32 flags, u64 unk);
|
||||
Result svcQueryDebugProcessMemory(MemInfo* meminfo_ptr, u32* pageinfo, Handle debug, u64 addr);
|
||||
Result svcReadDebugProcessMemory(void* buffer, Handle debug, u64 addr, u64 size);
|
||||
Result svcManageNamedPort(Handle* portServer, const char* name, s32 maxSessions);
|
||||
u64 svcCallSecureMonitor(regs_t *regs);
|
||||
u64 svcCallSecureMonitor(SecmonArgs* regs);
|
||||
|
@ -43,6 +43,14 @@ typedef u32 Result; ///< Function result.
|
||||
typedef void (*ThreadFunc)(void *); ///< Thread entrypoint function.
|
||||
typedef void (*voidfn)(void);
|
||||
|
||||
typedef enum {
|
||||
PERM_NONE = 0,
|
||||
PERM_R = 1,
|
||||
PERM_W = 2,
|
||||
PERM_RW = PERM_R | PERM_W,
|
||||
PERM_DONTCARE = 0x10000000
|
||||
} Permission;
|
||||
|
||||
/// Creates a bitmask from a bit number.
|
||||
#define BIT(n) (1U<<(n))
|
||||
|
||||
@ -51,6 +59,9 @@ typedef void (*voidfn)(void);
|
||||
/// Packs a struct (and other types?) so it won't include padding bytes.
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define IGNORE_ARG(x) (void)(x)
|
||||
|
||||
#ifndef LIBCTRU_NO_DEPRECATION
|
||||
/// Flags a function as deprecated.
|
||||
#define DEPRECATED __attribute__ ((deprecated))
|
||||
@ -59,3 +70,4 @@ typedef void (*voidfn)(void);
|
||||
#define DEPRECATED
|
||||
#endif
|
||||
|
||||
#define INVALID_HANDLE ((Handle) -1)
|
||||
|
@ -118,6 +118,16 @@ SVC_BEGIN svcReplyAndReceive
|
||||
ret
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcMapTransferMemory
|
||||
svc 0x51
|
||||
ret
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcUnmapTransferMemory
|
||||
svc 0x52
|
||||
ret
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcQueryPhysicalAddress
|
||||
str x0, [sp, #-16]!
|
||||
svc 0x54
|
||||
|
@ -1,21 +1,98 @@
|
||||
// Copyright 2017 plutoo
|
||||
#include <switch.h>
|
||||
|
||||
Result tmemCreate(TransferMemory* t, size_t size, Permission perm) {
|
||||
t->Size = size;
|
||||
|
||||
Result tmemCreate(TransferMemory* t, size_t size, Permission perm)
|
||||
{
|
||||
Result rc = 0;
|
||||
void* addr = heapAllocPages(size);
|
||||
|
||||
if (addr == NULL)
|
||||
rc = -1;
|
||||
t->MemHandle = INVALID_HANDLE;
|
||||
t->Size = size;
|
||||
t->Perm = perm;
|
||||
t->MappedAddr = NULL;
|
||||
t->SourceAddr = heapAllocPages(size);
|
||||
|
||||
if (t->SourceAddr == NULL) {
|
||||
rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
rc = svcCreateTransferMemory(&t->MemHandle, addr, size, perm);
|
||||
rc = svcCreateTransferMemory(&t->MemHandle, t->SourceAddr, size, perm);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result tmemClose(TransferMemory* t) {
|
||||
return svcCloseHandle(t->MemHandle);
|
||||
void tmemLoadRemote(TransferMemory* t, Handle handle, size_t size, Permission perm)
|
||||
{
|
||||
t->MemHandle = handle;
|
||||
t->Size = size;
|
||||
t->Perm = perm;
|
||||
t->MappedAddr = NULL;
|
||||
t->SourceAddr = NULL;
|
||||
}
|
||||
|
||||
Result tmemMap(TransferMemory* t)
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
if (t->MappedAddr == NULL)
|
||||
{
|
||||
void* addr = virtmemReserve(t->Size);
|
||||
|
||||
rc = svcMapTransferMemory(t->MemHandle, addr, t->Size, t->Perm);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
t->MappedAddr = addr;
|
||||
}
|
||||
else {
|
||||
virtmemFree(addr, t->Size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
rc = LIBNX_ALREADYMAPPED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result tmemUnmap(TransferMemory* t)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
rc = svcUnmapTransferMemory(t->MemHandle, t->MappedAddr, t->Size);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
t->MappedAddr = NULL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void* tmemGetAddr(TransferMemory* t) {
|
||||
return t->MappedAddr;
|
||||
}
|
||||
|
||||
Result tmemClose(TransferMemory* t)
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
if (t->SourceAddr != NULL) {
|
||||
// todo: Free is currently broken for page-aligned allocs.
|
||||
//heapFree(t->SourceAddr);
|
||||
}
|
||||
|
||||
if (t->MappedAddr != NULL) {
|
||||
rc = tmemUnmap(t);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (t->MemHandle != INVALID_HANDLE) {
|
||||
rc = svcCloseHandle(t->MemHandle);
|
||||
}
|
||||
|
||||
t->SourceAddr = NULL;
|
||||
t->MemHandle = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
21
nx/source/kernel/virtmem.c
Normal file
21
nx/source/kernel/virtmem.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <switch.h>
|
||||
|
||||
static u8* g_VirtBase;
|
||||
|
||||
void virtmemSetup() {
|
||||
// TODO: Implement this.
|
||||
}
|
||||
|
||||
void* virtmemReserve(size_t size) {
|
||||
void* ret = g_VirtBase;
|
||||
|
||||
size = (size + 0xFFF) &~ 0xFFF;
|
||||
g_VirtBase += size + 0x1000;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void virtmemFree(void* addr, size_t size) {
|
||||
(void) addr;
|
||||
(void) size;
|
||||
}
|
@ -27,7 +27,7 @@ void fatalSimple(Result err) {
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 1;
|
||||
raw->cmd_id = 0;
|
||||
raw->result = err;
|
||||
raw->unknown = 0;
|
||||
|
||||
|
@ -49,13 +49,11 @@ Result smInitialize() {
|
||||
return rc;
|
||||
}
|
||||
|
||||
void smExit(void)
|
||||
{
|
||||
if(smHasInitialized())
|
||||
{
|
||||
svcCloseHandle(g_smHandle);
|
||||
g_smHandle = -1;
|
||||
}
|
||||
void smExit(void) {
|
||||
if(smHasInitialized()) {
|
||||
svcCloseHandle(g_smHandle);
|
||||
g_smHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static u64 _EncodeName(const char* name) {
|
||||
|
@ -1,7 +0,0 @@
|
||||
#include <switch/types.h>
|
||||
#include <switch/services/sm.h>
|
||||
|
||||
void __attribute__((weak)) __appExit(void) {
|
||||
// Initialize services
|
||||
smExit();
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include <switch/types.h>
|
||||
#include <switch/services/sm.h>
|
||||
|
||||
void __attribute__((weak)) __appInit(void) {
|
||||
// Initialize services
|
||||
smInitialize();
|
||||
}
|
@ -20,7 +20,7 @@ void __nx_dynamic(uintptr_t base, const Elf64_Dyn* dyn)
|
||||
}
|
||||
|
||||
if (rela == NULL)
|
||||
fatalSimple(MAKERESULT(MODULE_LIBNX, MODULE_BADRELOC));
|
||||
fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_BADRELOC));
|
||||
|
||||
for (; relasz--; rela++)
|
||||
{
|
||||
|
62
nx/source/system/init.c
Normal file
62
nx/source/system/init.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include <switch.h>
|
||||
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/reent.h>
|
||||
#include <string.h>
|
||||
|
||||
void __nx_exit(int rc);
|
||||
|
||||
void virtmemSetup();
|
||||
void heapSetup();
|
||||
|
||||
void __attribute__((weak)) __appInit(void)
|
||||
{
|
||||
// Initialize default services.
|
||||
smInitialize();
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __appExit(void)
|
||||
{
|
||||
// Cleanup default services.
|
||||
smExit();
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __libnx_init(void)
|
||||
{
|
||||
// Called by crt0.
|
||||
|
||||
// Newlib initialization goes here.
|
||||
void exitImpl(int rc);
|
||||
__syscalls.exit = exitImpl;
|
||||
|
||||
// Libnx initialization goes here.
|
||||
virtmemSetup();
|
||||
heapSetup();
|
||||
|
||||
// Initialize services.
|
||||
__appInit();
|
||||
|
||||
// Call constructors.
|
||||
void __libc_init_array(void);
|
||||
__libc_init_array();
|
||||
}
|
||||
|
||||
void __attribute__((weak)) NORETURN __libnx_exit(void)
|
||||
{
|
||||
// Call destructors.
|
||||
void __libc_fini_array(void);
|
||||
__libc_fini_array();
|
||||
|
||||
// Clean up services.
|
||||
__appExit();
|
||||
|
||||
svcExitProcess();
|
||||
while(1);
|
||||
}
|
||||
|
||||
void NORETURN exitImpl(int rc)
|
||||
{
|
||||
__libnx_exit();
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <switch/types.h>
|
||||
#include <switch/svc.h>
|
||||
|
||||
void __system_initSyscalls(void);
|
||||
|
||||
void heapSetup();
|
||||
|
||||
void __attribute__((weak)) __libnx_init(void)
|
||||
{
|
||||
// Initialize newlib support system calls
|
||||
__system_initSyscalls();
|
||||
|
||||
heapSetup();
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include <switch/types.h>
|
||||
#include <switch/svc.h>
|
||||
|
||||
void __attribute__((weak)) __attribute__((noreturn)) __libnx_exit(int rc)
|
||||
{
|
||||
svcExitProcess();
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/reent.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <switch/types.h>
|
||||
#include <switch/svc.h>
|
||||
|
||||
void __nx_exit(int rc);
|
||||
|
||||
//TODO
|
||||
/*extern const u8 __tdata_lma[];
|
||||
extern const u8 __tdata_lma_end[];
|
||||
extern u8 __tls_start[];
|
||||
|
||||
static struct _reent* __nx_get_reent()
|
||||
{
|
||||
ThreadVars* tv = getThreadVars();
|
||||
if (tv->magic != THREADVARS_MAGIC)
|
||||
{
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
for (;;);
|
||||
}
|
||||
return tv->reent;
|
||||
}
|
||||
*/
|
||||
|
||||
void __system_initSyscalls(void)
|
||||
{
|
||||
// Register newlib syscalls
|
||||
__syscalls.exit = __nx_exit;
|
||||
//__syscalls.getreent = __nx_get_reent;
|
||||
|
||||
// Initialize thread vars for the main thread (TODO)
|
||||
/*ThreadVars* tv = getThreadVars();
|
||||
tv->magic = THREADVARS_MAGIC;
|
||||
tv->reent = _impure_ptr;
|
||||
tv->thread_ptr = NULL;
|
||||
tv->tls_tp = __tls_start-8; // ARM ELF TLS ABI mandates an 8-byte header
|
||||
|
||||
u32 tls_size = __tdata_lma_end - __tdata_lma;
|
||||
if (tls_size)
|
||||
memcpy(__tls_start, __tdata_lma, tls_size);*/
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
.text
|
||||
.global __nx_init
|
||||
.type __nx_init, %function
|
||||
|
||||
__nx_init:
|
||||
stp x29, x30, [sp, #-16]!
|
||||
bl __libnx_init
|
||||
bl __appInit
|
||||
bl __libc_init_array
|
||||
ldp x29, x30, [sp], #16
|
||||
ret
|
||||
|
||||
.global __nx_exit
|
||||
.type __nx_exit, %function
|
||||
|
||||
__nx_exit:
|
||||
bl __libc_fini_array
|
||||
bl __appExit
|
||||
b __libnx_exit
|
Loading…
Reference in New Issue
Block a user