Remove test directory

This commit is contained in:
rkx1209 2018-07-16 21:32:03 +09:00
parent 44451dedb3
commit 968a95b3d5
33 changed files with 0 additions and 32971 deletions

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "test/newlib"]
path = test/newlib
url = https://github.com/reswitched/newlib

View file

@ -1,89 +0,0 @@
LD := ld.lld
CC := clang
AS := llvm-mc
LD_FLAGS := -Bsymbolic --shared --no-gc-sections --no-undefined -T link.T
CC_FLAGS := -g -fPIC -ffreestanding -fexceptions -target aarch64-none-linux-gnu -O0 -mtune=cortex-a53 -I include/ -I newlib/newlib/libc/include/ -I newlib/newlib/libc/sys/switch/include/
AS_FLAGS := -arch=aarch64 -triple aarch64-none-switch
PYTHON2 := python2
MEPHISTO := ctu
RUBY := ruby
NSEMU_TESTS := simple_disas malloc bsd_ai_packing bsd sfdnsres
libtransistor_OBJECTS := build/lib/svc.o build/lib/ipc.o build/lib/tls.o build/lib/util.o build/lib/ipc/sm.o build/lib/ipc/bsd.o
# for building newlib
export AR_FOR_TARGET = llvm-ar
export AS_FOR_TARGET = llvm-mc -arch=aarch64 -mattr=+neon
export LD_FOR_TARGET = ld.lld
export RANLIB_FOR_TARGET = llvm-ranlib
export CC_FOR_TARGET = clang -g -fPIC -ffreestanding -fexceptions -target aarch64-none-linux-gnu -O0 -mtune=cortex-a53 -ccc-gcc-name aarch64-switch-gcc -Wno-unused-command-line-argument
.SUFFIXES: # disable built-in rules
all: build/lib/libtransistor.nro.a build/lib/libtransistor.nso.a $(addprefix build/test/test_,$(addsuffix .nro,$(NSEMU_TESTS))) $(addprefix build/test/test_,$(addsuffix .nso,$(NSEMU_TESTS))) $(addprefix build/test/test_,$(addsuffix .nro.so,$(NSEMU_TESTS))) $(addprefix build/test/test_,$(addsuffix .nso.so,$(NSEMU_TESTS)))
run_tests: run_malloc_test run_bsd_ai_packing_test run_bsd_test run_sfdnsres_test
run_bsd_test: build/test/test_bsd.nro test_helpers/bsd.rb
$(RUBY) test_helpers/bsd.rb $(MEPHISTO)
run_sfdnsres_test: build/test/test_sfdnsres.nro
$(MEPHISTO) --enable-sockets --load-nro $<
run_%_test: build/test/test_%.nro
$(MEPHISTO) --load-nro $<
build/test/%.o: test/%.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) -c -o $@ $<
build/test/%.o: test/%.S
mkdir -p $(@D)
$(AS) $(AS_FLAGS) $< -filetype=obj -o $@
build/lib/%.o: lib/%.c
mkdir -p $(@D)
$(CC) $(CC_FLAGS) -c -o $@ $<
build/lib/%.o: lib/%.S
mkdir -p $(@D)
$(AS) $(AS_FLAGS) $< -filetype=obj -o $@
build/test/%.nro: build/test/%.nro.so
mkdir -p $(@D)
$(PYTHON2) ./tools/elf2nxo.py $< $@ nro
build/test/%.nso: build/test/%.nso.so
mkdir -p $(@D)
$(PYTHON2) ./tools/elf2nxo.py $< $@ nso
build/test/%.nro.so: build/test/%.o build/lib/libtransistor.nro.a newlib/aarch64-none-switch/newlib/libc.a
mkdir -p $(@D)
$(LD) $(LD_FLAGS) -o $@ $< --whole-archive build/lib/libtransistor.nro.a --no-whole-archive newlib/aarch64-none-switch/newlib/libc.a
build/test/%.nso.so: build/test/%.o build/lib/libtransistor.nso.a newlib/aarch64-none-switch/newlib/libc.a
mkdir -p $(@D)
$(LD) $(LD_FLAGS) -o $@ $< --whole-archive build/lib/libtransistor.nso.a --no-whole-archive newlib/aarch64-none-switch/newlib/libc.a
build/lib/libtransistor.nro.a: build/lib/crt0.nro.o $(libtransistor_OBJECTS)
mkdir -p $(@D)
rm -f $@
ar rcs $@ $+
build/lib/libtransistor.nso.a: build/lib/crt0.nso.o $(libtransistor_OBJECTS)
mkdir -p $(@D)
rm -f $@
ar rcs $@ $+
newlib/Makefile:
cd newlib; ./configure --target=aarch64-none-switch --without-rdimon
newlib/aarch64-none-switch/newlib/libc.a: newlib/Makefile
make -C newlib/
newlib/aarch64-none-switch/libgloss/libnosys/libnosys.a: newlib/aarch64-none-switch/newlib/libc.a
newlib/aarch64-none-switch/libgloss/aarch64/librdimon.a: newlib/aarch64-none-switch/newlib/libc.a
clean:
rm -rf build/lib/* build/test/*

View file

@ -1,41 +0,0 @@
#pragma once
#define LIBTRANSISTOR_RESULT(code) (((code) << 8) | 0xDD)
// Misc
#define LIBTRANSISTOR_ERR_UNSPECIFIED LIBTRANSISTOR_RESULT(1)
#define LIBTRANSISTOR_ERR_UNIMPLEMENTED LIBTRANSISTOR_RESULT(2)
#define LIBTRANSISTOR_ERR_OUT_OF_MEMORY LIBTRANSISTOR_RESULT(3)
// IPC
#define LIBTRANSISTOR_ERR_UNSUPPORTED_BUFFER_TYPE LIBTRANSISTOR_RESULT(1001)
#define LIBTRANSISTOR_ERR_TOO_MANY_BUFFERS LIBTRANSISTOR_RESULT(1002)
#define LIBTRANSISTOR_ERR_INVALID_REQUEST_TYPE LIBTRANSISTOR_RESULT(1003)
#define LIBTRANSISTOR_ERR_TOO_MANY_HANDLES LIBTRANSISTOR_RESULT(1004)
#define LIBTRANSISTOR_ERR_INVALID_BUFFER_ADDRESS LIBTRANSISTOR_RESULT(1005)
#define LIBTRANSISTOR_ERR_INVALID_BUFFER_SIZE LIBTRANSISTOR_RESULT(1006)
#define LIBTRANSISTOR_ERR_INVALID_PROTECTION LIBTRANSISTOR_RESULT(1007)
#define LIBTRANSISTOR_ERR_INVALID_IPC_RESPONSE_TYPE LIBTRANSISTOR_RESULT(1008)
#define LIBTRANSISTOR_ERR_INVALID_IPC_RESPONSE_MAGIC LIBTRANSISTOR_RESULT(1009)
#define LIBTRANSISTOR_ERR_INVALID_RAW_DATA_SIZE LIBTRANSISTOR_RESULT(1010)
#define LIBTRANSISTOR_ERR_UNEXPECTED_RAW_DATA_SIZE LIBTRANSISTOR_RESULT(1011)
#define LIBTRANSISTOR_ERR_UNEXPECTED_PID LIBTRANSISTOR_RESULT(1012)
#define LIBTRANSISTOR_ERR_UNEXPECTED_COPY_HANDLES LIBTRANSISTOR_RESULT(1013)
#define LIBTRANSISTOR_ERR_UNEXPECTED_MOVE_HANDLES LIBTRANSISTOR_RESULT(1014)
#define LIBTRANSISTOR_ERR_ALREADY_A_DOMAIN LIBTRANSISTOR_RESULT(1015)
#define LIBTRANSISTOR_ERR_CANT_SEND_OBJECT_ACROSS_DOMAINS LIBTRANSISTOR_RESULT(1016)
#define LIBTRANSISTOR_ERR_CANT_SEND_DOMAIN_OBJECT_TO_SESSION LIBTRANSISTOR_RESULT(1017)
#define LIBTRANSISTOR_ERR_TOO_MANY_OBJECTS LIBTRANSISTOR_RESULT(1018)
#define LIBTRANSISTOR_ERR_UNEXPECTED_DOMAIN_HEADER_COMMAND LIBTRANSISTOR_RESULT(1018)
#define LIBTRANSISTOR_ERR_UNEXPECTED_OBJECTS LIBTRANSISTOR_RESULT(1019)
#define LIBTRANSISTOR_ERR_CANT_CLOSE_SESSIONS_LIKE_DOMAIN_OBJECTS LIBTRANSISTOR_RESULT(1020)
#define LIBTRANSISTOR_ERR_MALFORMED_CLOSE_REQUEST LIBTRANSISTOR_RESULT(1021)
// SM
#define LIBTRANSISTOR_ERR_SM_NOT_INITIALIZED LIBTRANSISTOR_RESULT(2001)
#define LIBTRANSISTOR_ERR_SM_SERVICE_NAME_TOO_LONG LIBTRANSISTOR_RESULT(2002)
// BSD
#define LIBTRANSISTOR_ERR_BSD_ERRNO_SET LIBTRANSISTOR_RESULT(3001)
#define LIBTRANSISTOR_ERR_BSD_BUFFER_TOO_SMALL LIBTRANSISTOR_RESULT(3002)
#define LIBTRANSISTOR_ERR_BSD_INVALID_MAGIC LIBTRANSISTOR_RESULT(3003)

View file

@ -1,92 +0,0 @@
#pragma once
#include<libtransistor/types.h>
typedef struct {
session_h session;
} ipc_domain_t;
typedef struct {
int32_t object_id; // -1 if this represents a session, >= 0 if this represents a domain object
union {
session_h session; // object_id = -1
ipc_domain_t *domain; // object_id >= 0
};
} ipc_object_t;
typedef struct {
void *addr;
u64 size;
u32 type;
} ipc_buffer_t;
typedef struct {
u32 type;
u32 num_buffers;
ipc_buffer_t **buffers;
u32 request_id;
u32 *raw_data;
u64 raw_data_size; // in BYTES
bool send_pid;
u8 num_copy_handles;
u8 num_move_handles;
u8 num_objects;
handle_t *copy_handles;
handle_t *move_handles;
ipc_object_t *objects;
bool close_object;
} ipc_request_t;
// fill this struct out with what you expect before passing it to ipc_unmarshal
typedef struct {
int num_copy_handles;
int num_move_handles;
int num_objects;
handle_t *copy_handles;
handle_t *move_handles;
ipc_object_t *objects;
int raw_data_size; // in BYTES
u32 *raw_data;
bool has_pid;
u32 *pid;
} ipc_response_fmt_t;
// see ipc.c for actual default values
extern ipc_request_t ipc_default_request;
extern ipc_response_fmt_t ipc_default_response_fmt;
extern ipc_object_t ipc_null_object;
/*
Packs the IPC message described by `rq` and `object` into `buffer`.
*/
result_t ipc_marshal(u32 *buffer, ipc_request_t *rq, ipc_object_t object);
/*
Unpacks the IPC message described by `rs` from `buffer`. `object` should
be the object the request was sent to.
*/
result_t ipc_unmarshal(u32 *buffer, ipc_response_fmt_t *rs, ipc_object_t object);
/*
Send a request described by `rq` to `object` and then unpack the response
*/
result_t ipc_send(ipc_object_t object, ipc_request_t *rq, ipc_response_fmt_t *rs);
/*
Converts `session` to a domain object and initializes `domain`.
Guarenteed to initialize `domain`, making it valid to call `ipc_close_domain`
on the newly initialized domain if this returns != RESULT_OK
*/
result_t ipc_convert_to_domain(ipc_object_t *session, ipc_domain_t *domain);
/*
Closes the `object`
*/
result_t ipc_close(ipc_object_t object);
/*
Closes the whole `domain`
*/
result_t ipc_close_domain(ipc_domain_t domain);

View file

@ -1,31 +0,0 @@
#pragma once
#include<libtransistor/types.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
extern result_t bsd_result;
extern int bsd_errno;
result_t bsd_init();
int bsd_socket(int domain, int type, int protocol);
int bsd_recv(int socket, void *message, size_t length, int flags);
int bsd_send(int socket, const void *data, size_t length, int flags);
int bsd_sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
int bsd_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
int bsd_bind(int socket, const struct sockaddr *address, socklen_t address_len);
int bsd_connect(int socket, const struct sockaddr *address, socklen_t address_len);
int bsd_getsockname(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
int bsd_listen(int socket, int backlog);
int bsd_setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
int bsd_shutdown(int socket, int how);
int bsd_select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout);
int bsd_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
void bsd_freeaddrinfo(struct addrinfo *res);
int bsd_close(int socket);
void bsd_finalize();
result_t bsd_ai_pack(const struct addrinfo *ai, uint8_t *buf, int size);
result_t bsd_ai_unpack(struct addrinfo **ai, const uint8_t *buf, int size);

