Minor changes

* Refactored system/*
* Implemented all of tmem
* Introduced virtmem
This commit is contained in:
plutoo 2017-10-07 15:32:08 +02:00
parent bfc15bb4e1
commit 3926969ebc
20 changed files with 225 additions and 141 deletions

View File

@ -31,11 +31,11 @@ bss_loop:
// initialize system // initialize system
mov x0, x28 mov x0, x28
bl __nx_init bl __libnx_init
// call entrypoint // call entrypoint
mov x0, #0 // argc mov x0, #0 // argc
mov x1, #0 // argv mov x1, #0 // argv
adrp x30, __nx_exit adrp x30, __libnx_exit
add x30, x30, #:lo12:__nx_exit add x30, x30, #:lo12:__libnx_exit
b main b main

View File

@ -16,6 +16,7 @@ extern "C" {
#include <switch/kernel/tmem.h> #include <switch/kernel/tmem.h>
#include <switch/kernel/mutex.h> #include <switch/kernel/mutex.h>
#include <switch/kernel/virtmem.h>
#include <switch/services/sm.h> #include <switch/services/sm.h>
#include <switch/services/bsd.h> #include <switch/services/bsd.h>

View File

@ -1,14 +1,16 @@
typedef struct { typedef struct {
Handle MemHandle; Handle MemHandle;
size_t Size; size_t Size;
Permission Perm;
void* SourceAddr;
void* MappedAddr;
} TransferMemory; } TransferMemory;
typedef enum {
PERM_NONE = 0,
PERM_R = 1,
PERM_RW = 3
} Permission;
Result tmemCreate(TransferMemory* t, size_t size, Permission perm); 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);

View File

@ -0,0 +1,2 @@
void* virtmemReserve(size_t size);
void virtmemFree(void* addr, size_t size);

View File

@ -19,4 +19,6 @@
((((module)&0x1FF)) | ((description)&0x1FFF)<<9) ((((module)&0x1FF)) | ((description)&0x1FFF)<<9)
#define MODULE_LIBNX 345 #define MODULE_LIBNX 345
#define MODULE_BADRELOC 1 #define LIBNX_BADRELOC 1
#define LIBNX_OUTOFMEM 2
#define LIBNX_ALREADYMAPPED 3

View File

@ -29,8 +29,7 @@ typedef struct {
u32 padding; u32 padding;
} MemInfo; } MemInfo;
typedef struct _regs_t typedef struct {
{
u64 X0; u64 X0;
u64 X1; u64 X1;
u64 X2; u64 X2;
@ -39,11 +38,11 @@ typedef struct _regs_t
u64 X5; u64 X5;
u64 X6; u64 X6;
u64 X7; u64 X7;
} __attribute__((packed)) regs_t; } __attribute__((packed)) SecmonArgs;
Result svcSetHeapSize(void** out_addr, u64 size); Result svcSetHeapSize(void** out_addr, u64 size);
Result svcQueryMemory(MemInfo* meminfo_ptr, u32 *pageinfo, u64 addr); Result svcQueryMemory(MemInfo* meminfo_ptr, u32 *pageinfo, u64 addr);
void svcExitProcess() __attribute__((noreturn)); void NORETURN svcExitProcess();
Result svcSleepThread(u64 nano); Result svcSleepThread(u64 nano);
Result svcCloseHandle(Handle handle); Result svcCloseHandle(Handle handle);
Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm); 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 svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0?
Result svcAcceptSession(Handle *session_handle, Handle port_handle); Result svcAcceptSession(Handle *session_handle, Handle port_handle);
Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout); 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 svcQueryPhysicalAddress(u64 out[3], u64 virtaddr);
Result svcQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size); Result svcQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
Result svcCreateDeviceAddressSpace(Handle *handle, u64 dev_addr, u64 dev_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 svcQueryDebugProcessMemory(MemInfo* meminfo_ptr, u32* pageinfo, Handle debug, u64 addr);
Result svcReadDebugProcessMemory(void* buffer, Handle debug, u64 addr, u64 size); Result svcReadDebugProcessMemory(void* buffer, Handle debug, u64 addr, u64 size);
Result svcManageNamedPort(Handle* portServer, const char* name, s32 maxSessions); Result svcManageNamedPort(Handle* portServer, const char* name, s32 maxSessions);
u64 svcCallSecureMonitor(regs_t *regs); u64 svcCallSecureMonitor(SecmonArgs* regs);

View File

@ -43,6 +43,14 @@ typedef u32 Result; ///< Function result.
typedef void (*ThreadFunc)(void *); ///< Thread entrypoint function. typedef void (*ThreadFunc)(void *); ///< Thread entrypoint function.
typedef void (*voidfn)(void); 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. /// Creates a bitmask from a bit number.
#define BIT(n) (1U<<(n)) #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. /// Packs a struct (and other types?) so it won't include padding bytes.
#define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))
#define NORETURN __attribute__((noreturn))
#define IGNORE_ARG(x) (void)(x)
#ifndef LIBCTRU_NO_DEPRECATION #ifndef LIBCTRU_NO_DEPRECATION
/// Flags a function as deprecated. /// Flags a function as deprecated.
#define DEPRECATED __attribute__ ((deprecated)) #define DEPRECATED __attribute__ ((deprecated))
@ -59,3 +70,4 @@ typedef void (*voidfn)(void);
#define DEPRECATED #define DEPRECATED
#endif #endif
#define INVALID_HANDLE ((Handle) -1)

View File

@ -118,6 +118,16 @@ SVC_BEGIN svcReplyAndReceive
ret ret
SVC_END SVC_END
SVC_BEGIN svcMapTransferMemory
svc 0x51
ret
SVC_END
SVC_BEGIN svcUnmapTransferMemory
svc 0x52
ret
SVC_END
SVC_BEGIN svcQueryPhysicalAddress SVC_BEGIN svcQueryPhysicalAddress
str x0, [sp, #-16]! str x0, [sp, #-16]!
svc 0x54 svc 0x54

View File

@ -1,21 +1,98 @@
// Copyright 2017 plutoo
#include <switch.h> #include <switch.h>
Result tmemCreate(TransferMemory* t, size_t size, Permission perm) { Result tmemCreate(TransferMemory* t, size_t size, Permission perm)
t->Size = size; {
Result rc = 0; Result rc = 0;
void* addr = heapAllocPages(size);
if (addr == NULL) t->MemHandle = INVALID_HANDLE;
rc = -1; 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)) { if (R_SUCCEEDED(rc)) {
rc = svcCreateTransferMemory(&t->MemHandle, addr, size, perm); rc = svcCreateTransferMemory(&t->MemHandle, t->SourceAddr, size, perm);
} }
return rc; return rc;
} }
Result tmemClose(TransferMemory* t) { void tmemLoadRemote(TransferMemory* t, Handle handle, size_t size, Permission perm)
return svcCloseHandle(t->MemHandle); {
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;
} }

View 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;
}

View File

@ -27,7 +27,7 @@ void fatalSimple(Result err) {
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 1; raw->cmd_id = 0;
raw->result = err; raw->result = err;
raw->unknown = 0; raw->unknown = 0;

View File

@ -49,10 +49,8 @@ Result smInitialize() {
return rc; return rc;
} }
void smExit(void) void smExit(void) {
{ if(smHasInitialized()) {
if(smHasInitialized())
{
svcCloseHandle(g_smHandle); svcCloseHandle(g_smHandle);
g_smHandle = -1; g_smHandle = -1;
} }

View File

@ -1,7 +0,0 @@
#include <switch/types.h>
#include <switch/services/sm.h>
void __attribute__((weak)) __appExit(void) {
// Initialize services
smExit();
}

View File

@ -1,7 +0,0 @@
#include <switch/types.h>
#include <switch/services/sm.h>
void __attribute__((weak)) __appInit(void) {
// Initialize services
smInitialize();
}

View File

@ -20,7 +20,7 @@ void __nx_dynamic(uintptr_t base, const Elf64_Dyn* dyn)
} }
if (rela == NULL) if (rela == NULL)
fatalSimple(MAKERESULT(MODULE_LIBNX, MODULE_BADRELOC)); fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_BADRELOC));
for (; relasz--; rela++) for (; relasz--; rela++)
{ {

62
nx/source/system/init.c Normal file
View 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();
}

View File

@ -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();
}

View File

@ -1,7 +0,0 @@
#include <switch/types.h>
#include <switch/svc.h>
void __attribute__((weak)) __attribute__((noreturn)) __libnx_exit(int rc)
{
svcExitProcess();
}

View File

@ -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);*/
}

View File

@ -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