code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Utils/SysWrappers.hpp>
#include <Utils/Kdlsym.hpp>
#include <Utils/Kernel.hpp>
#include <Utils/_Syscall.hpp>

extern "C"
{
    #include <sys/sysproto.h>
    #include <sys/sysent.h>
    #include <sys/pcpu.h>
    #include <sys/proc.h>
    #include <vm/vm.h>

    #include <sys/_iovec.h>
    #include <sys/uio.h>

    #include <fcntl.h>
}

#ifndef MAP_FAILED
#define MAP_FAILED      ((void *)-1)
#endif

///
/// 7: sys_wait4
//
int kwait4(int pid, int* status, int options, struct rusage* rusage)
{
	return kwait4_t(pid, status, options, rusage, curthread);
}

int kwait4_internal(int pid, int *status, int options, struct rusage *rusage, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto wait4 = (int(*)(struct thread* thread, struct wait_args*))sysents[SYS_WAIT4].sy_call;
	if (!wait4)
		return -1;

	int error;
	struct wait_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.pid = pid;
	uap.status = status;
	uap.options = options;
	uap.rusage = rusage;
	error = wait4(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kwait4_t(int pid, int* status, int options, struct rusage* rusage, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kwait4_internal(pid, status, options, rusage, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

//
// 203: sys_mlock
//
int kmlock(void* address, uint64_t size)
{
	return kmlock_t(address, size, curthread);
}

int kmlock_internal(void* address, uint64_t size, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto mlock = (int(*)(struct thread*, struct mlock_args*))sysents[SYS_MLOCK].sy_call;
	if (!mlock)
		return -1;

	int error;
	struct mlock_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.addr = (const void*)((uint64_t)address & 0xffffffffffffc000);
	uap.len = size;
	error = mlock(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kmlock_t(void* address, uint64_t size, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kmlock_internal(address, size, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

//
// 324: sys_mlockall
//
int kmlockall(int how)
{
	return kmlockall_t(how, curthread);
}

int kmlockall_internal(int how, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_mlockall = (int(*)(struct thread*, struct mlockall_args*))sysents[SYS_MLOCKALL].sy_call;
	if (!sys_mlockall)
		return -1;

	int error;
	struct mlockall_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.how = how;
	error = sys_mlockall(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kmlockall_t(int how, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kmlockall_internal(how, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

//
// 477: sys_mmap
//
caddr_t __attribute__((noinline)) kmmap_internal(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_mmap = (int(*)(struct thread*, struct mmap_args*))sysents[SYS_MMAP].sy_call;
	if (!sys_mmap)
		return (caddr_t)-1;

	int error;
	struct mmap_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.addr = addr;
	uap.len = len;
	uap.prot = prot;
	uap.flags = flags;
	uap.fd = fd;
	uap.pos = pos;
	error = sys_mmap(td, &uap);
	if (error)
		return (caddr_t)(int64_t)-error;

	// return
	return (caddr_t)td->td_retval[0];
}

caddr_t kmmap_t(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos, struct thread* td)
{
	int64_t ret = (-EIO);
	int retry = 0;

	for (;;)
	{
		ret = (int64_t)kmmap_internal(addr, len, prot, flags, fd, pos, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return (caddr_t)ret;
		}

		break;
	}

	return (caddr_t)ret;
}

caddr_t kmmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos)
{
	return kmmap_t(addr, len, prot, flags, fd, pos, curthread);
}

//
// 478: sys_lseek
//

off_t klseek_internal(int fd, off_t offset, int whence, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_lseek = (int(*)(struct thread*, struct lseek_args*))(void*)sysents[SYS_LSEEK].sy_call;

	if (!sys_lseek)
		return -1;

	int error;
	struct lseek_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	uap.offset = offset;
	uap.whence = whence;
	error = sys_lseek(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

off_t klseek_t(int fd, off_t offset, int whence, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = klseek_internal(fd, offset, whence, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

off_t klseek(int fd, off_t offset, int whence)
{
	return klseek_t(fd, offset, whence, curthread);
}

//
// 73: sys_munmap
//
int kmunmap_internal(void *addr, size_t len, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_munmap = (int(*)(struct thread*, struct munmap_args*))sysents[SYS_MUNMAP].sy_call;
	if (!sys_munmap)
		return -1;

	int error;
	struct munmap_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.addr = addr;
	uap.len = len;
	error = sys_munmap(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kmunmap_t(void *addr, size_t len, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kmunmap_internal(addr, len, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kmunmap(void *addr, size_t len)
{
	return kmunmap_t(addr, len, curthread);
}

//
// 3: sys_read
//
ssize_t kread_internal(int fd, void* buf, size_t count, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_read = (int(*)(struct thread*, struct read_args*))sysents[SYS_READ].sy_call;
	if (!sys_read)
		return -1;

	int error;
	struct read_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	uap.buf = buf;
	uap.nbyte = count;

	error = sys_read(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

ssize_t kread_t(int fd, void* buf, size_t count, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kread_internal(fd, buf, count, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

ssize_t kread(int fd, void* buf, size_t count)
{
	return kread_t(fd, buf, count, curthread);
}

//
// 189: sys_fstat
//
int kfstat_internal(int fd, struct stat* sb, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_fstat = (int(*)(struct thread*, struct fstat_args*))sysents[SYS_FSTAT].sy_call;
	if (!sys_fstat)
		return -1;

	int error;
	struct fstat_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	uap.sb = (struct stat *)sb;

	error = sys_fstat(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kfstat_t(int fd, struct stat* sb, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kfstat_internal(fd, sb, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kfstat(int fd, struct stat* sb)
{
	return kfstat_t(fd, sb, curthread);
}

//
// 188: sys_stat
//

int kstat_internal(char* path, struct stat* buf, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_stat = (int(*)(struct thread*, struct stat_args*))sysents[SYS_STAT].sy_call;
	if (!sys_stat)
		return -1;

	int error;
	struct stat_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = path;
	uap.ub = buf;

	error = sys_stat(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kstat_t(char* path, struct stat* buf, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kstat_internal(path, buf, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kstat(char* path, struct stat* buf)
{
	return kstat_t(path, buf, curthread);
}

//
// 6: sys_close
//
int kclose_internal(int fd, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_close = (int(*)(struct thread *, struct close_args *))sysents[SYS_CLOSE].sy_call;
	if (!ksys_close)
		return -1337;

	int error;
	struct close_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	error = ksys_close(td, &uap);
	if (error)
		return -error;

	return 0;
}

void kclose_t(int fd, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kclose_internal(fd, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return;
		}

		break;
	}

	return;
}

void kclose(int socket)
{
	kclose_t(socket, curthread);
}

//
// 97: sys_socket
//
int ksocket_internal(int a, int b, int c, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_socket = (int(*)(struct thread*, struct socket_args*))sysents[SYS_SOCKET].sy_call;

	int error;
	struct socket_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.domain = a;
	uap.type = b;
	uap.protocol = c;
	error = ksys_socket(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int ksocket_t(int a, int b, int c, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = ksocket_internal(a, b, c, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int ksocket(int a, int b, int c)
{
	return ksocket_t(a, b, c, curthread);
}

//
// 4: sys_write
//
ssize_t kwrite_internal(int d, const void* buf, size_t nbytes, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_write = (int(*)(struct thread*, struct write_args*))sysents[SYS_WRITE].sy_call;
	if (!ksys_write)
		return -1;

	int error;
	struct write_args uap;
	memset(&uap, 0, sizeof(uap));

	// clear errors
	td->td_retval[0] = 0;
	//const auto off = offsetof(struct thread, td_retval);

	// call syscall
	uap.fd = d;
	uap.buf = buf;
	uap.nbyte = nbytes;
	error = ksys_write(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

ssize_t kwrite_t(int d, const void* buf, size_t nbytes, struct thread* td)
{
	ssize_t ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kwrite_internal(d, buf, nbytes, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

ssize_t kwrite(int d, const void* buf, size_t nbytes)
{
	return kwrite_t(d, buf, nbytes, curthread);
}

//
// 272: sys_getdents
//
int kgetdents_internal(int fd, char* buf, int nbytes, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_getdents = (int(*)(struct thread*, struct getdents_args*))sysents[SYS_GETDENTS].sy_call;

	int error;
	struct getdents_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	uap.buf = buf;
	uap.count = (size_t)nbytes;
	error = sys_getdents(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kgetdents_t(int fd, char* buf, int nbytes, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kgetdents_internal(fd, buf, nbytes, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kgetdents(int fd, char* buf, int nbytes, struct thread* td)
{
	return kgetdents_t(fd, buf, nbytes, curthread);
}

//
// 104: sys_bind
//
int kbind_internal(int socket, const struct sockaddr * b, size_t c, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_bind = (int(*)(struct thread *, struct bind_args *))sysents[SYS_BIND].sy_call;

	int error;
	struct bind_args uap;

	(void)memset(&uap, 0, sizeof(uap));

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = socket;
	uap.name = (caddr_t)b;
	uap.namelen = (int)c;
	error = ksys_bind(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kbind_t(int socket, const struct sockaddr * b, size_t c, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kbind_internal(socket, b, c, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kbind(int socket, const struct sockaddr * b, size_t c)
{
	return kbind_t(socket, b, c, curthread);
}

//
// 106: sys_listen
//
int klisten_internal(int sockfd, int backlog, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_listen = (int(*)(struct thread *, struct listen_args *))sysents[SYS_LISTEN].sy_call;
	int error;
	struct listen_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = sockfd;
	uap.backlog = backlog;
	error = ksys_listen(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int klisten_t(int sockfd, int backlog, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = klisten_internal(sockfd, backlog, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int klisten(int sockfd, int backlog)
{
	return klisten_t(sockfd, backlog, curthread);
}

//
// 30: sys_accept
//

int kaccept_internal(int sock, struct sockaddr * b, size_t* c, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_accept = (int(*)(struct thread *, struct accept_args *))sysents[SYS_ACCEPT].sy_call;
	int error;
	struct accept_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = sock;
	uap.name = b;
	uap.anamelen = (__socklen_t*)c;
	error = ksys_accept(td, &uap);

	// success?
	if (error == 0)
	{
		// return socket
		return td->td_retval[0];
	}
	// interrupted?
	else if ((error == EINTR) || (error == ERESTART))
	{
		// failed
		return -EINTR;
	}
	// failed?
	else if (error > 0)
		return -error;
	else
		return error;
}

int kaccept_t(int sock, struct sockaddr * b, size_t* c, struct thread* td)
{
	int retry = 0;
	int ret = -EIO;

	for (;;)
	{
		ret = kaccept_internal(sock, b, c, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kaccept(int sock, struct sockaddr * b, size_t* c)
{
	return kaccept_t(sock, b, c, curthread);
}

//
// 29: sys_recvfrom
int krecv_internal(int s, void * buf, int len, int flags, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_recvfrom = (int(*)(struct thread *, struct recvfrom_args *))sysents[SYS_RECVFROM].sy_call;
	if (!ksys_recvfrom)
		return -1;

	int error;
	struct recvfrom_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = s;
	uap.buf = static_cast<caddr_t>(buf);
	uap.len = len;
	uap.flags = flags;
	uap.from = 0;
	uap.fromlenaddr = 0;
	error = ksys_recvfrom(td, &uap);

	// success?
	if (error == 0)
	{
		// return length
		return td->td_retval[0];
	}
	// invalid?
	else if (error == EFAULT)
	{
		// invalid memory
		return -EFAULT;
	}
	// interrupted?
	else if ((error == EINTR) || (error == ERESTART))
	{
		// failed
		return -EINTR;
	}
	// failed?
	else if (error > 0)
		return -error;
	else
		return error;
}

int krecv_t(int s, void * buf, int len, int flags, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = krecv_internal(s, buf, len, flags, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int krecv(int s, void * buf, int len, int flags)
{
	return krecv_t(s, buf, len, flags, curthread);
}

//
// 133: sys_sendto
//
int ksend_internal(int socket, caddr_t buf, size_t len, int flags, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_sendto = (int(*)(struct thread *, struct sendto_args *))sysents[SYS_SENDTO].sy_call;
	if (!ksys_sendto)
		return -1;

	int error;
	struct sendto_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = socket;
	uap.buf = buf;
	uap.len = len;
	uap.flags = flags;
	uap.to = 0;
	uap.tolen = 0;
	error = ksys_sendto(td, &uap);

	// success?
	if (error == 0)
	{
		// return length
		return td->td_retval[0];
	}
	// invalid?
	else if (error == EFAULT)
	{
		// invalid memory
		return -EFAULT;
	}
	// interrupted?
	else if ((error == EINTR) || (error == ERESTART))
	{
		// failed
		return -EINTR;
	}
	// failed?
	else if (error > 0)
		return -error;
	else
		return error;
}

int ksend_t(int socket, caddr_t buf, size_t len, int flags, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = ksend_internal(socket, buf, len, flags, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int ksend(int socket, caddr_t buf, size_t len, int flags)
{
	return ksend_t(socket, buf, len, flags, curthread);
}

//
// 5: sys_open
//
int kopen_internal(const char* path, int flags, int mode, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto ksys_open = (int(*)(struct thread *, struct open_args *))sysents[SYS_OPEN].sy_call;

	int error;
	struct open_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = const_cast<char*>(path);
	uap.flags = flags;
	uap.mode = mode;

	error = ksys_open(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kopen_t(const char* path, int flags, int mode, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kopen_internal(path, flags, mode, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kopen(const char* path, int flags, int mode)
{
	return kopen_t(path, flags, mode, curthread);
}

//
// 90: sys_dup2
//
int kdup2_internal(int oldd, int newd, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_dup2 = (int(*)(struct thread *, struct dup2_args *))sysents[SYS_DUP2].sy_call;

	int error;
	struct dup2_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.from = oldd;
	uap.to = newd;

	error = sys_dup2(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kdup2_t(int oldd, int newd, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kdup2_internal(oldd, newd, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kdup2(int oldd, int newd)
{
	return kdup2_t(oldd, newd, curthread);
}

//
// 136: sys_mkdir
//
int kmkdir_internal(char * path, int mode, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_mkdir = (int (*)(struct thread*, struct mkdir_args*))sysents[SYS_MKDIR].sy_call;

	int error;
	struct mkdir_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = path;
	uap.mode = mode;

	error = sys_mkdir(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kmkdir_t(char * path, int mode, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kmkdir_internal(path, mode, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kmkdir(char * path, int mode)
{
	return kmkdir_t(path, mode, curthread);
}

//
// 137: sys_rmdir
//
int krmdir_internal(char * path, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_rmdir = (int(*)(struct thread *, struct rmdir_args *))sysents[SYS_RMDIR].sy_call;

	int error;
	struct rmdir_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = path;

	error = sys_rmdir(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int krmdir_t(char * path, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = krmdir_internal(path, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int krmdir(char * path)
{
	return krmdir_t(path, curthread);
}

//
// 134: sys_shutdown
//
int kshutdown_internal(int s, int how, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_shutdown = (int(*)(struct thread *, struct shutdown_args *))sysents[SYS_SHUTDOWN].sy_call;

	int error;
	struct shutdown_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = s;
	uap.how = how;

	error = sys_shutdown(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kshutdown_t(int s, int how, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kshutdown_internal(s, how, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kshutdown(int s, int how)
{
	return kshutdown_t(s, how, curthread);
}

//
// 10: sys_unlink
//
int kunlink_internal(char* path, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_unlink = (int(*)(struct thread *, struct unlink_args *))sysents[SYS_UNLINK].sy_call;

	int error;
	struct unlink_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = path;

	error = sys_unlink(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kunlink_t(char* path, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kunlink_internal(path, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kunlink(char* path)
{
	return kunlink_t(path, curthread);
}

//
// 23: sys_setuid
//
int ksetuid_internal(uid_t uid, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_setuid = (int(*)(struct thread *, struct setuid_args *))sysents[SYS_SETUID].sy_call;

	int error;
	struct setuid_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.uid = uid;

	error = sys_setuid(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int ksetuid_t(uid_t uid, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = ksetuid_internal(uid, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int ksetuid(uid_t uid)
{
	return ksetuid_t(uid, curthread);
}

//
// 26: sys_ptrace
//
int kptrace_internal(int req, pid_t pid, caddr_t addr, int data, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_ptrace = (int(*)(struct thread *, struct ptrace_args *))sysents[SYS_PTRACE].sy_call;

	int error;
	struct ptrace_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.req = req;
	uap.pid = pid;
	uap.addr = addr;
	uap.data = data;

	error = sys_ptrace(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kptrace_t(int req, pid_t pid, caddr_t addr, int data, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kptrace_internal(req, pid, addr, data, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kptrace(int req, pid_t pid, caddr_t addr, int data)
{
	return kptrace_t(req, pid, addr, data, curthread);
}

//
// 37: sys_kill
//
int kkill_internal(int pid, int signum, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_kill = (int(*)(struct thread *, struct kill_args *))sysents[SYS_KILL].sy_call;

	int error;
	struct kill_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.pid = pid;
	uap.signum = signum;

	error = sys_kill(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kkill_t(int pid, int signum, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kkill_internal(pid, signum, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kkill(int pid, int signum)
{
	return kkill_t(pid, signum, curthread);
}

//
// 105: sys_setsockopt
//
int ksetsockopt_internal(int socket, int level, int name, caddr_t val, int valsize, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_setsockopt = (int(*)(struct thread *, struct setsockopt_args *))sysents[SYS_SETSOCKOPT].sy_call;

	int error;
	struct setsockopt_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.s = socket;
	uap.level = level;
	uap.name = name;
	uap.val = val;
	uap.valsize = valsize;

	error = sys_setsockopt(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int ksetsockopt_t(int socket, int level, int name, caddr_t val, int valsize, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = ksetsockopt_internal(socket, level, name, val, valsize, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int ksetsockopt(int socket, int level, int name, caddr_t val, int valsize)
{
	return ksetsockopt_t(socket, level, name, val, valsize, curthread);
}

//
// 480: sys_ftruncate
//
int kftruncate_internal(int fd, off_t length, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_ftruncate = (int(*)(struct thread *, struct ftruncate_args *))sysents[SYS_FTRUNCATE].sy_call;

	int error;
	struct ftruncate_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	uap.length = length;

	error = sys_ftruncate(td, &uap);
	if (error)
		return -error;

	// success
	return td->td_retval[0];
}

int kftruncate_t(int fd, off_t length, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kftruncate_internal(fd, length, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kftruncate(int fd, off_t length)
{
	return kftruncate_t(fd, length, curthread);
}

//
// 251: sys_rfork
//
pid_t krfork_internal(int flags, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_rfork= (int(*)(struct thread *, struct rfork_args *))sysents[SYS_RFORK].sy_call;

	int error;
	struct rfork_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.flags = flags;
	error = sys_rfork(td, &uap);
	if (error)
		return -error;

	// success
	return (pid_t)td->td_retval[0];
}

pid_t krfork_t(int flags, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = krfork_internal(flags, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

pid_t krfork(int flags, struct thread* td)
{
	return krfork_t(flags, curthread);
}

//
// 55: sys_reboot
//
int kreboot_internal(int opt, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_reboot = (int(*)(struct thread*, struct reboot_args*))sysents[SYS_REBOOT].sy_call;
	if (!sys_reboot)
		return -1;

	int error;
	struct reboot_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.opt = opt;
	error = sys_reboot(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kreboot_t(int opt, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kreboot_internal(opt, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kreboot(int opt)
{
	return kreboot_t(opt, curthread);
}

//
// 74: mprotect
int mprotect_internal(const void* addr, size_t len, int prot, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_mprotect = (int(*)(struct thread*, struct mprotect_args*))sysents[SYS_MPROTECT].sy_call;
	if (!sys_mprotect)
		return -1;

	int error;
	struct mprotect_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.addr = addr;
	uap.len = len;
	uap.prot = prot;
	error = sys_mprotect(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kmprotect_t(void* addr, size_t len, int prot, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = mprotect_internal(addr, len, prot, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kselect_internal(int	nfds, fd_set *readfds, fd_set *writefds, fd_set	*exceptfds, struct	timeval	*timeout, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_select = (int(*)(struct thread*, struct select_args*))sysents[SYS_SELECT].sy_call;
	if (!sys_select)
		return -1;

	int error;
	struct select_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.nd = nfds;
	uap.in = readfds;
	uap.ou = writefds;
	uap.ex = exceptfds;
	uap.tv = timeout;
	error = sys_select(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kselect_t(int	nfds, fd_set *readfds, fd_set *writefds, fd_set	*exceptfds, struct	timeval	*timeout, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kselect_internal(nfds, readfds, writefds, exceptfds, timeout, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kioctl_internal(int fd, u_long com, caddr_t data, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_ioctl = (int(*)(struct thread*, struct ioctl_args*))sysents[SYS_IOCTL].sy_call;
	if (!sys_ioctl)
		return -1;

	int error;
	struct ioctl_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd = fd;
	uap.com = com;
	uap.data = data;

	error = sys_ioctl(td, &uap);
	auto printf = (void(*)(const char *format, ...))kdlsym(printf);
	printf("err: (%d), retval: (%lld)\n", error, td->td_retval[0]);

	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kioctl_t(int fd, u_long com, caddr_t data, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kioctl_internal(fd, com, data, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kdynlib_load_prx_internal(char* path, uint64_t args, uint64_t argp, uint32_t flags, uint64_t pOpt, uint64_t pRes, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_dynlib_load_prx = (int(*)(struct thread*, struct dynlib_load_prx_args*))sysents[SYS_DYNLIB_LOAD_PRX].sy_call;
	if (!sys_dynlib_load_prx)
		return -1;

	int error;
	struct dynlib_load_prx_args uap;
	uap.path = path;
	uap.args = args;
	uap.argp = argp;
	uap.flags = flags;
	uap.pOpt = pOpt;
	uap.pRes = pRes;

	error = sys_dynlib_load_prx(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kdynlib_load_prx_t(char* path, uint64_t args, uint64_t argp, uint32_t flags, uint64_t pOpt, int* pRes, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kdynlib_load_prx_internal(path, args, argp, flags, pOpt, (uint64_t)pRes, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kdynlib_get_obj_member_internal(uint32_t handle, uint32_t index, uint64_t value, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_dynlib_get_obj_member = (int(*)(struct thread*, struct dynlib_get_obj_member*))sysents[SYS_DYNLIB_GET_OBJ_MEMBER].sy_call;
	if (!sys_dynlib_get_obj_member)
		return -1;

	int error;
	struct dynlib_get_obj_member uap;
	uap.handle = handle;
	uap.index = index;
	uap.value = value;

	error = sys_dynlib_get_obj_member(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kdynlib_get_obj_member_t(uint32_t handle, uint32_t index, void** value, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kdynlib_get_obj_member_internal(handle, index, (uint64_t)value, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int kunmount(char* path, int flags, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_unmount = (int(*)(struct thread*, struct unmount_args*))sysents[SYS_UNMOUNT].sy_call;
	if (!sys_unmount)
		return -1;

	int error;
	struct unmount_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = path;
	uap.flags = flags;

	error = sys_unmount(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int kunmount_t(char* path, int flags, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = kunmount(path, flags, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int knmount(struct iovec* iov, int iovlen, unsigned int flags, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_nmount = (int(*)(struct thread*, struct nmount_args*))sysents[SYS_NMOUNT].sy_call;
	if (!sys_nmount)
		return -1;

	int error;
	struct nmount_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.iovp = iov;
	uap.iovcnt = iovlen;
	uap.flags = flags;

	error = sys_nmount(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int knmount_t(struct iovec* iov, int iovlen, unsigned int flags, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = knmount(iov, iovlen, flags, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int klink(const	char *path, const char	*link, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_link = (int(*)(struct thread*, struct link_args*))sysents[SYS_LINK].sy_call;
	if (!sys_link)
		return -1;

	int error;
	struct link_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = (char*)path;
	uap.link = (char*)link;

	error = sys_link(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int klink_t(const char *path, const char *link, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = klink(path, link, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int klinkat(int	fd1, const char	*path1,	int fd2, const char *path2, int	flag, struct thread* td)
{
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_linkat = (int(*)(struct thread*, struct linkat_args*))sysents[SYS_LINKAT].sy_call;
	if (!sys_linkat)
		return -1;

	int error;
	struct linkat_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.fd1 = fd1;
	uap.path1 = (char*)path1;
	uap.fd2 = fd2;
	uap.path2 = (char*)path2;
	uap.flag = flag;

	error = sys_linkat(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int klinkat_t(int fd1, const char *path1, int fd2, const char *path2, int flag, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = klinkat(fd1, path1, fd2, path2, flag, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}

int ksandbox_path_internal(char* path, struct thread* td) {
	auto sv = (struct sysentvec*)kdlsym(self_orbis_sysvec);
	struct sysent* sysents = sv->sv_table;
	auto sys_sandbox_path = (int(*)(struct thread*, struct sandbox_path_args*))sysents[SYS_SANDBOX_PATH].sy_call;
	if (!sys_sandbox_path)
		return -1;

	int error;
	struct sandbox_path_args uap;

	// clear errors
	td->td_retval[0] = 0;

	// call syscall
	uap.path = path;

	error = sys_sandbox_path(td, &uap);
	if (error)
		return -error;

	// return socket
	return td->td_retval[0];
}

int ksandbox_path_t(char* path, struct thread* td)
{
	int ret = -EIO;
	int retry = 0;

	for (;;)
	{
		ret = ksandbox_path_internal(path, td);
		if (ret < 0)
		{
			if (ret == -EINTR)
			{
				if (retry > MaxInterruptRetries)
					break;

				retry++;
				continue;
			}

			return ret;
		}

		break;
	}

	return ret;
}


code:
#pragma once
#include <Utils/Types.hpp>

struct task_struct;
struct proc;
struct sockaddr;
struct cdev;
struct cdevsw;
struct ucred;
struct thread;
struct stat;
struct rusage;

///////////////////////////
// Sony specific definition
///////////////////////////

// Syscall 594 : sys_dynlib_load_prx
struct dynlib_load_prx_args {
    char*    path;  // const char *
    uint64_t args;   // size_t
    uint64_t argp;   // const void *
    uint32_t flags;  // uint32_t
    uint64_t pOpt;   // const SceKernelLoadModuleOpt *
    uint64_t pRes;   // int *
};

struct dynlib_get_obj_member {
    uint32_t handle;
    uint32_t index;
    uint64_t value;
};

struct sandbox_path_args {
    char* path;
};

extern "C"
{

    enum
    {
        MaxInterruptRetries = 3,
    };
    // 7
    //extern int kwait4(int pid, int *status, int options, struct rusage *rusage);
    extern int kwait4_t(int pid, int *status, int options, struct rusage *rusage, struct thread* td);

    // 203
    //extern int kmlock(void* address, uint64_t size);
    extern int kmlock_t(void* address, uint64_t size, struct thread* td);

    // 324
    //extern int kmlockall(int how);
    extern int kmlockall_t(int how, struct thread* td);

    // 477
    extern caddr_t kmmap_t(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos, struct thread* td);
    //extern caddr_t kmmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos);

    // 478
    extern off_t klseek_t(int fd, off_t offset, int whence, struct thread* td);
    //extern off_t klseek(int fd, off_t offset, int whence);

    //extern void kclose(int socket);
    extern void kclose_t(int socket, struct thread* td);

    //extern int ksocket(int, int, int);
    extern int ksocket_t(int, int, int, struct thread* td);

    //extern int kbind(int, const struct sockaddr*, size_t);
    extern int kbind_t(int, const struct sockaddr*, size_t, struct thread* td);

    //extern int klisten(int, int);
    extern int klisten_t(int, int, struct thread* td);

    //extern int kaccept(int, struct sockaddr*, size_t*);
    extern int kaccept_t(int, struct sockaddr*, size_t*, struct thread* td);

    //extern int krecv(int, void*, int, int);
    extern int krecv_t(int, void*, int, int, struct thread* td);

    //extern int kopen(const char* path, int flags, int mode);
    extern int kopen_t(const char* path, int flags, int mode, struct thread* td);

    //extern ssize_t kwrite(int d, const void* buf, size_t nbytes);
    extern ssize_t kwrite_t(int d, const void* buf, size_t nbytes, struct thread* td);

    //extern int kgetdents(int fd, char* buf, int nbytes);
    extern int kgetdents_t(int fd, char* buf, int nbytes, struct thread* td);

    //extern ssize_t kread(int fd, void* buf, size_t count);
    extern ssize_t kread_t(int fd, void* buf, size_t count, struct thread* td);

    //extern int ksend(int socket, caddr_t buf, size_t len, int flags);
    extern int ksend_t(int socket, caddr_t buf, size_t len, int flags, struct thread* td);

    //extern int kfstat(int fd, struct stat* sb);
    extern int kfstat_t(int fd, struct stat* sb, struct thread* td);

    //extern int kstat(char* path, struct stat* buf);
    extern int kstat_t(char* path, struct stat* buf, struct thread* td);

    //extern int kunlink(char* path);
    extern int kunlink_t(char* path, struct thread* td);

    //extern int ksetuid(uid_t uid);
    extern int ksetuid_t(uid_t uid, struct thread* td);

    //extern int kptrace(int req, pid_t pid, caddr_t addr, int data);
    extern int kptrace_t(int req, pid_t pid, caddr_t addr, int data, struct thread* td);

    //extern int kkill(int pid, int signum);
    extern int kkill_t(int pid, int signum, struct thread* td);

    //extern int kdup2(int oldd, int newd);
    extern int kdup2_t(int oldd, int newd, struct thread* td);

    //extern int kshutdown(int s, int how);
    extern int kshutdown_t(int s, int how, struct thread* td);

    //extern int kmkdir(char* path, int mode);
    extern int kmkdir_t(char * path, int mode, struct thread* td);

    //extern int krmdir(char* path);
    extern int krmdir_t(char * path, struct thread* td);

    extern int kmunmap_t(void *addr, size_t len, struct thread* td);
    //extern int kmunmap(void *addr, size_t len);

    //extern int ksetsockopt(int socket, int level, int name, caddr_t val, int valsize);
    extern int ksetsockopt_t(int socket, int level, int name, caddr_t val, int valsize, struct thread* td);

    //extern int kftruncate(int fd, off_t length);
    extern int kftruncate_t(int fd, off_t length, struct thread* td);

    //extern pid_t krfork(int flags);
    extern pid_t krfork_t(int flags, struct thread* td);

    //extern int kreboot(int opt);
    extern int kreboot_t(int opt, struct thread* td);

    extern int kmprotect_t(void* addr, size_t len, int prot, struct thread* td);

    extern int kselect_t(int	nfds, fd_set *readfds, fd_set *writefds, fd_set	*exceptfds, struct	timeval	*timeout, struct thread* td);

    extern int kioctl_t(int fd, u_long com, caddr_t data, struct thread* td);

    extern int kdynlib_load_prx_t(char* path, uint64_t args, uint64_t argp, uint32_t flags, uint64_t pOpt, int* pRes, struct thread* td);

    extern int kdynlib_get_obj_member_t(uint32_t handle, uint32_t index, void** value, struct thread* td);

    extern int kunmount_t(char* path, int flags, struct thread* td);

    extern int knmount_t(struct iovec* iov, int iovlen, unsigned int flags, struct thread* td);

    extern int klink_t(const char *path, const char *link, struct thread* td);

    extern int klinkat_t(int fd1, const char *path1, int fd2, const char *path2, int flag, struct thread* td);

    extern int ksandbox_path_t(char* path, struct thread* td);
};

repo_name: veiledmerc/mira

license: mit


code:
#pragma once
#include <sys/types.h>

#ifndef NULL
#define NULL 0
#endif

#ifndef true
#define true 1
#endif

#ifndef false
#define false 0
#endif

#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
#endif

#ifndef MSGPACK
#define MSGPACK __attribute__((__packed__))
#endif

typedef uint32_t u_int32_t;


code:
/**
 * @file  unique_ptr.hpp
 * @brief unique_ptr is a fake implementation to use in place of a C++11 std::unique_ptr when compiling on an older compiler.
 *
 * @see http://www.cplusplus.com/reference/memory/unique_ptr/
 *
 * Copyright (c) 2014-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */
#pragma once

//#include <cstddef>      // NULL
//#include <algorithm>    // std::swap

namespace std
{
    template<typename T> void swap(T& t1, T& t2)
    {
        T temp = t1; // std::move(t1); // or T temp(std::move(t1));
        t1 = t2; // std::move(t2);
        t2 = temp; // std::move(temp);
    }
}
// can be replaced by other error mechanism
//#include <cassert>
#define SHARED_ASSERT(x)    /*assert(x)*/

/**
 * @brief fake implementation to use in place of a C++11 std::move() when compiling on an older compiler.
 *
 * @see http://www.cplusplus.com/reference/utility/move/
*/
template <typename T>
inline T& move(T& v)
{
    return v;
}

/**
 * @brief minimal implementation of unique pointer, a subset of the C++11 std::unique_ptr or boost::unique_ptr.
 *
 * unique_ptr is a smart pointer retaining ownership of an object through a provided pointer,
 * without the overhead of the shared_ptr reference counter.
 * It does not allow sharing this ownership (but moving it is possible)
 * and destroys the object when the pointer is destroyed or reset.
 *
 * This implementation is a fake one, to use when compiling on an older compiler that does not have the move semantic.
 * As such, it cannot offer any guaranty that the pointer is not copied!
 * It is still usable in production on such a compiler if you also compile
 * your program on a recent compiler to verify that it does not violate this guaranty.
 */
template<class T>
class unique_ptr
{
public:
    /// The type of the managed object, aliased as member type
    typedef T element_type;

    /// @brief Default constructor
    unique_ptr(void) throw() : // never throws
        px(NULL)
    {
    }
    /// @brief Constructor with the provided pointer to manage
    explicit unique_ptr(T* p) throw() : // never throws
        px(p)
    {
    }
    /// @brief Copy constructor to convert from another pointer type
    /* TODO MSVC error C2248: 'unique_ptr<B>::px' : unique_ptr<A> cannot access private member declared in class 'unique_ptr<B>'
    template <class U>
    unique_ptr(const unique_ptr<U>& ptr) throw() : // never throws
        px(static_cast<typename unique_ptr<T>::element_type*>(ptr.px))
    {
        const_cast<unique_ptr<U>&>(ptr).px = NULL; // const-cast to force ownership transfer!
    }
    */
    /// @brief Copy constructor (used by the copy-and-swap idiom)
    unique_ptr(const unique_ptr& ptr) throw() : // never throws
        px(ptr.px)
    {
        const_cast<unique_ptr&>(ptr).px = NULL; // const-cast to force ownership transfer!
    }
    /// @brief Assignment operator using the copy-and-swap idiom (copy constructor and swap method)
    unique_ptr& operator=(unique_ptr ptr) throw() // never throws
    {
        swap(ptr);
        return *this;
    }
    /// @brief the destructor releases its ownership and destroy the object
    inline ~unique_ptr(void) throw() // never throws
    {
        destroy();
    }
    /// @brief this reset releases its ownership and destroy the object
    inline void reset(void) throw() // never throws
    {
        destroy();
    }
    /// @brief this reset release its ownership and re-acquire another one
    void reset(T* p) throw() // never throws
    {
        SHARED_ASSERT((NULL == p) || (px != p)); // auto-reset not allowed
        destroy();
        px = p;
    }

    /// @brief Swap method for the copy-and-swap idiom (copy constructor and swap method)
    void swap(unique_ptr& lhs) throw() // never throws
    {

        std::swap(px, lhs.px);
    }

    /// @brief release the ownership of the px pointer without destroying the object!
    inline void release(void) throw() // never throws
    {
        px = NULL;
    }

    // reference counter operations :
    inline operator bool() const throw() // never throws
    {
        return (NULL != px); // TODO nullptr
    }

    // underlying pointer operations :
    inline T& operator*()  const throw() // never throws
    {
        SHARED_ASSERT(NULL != px);
        return *px;
    }
    inline T* operator->() const throw() // never throws
    {
        SHARED_ASSERT(NULL != px);
        return px;
    }
    inline T* get(void)  const throw() // never throws
    {
        // no assert, can return NULL
        return px;
    }

private:
    /// @brief release the ownership of the px pointer and destroy the object
    inline void destroy(void) throw() // never throws
    {
        delete px;
        px = NULL;
    }

    /// @brief hack: const-cast release the ownership of the px pointer without destroying the object!
    inline void release(void) const throw() // never throws
    {
        px = NULL;
    }

private:
    T* px; //!< Native pointer
};

// comparaison operators
template<class T, class U> inline bool operator==(const unique_ptr<T>& l, const unique_ptr<U>& r) throw() // never throws
{
    return (l.get() == r.get());
}
template<class T, class U> inline bool operator!=(const unique_ptr<T>& l, const unique_ptr<U>& r) throw() // never throws
{
    return (l.get() != r.get());
}
template<class T, class U> inline bool operator<=(const unique_ptr<T>& l, const unique_ptr<U>& r) throw() // never throws
{
    return (l.get() <= r.get());
}
template<class T, class U> inline bool operator<(const unique_ptr<T>& l, const unique_ptr<U>& r) throw() // never throws
{
    return (l.get() < r.get());
}
template<class T, class U> inline bool operator>=(const unique_ptr<T>& l, const unique_ptr<U>& r) throw() // never throws
{
    return (l.get() >= r.get());
}
template<class T, class U> inline bool operator>(const unique_ptr<T>& l, const unique_ptr<U>& r) throw() // never throws
{
    return (l.get() > r.get());
}


code:
#pragma once
#include <Utils/Types.hpp>
#include <Utils/Logger.hpp>
#include <Utils/Kdlsym.hpp>

extern "C"
{
    #include <sys/param.h>
    #include <sys/lock.h>
    #include <sys/sx.h>
}

template <typename T>
class Vector
{
private:
    uint32_t m_Capacity;    // Available space
    uint32_t m_Size;        // Count
    T* m_Array;
    static T m_Default;

    //struct sx m_Mutex;

private:
    /**
     * This must be called while the proc is locked
     */
    void reserve_locked(uint32_t p_Count, bool p_Copy)
    {
        // Calculate the size that would be needed to copied
        uint32_t s_CopyCount = 0;
        if (p_Count < m_Size)
            s_CopyCount = p_Count;
        if (p_Count > m_Size)
            s_CopyCount = m_Size;

        // Allocate the new array
        T* s_NewArray = new T[p_Count];
        if (s_NewArray == nullptr)
        {
            //WriteLog(LL_Error, "could not allocate new array of size (%d).", p_Count);
            return;
        }

        // Copy everything from the old list to the new list
        if (p_Copy && m_Array != nullptr)
        {
            //WriteLog(LL_Debug, "copying %d entries", s_CopyCount);
            for (uint32_t i = 0; i < s_CopyCount; ++i)
                s_NewArray[i] = m_Array[i];
        }

        // Delete the previous array
        if (m_Array != nullptr)
        {
            //WriteLog(LL_Debug, "deleting previous array %p", m_Array);
            delete [] m_Array;
            m_Array = nullptr;
        }

        //WriteLog(LL_Debug, "replacing array (%p) with capacity (%d).", s_NewArray, p_Count);
        m_Array = s_NewArray;
        m_Capacity = p_Count;
    }

public:
    Vector() :
        m_Capacity(0),
        m_Size(0),
        m_Array(nullptr)
    {
        // auto mtx_init = (void(*)(struct mtx *m, const char *name, const char *type, int opts))kdlsym(mtx_init);
        // mtx_init(&m_Mutex, "", nullptr, MTX_SPIN);
    }

    ~Vector()
    {
        // auto _mtx_unlock_spin_flags = (void(*)(struct mtx* mutex, int flags))kdlsym(_mtx_unlock_spin_flags);
	    // auto _mtx_lock_spin_flags = (void(*)(struct mtx* mutex, int flags))kdlsym(_mtx_lock_spin_flags);
        // auto mtx_destroy = (void(*)(struct mtx* mutex))kdlsym(mtx_destroy);

        // _mtx_lock_spin_flags(&m_Mutex, 0);
        if (m_Array != nullptr)
        {
            delete [] m_Array;
            m_Capacity = 0;
            m_Size = 0;
        }
        // _mtx_unlock_spin_flags(&m_Mutex, 0);

        // Destroy the mutex afterwards
        // mtx_destroy(&m_Mutex);

        //WriteLog(LL_Debug, "deleted vector");
    }

    T& operator[] (uint32_t p_Index)
    {
        if (p_Index >= m_Size)
        {
            // Ghetto assert
            WriteLog(LL_Error, "out of bound index access");
            for (;;)
                __asm__("nop");
        }

        return m_Array[p_Index];
    }

    T& at(uint32_t p_Index)
    {
        if (p_Index >= m_Size)
        {
            WriteLog(LL_Error, "index out of bounds (%d) max (%d).", p_Index, m_Size);
            for (;;)
                __asm__("nop");
        }

        return m_Array[p_Index];
    }

    //template<typename T>
    void push_back(const T& obj)
    {
        // auto _mtx_unlock_spin_flags = (void(*)(struct mtx* mutex, int flags))kdlsym(_mtx_unlock_spin_flags);
	    // auto _mtx_lock_spin_flags = (void(*)(struct mtx* mutex, int flags))kdlsym(_mtx_lock_spin_flags);

        // _mtx_lock_spin_flags(&m_Mutex, 0);
        if (m_Size == m_Capacity)
        {
            if (m_Capacity == 0)
            {
                //WriteLog(LL_Debug, "Allocating (1) capacity");
                reserve_locked(1, false); // Allocate 1 entry, don't copy any
            }
            else
            {
                //WriteLog(LL_Debug, "Doubling the capacity from (%d) to (%d).", m_Capacity, (2 * m_Capacity));
                reserve_locked(2 * m_Capacity, true); // Double the capacity
            }
        }

        //WriteLog(LL_Debug, "pushing object at %p", &obj);
        m_Array[m_Size] = obj;
        m_Size++;
        // _mtx_unlock_spin_flags(&m_Mutex, 0);
    }

    uint32_t size()
    {
        return m_Size;
    }

    T& front()
    {
        if (m_Size <= 0)
            return T();

        if (m_Array == nullptr)
            return T();

        return m_Array[0];
    }

    T& back()
    {
        if (m_Size <= 0)
            return T();

        if (m_Array == nullptr)
            return T();

        uint32_t s_Index = m_Size - 1;
        return m_Array[s_Index];
    }

    void clear()
    {
        // auto _mtx_unlock_spin_flags = (void(*)(struct mtx* mutex, int flags))kdlsym(_mtx_unlock_spin_flags);
	    // auto _mtx_lock_spin_flags = (void(*)(struct mtx* mutex, int flags))kdlsym(_mtx_lock_spin_flags);

        // _mtx_lock_spin_flags(&m_Mutex, 0);
        reserve_locked(1, false);
        m_Size = 0;
        // _mtx_unlock_spin_flags(&m_Mutex, 0);
    }
};


code:
.intel_syntax noprefix
.text

# Convenince
.global	kernelRdmsr
.global	cpu_enable_wp
.global	cpu_disable_wp

# This is needed for freestanding modules
.global memcpy
.global memmove
.global memset
.global memcmp
.global strlen
.global strcmp

# Debugger related
.global cpu_sidt
.global cpu_sldt
.global cpu_sgdt

kernelRdmsr:
	mov	ecx, edi
	rdmsr
	shl	rdx, 32
	or	rax, rdx
	ret

cpu_enable_wp:
  mov rax, cr0
  or rax, 0x10000
  mov cr0, rax
  ret

cpu_disable_wp:
  mov rax, cr0
  and rax, ~0x10000
  mov cr0, rax
  ret

memcpy:

    # Preserve destination address because we have to return it.
    mov     rax,    rdi

    # Do a byte-by-byte move. On modern x86 chips, there is not a significant
    # performance difference between byte-wise and word-wise moves. In fact,
    # sometimes movsb is faster. See instlatx64.atw.hu for benchmarks.
    mov     rcx,    rdx
    rep     movsb

    ret

memmove:

    # Preserve destination address because we have to return it.
    mov     rax,    rdi

    # If dest < src, we can always do a fast pointer-incrementing move.
    # If dest == src, do nothing.
    cmp     rdi,    rsi
    je      .done
    jb      .fast

    # If dest > src and there are no overlapping regions (dest >= src+num), we
    # can still do a fast pointer-incrementing move.
    mov     rcx,    rsi
    add     rcx,    rdx
    cmp     rdi,    rcx
    jae     .fast

    # If dest > src and dest < src+num, we have to do a right-to-left move to
    # preserve overlapping data.
    .slow:

        # Set the direction flag so copying is right-to-left.
        std

        # Set the move count register.
        mov     rcx,    rdx

        # Update pointers to the right-hand side (minus one).
        dec     rdx
        add     rsi,    rdx
        add     rdi,    rdx

        # Do a byte-by-byte move.
        rep     movsb

        # Reset the direction flag.
        cld

        ret

    .fast:

        # Do a byte-by-byte move.
        mov     rcx,    rdx
        rep     movsb

    .done:

        ret

memset:

    # Preserve the original destination address.
    mov     r8,     rdi

    # The value to store is the second parameter (rsi).
    mov     rax,    rsi

    # Do a byte-by-byte store.
    mov     rcx,    rdx
    rep     stosb

    # Return the original destination address.
    mov     rax,    r8
    ret

memcmp:                                 # @memcmp
        test    rdx, rdx
        je      .LBB0_5
        xor     ecx, ecx
.LBB0_2:                                # =>This Inner Loop Header: Depth=1
        movzx   eax, byte ptr [rdi + rcx]
        movzx   r8d, byte ptr [rsi + rcx]
        cmp     al, r8b
        jne     .LBB0_3
        add     rcx, 1
        cmp     rdx, rcx
        jne     .LBB0_2
.LBB0_5:
        xor     eax, eax
        ret
.LBB0_3:
        sub     eax, r8d
        ret

strlen:
    # save rdi
    push rdi

    # *al = '\0'
    xor al, al
    # clear rcx
    xor rcx, rcx
    # *rcx = ~*rcx
    not rcx
    # while (*al /* '\0' */ != *rdi) ++rdi, --*rcx#
    cld
    repne scasb
    # *rcx = ~*rcx
    not rcx
    dec rcx

    # set return value
    mov rax, rcx
    # restore rdi
    pop rdi

    ret

strcmp:
myasm_strcmp:
    mov r8, 0 #i = 0
    mov r10, 0
myasm_loop:
    mov r9b, [rdi + r8]
    mov r10b, [rsi + r8]

    cmp r9b, r10b
    jne myasm_end

    cmp r9b, 0
    je myasm_end

    inc r8 #i++
    jmp myasm_loop

myasm_end:
    mov rax, 0
    mov al, r9b
    sub rax, r10
	ret

cpu_sidt:
  sidt [rdi]
  xor rax,rax
  ret

cpu_sldt:
  sldt rdi
  xor rax,rax
  ret

cpu_sgdt:
  sgdt [rdi]
  xor rax,rax
  ret


code:
#pragma once
#include <Utils/Types.hpp>

extern "C"
{
void* syscall1(
	uint64_t number,
	void* arg1
);

void* syscall2(
	uint64_t number,
	void* arg1,
	void* arg2
);

void* syscall3(
	uint64_t number,
	void* arg1,
	void* arg2,
	void* arg3
);

void* syscall4(
	uint64_t number,
	void* arg1,
	void* arg2,
	void* arg3,
	void* arg4
);

void* syscall5(
	uint64_t number,
	void* arg1,
	void* arg2,
	void* arg3,
	void* arg4,
	void* arg5
);

caddr_t _mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos);
//caddr_t _mmap(void);
caddr_t _Allocate3MB(void);
caddr_t _Allocate5MB(void);
};

// THIS IS AUTO-GENERATED DO NOT MODIFY UNLESS YOU KNOW WTF YOU ARE DOING
// Created by: OpenOrbis toolchain
#pragma once
#define NOSYS 0
#define LKMRESSYS 169
#define LKMNOSYS 210
#define SYS_EXIT 1
#define SYS_FORK 2
#define SYS_READ 3
#define SYS_WRITE 4
#define SYS_OPEN 5
#define SYS_CLOSE 6
#define SYS_WAIT4 7
#define SYS_LINK 9
#define SYS_UNLINK 10
#define SYS_CHDIR 12
#define SYS_FCHDIR 13
#define SYS_MKNOD 14
#define SYS_CHMOD 15
#define SYS_CHOWN 16
#define SYS_GETPID 20
#define SYS_MOUNT 21
#define SYS_UNMOUNT 22
#define SYS_SETUID 23
#define SYS_GETUID 24
#define SYS_GETEUID 25
#define SYS_PTRACE 26
#define SYS_RECVMSG 27
#define SYS_SENDMSG 28
#define SYS_RECVFROM 29
#define SYS_ACCEPT 30
#define SYS_GETPEERNAME 31
#define SYS_GETSOCKNAME 32
#define SYS_ACCESS 33
#define SYS_CHFLAGS 34
#define SYS_FCHFLAGS 35
#define SYS_SYNC 36
#define SYS_KILL 37
#define SYS_GETPPID 39
#define SYS_DUP 41
#define SYS_PIPE 42
#define SYS_GETEGID 43
#define SYS_PROFIL 44
#define SYS_KTRACE 45
#define SYS_GETGID 47
#define SYS_GETLOGIN 49
#define SYS_SETLOGIN 50
#define SYS_SIGALTSTACK 53
#define SYS_IOCTL 54
#define SYS_REBOOT 55
#define SYS_REVOKE 56
#define SYS_SYMLINK 57
#define SYS_READLINK 58
#define SYS_EXECVE 59
#define SYS_UMASK 60
#define SYS_CHROOT 61
#define SYS_MSYNC 65
#define SYS_VFORK 66
#define SYS_SBRK 69
#define SYS_SSTK 70
#define SYS_MUNMAP 73
#define SYS_MPROTECT 74
#define SYS_MADVISE 75
#define SYS_MINCORE 78
#define SYS_GETGROUPS 79
#define SYS_SETGROUPS 80
#define SYS_GETPGRP 81
#define SYS_SETPGID 82
#define SYS_SETITIMER 83
#define SYS_SWAPON 85
#define SYS_GETITIMER 86
#define SYS_GETDTABLESIZE 89
#define SYS_DUP2 90
#define SYS_FCNTL 92
#define SYS_SELECT 93
#define SYS_FSYNC 95
#define SYS_SETPRIORITY 96
#define SYS_SOCKET 97
#define SYS_CONNECT 98
#define SYS_NETCONTROL 99
#define SYS_GETPRIORITY 100
#define SYS_NETABORT 101
#define SYS_NETGETSOCKINFO 102
#define SYS_BIND 104
#define SYS_SETSOCKOPT 105
#define SYS_LISTEN 106
#define SYS_SOCKETEX 113
#define SYS_SOCKETCLOSE 114
#define SYS_GETTIMEOFDAY 116
#define SYS_GETRUSAGE 117
#define SYS_GETSOCKOPT 118
#define SYS_READV 120
#define SYS_WRITEV 121
#define SYS_SETTIMEOFDAY 122
#define SYS_FCHOWN 123
#define SYS_FCHMOD 124
#define SYS_NETGETIFLIST 125
#define SYS_SETREUID 126
#define SYS_SETREGID 127
#define SYS_RENAME 128
#define SYS_FLOCK 131
#define SYS_MKFIFO 132
#define SYS_SENDTO 133
#define SYS_SHUTDOWN 134
#define SYS_SOCKETPAIR 135
#define SYS_MKDIR 136
#define SYS_RMDIR 137
#define SYS_UTIMES 138
#define SYS_ADJTIME 140
#define SYS_KQUEUEEX 141
#define SYS_SETSID 147
#define SYS_NLM_SYSCALL 154
#define SYS_NFSSVC 155
#define SYS_SYSARCH 165
#define SYS_RTPRIO 166
#define SYS_SETGID 181
#define SYS_SETEGID 182
#define SYS_SETEUID 183
#define SYS_STAT 188
#define SYS_FSTAT 189
#define SYS_LSTAT 190
#define SYS_PATHCONF 191
#define SYS_FPATHCONF 192
#define SYS_GETRLIMIT 194
#define SYS_SETRLIMIT 195
#define SYS_GETDIRENTRIES 196
#define SYS___SYSCTL 202
#define SYS_MLOCK 203
#define SYS_MUNLOCK 204
#define SYS_FUTIMES 206
#define SYS_GETPGID 207
#define SYS_POLL 209
#define SYS_CLOCK_GETTIME 232
#define SYS_CLOCK_SETTIME 233
#define SYS_CLOCK_GETRES 234
#define SYS_KTIMER_CREATE 235
#define SYS_KTIMER_DELETE 236
#define SYS_KTIMER_SETTIME 237
#define SYS_KTIMER_GETTIME 238
#define SYS_KTIMER_GETOVERRUN 239
#define SYS_NANOSLEEP 240
#define SYS_MINHERIT 250
#define SYS_RFORK 251
#define SYS_ISSETUGID 253
#define SYS_LCHOWN 254
#define SYS_AIO_READ 255
#define SYS_AIO_WRITE 256
#define SYS_GETDENTS 272
#define SYS_LCHMOD 274
#define SYS_NETBSD_LCHOWN 275
#define SYS_LUTIMES 276
#define SYS_NETBSD_MSYNC 277
#define SYS_PREADV 289
#define SYS_PWRITEV 290
#define SYS_KLDLOAD 304
#define SYS_KLDUNLOAD 305
#define SYS_KLDFIND 306
#define SYS_KLDNEXT 307
#define SYS_KLDSTAT 308
#define SYS_KLDFIRSTMOD 309
#define SYS_GETSID 310
#define SYS_SETRESUID 311
#define SYS_SETRESGID 312
#define SYS_AIO_RETURN 314
#define SYS_AIO_SUSPEND 315
#define SYS_AIO_CANCEL 316
#define SYS_AIO_ERROR 317
#define SYS_YIELD 321
#define SYS_MLOCKALL 324
#define SYS_MUNLOCKALL 325
#define SYS___GETCWD 326
#define SYS_SCHED_SETPARAM 327
#define SYS_SCHED_GETPARAM 328
#define SYS_SCHED_SETSCHEDULER 329
#define SYS_SCHED_GETSCHEDULER 330
#define SYS_SCHED_YIELD 331
#define SYS_SCHED_GET_PRIORITY_MAX 332
#define SYS_SCHED_GET_PRIORITY_MIN 333
#define SYS_SCHED_RR_GET_INTERVAL 334
#define SYS_UTRACE 335
#define SYS_KLDSYM 337
#define SYS_SIGPROCMASK 340
#define SYS_SIGSUSPEND 341
#define SYS_SIGPENDING 343
#define SYS_SIGTIMEDWAIT 345
#define SYS_SIGWAITINFO 346
#define SYS_AIO_WAITCOMPLETE 359
#define SYS_GETRESUID 360
#define SYS_GETRESGID 361
#define SYS_KQUEUE 362
#define SYS_KEVENT 363
#define SYS___SETUGID 374
#define SYS_NMOUNT 378
#define SYS_MTYPEPROTECT 379
#define SYS___MAC_GET_PROC 384
#define SYS___MAC_SET_PROC 385
#define SYS___MAC_GET_FD 386
#define SYS___MAC_GET_FILE 387
#define SYS___MAC_SET_FD 388
#define SYS___MAC_SET_FILE 389
#define SYS_KENV 390
#define SYS_LCHFLAGS 391
#define SYS_UUIDGEN 392
#define SYS_SENDFILE 393
#define SYS_MAC_SYSCALL 394
#define SYS_GETFSSTAT 395
#define SYS_STATFS 396
#define SYS_FSTATFS 397
#define SYS_KSEM_CLOSE 400
#define SYS_KSEM_POST 401
#define SYS_KSEM_WAIT 402
#define SYS_KSEM_TRYWAIT 403
#define SYS_KSEM_INIT 404
#define SYS_KSEM_OPEN 405
#define SYS_KSEM_UNLINK 406
#define SYS_KSEM_GETVALUE 407
#define SYS_KSEM_DESTROY 408
#define SYS___MAC_GET_PID 409
#define SYS___MAC_GET_LINK 410
#define SYS___MAC_SET_LINK 411
#define SYS___MAC_EXECVE 415
#define SYS_SIGACTION 416
#define SYS_SIGRETURN 417
#define SYS_GETCONTEXT 421
#define SYS_SETCONTEXT 422
#define SYS_SWAPCONTEXT 423
#define SYS_SIGWAIT 429
#define SYS_THR_CREATE 430
#define SYS_THR_EXIT 431
#define SYS_THR_SELF 432
#define SYS_THR_KILL 433
#define SYS__UMTX_LOCK 434
#define SYS__UMTX_UNLOCK 435
#define SYS_KSEM_TIMEDWAIT 441
#define SYS_THR_SUSPEND 442
#define SYS_THR_WAKE 443
#define SYS_KLDUNLOADF 444
#define SYS__UMTX_OP 454
#define SYS_THR_NEW 455
#define SYS_SIGQUEUE 456
#define SYS_THR_SET_NAME 464
#define SYS_AIO_FSYNC 465
#define SYS_RTPRIO_THREAD 466
#define SYS_PREAD 475
#define SYS_PWRITE 476
#define SYS_MMAP 477
#define SYS_LSEEK 478
#define SYS_TRUNCATE 479
#define SYS_FTRUNCATE 480
#define SYS_THR_KILL2 481
#define SYS_SHM_OPEN 482
#define SYS_SHM_UNLINK 483
#define SYS_CPUSET 484
#define SYS_CPUSET_SETID 485
#define SYS_CPUSET_GETID 486
#define SYS_CPUSET_GETAFFINITY 487
#define SYS_CPUSET_SETAFFINITY 488
#define SYS_FCHMODAT 490
#define SYS_FCHOWNAT 491
#define SYS_FSTATAT 493
#define SYS_FUTIMESAT 494
#define SYS_LINKAT 495
#define SYS_MKDIRAT 496
#define SYS_MKFIFOAT 497
#define SYS_MKNODAT 498
#define SYS_OPENAT 499
#define SYS_RENAMEAT 501
#define SYS_SYMLINKAT 502
#define SYS_UNLINKAT 503
#define SYS_CAP_NEW 514
#define SYS_CAP_GETRIGHTS 515
#define SYS_CAP_ENTER 516
#define SYS_CAP_GETMODE 517
#define SYS_PDFORK 518
#define SYS_PDKILL 519
#define SYS_PDGETPID 520
#define SYS_PSELECT 522
#define SYS_RCTL_GET_RACCT 525
#define SYS_RCTL_GET_RULES 526
#define SYS_RCTL_GET_LIMITS 527
#define SYS_RCTL_ADD_RULE 528
#define SYS_RCTL_REMOVE_RULE 529
#define SYS_REGMGR_CALL 532
#define SYS_JITSHM_CREATE 533
#define SYS_JITSHM_ALIAS 534
#define SYS_DL_GET_LIST 535
#define SYS_DL_GET_INFO 536
#define SYS_DL_NOTIFY_EVENT 537
#define SYS_EVF_CREATE 538
#define SYS_EVF_DELETE 539
#define SYS_EVF_OPEN 540
#define SYS_EVF_CLOSE 541
#define SYS_EVF_WAIT 542
#define SYS_EVF_TRYWAIT 543
#define SYS_EVF_SET 544
#define SYS_EVF_CLEAR 545
#define SYS_EVF_CANCEL 546
#define SYS_QUERY_MEMORY_PROTECTION 547
#define SYS_BATCH_MAP 548
#define SYS_OSEM_CREATE 549
#define SYS_OSEM_DELETE 550
#define SYS_OSEM_OPEN 551
#define SYS_OSEM_CLOSE 552
#define SYS_OSEM_WAIT 553
#define SYS_OSEM_TRYWAIT 554
#define SYS_OSEM_POST 555
#define SYS_OSEM_CANCEL 556
#define SYS_NAMEDOBJ_CREATE 557
#define SYS_NAMEDOBJ_DELETE 558
#define SYS_SET_VM_CONTAINER 559
#define SYS_DEBUG_INIT 560
#define SYS_SUSPEND_PROCESS 561
#define SYS_RESUME_PROCESS 562
#define SYS_OPMC_ENABLE 563
#define SYS_OPMC_DISABLE 564
#define SYS_OPMC_SET_CTL 565
#define SYS_OPMC_SET_CTR 566
#define SYS_OPMC_GET_CTR 567
#define SYS_BUDGET_CREATE 568
#define SYS_BUDGET_DELETE 569
#define SYS_BUDGET_GET 570
#define SYS_BUDGET_SET 571
#define SYS_VIRTUAL_QUERY 572
#define SYS_MDBG_CALL 573
#define SYS_SBLOCK_CREATE 574
#define SYS_SBLOCK_DELETE 575
#define SYS_SBLOCK_ENTER 576
#define SYS_SBLOCK_EXIT 577
#define SYS_SBLOCK_XENTER 578
#define SYS_SBLOCK_XEXIT 579
#define SYS_EPORT_CREATE 580
#define SYS_EPORT_DELETE 581
#define SYS_EPORT_TRIGGER 582
#define SYS_EPORT_OPEN 583
#define SYS_EPORT_CLOSE 584
#define SYS_IS_IN_SANDBOX 585
#define SYS_DMEM_CONTAINER 586
#define SYS_GET_AUTHINFO 587
#define SYS_MNAME 588
#define SYS_DYNLIB_DLOPEN 589
#define SYS_DYNLIB_DLCLOSE 590
#define SYS_DYNLIB_DLSYM 591
#define SYS_DYNLIB_GET_LIST 592
#define SYS_DYNLIB_GET_INFO 593
#define SYS_DYNLIB_LOAD_PRX 594
#define SYS_DYNLIB_UNLOAD_PRX 595
#define SYS_DYNLIB_DO_COPY_RELOCATIONS 596
#define SYS_DYNLIB_PREPARE_DLCLOSE 597
#define SYS_DYNLIB_GET_PROC_PARAM 598
#define SYS_DYNLIB_PROCESS_NEEDED_AND_RELOCATE 599
#define SYS_SANDBOX_PATH 600
#define SYS_MDBG_SERVICE 601
#define SYS_RANDOMIZED_PATH 602
#define SYS_RDUP 603
#define SYS_DL_GET_METADATA 604
#define SYS_WORKAROUND8849 605
#define SYS_IS_DEVELOPMENT_MODE 606
#define SYS_GET_SELF_AUTH_INFO 607
#define SYS_DYNLIB_GET_INFO_EX 608
#define SYS_BUDGET_GETID 609
#define SYS_BUDGET_GET_PTYPE 610
#define SYS_GET_PAGING_STATS_OF_ALL_THREADS 611
#define SYS_GET_PROC_TYPE_INFO 612
#define SYS_GET_RESIDENT_COUNTV 613
#define SYS_PREPARE_TO_SUSPEND_PROCESSV 614
#define SYS_GET_RESIDENT_FMEM_COUNT 615
#define SYS_THR_GET_NAME 616
#define SYS_SET_GPO 617
#define SYS_GET_PAGING_STATS_OF_ALL_OBJECTS 618
#define SYS_TEST_DEBUG_RWMEM 619
#define SYS_FREE_STACK 620
#define SYS_SUSPEND_SYSTEM 621
#define SYS_IPMIMGR_CALL 622
#define SYS_GET_GPO 623
#define SYS_GET_VM_MAP_TIMESTAMP 624
#define SYS_OPMC_SET_HW 625
#define SYS_OPMC_GET_HW 626
#define SYS_GET_CPU_USAGE_ALL 627
#define SYS_MMAP_DMEM 628
#define SYS_PHYSHM_OPEN 629
#define SYS_PHYSHM_UNLINK 630
#define SYS_RESUME_INTERNAL_HDD 631
#define SYS_THR_SUSPEND_UCONTEXT 632
#define SYS_THR_RESUME_UCONTEXT 633
#define SYS_THR_GET_UCONTEXT 634
#define SYS_THR_SET_UCONTEXT 635
#define SYS_SET_TIMEZONE_INFO 636
#define SYS_SET_PHYS_FMEM_LIMIT 637
#define SYS_UTC_TO_LOCALTIME 638
#define SYS_LOCALTIME_TO_UTC 639
#define SYS_SET_UEVT 640
#define SYS_GET_CPU_USAGE_PROC 641
#define SYS_GET_MAP_STATISTICS 642
#define SYS_SET_CHICKEN_SWITCHES 643
#define SYS_EXTEND_PAGE_TABLE_POOL 644
#define SYS_GET_KERNEL_MEM_STATISTICS 646
#define SYS_GET_SDK_COMPILED_VERSION 647
#define SYS_APP_STATE_CHANGE 648
#define SYS_DYNLIB_GET_OBJ_MEMBER 649
#define SYS_BUDGET_GET_PTYPE_OF_BUDGET 650
#define SYS_PREPARE_TO_RESUME_PROCESS 651
#define SYS_PROCESS_TERMINATE 652
#define SYS_BLOCKPOOL_OPEN 653
#define SYS_BLOCKPOOL_MAP 654
#define SYS_BLOCKPOOL_UNMAP 655
#define SYS_DYNLIB_GET_INFO_FOR_LIBDBG 656


code:
.intel_syntax noprefix
.text

.global syscall1, syscall2, syscall3, syscall4, syscall5, syscall6, _mmap

syscall:
    mov rax,rdi
    syscall
    ret

syscall1:
    mov rax,rdi
    mov rdi,rsi
    syscall
    ret

syscall2:
    mov rax,rdi
    mov rdi,rsi
    mov rsi,rdx
    syscall
    ret

syscall3:
    mov rax,rdi
    mov rdi,rsi
    mov rsi,rdx
    mov rdx,rcx
    syscall
    ret

syscall4:
    mov rax,rdi
    mov rdi,rsi
    mov rsi,rdx
    mov rdx,rcx
    mov r10,r8
    syscall
    ret

syscall5:
    mov rax,rdi
    mov rdi,rsi
    mov rsi,rdx
    mov rdx,rcx
    mov r10,r8
    mov r8,r9
    syscall
    ret

syscall6:
	mov rax,rdi
    mov rdi,rsi
    mov rsi,rdx
    mov rdx,rcx
    mov r10,r8
    mov r8,r9
	mov r9, [rsp]
    syscall
    ret

_mmap:
	mov rax, 477
	mov r10, rcx
	syscall
	ret


code:
# CHANGEME: Default Orbis Version
ifeq ($(MIRA_PLATFORM),)
MIRA_PLATFORM := MIRA_PLATFORM_ORBIS_BSD_505
# $(error No firmware version set for MIRA_PLATFORM)
endif

# Check to see if we are building in CI/Checking mode
# Leave empty (erase TRUE) if disabling
ifeq ($(MIRA_CHECKS),)
MIRA_CHECKS :=
endif

# Project name
PROJ_NAME := MiraLoader

# C++ compiler
CPPC := clang

# Linker
LNK := ld # ps4-ld, we are compiling for the kernel so this is not going to use the OpenOrbis userland linker

# C compiler
CC := clang

# Archiver
AS := llvm-ar

# Objcopy
OBJCOPY := objcopy

# cppcheck
CPPCHECK := cppcheck

# Output directory, by default is build
ifeq ($(OUT_DIR),)
OUT_DIR := build
endif

# Source directory
SRC_DIR := src

# If the FREEBSD headers path is not set we will try to use the relative path
ifeq ($(BSD_INC),)
BSD_INC := ../external/freebsd-headers/include
endif

MIRACPP_DIR = $(abspath ${CURDIR}/../kernel/src)

# Include directory paths
I_DIRS := -I. -I$(SRC_DIR) -I$(MIRACPP_DIR) -I"$(BSD_INC)"

# Library directory paths
L_DIRS := -L. -Llib

# Included libraries
LIBS :=

# C Defines
C_DEFS := -D_KERNEL=1 -D_DEBUG -D_STANDALONE -D"MIRA_PLATFORM=${MIRA_PLATFORM}" -DMIRA_UNSUPPORTED_PLATFORMS -D__LP64__ -D_M_X64 -D__amd64__ -D__BSD_VISIBLE

# C++ Flags, -02 Optimizations break shit badly
CFLAGS := $(I_DIRS) $(C_DEFS) -fpie -fPIC -m64 -std=c++17 -O0 -fno-builtin -nodefaultlibs -nostdlib -nostdinc -fcheck-new -ffreestanding -fno-strict-aliasing -fno-exceptions -fno-asynchronous-unwind-tables -Wall -Werror -Wno-unknown-pragmas

# Assembly flags
SFLAGS := -fPIE -m64 -nodefaultlibs -nostdlib

# Linker flags
# -Wl,--build-id=none -T $(SRC_DIR)/link.x --emit-relocs -gc-sections -nmagic --relocatable
LFLAGS := -v $(L_DIRS) -nostdlib -T $(SRC_DIR)/link.x -gc-sections -nmagic

# Calculate the listing of all file paths
ALL_CPP := $(sort $(shell find $(SRC_DIR)/ -type f -name '*.cpp'))
ALL_C := $(sort $(shell find $(SRC_DIR)/ -type f -name '*.c'))
ALL_S := $(sort $(shell find $(SRC_DIR)/ -type f -name '*.s'))

ALL_SOURCES := $(ALL_S) $(ALL_C) $(ALL_CPP)
TO_BUILD := $(ALL_S:$(SRC_DIR)%=$(OUT_DIR)/$(SRC_DIR)%) $(ALL_C:$(SRC_DIR)%=$(OUT_DIR)/$(SRC_DIR)%) $(ALL_CPP:$(SRC_DIR)%=$(OUT_DIR)/$(SRC_DIR)%)
ALL_OBJ_CPP := $(TO_BUILD:.cpp=.o)
ALL_OBJ_C := $(ALL_OBJ_CPP:.c=.o)
ALL_OBJ := $(ALL_OBJ_C:.s=.o)
# Target elf name
TARGET = "$(PROJ_NAME)_Orbis_${MIRA_PLATFORM}.elf"

# Target payload name (data + text only, no elf)
PAYLOAD = "$(PROJ_NAME)_Orbis_${MIRA_PLATFORM}.bin"

.PHONY: all clean

all: post-build

pre-build:
	@echo "Pre-Build"
ifneq ($(strip $(MIRA_CHECKS)),)
	@cppcheck $(SRC_DIR) $(I_DIRS) $(C_DEFS) --enable=information --check-config
endif
	@$(MAKE) --no-print-directory clean

post-build: main-build
	@echo "Post-Build"
	@echo "Linking $(PROJ_NAME)..."
	@$(LNK) $(ALL_OBJ) -o $(OUT_DIR)/$(TARGET) $(LFLAGS) $(LIBS)
	@echo "Creating Payload..."
	@$(OBJCOPY) -O binary $(OUT_DIR)/$(TARGET) $(OUT_DIR)/$(PAYLOAD)

main-build: pre-build
	@echo "Building for Firmware $(MIRA_PLATFORM)..."
ifneq ($(strip $(MIRA_CHECKS)),)
	@scan-build $(MAKE) --no-print-directory $(ALL_OBJ)
else
	$(MAKE) --no-print-directory $(ALL_OBJ)
endif

$(OUT_DIR)/$(SRC_DIR)/%.o: $(SRC_DIR)/%.c
	@echo "Compiling $< ..."
ifneq ($(strip $(MIRA_CHECKS)),)
	@clang-tidy -checks=clang-analyzer-*,bugprone-*,portability-*,cert-* $< -- $(I_DIRS) $(C_DEFS)
endif
	@$(CC) $(CFLAGS) $(I_DIRS) -c $< -o $@

$(OUT_DIR)/$(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
	@echo "Compiling $< ..."
ifneq ($(strip $(MIRA_CHECKS)),)
	@clang-tidy -checks=clang-analyzer-*,bugprone-*,portability-*,cert-* $< -- $(I_DIRS) $(C_DEFS)
endif
	@$(CPPC) $(CFLAGS) $(I_DIRS) -c $< -o $@

$(OUT_DIR)/$(SRC_DIR)/%.o: $(SRC_DIR)/%.s
	@echo "Assembling $< ..."
	@$(CC) $(SFLAGS) -c -o $@ $<

$(OUT_DIR)/$(MIRACPP_DIR)/%.o: $(MIRACPP_DIR)/%.c
	@echo "Compiling $< ..."
	@$(CC) $(CFLAGS) $(I_DIRS) -c $< -o $@

$(OUT_DIR)/$(MIRACPP_DIR)/%.o: $(MIRACPP_DIR)/%.cpp
	@echo "Compiling $< ..."
	$(CPPC) $(CFLAGS) $(I_DIRS) -c $< -o $@

$(OUT_DIR)/$(MIRACPP_DIR)/%.o: $(MIRACPP_DIR)/%.s
	@echo "Assembling $< ..."
	@$(CC) $(SFLAGS) -c -o $@ $<

clean:
	@echo "Cleaning project..."
	@rm -f $(OUT_DIR)/$(TARGET) $(OUT_DIR)/$(PAYLOAD) $(shell find $(OUT_DIR)/ -type f -name '*.o')

create:
	@echo "Creating directories..."
	@mkdir -p $(shell find '$(SRC_DIR)/' -type d -printf '$(OUT_DIR)/%p\n')

path: loader/Makefile


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

void Mira::Boot::Patches::install_prePatches()
{
	switch (MIRA_PLATFORM)
	{
		case MIRA_PLATFORM_ORBIS_BSD_176:
			install_prerunPatches_176();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_405:
			install_prerunPatches_405();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_455:
			install_prerunPatches_455();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_474:
			install_prerunPatches_474();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_501:
			install_prerunPatches_501();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_503:
			install_prerunPatches_503();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_505:
			install_prerunPatches_505();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_555:
			install_prerunPatches_555();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_620:
			install_prerunPatches_620();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_650:
			install_prerunPatches_650();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_672:
			install_prerunPatches_672();
			break;
		case MIRA_PLATFORM_ORBIS_BSD_900:
			install_prerunPatches_900();
		default:
			break;
	}
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_176()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_176
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x011242F6];
	kmem[0] = 0x00;

	// Verbose Panics
	kmem = (uint8_t *)&gKernelBase[0x00415AD3];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x65;
	kmem[6] = 0x8B;
	kmem[7] = 0x34;

	//Allow system level debugging
	kmem = (uint8_t *)&gKernelBase[0x003F5180];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;
	kmem[6] = 0x90;
	kmem[7] = 0x90;

	//Allow coredump
	kmem = (uint8_t *)&gKernelBase[0x003F51A0];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;
	kmem[6] = 0x90;
	kmem[7] = 0x90;

	// Enable rwx mapping
	kmem = (uint8_t *)&gKernelBase[0x003AB305];
	kmem[0] = 0x07;

	// Patch copyin/copyout to allow userland + kernel addresses in both params
	kmem = (uint8_t *)&gKernelBase[0x00413CEE];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x00413C6E];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Enable MAP_SELF
	kmem = (uint8_t *)&gKernelBase[0x003F5200];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;

	kmem = (uint8_t *)&gKernelBase[0x003F5210];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;

	kmem = (uint8_t *)&gKernelBase[0x003B6873];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x0041403A];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x0041406A];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// setlogin patch (for autolaunch check)
	kmem = (uint8_t *)&gKernelBase[0x002300A7];
	kmem[0] = 0x48;
	kmem[1] = 0x31;
	kmem[2] = 0xC0;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

// Patches done by SiSTRo & Joonie

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_405()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_405
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x0186B0A0];
	kmem[0] = 0x00;

	// Patch sys_dynlib_dlsym: Allow from anywhere
	//kmem = (uint8_t *)&gKernelBase[0x003CF6FE];
	kmem[0] = 0xE9;
	kmem[1] = 0x52;
	kmem[2] = 0x03;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	//kmem = (uint8_t *)&gKernelBase[0x000690C0];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0xC3;

	// Patch sys_mmap: Allow RWX (read-write-execute) mapping
	//kmem = (uint8_t *)&gKernelBase[0x00141D14];
	kmem[0] = 0x37;
	kmem[3] = 0x37;

	// Patch setuid: Don't run kernel exploit more than once/privilege escalation
	//kmem = (uint8_t *)&gKernelBase[0x001144E3];
	kmem[0] = 0xB8;
	kmem[1] = 0x00;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	// Enable RWX (kmem_alloc) mapping
	kmem = (uint8_t *)&gKernelBase[0x0036958D];
	kmem[0] = 0x07;

	kmem = (uint8_t *)&gKernelBase[0x003695A5];
	kmem[0] = 0x07;

	// Patch copyin/copyout: Allow userland + kernel addresses in both params
	kmem = (uint8_t *)&gKernelBase[0x00286E21];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x00286DA1];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x0028718D];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x002871BD];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch mprotect: Allow RWX (mprotect) mapping
	kmem = (uint8_t *)&gKernelBase[0x004423E9];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

// Patches done by CrazyVoid
// Thanks to
// WildCard for helping with patches
// Joonie for helping with memcpy patch
// LightingMod for being a tester
// Updated by SiSTRo

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_455()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_455
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	// Done by WildCard
	kmem = (uint8_t *)&gKernelBase[0x01997BC8];
	kmem[0] = 0x00;

	// Patch sys_dynlib_dlsym: Allow from anywhere
	kmem = (uint8_t *)&gKernelBase[0x003CF6FE];
	kmem[0] = 0xE9;
	kmem[1] = 0x52;
	kmem[2] = 0x03;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	kmem = (uint8_t *)&gKernelBase[0x000690C0];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0xC3;

	// Patch sys_mmap: Allow RWX (read-write-execute) mapping
	kmem = (uint8_t *)&gKernelBase[0x00141D14];
	kmem[0] = 0x37;
	kmem[3] = 0x37;

	// Patch setuid: Don't run kernel exploit more than once/privilege escalation
	kmem = (uint8_t *)&gKernelBase[0x001144E3];
	kmem[0] = 0xB8;
	kmem[1] = 0x00;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	// Enable RWX (kmem_alloc) mapping
	// Done By WildCard
	kmem = (uint8_t *)&gKernelBase[0x0016ED8C];
	kmem[0] = 0x07;

	kmem = (uint8_t *)&gKernelBase[0x0016EDA2];
	kmem[0] = 0x07;

	// Patch copyin/copyout: Allow userland + kernel addresses in both params
	// Done by CrazyVoid
	kmem = (uint8_t *)&gKernelBase[0x0014A8E7];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x0014A802];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch copyinstr
	// Done by CrazyVoid
	kmem = (uint8_t *)&gKernelBase[0x0014AD53];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x0014AD83];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch memcpy stack
	// Done by CrazyVoid
	kmem = (uint8_t *)&gKernelBase[0x0014A6BD];
	kmem[0] = 0xEB;

	// Patch mprotect: Allow RWX (mprotect) mapping
	kmem = (uint8_t *)&gKernelBase[0x00396A58];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_474()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_474
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x0199FC18];
	kmem[0] = 0x00;

	// Patch sys_dynlib_dlsym: Allow from anywhere
	kmem = (uint8_t *)&gKernelBase[0x003D05AE];
	kmem[0] = 0xE9;
	kmem[1] = 0x52;
	kmem[2] = 0x03;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	kmem = (uint8_t *)&gKernelBase[0x000686A0];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0xC3;

	// Patch sys_mmap: Allow RWX (read-write-execute) mapping
	kmem = (uint8_t *)&gKernelBase[0x001413A4];
	kmem[0] = 0x37;
	kmem[3] = 0x37;

	// Patch setuid: Don't run kernel exploit more than once/privilege escalation
	kmem = (uint8_t *)&gKernelBase[0x00113B73];
	kmem[0] = 0xB8;
	kmem[1] = 0x00;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	// Enable RWX (kmem_alloc) mapping
	kmem = (uint8_t *)&gKernelBase[0x0016DFEC];
	kmem[0] = 0x07;

	kmem = (uint8_t *)&gKernelBase[0x0016E002];
	kmem[0] = 0x07;

	// Patch copyin/copyout: Allow userland + kernel addresses in both params
	kmem = (uint8_t *)&gKernelBase[0x00149F77];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x00149E92];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x0014A3E3];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x0014A413];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch memcpy stack
	kmem = (uint8_t *)&gKernelBase[0x00149D4D];
	kmem[0] = 0xEB;

	// Patch mprotect: Allow RWX (mprotect) mapping
	kmem = (uint8_t *)&gKernelBase[0x00397878];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_501()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_501
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x019ECEB0];
	kmem[0] = 0x00;

	// Patch sys_dynlib_dlsym: Allow from anywhere
	kmem = (uint8_t *)&gKernelBase[0x00237E2A];
	kmem[0] = 0xE9;
	kmem[1] = 0xC1;
	kmem[2] = 0x01;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	kmem = (uint8_t *)&gKernelBase[0x002B2350];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0xC3;

	// Patch sys_mmap: Allow RWX (read-write-execute) mapping
	kmem = (uint8_t *)&gKernelBase[0x0013D510];
	kmem[0] = 0x37;
	kmem[3] = 0x37;

	// Patch setuid: Don't run kernel exploit more than once/privilege escalation
	kmem = (uint8_t *)&gKernelBase[0x00054A72];
	kmem[0] = 0xB8;
	kmem[1] = 0x00;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	// Enable RWX (kmem_alloc) mapping
	kmem = (uint8_t *)&gKernelBase[0x000FCC38];
	kmem[0] = 0x07;

	kmem = (uint8_t *)&gKernelBase[0x000FCC46];
	kmem[0] = 0x07;

	// Patch copyin/copyout: Allow userland + kernel addresses in both params
	kmem = (uint8_t *)&gKernelBase[0x001EA572];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001EA657];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x001EAA83];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001EAAB3];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch memcpy stack
	kmem = (uint8_t *)&gKernelBase[0x001EA42D];
	kmem[0] = 0xEB;

	// Patch mprotect: Allow RWX (mprotect) mapping
	kmem = (uint8_t *)&gKernelBase[0x00080B8B];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_503()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_503
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x019ECEB0];
	kmem[0] = 0x00;

	// Patch sys_dynlib_dlsym: Allow from anywhere
	kmem = (uint8_t *)&gKernelBase[0x00237F3A];
	kmem[0] = 0xE9;
	kmem[1] = 0xC1;
	kmem[2] = 0x01;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	kmem = (uint8_t *)&gKernelBase[0x002B2620];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0xC3;

	// Patch sys_mmap: Allow RWX (read-write-execute) mapping
	kmem = (uint8_t *)&gKernelBase[0x0013D620];
	kmem[0] = 0x37;
	kmem[3] = 0x37;

	// Patch setuid: Don't run kernel exploit more than once/privilege escalation
	kmem = (uint8_t *)&gKernelBase[0x00054A72];
	kmem[0] = 0xB8;
	kmem[1] = 0x00;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	// Enable RWX (kmem_alloc) mapping
	kmem = (uint8_t *)&gKernelBase[0x000FCD48];
	kmem[0] = 0x07;

	kmem = (uint8_t *)&gKernelBase[0x000FCD56];
	kmem[0] = 0x07;

	// Patch copyin/copyout: Allow userland + kernel addresses in both params
	kmem = (uint8_t *)&gKernelBase[0x001EA767];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001EA682];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x001EAB93];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001EABC3];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch memcpy stack
	kmem = (uint8_t *)&gKernelBase[0x001EA53D];
	kmem[0] = 0xEB;

	// Patch mprotect: Allow RWX (mprotect) mapping
	kmem = (uint8_t *)&gKernelBase[0x001A3C08];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_505()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_505
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x019ECEB0];
	kmem[0] = 0x00;

	// Patch sys_dynlib_dlsym: Allow from anywhere
	kmem = (uint8_t *)&gKernelBase[0x00237F3A];
	kmem[0] = 0xE9;
	kmem[1] = 0xC1;
	kmem[2] = 0x01;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	kmem = (uint8_t *)&gKernelBase[0x002B2620];
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0xC3;

	// Patch sys_mmap: Allow RWX (read-write-execute) mapping
	kmem = (uint8_t *)&gKernelBase[0x0013D620];
	kmem[0] = 0x37;
	kmem[3] = 0x37;

	// Patch setuid: Don't run kernel exploit more than once/privilege escalation
	kmem = (uint8_t *)&gKernelBase[0x00054A72];
	kmem[0] = 0xB8;
	kmem[1] = 0x00;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;

	// Enable RWX (kmem_alloc) mapping
	kmem = (uint8_t *)&gKernelBase[0x000FCD48];
	kmem[0] = 0x07;

	kmem = (uint8_t *)&gKernelBase[0x000FCD56];
	kmem[0] = 0x07;

	// Patch copyin/copyout: Allow userland + kernel addresses in both params
	kmem = (uint8_t *)&gKernelBase[0x001EA767];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001EA682];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x001EAB93];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001EABC3];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	// Patch memcpy stack
	kmem = (uint8_t *)&gKernelBase[0x001EA53D];
	kmem[0] = 0xEB;

	// Patch mprotect: Allow RWX (mprotect) mapping
	kmem = (uint8_t *)&gKernelBase[0x001A3C08];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;
#endif
}


code:
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com

#include <Boot/Patches.hpp>

/*
	Please, please, please!
	Keep patches consistent with the used patch style for readability.
*/
void Mira::Boot::Patches::install_prerunPatches_555()
{
#if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_555
	// NOTE: Only apply patches that the loader requires to run, the rest of them should go into Mira's ELF
	// You must assign the kernel base pointer before anything is done
	if (!gKernelBase)
		return;

	// Use "kmem" for all patches
	uint8_t *kmem;

	// Enable UART
	kmem = (uint8_t *)&gKernelBase[0x01A63DD0];
	kmem[0] = 0x00;

	// Verbose Panics
	kmem = (uint8_t *)&gKernelBase[0x000A1826];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x65;
	kmem[6] = 0x8B;
	kmem[7] = 0x34;

	// sceSblACMgrIsAllowedSystemLevelDebugging
	kmem = (uint8_t *)&gKernelBase[0x001B4410];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;
	kmem[6] = 0x90;
	kmem[7] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001B4B90];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;
	kmem[6] = 0x90;
	kmem[7] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x001B4BB0];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;
	kmem[6] = 0x90;
	kmem[7] = 0x90;

  // Enable rwx mapping in kmem_alloc
	kmem = (uint8_t *)&gKernelBase[0x001423A8];
	kmem[0] = 0x07; // set maxprot to RWX

	kmem = (uint8_t *)&gKernelBase[0x001423B6];
	kmem[0] = 0x07; // set maxprot to RWX

	// Patch copyin/copyout to allow userland + kernel addresses in both params
  // copyin
  kmem = (uint8_t *)&gKernelBase[0x00405DD2];
  kmem[0] = 0x90;
  kmem[1] = 0x90;

  kmem = (uint8_t *)&gKernelBase[0x00405DDE];
  kmem[0] = 0x90;
  kmem[1] = 0x90;
  kmem[2] = 0x90;

  // copyout
  kmem = (uint8_t *)&gKernelBase[0x00405EC7];
  kmem[0] = 0x90;
  kmem[1] = 0x90;

  kmem = (uint8_t *)&gKernelBase[0x00405ED3];
  kmem[0] = 0x90;
  kmem[1] = 0x90;
  kmem[2] = 0x90;

	// Enable MAP_SELF

  // Patches: sceSblACMgrHasMmapSelfCapability
	kmem = (uint8_t*)&gKernelBase[0x001B4C00];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;

	// Patches: sceSblACMgrIsAllowedToMmapSelf
	kmem = (uint8_t *)&gKernelBase[0x001B4C10];
	kmem[0] = 0xB8;
	kmem[1] = 0x01;
	kmem[2] = 0x00;
	kmem[3] = 0x00;
	kmem[4] = 0x00;
	kmem[5] = 0xC3;

	// Patches: call    sceSblAuthMgrIsLoadable in vm_mmap2 (right above the only call to allowed to mmap self)
  kmem = (uint8_t *)&gKernelBase[0x003C427D]; // xor eax, eax; nop; nop;
	kmem[0] = 0x31;
	kmem[1] = 0xC0;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;

	// Patch copyinstr
	kmem = (uint8_t *)&gKernelBase[0x00406373];
	kmem[0] = 0x90;
	kmem[1] = 0x90;

	kmem = (uint8_t *)&gKernelBase[0x0040637F];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;

	// Patch memcpy stack
	kmem = (uint8_t *)&gKernelBase[0x00405C8D];
	kmem[0] = 0xEB;

	// ptrace patches
	kmem = (uint8_t *)&gKernelBase[0x00393F01];
	kmem[0] = 0x90;
	kmem[1] = 0x90;
	kmem[2] = 0x90;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
	kmem[5] = 0x90;

	// setlogin patch (for autolaunch check)
	kmem = (uint8_t *)&gKernelBase[0x0001352C];
	kmem[0] = 0x48;
	kmem[1] = 0x31;
	kmem[2] = 0xC0;
	kmem[3] = 0x90;
	kmem[4] = 0x90;
#endif
}