View file

@ -1,7 +0,0 @@
#pragma once
#include<libtransistor/types.h>
result_t sm_init();
result_t sm_get_service(ipc_object_t *session, char *name);
void sm_finalize();

View file

@ -1,22 +0,0 @@
/**
* @file switch.h
* @brief Central Switch header. Includes all others.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include<libtransistor/types.h>
#include<libtransistor/svc.h>
#include<libtransistor/ipc.h>
#include<libtransistor/tls.h>
#include<libtransistor/util.h>
#include<libtransistor/ipc/sm.h>
#include<libtransistor/ipc/bsd.h>
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,122 +0,0 @@
#pragma once
typedef struct PACKED {
void *base_addr;
u64 size;
u32 memory_type;
u32 memory_attribute;
u32 permission;
u32 device_ref_count;
u32 ipc_ref_count;
u32 padding;
} memory_info_t;
result_t svcSetHeapSize(void **outAddr, u32 size);
result_t svcSetMemoryPermission(void *addr, u64 size, u32 permission);
result_t svcSetMemoryAttribute(void *addr, u64 size, u32 state0, u32 state1);
result_t svcMapMemory(void *dest, void *src, u64 size);
result_t svcUnmapMemory(void *dest, void *src, u64 size);
result_t svcQueryMemory(memory_info_t *memory_info, u32 *page_info, void *addr);
void svcExitProcess();
result_t svcCreateThread(thread_h *out, thread_entry entry, u64 arg, void *stacktop, s32 priority, s32 processor_id);
result_t svcStartThread(thread_h thread);
void svcExitThread();
result_t svcSleepThread(u64 nanos);
result_t svcGetThreadPriority(u32 *priority, thread_h thread);
result_t svcSetThreadCoreMask(thread_h thread, u32 in, u64 in2);
u32 svcGetCurrentProcessorNumber();
result_t svcSignalEvent(handle_t event);
result_t svcClearEvent(handle_t event);
result_t svcMapSharedMemory(shared_memory_h block, void *addr, u64 size, u32 permission);
result_t svcUnmapSharedMemory(shared_memory_h block, void *addr, u64 size);
result_t svcCreateTransferMemory(transfer_memory_h *out, void *addr, u64 size, u32 permission);
result_t svcCloseHandle(handle_t handle);
result_t svcResetSignal(handle_t signal);
result_t svcWaitSynchronization(u32 *handle_index, handle_t *handles, u32 num_handles, u64 timeout);
result_t svcCancelSynchronization(handle_t handle);
void svcArbitrateLock(thread_h current_thread, void *lock, thread_h requesting_thread);
void svcArbitrateUnlock(void *lock);
result_t svcWaitProcessWideKeyAtomic(void *ptr0, void *ptr1, thread_h thread, u64 timeout);
result_t svcSignalProcessWideKey(void *ptr, u32 value);
u64 svcGetSystemTick();
result_t svcConnectToNamedPort(session_h *out, char name[8]);
// sendSyncRequestLight
result_t svcSendSyncRequest(session_h session);
result_t svcSendSyncRequestWithUserBuffer(void *buffer, u64 size, session_h session);
// sendAsyncRequestWithUserBuffer
// getProcessId
// getThreadId
// break
void svcOutputDebugString(char *str, u64 size);
void svcReturnFromException(u64 result);
result_t svcGetInfo(u64 *info, u64 info_id, handle_t handle, u64 info_sub_id);
// flushEntireDataCache
// flushDataCache
// mapPhysicalMemory
// unmapPhysicalMemory
// 0x2E?
// getLastThreadInfo
// getResourceLimitLimitValue
// getResourceLimitCurrentValue
// setThreadActivity
// getThreadContext3
// 0x34-0x3B?
// dumpInfo
// 0x3D-0x3F?
// createSession
result_t svcAcceptSession(session_h *out, port_h port);
// replyAndReceiveLight
result_t svcReplyAndReceive(u32 *handle_idx, session_h *handles, u32 num_handles, session_h reply_session, u64 timeout);
result_t svcReplyAndReceiveWithUserBuffer(u32 *handle_idx, void *buffer, u64 size, session_h *handles, u32 num_handles, session_h reply_session, u64 timeout);
// createEvent
// 0x46-0x4E?
// sleepSystem
result_t svcReadWriteRegister(u32 *out_value, u64 addr, u32 rw_mask, u32 in_value);
// setProcessActivity
result_t svcCreateSharedMemory(shared_memory_h *out, u64 size, u32 self_permissions, u32 foreign_permissions);
result_t svcMapTransferMemory(transfer_memory_h handle, void *addr, u64 size, u32 perm);
result_t svcUnmapTransferMemory(transfer_memory_h handle, void *addr, u64 size);
// createInterruptEvent
// queryPhysicalAddress
result_t svcQueryIoMapping(void *virt_addr, u64 phys_addr, u64 size);
// createDeviceAddressSpace
result_t svcAttachDeviceAddressSpace(u32 device, dev_addr_space_h space);
result_t svcDetachDeviceAddressSpace(u32 device, dev_addr_space_h space);
result_t svcMapDeviceAddressSpaceByForce(dev_addr_space_h space, process_h process, u64 dev_addr, u64 dev_size, u64 map_addr, u32 perm);
result_t svcMapDeviceAddressSpaceAligned(dev_addr_space_h space, process_h process, u64 dev_addr, u64 dev_size, u64 map_addr, u32 perm);
// mapDeviceAddressSpace
result_t svcUnmapDeviceAddressSpace(dev_addr_space_h space, process_h process, u64 map_addr, u64 map_size, u32 perm);
// invalidateProcessDataCache
// storeProcessDataCache
// flushProcessDataCache
result_t svcDebugActiveprocess(debug_h *out, u64 process_id);
// breakDebugProcess
// terminateDebugProcess
// getDebugEvent
// continueDebugEvent
// getProcessList
// getThreadList
// getDebugThreadContext
// setDebugThreadContext
result_t svcQueryDebugProcessMemory(memory_info_t *memory_info, u32 *page_info, debug_h debug, u64 addr);
result_t svcReadDebugProcessMemory(void *buffer, debug_h debug, u64 addr, u64 size);
result_t svcWriteDebugProcessMemory(debug_h debug, void *buffer, u64 addr, u64 size);
// setHardwareBreakPoint
// getDebugThreadParam
// 0x6D-0x6F?
// createPort
// manageNamedPort
// connectToPort
// setProcessMemoryPermission
// mapProcessMemory
// unmapProcessMemory
// queryProcessmemory
// mapProcessCodeMemory
// unmapProcessCodeMemory
// createProcess
// startProcess
// terminateProcess
// getProcessInfo
// createResourceLimit
// setResourceLimitLimitValue
// callSecureMonitor

View file

@ -1,3 +0,0 @@
#pragma once
void *get_tls();

View file

@ -1,73 +0,0 @@
/**
* @file types.h
* @brief Various system types.
*/
// Based on ctrulib's types.h
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/// The maximum value of a u64.
#define U64_MAX UINT64_MAX
/// would be nice if newlib had this already
#ifndef SSIZE_MAX
#ifdef SIZE_MAX
#define SSIZE_MAX ((SIZE_MAX) >> 1)
#endif
#endif
typedef uint8_t u8; ///< 8-bit unsigned integer
typedef uint16_t u16; ///< 16-bit unsigned integer
typedef uint32_t u32; ///< 32-bit unsigned integer
typedef uint64_t u64; ///< 64-bit unsigned integer
typedef int8_t s8; ///< 8-bit signed integer
typedef int16_t s16; ///< 16-bit signed integer
typedef int32_t s32; ///< 32-bit signed integer
typedef int64_t s64; ///< 64-bit signed integer
typedef volatile u8 vu8; ///< 8-bit volatile unsigned integer.
typedef volatile u16 vu16; ///< 16-bit volatile unsigned integer.
typedef volatile u32 vu32; ///< 32-bit volatile unsigned integer.
typedef volatile u64 vu64; ///< 64-bit volatile unsigned integer.
typedef volatile s8 vs8; ///< 8-bit volatile signed integer.
typedef volatile s16 vs16; ///< 16-bit volatile signed integer.
typedef volatile s32 vs32; ///< 32-bit volatile signed integer.
typedef volatile s64 vs64; ///< 64-bit volatile signed integer.
typedef u32 handle_t; ///< Resource handle.
typedef handle_t thread_h;
typedef handle_t shared_memory_h;
typedef handle_t transfer_memory_h;
typedef handle_t session_h;
typedef handle_t port_h;
typedef handle_t dev_addr_space_h;
typedef handle_t process_h;
typedef handle_t debug_h;
typedef u32 result_t; ///< Function result.
typedef void (*thread_entry)(void *); ///< Thread entrypoint function.
typedef void (*voidfn)(void);
/// Creates a bitmask from a bit number.
#define BIT(n) (1U<<(n))
/// Aligns a struct (and other types?) to m, making sure that the size of the struct is a multiple of m.
#define ALIGN(m) __attribute__((aligned(m)))
/// Packs a struct (and other types?) so it won't include padding bytes.
#define PACKED __attribute__((packed))
#ifndef LIBTRANSISTOR
/// Flags a function as deprecated.
#define DEPRECATED __attribute__ ((deprecated))
#else
/// Flags a function as deprecated.
#define DEPRECATED
#endif
#define RESULT_OK 0

View file

@ -1,15 +0,0 @@
#pragma once
char nybble2hex(u8 nybble);
void hexdump(void *rawbuf, size_t size);
void hexnum(int num);
int log_string(char *string, size_t len);
#define STB_SPRINTF_DECORATE(name) dbg_##name
#include "stb_sprintf.h"
#include<stdarg.h>
int dbg_printf(char const *fmt, ...);
int dbg_vprintf(char const *fmt, va_list va);

View file

@ -1,58 +0,0 @@
.hidden NORELOC__filestart
.global NORELOC__nro_modhdr
.hidden NORELOC__nro_modhdr
.hidden NORELOC_TEXT_START_
.hidden NORELOC_TEXT_END_
.hidden NORELOC_RODATA_START_
.hidden NORELOC_DYNSTR_START_
.hidden NORELOC_DYNSYM_START_
.hidden NORELOC_RODATA_END_
.hidden NORELOC_DATA_START_
.hidden NORELOC_DYNAMIC_START_
.hidden NORELOC_GOT_START_
.hidden NORELOC_GOT_PLT_START_
.hidden NORELOC_DATA_END_
.hidden NORELOC_BSS_START_
.hidden NORELOC_BSS_END_
.section .text, "e"
NORELOC__filestart:
.global _start
_start:
.fill 0x80, 1, 0
.section .data, "e"
.word 0, 8
NORELOC__nro_modhdr:
.ascii "MOD0"
.word NORELOC_DYNAMIC_START_ - NORELOC__nro_modhdr
.word NORELOC_BSS_START_ - NORELOC__nro_modhdr
.word NORELOC_BSS_END_ - NORELOC__nro_modhdr
.word 0, 0 // eh_frame_hdr start/end
.word 0 // runtime-generated module object offset
.quad log_buffer
.quad log_length
.section .text, "e"
.global start
start:
sub sp, sp, 0x10
stp x29, x30, [sp]
//ldr x1, __crt0_exit_frame
//stp x29, x30, [x1]
bl main
ldp x29, x30, [sp], 0x10
ret
.global _exit
_exit:
//ldr x1, __crt0_exit_frame
//ldp x29, x30, [x1]
//ret
b _exit
.section .bss
__crt0_exit_frame:
.quad 0
.quad 0

View file

@ -1,42 +0,0 @@
.hidden NORELOC__filestart
.global NORELOC__nro_modhdr
.hidden NORELOC__nro_modhdr
.hidden NORELOC_TEXT_START_
.hidden NORELOC_TEXT_END_
.hidden NORELOC_RODATA_START_
.hidden NORELOC_DYNSTR_START_
.hidden NORELOC_DYNSYM_START_
.hidden NORELOC_RODATA_END_
.hidden NORELOC_DATA_START_
.hidden NORELOC_DYNAMIC_START_
.hidden NORELOC_GOT_START_
.hidden NORELOC_GOT_PLT_START_
.hidden NORELOC_DATA_END_
.hidden NORELOC_BSS_START_
.hidden NORELOC_BSS_END_
.section .text, "e"
NORELOC__filestart:
.global _start
_start:
b start
.word NORELOC__nro_modhdr - NORELOC__filestart
.section .data, "e"
.word 0, 8
NORELOC__nro_modhdr:
.ascii "MOD0"
.word NORELOC_DYNAMIC_START_ - NORELOC__nro_modhdr
.word NORELOC_BSS_START_ - NORELOC__nro_modhdr
.word NORELOC_BSS_END_ - NORELOC__nro_modhdr
.word 0, 0 // eh_frame_hdr start/end
.word 0 // runtime-generated module object offset
.section .text, "e"
start:
bl main
loop:
.global _exit
_exit:
b loop

View file

@ -1,526 +0,0 @@
#include<libtransistor/ipc.h>
#include<libtransistor/tls.h>
#include<libtransistor/svc.h>
#include<libtransistor/err.h>
#include<libtransistor/util.h>
ipc_buffer_t null_buffer = {
.addr = 0,
.size = 0,
.type = 0
};
ipc_object_t ipc_null_object = {
.session = 0,
.object_id = -1
};
ipc_request_t ipc_default_request = {
.type = 4,
.num_buffers = 0,
.buffers = NULL,
.raw_data = 0,
.raw_data_size = 0,
.send_pid = false,
.num_copy_handles = 0,
.num_move_handles = 0,
.num_objects = 0,
.copy_handles = NULL,
.move_handles = NULL,
.objects = NULL,
.close_object = false
};
ipc_response_fmt_t ipc_default_response_fmt = {
.num_copy_handles = 0,
.num_move_handles = 0,
.num_objects = 0,
.copy_handles = NULL,
.move_handles = NULL,
.objects = NULL,
.raw_data_size = 0,
.raw_data = NULL,
.has_pid = false,
.pid = NULL
};
result_t ipc_marshal(u32 *buffer, ipc_request_t *rq, ipc_object_t object) {
int h = 0; // h is for HEAD
ipc_buffer_t *a_descriptors[16];
ipc_buffer_t *b_descriptors[16];
ipc_buffer_t *c_descriptors[16];
ipc_buffer_t *x_descriptors[16];
int num_a_descriptors = 0, num_b_descriptors = 0,
num_c_descriptors = 0, num_x_descriptors = 0;
bool to_domain = object.object_id >= 0;
// group buffers by descriptor type
for(int i = 0; i < rq->num_buffers; i++) {
ipc_buffer_t *buffer = rq->buffers[i];
int direction = (buffer->type & 0b0011) >> 0; // in or out (ax or bc)
int family = (buffer->type & 0b1100) >> 2; // ab or xc
if(!(buffer->type & 0x20)) {
ipc_buffer_t **list;
int *count;
if(direction == 0b01) { // IN (ax)
if(family == 0b01) { // A
list = a_descriptors;
count = &num_a_descriptors;
} else if(family == 0b10) { // X
list = x_descriptors;
count = &num_x_descriptors;
} else {
return LIBTRANSISTOR_ERR_UNSUPPORTED_BUFFER_TYPE;
}
} else if(direction == 0b10) { // OUT (bc)
if(family == 0b01) { // B
list = b_descriptors;
count = &num_b_descriptors;
} else if(family == 0b10) { // C
list = c_descriptors;
count = &num_c_descriptors;
} else {
return LIBTRANSISTOR_ERR_UNSUPPORTED_BUFFER_TYPE;
}
} else {
return LIBTRANSISTOR_ERR_UNSUPPORTED_BUFFER_TYPE;
}
// make sure we don't overflow our descriptor count fields
if(*count >= 16) {
return LIBTRANSISTOR_ERR_TOO_MANY_BUFFERS;
}
// add the buffer to the list
list[(*count)++] = buffer;
} else { // flag 0x20 set
// this isn't entirely correct. the nintendo code is kinda complicated though
if(buffer->type == 0x21) { // IN (ax)
if(num_a_descriptors >= 16 || num_x_descriptors >= 16) {
return LIBTRANSISTOR_ERR_TOO_MANY_BUFFERS;
}
a_descriptors[num_a_descriptors++] = buffer;
x_descriptors[num_x_descriptors++] = &null_buffer;
} else if(buffer->type == 0x22) { // OUT (bc)
if(num_b_descriptors >= 16 || num_c_descriptors >= 16) {
return LIBTRANSISTOR_ERR_TOO_MANY_BUFFERS;
}
b_descriptors[num_b_descriptors++] = buffer;
c_descriptors[num_c_descriptors++] = &null_buffer;
} else {
return LIBTRANSISTOR_ERR_UNSUPPORTED_BUFFER_TYPE;
}
}
}
// type must fit within 16 bits
if(rq->type & ~0xFFFF) {
return LIBTRANSISTOR_ERR_INVALID_REQUEST_TYPE;
}
// header field 1
buffer[h++] = rq->type
| (num_x_descriptors << 16)
| (num_a_descriptors << 20)
| (num_b_descriptors << 24)
| (0 << 28); // "w" descriptors
int c_descriptor_flags = 0;
if(num_c_descriptors == 1) {
c_descriptor_flags = 2;
} else if(num_c_descriptors > 1) {
c_descriptor_flags = num_c_descriptors + 2;
}
if(rq->raw_data_size & 3) {
return LIBTRANSISTOR_ERR_INVALID_RAW_DATA_SIZE;
}
int raw_data_words = rq->raw_data_size / sizeof(uint32_t);
int raw_data_section_size = raw_data_words
+ 4 // SFCI + command ID
+ 4 // padding
+ (to_domain ? 4 + rq->num_objects : 0); // domain header and in objects
int num_move_handles = rq->num_move_handles;
if(!to_domain) { // not sure if this is actually legit or not
num_move_handles+= rq->num_objects;
}
int handle_descriptor_enabled = rq->num_copy_handles || num_move_handles || rq->send_pid;
// header field 2
buffer[h++] = raw_data_section_size
| (c_descriptor_flags << 10)
| (handle_descriptor_enabled << 31);
// handle descriptor
if(handle_descriptor_enabled) {
if(rq->num_copy_handles >= 16 || num_move_handles >= 16) {
return LIBTRANSISTOR_ERR_TOO_MANY_HANDLES;
}
buffer[h++] = (rq->send_pid ? 1 : 0)
| (rq->num_copy_handles << 1)
| (rq->num_move_handles << 5);
h+= (rq->send_pid ? 2 : 0);
for(int i = 0; i < rq->num_copy_handles; i++) {
buffer[h++] = rq->copy_handles[i];
}
if(!to_domain) {
for(int i = 0; i < rq->num_objects; i++) {
ipc_object_t *tobject = rq->objects + i;
if(tobject->object_id >= 0) {
return LIBTRANSISTOR_ERR_CANT_SEND_DOMAIN_OBJECT_TO_SESSION;
}
buffer[h++] = tobject->session;
}
}
for(int i = 0; i < rq->num_move_handles; i++) {
buffer[h++] = rq->move_handles[i];
}
}
// x descriptors
for(int i = 0; i < num_x_descriptors; i++) {
int counter = i;
ipc_buffer_t *buf = x_descriptors[i];
if((u64) buf->addr >> 39) {
return LIBTRANSISTOR_ERR_INVALID_BUFFER_ADDRESS;
}
if(buf->size >> 16) {
return LIBTRANSISTOR_ERR_INVALID_BUFFER_SIZE;
}
buffer[h++] = counter
| (((u64) buf->addr >> 36) & 0b111) << 6
| ((counter >> 9) & 0b111) << 9
| (((u64) buf->addr >> 32) & 0b1111) << 12
| (buf->size << 16);
buffer[h++] = (u64) buf->addr & 0xFFFFFFFF;
}
// a & b descriptors
for(int i = 0; i < num_a_descriptors + num_b_descriptors; i++) {
ipc_buffer_t *buf = ((i < num_a_descriptors) ? a_descriptors : (b_descriptors - num_a_descriptors))[i];
if((u64) buf->addr >> 39) {
dbg_printf("a descriptor addr too long: %p", buf->addr);
return LIBTRANSISTOR_ERR_INVALID_BUFFER_ADDRESS;
}
if(buf->size >> 35) {
return LIBTRANSISTOR_ERR_INVALID_BUFFER_SIZE;
}
buffer[h++] = buf->size & 0xFFFFFFFF;
buffer[h++] = (u64) buf->addr & 0xFFFFFFFF;
if(buf->type >> 8) {
return LIBTRANSISTOR_ERR_INVALID_PROTECTION;
}
buffer[h++] = (buf->type >> 6) // flags/permissions
| (((u64) buf->addr >> 36) & 0b111) << 2
| ((buf->size >> 32) & 0b1111) << 24
| (((u64) buf->addr >> 32) & 0b1111) << 28;
}
// "w" descriptors would go here
// raw data
// align head to 4 words
int raw_data_start = h;
h = (h + 3) & ~3;
int pre_padding = h - raw_data_start; // the padding before this section and after it needs to add up to be 0x10 bytes long
int domain_header_location = h;
if(to_domain) {
if(rq->num_objects > 8) { // server code responds with result code 0x1d60a
return LIBTRANSISTOR_ERR_TOO_MANY_OBJECTS;
}
buffer[h++] = (rq->close_object ? 2 : 1)
| (rq->num_objects << 8); // we OR in the data payload size later;
buffer[h++] = object.object_id;
h+= 2; // alignment
}
int payload_start = h;
if(!rq->close_object) {
buffer[h++] = *((uint32_t*) "SFCI");
buffer[h++] = 0;
buffer[h++] = rq->request_id;
buffer[h++] = 0;
for(int i = 0; i < raw_data_words; i++) {
buffer[h++] = rq->raw_data[i];
}
} else {
if(!to_domain) {
return LIBTRANSISTOR_ERR_CANT_CLOSE_SESSIONS_LIKE_DOMAIN_OBJECTS;
}
if(
(rq->type != 4) ||
(rq->num_buffers != 0) ||
(rq->raw_data_size != 0) ||
(rq->send_pid != false) ||
(rq->num_copy_handles != 0) ||
(rq->num_move_handles != 0) ||
(rq->num_objects != 0)) {
return LIBTRANSISTOR_ERR_MALFORMED_CLOSE_REQUEST;
}
}
if(to_domain) {
buffer[domain_header_location]|= ((h - payload_start) * sizeof(*buffer)) << 16;
for(int i = 0; i < rq->num_objects; i++) {
if(rq->objects[i].domain != object.domain) {
return LIBTRANSISTOR_ERR_CANT_SEND_OBJECT_ACROSS_DOMAINS;
}
buffer[h++] = rq->objects[i].object_id;
}
}
h+= 0x10 - pre_padding;
int u16_length_count;
uint16_t *u16_length_list = (uint16_t*) (buffer + h);
// c descriptor u16 length list
for(int i = 0; i < num_c_descriptors; i++) {
ipc_buffer_t *buf = c_descriptors[i];
if(!(buf->type & 0x10)) { // u16 length list flag
if(buf->size >> 16) {
return LIBTRANSISTOR_ERR_INVALID_BUFFER_SIZE;
}
u16_length_list[u16_length_count++] = buf->size;
}
}
h+= (u16_length_count + 1) >> 1;
// c descriptors
for(int i = 0; i < num_c_descriptors; i++) {
ipc_buffer_t *buf = c_descriptors[i];
if((u64) buf->addr >> 48) {
return LIBTRANSISTOR_ERR_INVALID_BUFFER_ADDRESS;
}
if(buf->size >> 16) {
return LIBTRANSISTOR_ERR_INVALID_BUFFER_SIZE;
}
buffer[h++] = (u64) buf->addr & 0xFFFFFFFF;
buffer[h++] = ((u64) buf->addr >> 32)
| (buf->size << 16);
}
return RESULT_OK;
}
result_t ipc_unmarshal(u32 *buffer, ipc_response_fmt_t *rs, ipc_object_t object) {
if(rs->raw_data_size & 3) {
return LIBTRANSISTOR_ERR_INVALID_RAW_DATA_SIZE;
}
bool from_domain = object.object_id >= 0;
int raw_data_words = rs->raw_data_size / sizeof(uint32_t);
int h = 0; // h for HEAD
u32 header0 = buffer[h++];
u32 header1 = buffer[h++];
int response_type = header0 & 0xFFFF;
if(response_type != 0) {
return LIBTRANSISTOR_ERR_INVALID_IPC_RESPONSE_TYPE;
}
int num_x_descriptors = (header0 >> 16) & 0xF;
int num_a_descriptors = (header0 >> 20) & 0xF;
int num_b_descriptors = (header0 >> 24) & 0xF;
int num_w_descriptors = (header0 >> 28) & 0xF;
int raw_data_section_size = header1 & 0b1111111111;
int c_descriptor_flags = (header1 >> 10) & 0xF;
bool has_handle_descriptor = header1 >> 31;
int num_copy_handles = 0;
int num_move_handles = 0;
handle_t *copy_handles;
handle_t *move_handles;
bool has_pid = false;
int pid;
if(has_handle_descriptor) {
int handle_descriptor = buffer[h++];
if(handle_descriptor & 1) {
has_pid = true;
pid = *(u64*)(buffer + h);
h+= 2;
}
num_copy_handles = (handle_descriptor >> 1) & 0xF;
num_move_handles = (handle_descriptor >> 5) & 0xF;
copy_handles = buffer + h; h+= num_copy_handles;
move_handles = buffer + h; h+= num_move_handles;
}
// skip descriptors
h+= num_x_descriptors * 2;
h+= num_a_descriptors * 3;
h+= num_b_descriptors * 3;
h+= num_w_descriptors * 3;
// align head to 4 words
int raw_data_start = h;
h = (h + 3) & ~3;
int domain_header_location = h;
if(from_domain) {
h+= 4;
}
if(buffer[h++] != *((uint32_t*) "SFCO")) {
return LIBTRANSISTOR_ERR_INVALID_IPC_RESPONSE_MAGIC;
}
h++;
// if this isn't ok, none of our other expectations will make
// sense, so this is the most meaningful result to return.
result_t response_code = buffer[h++];
if(response_code != RESULT_OK) {
return response_code;
}
h++;
u32 *raw_data = buffer + h;
if((raw_data_section_size
- 4 // SFCI, command id
- 4 // padding
- (from_domain ? 4 + rs->num_objects : 0) // domain header + out objects
) != raw_data_words) {
return LIBTRANSISTOR_ERR_UNEXPECTED_RAW_DATA_SIZE;
}
if(has_pid != rs->has_pid) {
return LIBTRANSISTOR_ERR_UNEXPECTED_PID;
}
if(num_copy_handles != rs->num_copy_handles) {
return LIBTRANSISTOR_ERR_UNEXPECTED_COPY_HANDLES;
}
if(num_move_handles != rs->num_move_handles + (from_domain ? 0 : rs->num_objects)) {
return LIBTRANSISTOR_ERR_UNEXPECTED_MOVE_HANDLES;
}
if(from_domain) {
uint8_t *domain_header = (uint8_t*) (buffer + domain_header_location);
uint8_t command = domain_header[0];
uint8_t object_count = domain_header[1];
uint16_t raw_data_size = ((uint16_t*) domain_header)[1];
if(command != 0) {
return LIBTRANSISTOR_ERR_UNEXPECTED_DOMAIN_HEADER_COMMAND;
}
if(object_count != rs->num_objects) {
return LIBTRANSISTOR_ERR_UNEXPECTED_OBJECTS;
}
uint32_t *domain_ids = (uint32_t*) (domain_header + 16 + raw_data_size);
for(int i = 0; i < rs->num_objects; i++) {
rs->objects[i].domain = object.domain;
rs->objects[i].object_id = domain_ids[i];
}
}
for(int i = 0; i < rs->num_copy_handles; i++) { rs->copy_handles[i] = copy_handles[i]; }
int mhi = 0; // move handle index
if(!from_domain) {
for(int i = 0; i < rs->num_objects; i++) {
rs->objects[i].session = move_handles[mhi++];
rs->objects[i].object_id = -1;
}
}
for(int i = 0; i < rs->num_move_handles; i++) { rs->move_handles[i] = move_handles[mhi++]; }
for(int i = 0; i < raw_data_words; i++) {
rs->raw_data[i] = raw_data[i];
}
return RESULT_OK;
}
result_t ipc_convert_to_domain(ipc_object_t *object, ipc_domain_t *domain) {
ipc_object_t session = *object;
domain->session = session.session;
if(object->object_id != -1) {
return LIBTRANSISTOR_ERR_ALREADY_A_DOMAIN;
}
object->domain = domain;
ipc_request_t rq = ipc_default_request;
rq.type = 5;
rq.request_id = 0;
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(object->object_id);
rs.raw_data = (uint32_t*) &(object->object_id);
return ipc_send(session, &rq, &rs);
}
result_t ipc_send(ipc_object_t object, ipc_request_t *rq, ipc_response_fmt_t *rs) {
result_t r;
u32 *tls = get_tls();
r = ipc_marshal(tls, rq, object); if(r) { return r; }
r = svcSendSyncRequest(object.object_id >= 0 ? object.domain->session : object.session); if(r) { return r; }
r = ipc_unmarshal(tls, rs, object); if(r) { return r; }
return RESULT_OK;
}
result_t ipc_close(ipc_object_t object) {
if(object.object_id < 0) {
return svcCloseHandle(object.session);
}
ipc_request_t rq = ipc_default_request;
rq.close_object = true;
u32 *tls = get_tls();
result_t r;
r = ipc_marshal(tls, &rq, object); if(r) { return r; }
r = svcSendSyncRequest(object.domain->session); if (r) { return r; }
// remote end doesn't seem to actually write a response
return RESULT_OK;
}
result_t ipc_close_domain(ipc_domain_t domain) {
return svcCloseHandle(domain.session);
}

View file

@ -1,850 +0,0 @@
#include<libtransistor/types.h>
#include<libtransistor/svc.h>
#include<libtransistor/ipc.h>
#include<libtransistor/err.h>
#include<libtransistor/util.h>
#include<libtransistor/ipc/sm.h>
#include<libtransistor/ipc/bsd.h>
#include<string.h>
#include<malloc.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#define TRANSFER_MEM_SIZE 256*1024
result_t bsd_result;
int bsd_errno;
static ipc_domain_t bsd_domain;
static ipc_object_t bsd_object;
static ipc_object_t iresolver_object;
static uint8_t __attribute__((aligned(0x1000))) transfer_buffer[TRANSFER_MEM_SIZE];
static transfer_memory_h transfer_mem;
result_t bsd_init() {
result_t r;
r = sm_get_service(&bsd_object, "bsd:u");
if(r) {
r = sm_get_service(&bsd_object, "bsd:s");
if(r) { return r; }
}
dbg_printf("connected to bsd");
r = ipc_convert_to_domain(&bsd_object, &bsd_domain);
if(r) {
ipc_close_domain(bsd_domain);
return r;
}
dbg_printf("converted bsd to domain");
r = sm_get_service(&iresolver_object, "sfdnsres");
if(r) {
ipc_close_domain(bsd_domain);
return r;
}
dbg_printf("connected to sfdnsres");
r = svcCreateTransferMemory(&transfer_mem, transfer_buffer, TRANSFER_MEM_SIZE, 0);
if(r) {
ipc_close_domain(bsd_domain);
ipc_close(iresolver_object);
return r;
}
uint64_t raw[] = {32*1024, 32*1024, 16*1024, 16*1024,
0, // server copies pid to here
TRANSFER_MEM_SIZE};
ipc_request_t rq = ipc_default_request;
rq.type = 4;
rq.request_id = 0;
rq.raw_data = (uint32_t*) raw;
rq.raw_data_size = sizeof(raw);
rq.send_pid = true;
rq.num_copy_handles = 1;
rq.copy_handles = &transfer_mem;
uint32_t response[1];
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = response;
r = ipc_send(bsd_object, &rq, &rs); // not working under mephisto
if(r) {
svcCloseHandle(transfer_mem);
ipc_close_domain(bsd_domain);
ipc_close(iresolver_object);
return r;
}
if(response[0]) {
bsd_errno = response[0];
svcCloseHandle(transfer_mem);
ipc_close_domain(bsd_domain);
ipc_close(iresolver_object);
return LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
}
return 0;
}
// def tested via PS
// impl tested via Mephisto
int bsd_socket(int domain, int type, int protocol) {
result_t r;
uint32_t raw[] = {domain, type, protocol};
ipc_request_t rq = ipc_default_request;
rq.request_id = 2;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // fd, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def tested via PS
// impl untested
int bsd_recv(int socket, void *message, size_t length, int flags) {
result_t r;
uint32_t raw[] = {socket, flags};
ipc_buffer_t buffer;
buffer.addr = message;
buffer.size = length;
buffer.type = 0x22;
ipc_buffer_t *buffers[] = {&buffer};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 1;
rq.buffers = buffers;
rq.request_id = 8;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def tested via PS
// impl tested via Mephisto
int bsd_send(int socket, const void *data, size_t length, int flags) {
result_t r;
uint32_t raw[] = {socket, flags};
ipc_buffer_t buffer;
buffer.addr = (void*) data;
buffer.size = length;
buffer.type = 0x21; // A+X
ipc_buffer_t *buffers[] = {&buffer};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 1;
rq.buffers = buffers;
rq.request_id = 10;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def tested via PS
// impl untested
int bsd_sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len) {
result_t r;
uint32_t raw[] = {socket, flags};
ipc_buffer_t message_buffer;
message_buffer.addr = (void*) message;
message_buffer.size = length;
message_buffer.type = 0x21; // A+X
ipc_buffer_t addr_buffer;
addr_buffer.addr = (void*) dest_addr;
addr_buffer.size = dest_len;
addr_buffer.type = 0x21; // A+X
ipc_buffer_t *buffers[] = {&message_buffer, &addr_buffer};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 2;
rq.buffers = buffers;
rq.request_id = 11;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def tested via PS
// impl untested
int bsd_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {
result_t r;
uint32_t raw[] = {socket};
ipc_buffer_t addr_buffer;
addr_buffer.addr = (void*) address;
addr_buffer.size = *address_len;
addr_buffer.type = 0x22;
ipc_buffer_t *buffers[] = {&addr_buffer};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 1;
rq.buffers = buffers;
rq.request_id = 12;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[3]; // ret, errno, address_len
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
*address_len = response[2];
return response[0];
}
// def tested via PS
// impl untested
int bsd_bind(int socket, const struct sockaddr *address, socklen_t address_len) {
result_t r;
uint32_t raw[] = {socket};
ipc_buffer_t buffer;
buffer.addr = (void*) address;
buffer.size = address_len;
buffer.type = 0x21; // A+X
ipc_buffer_t *buffers[] = {&buffer};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 1;
rq.buffers = buffers;
rq.request_id = 13;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def tested via PS
// impl tested via Mephisto
int bsd_connect(int socket, const struct sockaddr *address, socklen_t address_len) {
result_t r;
uint32_t raw[] = {socket};
ipc_buffer_t buffer;
buffer.addr = (void*) address;
buffer.size = address_len;
buffer.type = 0x21; // A+X
ipc_buffer_t *buffers[] = {&buffer};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 1;
rq.buffers = buffers;
rq.request_id = 14;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
uint32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] != 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def untested
int bsd_getsockname(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {
return 0;
}
// def tested via PS
int bsd_listen(int socket, int backlog) {
result_t r;
uint32_t raw[] = {socket, backlog};
ipc_request_t rq = ipc_default_request;
rq.request_id = 18;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
// def untested
int bsd_setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len) {
return 0;
}
// def untested
int bsd_shutdown(int socket, int how) {
return 0;
}
// def untested
int bsd_select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout) {
result_t r;
uint64_t timeout_words[3];
if(timeout != NULL) {
timeout_words[0] = timeout->tv_sec;
timeout_words[1] = timeout->tv_usec;
timeout_words[2] = 0;
} else {
timeout_words[0] = 0;
timeout_words[1] = 0;
timeout_words[2] = 1;
}
uint32_t raw[7];
raw[0] = nfds;
memcpy(raw + 1, timeout_words, sizeof(timeout_words));
ipc_buffer_t readfds_in = {
.addr = readfds,
.size = (readfds == NULL) ? 0 : sizeof(readfds),
.type = 0x21
};
ipc_buffer_t writefds_in = {
.addr = writefds,
.size = (writefds == NULL) ? 0 : sizeof(writefds),
.type = 0x21
};
ipc_buffer_t errorfds_in = {
.addr = errorfds,
.size = (errorfds == NULL) ? 0 : sizeof(errorfds),
.type = 0x21
};
ipc_buffer_t readfds_out = {
.addr = readfds,
.size = (readfds == NULL) ? 0 : sizeof(readfds),
.type = 0x22
};
ipc_buffer_t writefds_out = {
.addr = writefds,
.size = (writefds == NULL) ? 0 : sizeof(writefds),
.type = 0x22
};
ipc_buffer_t errorfds_out = {
.addr = errorfds,
.size = (errorfds == NULL) ? 0 : sizeof(errorfds),
.type = 0x22
};
ipc_buffer_t *buffers[] = {
&readfds_in,
&writefds_in,
&errorfds_in,
&readfds_out,
&writefds_out,
&errorfds_out
};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 6;
rq.buffers = buffers;
rq.request_id = 5;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2];
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
int bsd_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
result_t r;
struct {
uint8_t enable_nsd_resolve;
uint8_t padding[3];
uint32_t unknown;
uint64_t pid;
} __attribute__((packed)) raw;
raw.enable_nsd_resolve = 1;
raw.unknown = 0;
raw.pid = 0;
uint8_t hints_packed[0x400];
uint8_t response_packed[0x1000];
memset(hints_packed, 0, sizeof(hints_packed));
if(hints != NULL) {
r = bsd_ai_pack(hints, hints_packed, sizeof(hints_packed));
if(r) {
bsd_result = r;
return -1;
}
}
ipc_buffer_t host_buf = {
.addr = (void*) node,
.size = (node == NULL) ? 0 : strlen(node)+1,
.type = 5
};
ipc_buffer_t service_buf = {
.addr = (void*) service,
.size = (service == NULL) ? 0 : strlen(service)+1,
.type = 5
};
ipc_buffer_t hints_buf = {
.addr = hints_packed,
.size = (hints == NULL) ? 0 : sizeof(hints_packed),
.type = 5
};
ipc_buffer_t response_buf = {
.addr = response_packed,
.size = sizeof(response_packed),
.type = 6
};
ipc_buffer_t *buffers[] = {
&host_buf,
&service_buf,
&hints_buf,
&response_buf
};
ipc_request_t rq = ipc_default_request;
rq.num_buffers = 4;
rq.buffers = buffers;
rq.request_id = 6;
rq.raw_data = (uint32_t*) &raw;
rq.raw_data_size = sizeof(raw);
rq.send_pid = true;
int32_t response[3]; // ret, errno, response_size
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(iresolver_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
r = bsd_ai_unpack(res, response_packed, response[2]);
if(r) {
bsd_result = r;
return -1;
}
return response[0];
}
// def tested via PS
int bsd_close(int socket) {
result_t r;
uint32_t raw[] = {socket};
ipc_request_t rq = ipc_default_request;
rq.request_id = 26;
rq.raw_data = raw;
rq.raw_data_size = sizeof(raw);
int32_t response[2]; // ret, errno
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.raw_data_size = sizeof(response);
rs.raw_data = (uint32_t*) response;
r = ipc_send(bsd_object, &rq, &rs);
if(r) {
bsd_result = r;
return -1;
}
if(response[0] < 0) {
bsd_result = LIBTRANSISTOR_ERR_BSD_ERRNO_SET;
bsd_errno = response[1];
return -1;
}
return response[0];
}
void bsd_finalize() {
svcCloseHandle(transfer_mem);
ipc_close(bsd_object);
ipc_close_domain(bsd_domain);
}
result_t bsd_ai_pack(const struct addrinfo *ai, uint8_t *buf, int size) {
struct {
uint32_t magic;
int32_t ai_flags;
int32_t ai_family;
int32_t ai_socktype;
int32_t ai_protocol;
int32_t ai_addrlen;
} __attribute__((packed)) ai_packed_header = {
htonl(0xBEEFCAFE),
htonl(ai->ai_flags),
htonl(ai->ai_family),
htonl(ai->ai_socktype),
htonl(ai->ai_protocol),
htonl(ai->ai_addrlen)
};
if(size < sizeof(ai_packed_header)) {
return LIBTRANSISTOR_ERR_BSD_BUFFER_TOO_SMALL;
}
memcpy(buf, &ai_packed_header, sizeof(ai_packed_header));
buf+= sizeof(ai_packed_header);
size-= sizeof(ai_packed_header);
if(size < (ai->ai_addrlen == 0 ? 4 : ai->ai_addrlen)) {
return LIBTRANSISTOR_ERR_BSD_BUFFER_TOO_SMALL;
}
if(ai->ai_addrlen == 0) {
*((uint32_t*) buf) = 0;
} else {
switch(ai->ai_family) {
case AF_INET: {
struct sockaddr_in *buf_as_sockaddr_in = (struct sockaddr_in*) buf;
struct sockaddr_in *sockaddr = (struct sockaddr_in*) ai->ai_addr;
//buf_as_sockaddr_in->sin_len = 0;
buf_as_sockaddr_in->sin_family = sockaddr->sin_family;
buf_as_sockaddr_in->sin_port = htons(sockaddr->sin_port); // I think that this is erroneously byteswapped
buf_as_sockaddr_in->sin_addr.s_addr = htonl(sockaddr->sin_addr.s_addr); // this too
memset(&buf_as_sockaddr_in->sin_zero, 0, sizeof(buf_as_sockaddr_in->sin_zero));
break;
}
case AF_INET6:
// TODO
return LIBTRANSISTOR_ERR_UNIMPLEMENTED;
default:
memcpy(buf, ai->ai_addr, ai->ai_addrlen);
break;
}
}
buf+= ai->ai_addrlen;
size-= ai->ai_addrlen == 0 ? 4 : ai->ai_addrlen;
int canonlen = ai->ai_canonname == NULL ? 0 : strlen(ai->ai_canonname);
if(size < canonlen + 1) {
return LIBTRANSISTOR_ERR_BSD_BUFFER_TOO_SMALL;
}
memcpy(buf, ai->ai_canonname, canonlen);
buf[canonlen] = 0;
buf+= canonlen + 1;
size-= canonlen + 1;
if(ai->ai_next != NULL) {
return bsd_ai_pack(ai->ai_next, buf, size);
} else {
if(size < 4) {
return LIBTRANSISTOR_ERR_BSD_BUFFER_TOO_SMALL;
}
*((uint32_t*) buf) = 0;
return 0;
}
}
result_t bsd_ai_unpack(struct addrinfo **res, const uint8_t *buf, int size) {
struct {
uint32_t magic;
int32_t ai_flags;
int32_t ai_family;
int32_t ai_socktype;
int32_t ai_protocol;
int32_t ai_addrlen;
} __attribute__((packed)) ai_packed_header = {};
result_t r;
struct addrinfo *ai;
ai = malloc(sizeof(struct addrinfo));
if(ai == NULL) {
return LIBTRANSISTOR_ERR_OUT_OF_MEMORY;
}
memset(ai, 0, sizeof(struct addrinfo));
if(size < sizeof(ai_packed_header)) {
r = LIBTRANSISTOR_ERR_BSD_BUFFER_TOO_SMALL;
goto bail;
}
memcpy(&ai_packed_header, buf, sizeof(ai_packed_header));
buf+= sizeof(ai_packed_header);
size-= sizeof(ai_packed_header);
if(ntohl(ai_packed_header.magic) != 0xBEEFCAFE) {
r = LIBTRANSISTOR_ERR_BSD_INVALID_MAGIC;
goto bail;
}
ai->ai_flags = ntohl(ai_packed_header.ai_flags);
ai->ai_family = ntohl(ai_packed_header.ai_family);
ai->ai_socktype = ntohl(ai_packed_header.ai_socktype);
ai->ai_protocol = ntohl(ai_packed_header.ai_protocol);
ai->ai_addrlen = ntohl(ai_packed_header.ai_addrlen);
if(ai->ai_addrlen == 0) {
ai->ai_addr = NULL;
buf+= 4;
size-= 4;
} else {
ai->ai_addr = malloc(ai->ai_addrlen);
if(ai->ai_addr == NULL) {
dbg_printf("could not allocate ai_addr, len: %d", ai->ai_addrlen);
r = LIBTRANSISTOR_ERR_OUT_OF_MEMORY;
goto bail;
}
switch(ai->ai_family) {
case AF_INET: {
struct sockaddr_in *buf_as_sockaddr_in = (struct sockaddr_in*) buf;
struct sockaddr_in *sockaddr = (struct sockaddr_in*) ai->ai_addr;
//sockaddr->sin_len = 0;
sockaddr->sin_family = buf_as_sockaddr_in->sin_family;
sockaddr->sin_port = htons(buf_as_sockaddr_in->sin_port); // erroneous byte swapping
sockaddr->sin_addr.s_addr = htonl(buf_as_sockaddr_in->sin_addr.s_addr); // again
memset(&sockaddr->sin_zero, 0, sizeof(sockaddr->sin_zero));
break;
}
case AF_INET6:
// TODO
return LIBTRANSISTOR_ERR_UNIMPLEMENTED;
default:
memcpy(ai->ai_addr, buf, ai->ai_addrlen);
break;
}
buf+= ai->ai_addrlen;
size-= ai->ai_addrlen;
}
int canonlen = strlen((char*) buf);
char *canonname;
if(canonlen > 0) {
canonname = malloc(canonlen+1);
if(canonname == NULL) {
r = LIBTRANSISTOR_ERR_OUT_OF_MEMORY;
goto bail;
}
memcpy(canonname, buf, canonlen+1);
} else {
canonname = NULL;
}
ai->ai_canonname = canonname;
buf+= canonlen+1;
size-= canonlen+1;
if(*((uint32_t*) buf) == htonl(0xBEEFCAFE)) {
r = bsd_ai_unpack(&ai->ai_next, buf, size);
if(r) {
goto bail;
}
}
*res = ai;
return 0;
bail:
if(ai->ai_addr != NULL) {
free(ai->ai_addr);
}
if(ai->ai_canonname != NULL) {
free(ai->ai_canonname);
}
free(ai);
return r;
}
void bsd_freeaddrinfo(struct addrinfo *res) {
if(res->ai_next != NULL) {
bsd_freeaddrinfo(res->ai_next);
}
if(res->ai_addr != NULL) {
free(res->ai_addr);
}
if(res->ai_canonname != NULL) {
free(res->ai_canonname);
}
free(res);
}

View file

@ -1,59 +0,0 @@
#include<libtransistor/types.h>
#include<libtransistor/svc.h>
#include<libtransistor/ipc.h>
#include<libtransistor/err.h>
#include<libtransistor/util.h>
#include<libtransistor/ipc/sm.h>
#include<string.h>
static ipc_object_t sm_object;
static u64 str2u64(char *str) {
char buf[8];
int i = 0;
for(; i < 8; i++) {
if(str[i] == 0) { break; }
buf[i] = str[i];
}
for(; i < 8; i++) {
buf[i] = 0;
}
return *(u64*) buf;
}
result_t sm_init() {
dbg_printf("initializing sm");
sm_object.object_id = -1;
return svcConnectToNamedPort(&(sm_object.session), "sm:");
}
void sm_finalize() {
ipc_close(sm_object);
}
result_t sm_get_service(ipc_object_t *out_object, char *name) {
if(!sm_object.session) {
return LIBTRANSISTOR_ERR_SM_NOT_INITIALIZED;
}
u64 service_name = str2u64(name);
int i;
if(strlen(name) > 8) {
return LIBTRANSISTOR_ERR_SM_SERVICE_NAME_TOO_LONG;
}
out_object->object_id = -1;
ipc_request_t rq = ipc_default_request;
rq.request_id = 1;
rq.raw_data = (u32*) &service_name;
rq.raw_data_size = sizeof(service_name);
ipc_response_fmt_t rs = ipc_default_response_fmt;
rs.num_move_handles = 1;
rs.move_handles = &(out_object->session);
return ipc_send(sm_object, &rq, &rs);
}

File diff suppressed because it is too large Load diff

View file

@ -1,240 +0,0 @@
.align 4
.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
.macro DEFINE_OUT00_SVC id, name
SVC_BEGIN svc\name
svc \id
ret
SVC_END
.endm
.macro DEFINE_OUT32_SVC id, name
SVC_BEGIN svc\name
str x0, [sp, #-0x10]!
svc \id
ldr x2, [sp]
str w1, [x2]
add sp, sp, #0x10
ret
SVC_END
.endm
.macro DEFINE_OUT64_SVC id, name
SVC_BEGIN svc\name
str x0, [sp, #-0x10]!
svc \id
ldr x2, [sp]
str x1, [x2]
add sp, sp, #0x10
ret
SVC_END
.endm
.macro DEFINE_OUT32_ARG2_SVC id, name
SVC_BEGIN svc\name
str x1, [sp, #-0x10]!
svc \id
ldr x2, [sp]
str w1, [x2]
add sp, sp, #0x10
ret
SVC_END
.endm
.macro DEFINE_OUT32_PAIR_SVC id, name
SVC_BEGIN svc\name
stp x0, x1, [sp, #-0x10]!
svc \id
ldr x3, [sp]
str w1, [x3]
ldr x3, [sp, #8]
str w2, [x3]
add sp, sp, #0x10
ret
SVC_END
.endm
DEFINE_OUT64_SVC 0x01, SetHeapSize
DEFINE_OUT00_SVC 0x02, SetMemoryPermission
DEFINE_OUT00_SVC 0x03, SetMemoryAttribute
DEFINE_OUT00_SVC 0x04, MapMemory
DEFINE_OUT00_SVC 0x05, UnmapMemory
DEFINE_OUT32_SVC 0x06, QueryMemory
DEFINE_OUT00_SVC 0x07, ExitProcess
DEFINE_OUT32_SVC 0x08, CreateThread
DEFINE_OUT00_SVC 0x09, StartThread
DEFINE_OUT00_SVC 0x0A, ExitThread
DEFINE_OUT00_SVC 0x0B, SleepThread
DEFINE_OUT32_SVC 0x0C, GetThreadPriority
DEFINE_OUT00_SVC 0x0D, SetThreadPriority
SVC_BEGIN svcGetThreadCoreMask
stp x0, x1, [sp, #-0x10]!
svc 0xE
ldr x3, [sp]
str w1, [x3]
ldr x3, [sp, #8]
str x2, [x3]
add sp, sp, #0x10
ret
SVC_END
DEFINE_OUT00_SVC 0x0F, SetThreadCoreMask
DEFINE_OUT00_SVC 0x10, GetCurrentProcessorNumber
DEFINE_OUT00_SVC 0x11, SignalEvent
DEFINE_OUT00_SVC 0x12, ClearEvent
DEFINE_OUT00_SVC 0x13, MapSharedMemory
DEFINE_OUT00_SVC 0x14, UnmapSharedMemory
DEFINE_OUT32_SVC 0x15, CreateTransferMemory
DEFINE_OUT00_SVC 0x16, CloseHandle
DEFINE_OUT00_SVC 0x17, ResetSignal
DEFINE_OUT32_SVC 0x18, WaitSynchronization
DEFINE_OUT00_SVC 0x19, CancelSynchronization
DEFINE_OUT00_SVC 0x1A, ArbitrateLock
DEFINE_OUT00_SVC 0x1B, ArbitrateUnlock
DEFINE_OUT00_SVC 0x1C, WaitProcessWideKeyAtomic
DEFINE_OUT00_SVC 0x1D, SignalProcessWideKey
DEFINE_OUT00_SVC 0x1E, GetSystemTick
DEFINE_OUT32_SVC 0x1F, ConnectToNamedPort
DEFINE_OUT00_SVC 0x20, SendSyncRequestLight
DEFINE_OUT00_SVC 0x21, SendSyncRequest
DEFINE_OUT00_SVC 0x22, SendSyncRequestWithUserBuffer
DEFINE_OUT32_SVC 0x23, SendAsyncRequestWithUserBuffer
DEFINE_OUT64_SVC 0x24, GetProcessId
DEFINE_OUT64_SVC 0x25, GetThreadId
DEFINE_OUT00_SVC 0x26, Break
DEFINE_OUT00_SVC 0x27, OutputDebugString
DEFINE_OUT00_SVC 0x28, ReturnFromException
DEFINE_OUT64_SVC 0x29, GetInfo
DEFINE_OUT00_SVC 0x2A, FlushEntireDataCache
DEFINE_OUT00_SVC 0x2B, FlushDataCache
SVC_BEGIN svcGetLastThreadInfo
str x2, [sp, #-0x10]!
stp x0, x1, [sp, #-0x10]!
svc 0x2F
ldr x7, [sp]
str x1, [x7]
str x2, [x7, #8]
str x3, [x7, #0x10]
str x4, [x7, #0x18]
ldr x7, [sp, #8]
str x5, [x7]
ldr x7, [sp, #0x10]
str w6, [x7]
add sp, sp, #0x20
ret
SVC_END
DEFINE_OUT64_SVC 0x30, GetResourceLimitLimitValue
DEFINE_OUT64_SVC 0x31, GetResourceLimitCurrentValue
DEFINE_OUT00_SVC 0x32, SetThreadActivity
DEFINE_OUT00_SVC 0x33, GetThreadContext3
DEFINE_OUT00_SVC 0x3C, DumpInfo
DEFINE_OUT32_PAIR_SVC 0x40, CreateSession
DEFINE_OUT32_SVC 0x41, AcceptSession
DEFINE_OUT00_SVC 0x42, ReplyAndReceiveLight
DEFINE_OUT32_SVC 0x43, ReplyAndReceive
DEFINE_OUT32_SVC 0x44, ReplyAndReceiveWithUserBuffer
DEFINE_OUT32_PAIR_SVC 0x45, CreateEvent
DEFINE_OUT00_SVC 0x4D, SleepSystem
DEFINE_OUT32_SVC 0x4E, ReadWriteRegister
DEFINE_OUT00_SVC 0x4F, SetProcessActivity
DEFINE_OUT32_SVC 0x50, CreateSharedMemory
DEFINE_OUT00_SVC 0x51, MapTransferMemory
DEFINE_OUT00_SVC 0x52, UnmapTransferMemory
DEFINE_OUT32_SVC 0x53, CreateInterruptEvent
SVC_BEGIN svcQueryPhysicalAddress
str x0, [sp, #-0x10]!
svc 0x54
ldr x4, [sp]
str x1, [x4]
str x2, [x4, #8]
str x3, [x4, #0x10]
add sp, sp, #0x10
ret
SVC_END
DEFINE_OUT64_SVC 0x55, QueryIoMapping
DEFINE_OUT32_SVC 0x56, CreateDeviceAddressSpace
DEFINE_OUT00_SVC 0x57, AttachDeviceAddressSpace
DEFINE_OUT00_SVC 0x58, DetachDeviceAddressSpace
DEFINE_OUT00_SVC 0x59, MapDeviceAddressSpaceByForce
DEFINE_OUT00_SVC 0x5A, MapDeviceAddressSpaceAligned
DEFINE_OUT64_SVC 0x5B, MapDeviceAddressSpace
DEFINE_OUT00_SVC 0x5C, UnmapDeviceAddressSpace
DEFINE_OUT00_SVC 0x5D, InvalidateProcessDataCache
DEFINE_OUT00_SVC 0x5E, StoreProcessDataCache
DEFINE_OUT00_SVC 0x5F, FlushProcessDataCache
DEFINE_OUT32_SVC 0x60, DebugActiveProcess
DEFINE_OUT00_SVC 0x61, BreakDebugProcess
DEFINE_OUT00_SVC 0x62, TerminateDebugProcess
DEFINE_OUT00_SVC 0x63, GetDebugEvent
DEFINE_OUT00_SVC 0x64, ContinueDebugEvent
DEFINE_OUT32_SVC 0x65, GetProcessList
DEFINE_OUT32_SVC 0x66, GetThreadList
DEFINE_OUT00_SVC 0x67, GetDebugThreadContext
DEFINE_OUT00_SVC 0x68, SetDebugThreadContext
DEFINE_OUT32_ARG2_SVC 0x69, QueryDebugProcessMemory
DEFINE_OUT00_SVC 0x6A, ReadDebugProcessMemory
DEFINE_OUT00_SVC 0x6B, WriteDebugProcessMemory
DEFINE_OUT00_SVC 0x6C, SetHardwareBreakPoint
SVC_BEGIN svcGetDebugThreadParam
stp x0, x1, [sp, #-0x10]!
svc 0x6D
ldr x3, [sp]
str x1, [x3]
ldr x3, [sp, #8]
str w2, [x3]
add sp, sp, #0x10
ret
SVC_END
DEFINE_OUT32_PAIR_SVC 0x70, CreatePort
DEFINE_OUT32_SVC 0x71, ManageNamedPort
DEFINE_OUT32_SVC 0x72, ConnectToPort
DEFINE_OUT00_SVC 0x73, SetProcessMemoryPermission
DEFINE_OUT00_SVC 0x74, MapProcessMemory
DEFINE_OUT00_SVC 0x75, UnmapProcessMemory
DEFINE_OUT32_ARG2_SVC 0x76, QueryProcessMemory
DEFINE_OUT00_SVC 0x77, MapProcessCodeMemory
DEFINE_OUT00_SVC 0x78, UnmapProcessCodeMemory
DEFINE_OUT32_SVC 0x79, CreateProcess
DEFINE_OUT00_SVC 0x7A, StartProcess
DEFINE_OUT00_SVC 0x7B, TerminateProcess
DEFINE_OUT64_SVC 0x7C, GetProcessInfo
DEFINE_OUT32_SVC 0x7D, CreateResourceLimit
DEFINE_OUT00_SVC 0x7E, SetResourceLimitLimitValue
DEFINE_OUT00_SVC 0x7F, CallSecureMonitor

View file

@ -1,5 +0,0 @@
.global get_tls
get_tls:
mrs x0, tpidrro_el0
ret

View file

@ -1,104 +0,0 @@
#include<libtransistor/types.h>
#include<libtransistor/svc.h>
#include<libtransistor/util.h>
char nybble2hex(u8 nybble) {
if(nybble < 10) {
return '0' + nybble;
} else {
return 'a' + (nybble - 10);
}
}
size_t log_length = 0;
char log_buffer[0x10000];
int log_string(char *string, size_t len) {
svcOutputDebugString(string, len);
for(int i = 0; i < len; i++) {
if(string[i] == 0) { break; }
log_buffer[log_length++] = string[i];
}
log_buffer[log_length++] = '\n';
log_buffer[log_length] = 0;
return 4;
}
void hexdump(void *rawbuf, size_t size) {
u8 *buf = rawbuf;
char line[0x31 + 4 + 0x10 + 1];
int i = 0;
int total = 0;
while(total < size) {
i = 0;
int linestart = total;
// hexdump section
while(total < linestart + 0x10) {
if(total < size) {
u8 byte = buf[total++];
line[i++] = nybble2hex(byte >> 4);
line[i++] = nybble2hex(byte & 15);
line[i++] = ' ';
} else {
line[i++] = ' ';
line[i++] = ' ';
line[i++] = ' ';
}
if(i == 3*8) { line[i++] = ' '; }
}
line[i++] = ' ';
line[i++] = '|';
line[i++] = ' ';
line[i++] = ' ';
total = linestart;
while(total < linestart + 0x10) {
if(total < size) {
u8 ch = buf[total++];
if(ch >= ' ' && ch < 0x7F) {
line[i++] = ch;
} else {
line[i++] = '.';
}
} else {
line[i++] = ' ';
}
}
line[i++] = 0;
log_string(line, sizeof(line));
}
}
void hexnum(int num) {
char buf[16];
buf[15] = 0;
int i = 14;
for(; num; i--, num>>= 4) {
buf[i] = nybble2hex(num & 0xF);
}
buf[i--] = 'x';
buf[i--] = '0';
log_string(buf + i + 1, 16 - i);
}
#define STB_SPRINTF_IMPLEMENTATION
#include<libtransistor/stb_sprintf.h>
#include<stdarg.h>
int dbg_printf(char const *fmt, ...) {
va_list vl;
char buf[512];
int ret;
va_start(vl, fmt);
ret = dbg_vsnprintf(buf, 511, fmt, vl);
log_string(buf, ret+1);
va_end(vl);
return ret;
}

View file

@ -1,71 +0,0 @@
OUTPUT_FORMAT(elf64-littleaarch64)
SECTIONS
{
.text : ALIGN(0x1000) {
NORELOC_TEXT_START_ = .;
KEEP(crt0.nso.o(.text*))
KEEP(crt0.nro.o(.text*))
*(.text .text*)
*(.plt .plt*)
NORELOC_TEXT_END_ = .;
}
.rodata : ALIGN(0x1000) {
NORELOC_RODATA_START_ = .;
*(.rodata .rodata*)
NORELOC_RODATA_END_ = .;
}
.rela.dyn : ALIGN(8) {
NORELOC_RELA_START_ = .;
*(.rela.dyn)
}
.data : ALIGN(0x1000) {
NORELOC_DATA_START_ = .;
KEEP(crt0.nso.o(.data))
KEEP(crt0.nro.o(.data))
*(.data .data*)
NORELOC_GOT_START_ = .;
*(.got .got*)
NORELOC_GOT_PLT_START_ = .;
*(.got.plt .got.plt*)
NORELOC_DATA_END_ = .;
}
.dynamic : ALIGN(0x8) {
NORELOC_DYNAMIC_START_ = .;
*(.dynamic)
NORELOC_DYNAMIC_END_ = .;
}
.bss : ALIGN(0x1000) {
NORELOC_BSS_START_ = .;
*(.bss)
*(COMMON)
NORELOC_BSS_END_ = .;
}
.hash : {
*(.hash)
}
.dynstr : {
NORELOC_DYNSTR_START_ = .;
*(.dynstr .dynstr*)
NORELOC_DYNSTR_END_ = .;
}
.dynsym : {
NORELOC_DYNSYM_START_ = .;
*(.dynsym .dynsym*)
NORELOC_DYNSYM_END_ = .;
}
/DISCARD/ : {
*(.comment)
*(.note.GNU-stack)
*(.eh_frame)
}
}

@ -1 +0,0 @@
Subproject commit ca507418b832a4828a6b8b480f22132e2dc8e22a

View file

@ -1,2 +0,0 @@
pyelftools>=0.24
lz4>=0.10

View file

@ -1 +0,0 @@
hoge

View file

@ -1,153 +0,0 @@
#include<libtransistor/nx.h>
#include<sys/socket.h>
int main() {
svcSleepThread(100000000);
result_t r;
if((r = sm_init()) != RESULT_OK) {
dbg_printf("failed to init sm: 0x%x", r);
return 1;
}
svcSleepThread(100000000);
if((r = bsd_init()) != RESULT_OK) {
dbg_printf("failed to init bsd: 0x%x, %d", r, bsd_errno);
goto err_only_sm;
}
char bind_ip_addr[4] = {0, 0, 0, 0};
char server_ip_addr[4] = {127, 0, 0, 1};
struct sockaddr_in bind_addr = {
.sin_family = AF_INET,
.sin_port = htons(4444),
.sin_addr = {
.s_addr = *(uint32_t*) bind_ip_addr
}
};
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_port = htons(5555),
.sin_addr = {
.s_addr = *(uint32_t*) server_ip_addr
}
};
// client socket test
// socket, connect, sendto, recv, close
int cfd = bsd_socket(2, 1, 6); // AF_INET, SOCK_STREAM, PROTO_TCP
if(cfd < 0) {
dbg_printf("failed to create socket: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
dbg_printf("made client socket %d", cfd);
if(bsd_connect(cfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
dbg_printf("failed to connect socket: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
char hello[] = "Hello from libtransistor over a socket!";
if(bsd_sendto(cfd, hello, sizeof(hello), 0, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
dbg_printf("failed to sendto: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
int num_bytes;
char response[512];
char expected_response[] = "testing recv...";
if((num_bytes = bsd_recv(cfd, response, sizeof(response), 0)) < 0) {
dbg_printf("failed to recv: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
response[num_bytes] = 0;
if(num_bytes != sizeof(expected_response)) {
dbg_printf("got back wrong response: %s", response);
goto err;
}
for(int i = 0; i < num_bytes; i++) {
if(response[i] != expected_response[i]) {
dbg_printf("got back wrong response: %s", response);
goto err;
}
}
// server socket test
// socket, bind, listen, accept, send, recv, close
int sfd = bsd_socket(2, 1, 6); // AF_INET, SOCK_STREAM, PROTO_TCP
if(sfd < 0) {
dbg_printf("failed to create socket: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
if(bsd_bind(sfd, (struct sockaddr*) &bind_addr, sizeof(bind_addr)) < 0) {
dbg_printf("failed to bind socket: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
if(bsd_listen(sfd, 20) != 0) {
dbg_printf("failed to listen on socket: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
// don't close client test's socket until we're all set up.
// closing the client test's socket signals to the test helper
// that we're listening.
if(bsd_close(cfd) < 0) {
dbg_printf("failed to close: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
struct sockaddr_in remote_addr;
socklen_t remote_addr_len = sizeof(remote_addr);
int rfd;
if((rfd = bsd_accept(sfd, (struct sockaddr*) &remote_addr, &remote_addr_len)) < 0) {
dbg_printf("failed to accept: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
if(bsd_send(rfd, hello, sizeof(hello), 0) < 0) {
dbg_printf("failed to send: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
if((num_bytes = bsd_recv(rfd, response, sizeof(response), 0)) < 0) {
dbg_printf("failed to recv: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
response[num_bytes] = 0;
if(num_bytes != sizeof(expected_response)) {
dbg_printf("got back wrong response: %s", response);
goto err;
}
for(int i = 0; i < num_bytes; i++) {
if(response[i] != expected_response[i]) {
dbg_printf("got back wrong response: %s", response);
goto err;
}
}
if(bsd_close(rfd) < 0) {
dbg_printf("failed to close: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
if(bsd_close(sfd) < 0) {
dbg_printf("failed to close: 0x%x, %d", bsd_result, bsd_errno);
goto err;
}
bsd_finalize();
sm_finalize();
dbg_printf("bsd tests passed.");
return 0;
err:
bsd_finalize();
err_only_sm:
sm_finalize();
return 1;
}

View file

@ -1,89 +0,0 @@
#include<libtransistor/nx.h>
#include<sys/socket.h>
#include<string.h>
int main() {
result_t r;
char ip_addr[4] = {10, 0, 0, 192};
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(6767);
sa.sin_addr.s_addr = *(uint32_t*) ip_addr;
struct addrinfo ai_udp;
struct addrinfo ai_tcp;
ai_udp.ai_flags = 0;
ai_udp.ai_family = AF_INET;
ai_udp.ai_socktype = SOCK_DGRAM;
ai_udp.ai_protocol = IPPROTO_UDP;
ai_udp.ai_addrlen = sizeof(sa);
ai_udp.ai_addr = (struct sockaddr*) &sa;
ai_udp.ai_canonname = NULL;
ai_udp.ai_next = &ai_tcp;
ai_tcp.ai_flags = 0;
ai_tcp.ai_family = AF_INET;
ai_tcp.ai_socktype = SOCK_STREAM;
ai_tcp.ai_protocol = IPPROTO_TCP;
ai_tcp.ai_addrlen = sizeof(sa);
ai_tcp.ai_addr = (struct sockaddr*) &sa;
ai_tcp.ai_canonname = NULL;
ai_tcp.ai_next = NULL;
uint8_t buf[0x400];
r = bsd_ai_pack(&ai_udp, buf, sizeof(buf));
if(r) {
dbg_printf("failed to pack addrinfo: 0x%x", r);
return 1;
}
uint8_t template[] = {
0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x6f, 0x1a, 0xc0, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x10, 0x00, 0x02, 0x6f, 0x1a, 0xc0, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
for(int i = 0; i < sizeof(template); i++) {
if(buf[i] != template[i]) {
dbg_printf("packing mismatch at +0x%x", i);
hexdump(buf, 0x50);
return 1;
}
}
dbg_printf("bsd addrinfo packing test passed");
struct addrinfo *out;
r = bsd_ai_unpack(&out, template, sizeof(template));
if(r) {
dbg_printf("failed to unpack addrinfo: 0x%x", r);
return 1;
}
if(!(memcmp(out, &ai_udp, sizeof(struct addrinfo) - sizeof(ai_udp.ai_next)))) {
dbg_printf("ai_udp does not match");
return 1;
}
if(out->ai_next == NULL) {
dbg_printf("only unpacked one addrinfo struct");
return 1;
}
if(!(memcmp(out->ai_next, &ai_tcp, sizeof(struct addrinfo)))) {
dbg_printf("ai_tcp does not match");
return 1;
}
bsd_freeaddrinfo(out);
dbg_printf("bsd addrinfo unpacking test passed");
return 0;
}

View file

@ -1,16 +0,0 @@
#include<libtransistor/nx.h>
#include<malloc.h>
int main() {
svcSleepThread(100000000);
void *buf = malloc(4);
dbg_printf("malloc returned %p", buf);
if(buf == NULL) {
return 1;
}
return 0;
}

View file

@ -1,76 +0,0 @@
#include<libtransistor/nx.h>
#include<sys/socket.h>
void dumpsockaddrin(struct sockaddr_in *sin) {
dbg_printf("sin_family: %d", sin->sin_family);
dbg_printf("sin_port: %d", ntohs(sin->sin_port));
uint32_t addr = sin->sin_addr.s_addr;
uint8_t *bytes = (uint8_t*) &addr;
dbg_printf("sin_addr: %d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
}
void dumpaddrinfo(struct addrinfo *ai) {
dbg_printf("ai_flags: %d", ai->ai_flags);
dbg_printf("ai_family: %d", ai->ai_family);
dbg_printf("ai_socktype: %d", ai->ai_socktype);
dbg_printf("ai_protocol: %d", ai->ai_protocol);
dbg_printf("ai_addrlen: %d", ai->ai_addrlen);
if(ai->ai_family == AF_INET) {
dumpsockaddrin((struct sockaddr_in*) ai->ai_addr);
}
if(ai->ai_canonname) {
dbg_printf("ai_canonname: \"%s\"", ai->ai_canonname);
} else {
dbg_printf("ai_canonname: NULL");
}
if(ai->ai_next) {
dbg_printf("ai_next:");
dumpaddrinfo(ai->ai_next);
}
}
int main() {
svcSleepThread(100000000);
result_t r;
if((r = sm_init()) != RESULT_OK) {
dbg_printf("failed to init sm: 0x%x", r);
return 1;
}
if((r = bsd_init()) != RESULT_OK) {
dbg_printf("failed to init bsd: 0x%x, %d", r, bsd_errno);
goto err_only_sm;
}
struct addrinfo *ai = NULL;
struct addrinfo hints;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int e = bsd_getaddrinfo("conntest.nintendowifi.net", "6767", &hints, &ai);
if(e) {
dbg_printf("failed to getaddrinfo: %d, 0x%x", e, bsd_result);
goto err;
}
if(ai == NULL) {
dbg_printf("addrinfo is null?");
goto err;
}
dumpaddrinfo(ai);
bsd_finalize();
sm_finalize();
return 0;
err:
bsd_finalize();
err_only_sm:
sm_finalize();
return 1;
}

View file

@ -1,19 +0,0 @@
.section .text, "e"
.global main
main:
eor x2, x2, x2
movz x1, 0xbeef
mov x2, x1
movk x2, 0xdead, lsl 16
sub x3, x1, #0x431 // x3 = 0xbabe
movk x4, 0xcafe, lsl 16 // x4 = 0xcafe0000
orr x3, x3, x4 // x3 = 0xcafebabe
cmp w9, 0
subs wzr, w9, #0
subs w31, w9, #0
cmp x9, 0
subs xzr, x9, #0
subs x31, x9, #0
//subs sp, x9, #0 assembler error!
sub sp, x9, #0
b main

View file

@ -1,43 +0,0 @@
require "socket"
server = TCPServer.new(5555)
child = fork do
exec(ARGV[0], "--load-nro", "build/test/test_bsd.nro", "--enable-sockets")
end
client = server.accept
msg = client.recv(512)
if(msg != "Hello from libtransistor over a socket!\x00") then
Process.kill("INT", child)
raise "wrong hello message (got '#{msg}')"
end
client.send("testing recv...\x00", 0)
puts "waiting on eof..."
if(!client.eof) then
Process.kill("INT", child)
raise "remote end didn't close socket"
end
puts "eof reached"
client.close
server.close
puts "connecting"
client = TCPSocket.new("127.0.0.1", 4444)
puts "connected"
msg = client.recv(512)
if(msg != "Hello from libtransistor over a socket!\x00") then
Process.kill("INT", child)
raise "wrong hello message (got '#{msg}')"
end
client.send("testing recv...\x00", 0)
if(!client.eof) then
Process.kill("INT", child)
raise "remote end didn't close socket"
end
Process.wait(child)
exit($?.exitstatus)

View file

@ -1,115 +0,0 @@
#!/usr/bin/env python
import struct, sys
from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection
from elftools.elf.sections import *
import lz4.block
R_AARCH64_ABS64 = 257
R_AARCH64_ABS32 = 258
R_AARCH64_ABS16 = 259
R_AARCH64_PREL64 = 260
R_AARCH64_PREL32 = 261
R_AARCH64_PREL16 = 262
def main(input, output, format='nro'):
format = format.lower()
assert format in ('nro', 'nso')
with file(input, 'rb') as f:
elffile = ELFFile(f)
elffile.iter_sections_by_type = lambda type: (x for x in elffile.iter_sections() if isinstance(x, type))
symbols = {}
symbolList = []
for x in elffile.iter_sections_by_type(SymbolTableSection):
for i, sym in enumerate(x.iter_symbols()):
sectaddr = elffile.get_section(sym['st_shndx'])['sh_addr'] if isinstance(sym['st_shndx'], int) else 0
symbols[sym.name] = sectaddr + sym['st_value']
symbolList.append(sym.name)
textCont, rodataCont, relaDynCont, dataCont, dynamicCont = [elffile.get_section_by_name(x).data() for x in ('.text', '.rodata', '.rela.dyn', '.data', '.dynamic')]
csec = dict(text=textCont, rodata=rodataCont, relaDyn=relaDynCont, data=dataCont, dynamic=dynamicCont)
def replace(tgt, offset, data):
orig = csec[tgt]
csec[tgt] = orig[:offset] + data + orig[offset+len(data):]
for x in elffile.iter_sections_by_type(RelocationSection):
tgtsect = elffile.get_section(x['sh_info'])
tgt = tgtsect.name[1:]
if tgt not in csec:
continue
for iter in x.iter_relocations():
symname = symbolList[iter['r_info_sym']]
if not symname.startswith('NORELOC_'):
continue
type = iter['r_info_type']
if type == R_AARCH64_PREL32:
replace(tgt, iter['r_offset'], struct.pack('<i', symbols[symname] + iter['r_addend'] - (tgtsect['sh_addr'] + iter['r_offset'])))
elif type == R_AARCH64_ABS32:
replace(tgt, iter['r_offset'], struct.pack('<I', symbols[symname] + iter['r_addend']))
else:
print 'Unknown relocation type!', type
assert False
text, rodata, data = csec['text'], csec['rodata'], csec['data']
if len(rodata) & 0x7:
rodata += '\0' * (0x8 - (len(rodata) & 0x7))
rodata += csec['relaDyn']
if len(data) & 0x7:
data += '\0' * (0x8 - (len(data) & 0x7))
data += csec['dynamic']
if len(text) & 0xFFF:
text += '\0' * (0x1000 - (len(text) & 0xFFF))
if len(rodata) & 0xFFF:
rodata += '\0' * (0x1000 - (len(rodata) & 0xFFF))
if len(data) & 0xFFF:
data += '\0' * (0x1000 - (len(data) & 0xFFF))
bssSize = symbols['NORELOC_BSS_END_'] - symbols['NORELOC_BSS_START_']
if bssSize & 0xFFF:
bssSize += 0x1000 - (bssSize & 0xFFF)
if format == 'nro':
#text = text[0x80:]
with file(output, 'wb') as fp:
fp.write(struct.pack('<IIII', 0, len(text) + len(rodata) + 8, 0, 0))
fp.write('NRO0')
fp.write(struct.pack('<III', 0, len(text) + len(rodata) + len(data), 0))
fp.write(struct.pack('<IIII', 0, len(text), len(text), len(rodata)))
fp.write(struct.pack('<IIII', len(text) + len(rodata), len(data), bssSize, 0))
fp.write('\0' * 0x40)
fp.write(text[0x80:])
fp.write(rodata)
fp.write(data)
else:
with file(output, 'wb') as fp:
ctext, crodata, cdata = [lz4.block.compress(x, store_size=False) for x in (text, rodata, data)]
fp.write('NSO0')
fp.write('\0' * 0xC)
off = 0x101
fp.write(struct.pack('<IIII', off, 0, len(text), 0))
off += len(ctext)
fp.write(struct.pack('<IIII', off, len(text), len(rodata), 0))
off += len(crodata)
fp.write(struct.pack('<IIII', off, len(text) + len(rodata), len(data), symbols['NORELOC_BSS_END_'] - symbols['NORELOC_BSS_START_']))
fp.write('\0' * 0x20)
fp.write(struct.pack('<IIII', len(ctext), len(crodata), len(cdata), 0))
fp.write('\0' * 0x91)
fp.write(ctext)
fp.write(crodata)
fp.write(cdata)
if __name__=='__main__':
sys.exit(main(*sys.argv[1:]))

View file

@ -1,320 +0,0 @@
import sys
sys.path.append('SwIPC')
import idparser
import glob, re
def emitInt(x):
return '0x%x' % x if x > 9 else str(x)
typemap = dict(
i8='int8_t',
i16='int16_t',
i32='int32_t',
i64='int64_t',
i128='int128_t',
u8='uint8_t',
u16='uint16_t',
u32='uint32_t',
u64='uint64_t',
u128='uint128_t',
f32='float32_t',
pid='gpid',
bool='bool',
)
typesizes = dict(
i8=1,
i16=2,
i32=4,
i64=8,
i128=16,
u8=1,
u16=2,
u32=4,
u64=8,
u128=16,
f32=4,
pid=8,
bool=1,
)
allTypes = None
def typeSize(type):
if type[0] in ('unknown', 'i8', 'u8'):
return 1
elif type[0] == 'bytes':
return type[1]
elif type[0] in allTypes:
return typeSize(allTypes[type[0]])
elif type[0] in typesizes:
return typesizes[type[0]]
return 1
def splitByNs(obj):
ons = {}
for type, x in obj.items():
ns = type.rsplit('::', 1)[0] if '::' in type else None
name = type.rsplit('::', 1)[-1]
if ns not in ons:
ons[ns] = {}
ons[ns][name] = x
return ons
def retype(spec, noIndex=False):
if spec[0] == 'unknown':
return 'uint8_t'
elif spec[0] == 'bytes':
return 'uint8_t%s' % ('[%s]' % emitInt(spec[1]) if not noIndex else ' *')
else:
return typemap[spec[0]] if spec[0] in typemap else spec[0];
def formatParam(param, input, i):
name, spec = param
if name is None:
name = '_%i' % i
hasSize = False
if spec[0] == 'align':
return formatParam((name, spec[2]), input, i)
if spec[0] == 'bytes':
type = 'uint8_t *'
elif spec[0] == 'unknown':
assert False
elif spec[0] == 'buffer':
type = '%s *' % retype(spec[1])
hasSize = True
elif spec[0] == 'array':
type = retype(spec[1]) + ' *'
hasSize = True
elif spec[0] == 'object':
type = '%s *' % spec[1][0]
elif spec[0] == 'KObject':
type = 'KObject *'
else:
type = typemap[spec[0]] if spec[0] in typemap else spec[0]
if type.endswith(']'):
arrspec = type[type.index('['):]
type = type[:-len(arrspec)]
else:
arrspec = ''
return '%s %s%s %s%s%s' % ('IN' if input else 'OUT', type, '&' if not input and (not type.endswith('*') and not arrspec) else '', name, arrspec, ', guint %s_size' % name if hasSize else '')
def generatePrototype(func):
return ', '.join([formatParam(x, True, i) for i, x in enumerate(func['inputs'])] + [formatParam(x, False, i + len(func['inputs'])) for i, x in enumerate(func['outputs'])])
def isPointerType(type):
if type[0] in typesizes:
return False
elif type[0] == 'bytes':
return True
elif type[0] in allTypes:
return isPointerType(allTypes[type[0]])
return True
AFTER = 'AFTER'
def generateCaller(qname, fname, func):
def tempname():
tempI[0] += 1
return 'temp%i' % tempI[0]
params = []
logFmt, logElems = [], []
tempI = [0]
inpOffset = 8
bufOffs = {}
hndOff = 0
objOff = 0
bufSizes = 0
for name, elem in func['inputs']:
type, rest = elem[0], elem[1:]
if type in ('array', 'buffer'):
if rest[1] not in bufOffs:
bufOffs[rest[1]] = 0
cbo = bufOffs[rest[1]]
bufOffs[rest[1]] += 1
an, sn, bn = tempname(), tempname(), tempname()
yield 'guint %s;' % sn
yield 'auto %s = req.getBuffer(%s, %i, %s);' % (an, emitInt(rest[1]), cbo, sn)
#yield 'auto %s = new uint8_t[%s];' % (bn, sn)
yield 'ctu->cpu.readmem(%s, %s, %s);' % (an, bn, sn)
params.append('(%s *) %s' % (retype(rest[0]), bn))
params.append(sn)
logFmt.append('%s *%s= buffer<0x" ADDRFMT ">' % (retype(rest[0]), '%s ' % name if name else ''))
logElems.append(sn)
bufSizes += 1
yield AFTER, 'delete[] %s;' % bn
elif type == 'object':
params.append('ctu->getHandle<%s>(req.getMoved(%i))' % (rest[0][0], objOff))
logFmt.append('%s %s= 0x%%x' % (rest[0][0], '%s ' % name if name else ''))
logElems.append('req.getMoved(%i)' % objOff)
objOff += 1
elif type == 'KObject':
params.append('ctu->getHandle<KObject>(req.getCopied(%i))' % hndOff)
logFmt.append('KObject %s= 0x%%x' % ('%s ' % name if name else ''))
logElems.append('req.getCopied(%i)' % objOff)
hndOff += 1
elif type == 'pid':
params.append('req.pid')
else:
if elem[0] == 'align':
alignment = elem[1]
elem = elem[2]
else:
alignment = min(8, typeSize(elem))
while inpOffset % alignment:
inpOffset += 1
if isPointerType(elem):
params.append('req.getDataPointer<%s>(%s)' % (retype(elem, noIndex=True), emitInt(inpOffset)))
logFmt.append('%s %s= %%s' % (retype(elem), '%s ' % name if name else ''))
logElems.append('bufferToString(req.getDataPointer<uint8_t *>(%s), %s).c_str()' % (emitInt(inpOffset), emitInt(typeSize(elem))))
else:
params.append('req.getData<%s>(%s)' % (retype(elem), emitInt(inpOffset)))
if typeSize(elem) == 16:
logFmt.append('%s %s= %%s' % (retype(elem), '%s ' % name if name else ''))
logElems.append('bufferToString(req.getDataPointer<uint8_t *>(%s), %s).c_str()' % (emitInt(inpOffset), emitInt(typeSize(elem))))
else:
type = retype(elem)
ct = '0x%x'
if type == 'float32_t':
ct = '%f'
elif typeSize(elem) == 8:
ct = '0x" ADDRFMT "'
logFmt.append('%s %s= %s' % (type, '%s ' % name if name else '', ct))
logElems.append('%sreq.getData<%s>(%s)' % ('(double) ' if type == 'float32_t' else '', type, emitInt(inpOffset)))
inpOffset += typeSize(elem)
outOffset = 8
hndOff = 0
objOff = 0
for i, (name, elem) in enumerate(func['outputs']):
if name is None:
name = '_%i' % (i + len(func['inputs']))
type, rest = elem[0], elem[1:]
if type in ('array', 'buffer'):
if rest[1] not in bufOffs:
bufOffs[rest[1]] = 0
cbo = bufOffs[rest[1]]
bufOffs[rest[1]] += 1
an, sn, bn = tempname(), tempname(), tempname()
yield 'guint %s;' % sn
yield 'auto %s = req.getBuffer(%s, %i, %s);' % (an, emitInt(rest[1]), cbo, sn)
#yield 'auto %s = new uint8_t[%s];' % (bn, sn)
bufSizes += 1
yield AFTER, 'ctu->cpu.writemem(%s, %s, %s);' % (an, bn, sn)
yield AFTER, 'delete[] %s;' % bn
elif type == 'object':
yield AFTER, '%s = new %s(resp.move_handles[%i]);' % (name, rest[0][0], objOff)
objOff += 1
elif type == 'KObject':
hndOff += 1
elif type == 'pid':
assert False
else:
if elem[0] == 'align':
alignment = elem[1]
elem = elem[2]
else:
alignment = min(8, typeSize(elem))
while outOffset % alignment:
outOffset += 1
if isPointerType(elem):
tn = tempname()
yield 'auto %s = resp.getDataPointer<%s>(%s);' % (tn, retype(elem, noIndex=True), emitInt(outOffset))
params.append(tn)
else:
params.append('*resp.getDataPointer<%s *>(%s)' % (retype(elem), emitInt(outOffset)))
outOffset += typeSize(elem)
yield 'auto ret = ipc_send(session, &req, &resp);'
yield AFTER
yield 'return ret;'
def reorder(gen):
after = []
for x in gen:
if x == AFTER:
for elem in after:
yield elem
elif isinstance(x, tuple) and x[0] == AFTER:
after.append(x[1])
else:
yield x
def parsePartials(code):
code = '\n'.join(re.findall(r'/\*\$IPC\$(.*?)\*/', code, re.M|re.S))
return partialparser.parse(code)
def main():
global allTypes
types, ifaces, services = idparser.getAll()
allTypes = types
typesByNs = splitByNs(types)
ifacesByNs = splitByNs(ifaces)
namespaces = {x : [] for x in typesByNs.keys() + ifacesByNs.keys()}
for ns, types in typesByNs.items():
for name, spec in sorted(types.items(), key=lambda x: x[0]):
retyped, plain = retype(spec, noIndex=True), retype(spec)
namespaces[ns].append('using %s = %s;%s' % (name, retyped, ' // ' + plain if retyped != plain else ''))
for ns, ifaces in ifacesByNs.items():
for name in sorted(ifaces.keys()):
namespaces[ns].append('class %s;' % name)
with file('lib/ipcClients.h', 'w') as fp:
print >>fp, '#pragma once'
print >>fp, '#include<libtransistor/ipc.h>'
print >>fp
for ns, elems in sorted(namespaces.items(), key=lambda x: x[0]):
if ns is not None:
print >>fp, 'namespace %s {' % ns
hasUsing = False
for elem in elems:
if not hasUsing and elem.startswith('using'):
hasUsing = True
elif hasUsing and elem.startswith('class'):
print >>fp
hasUsing = False
print >>fp, ('\t' if ns is not None else '') + elem
if ns is not None:
print >>fp, '}'
print >>fp
for ns, ifaces in sorted(ifacesByNs.items(), key=lambda x: x[0]):
print >>fp, '%snamespace %s {' % ('//// ' if ns is None else '', ns)
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
qname = '%s::%s' % (ns, name) if ns else name
print >>fp, '\tclass %s {' % name
print >>fp, '\tpublic:'
print >>fp, '\t\t%s();' % name
for fname, func in sorted(funcs.items(), key=lambda x: x[0]):
print >>fp, '\t\tuint32_t %s(%s);' % (fname, generatePrototype(func))
print >>fp, '\t};'
print >>fp, '%s}' % ('//// ' if ns is None else '')
print >>fp, '#ifdef DEFINE_CALLERS'
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
qname = '%s::%s' % (ns, name) if ns else name
for fname, func in sorted(funcs.items(), key=lambda x: x[0]):
print >>fp, 'uint32_t %s::%s(%s) {' % (qname, fname, generatePrototype(func))
print >>fp, '\tipc_request_t req;'
print >>fp, '\tipc_response_t resp;'
print >>fp, '\tmemset(&req, 0, sizeof(ipc_request_t));'
print >>fp, '\n'.join('\t' + x for x in reorder(generateCaller(qname, fname, func)))
print >>fp, '}'
print >>fp, '#endif // DEFINE_CALLERS'
if __name__=='__main__':
main(*sys.argv[1:])