TinyRT abstraction layer

This commit is contained in:
flysand7 2023-07-24 02:33:12 +11:00
parent 42e9d208fb
commit d49add907c
10 changed files with 251 additions and 1 deletions

1
.gitignore vendored
View File

@ -12,5 +12,6 @@ a.out
*.o
*.4coder
*.rdbg
*.iface.h
test/
test_folder/

View File

@ -97,10 +97,43 @@ function prefix_quote(prefix)
end
end
-- Generate TinyRT interface file for the platform
print('==> Generating TinyRT interface definitions')
local tinyrt_manifest_path = path.join('src', platform, 'tinyrt.mf')
if not path.exists(tinyrt_manifest_path) then
print('ERROR: tinyrt manifest wasnt found: '..tinyrt_manifest_path)
end
tinyrt_iface_hdr = io.open(path.join('src', platform, 'tinyrt.iface.h'), 'wb')
tinyrt_iface_hdr:write('\n')
tinyrt_iface_hdr:write('// This file is AUTO-GENERATED\n')
tinyrt_iface_hdr:write('// See tinyrt.mf\n')
tinyrt_iface_hdr:write('\n')
n = 1
for line in io.lines(tinyrt_manifest_path) do
if line:len() ~= 0 and line:sub(1,1) ~= '#' and line:gsub('%s+', '') ~= '' then
local line_it = line:gmatch('[a-zA-Z0-9]+')
local api_name = line_it():upper()
local has_impl = line_it()
if has_impl == '0' or has_impl == '1' then
if has_impl == '1' then
local api_define = '#define RT_API_' .. api_name .. '\n'
tinyrt_iface_hdr:write(api_define)
end
else
print('SYNTAX ERROR AT LINE '..i..': Expected 1 or 0 for the value')
end
end
n = n+1
end
io.close(tinyrt_iface_hdr)
-- Figure out compiler flags
local cflags = table.concat(compiler_flags, ' ')..' '..
table.concat(map(compiler_defines, prefix('-D ')), ' ')..' '..
table.concat(map(includes, prefix_quote('-I ')), ' ')..' '
print('==> Compiling ciabatta')
print('Flags: ' .. cflags)
-- Functions for compiling, linking and assembling individual files
@ -130,6 +163,7 @@ function archive(srcs, out)
os.execute(cmdline)
end
-- Build ciabatta
path.mkdir('lib')
path.mkdir('bin')

View File

@ -59,6 +59,11 @@ typedef unsigned int uint32_t;
#error "Platform not implemented"
#endif
// stdbool.h
typedef _Bool bool;
#define true ((bool)1)
#define false ((bool)0)
// Short type definitions
typedef int8_t i8;
typedef uint8_t u8;

View File

@ -3,5 +3,12 @@
#if os_is_linux()
#include "linux/syscall.c"
#include "linux/errno.c"
#include "linux/entry.c"
// TinyRT interface
#include "linux/tinyrt.iface.h"
#include "tinyrt.h"
#include "linux/tinyrt.c"
#elif os_is_windows()
#error "Not implemented yet"
#endif

View File

@ -24,6 +24,6 @@ void __libc_start_main(
main(argc, argv, envp);
fini();
// glibc bug
dl_fini();
// dl_fini();
syscall_exit(0);
}

76
src/linux/errno.c Normal file
View File

@ -0,0 +1,76 @@
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* Input/output error */
#define ENXIO 6 /* Device not configured */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file descriptor */
#define ECHILD 10 /* No child processes */
#define EDEADLK 11 /* Resource deadlock avoided */
#define ENOMEM 12 /* Cannot allocate memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define EBUSY 16 /* Device busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* Operation not supported by device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* Too many open files in system */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Inappropriate ioctl for device */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Numerical argument out of domain */
#define ERANGE 34 /* Result too large */
#define EAGAIN 35 /* Resource temporarily unavailable */
#define EWOULDBLOCK 35 /* Operation would block */
#define EINPROGRESS 36 /* Operation now in progress */
#define EALREADY 37 /* Operation already in progress */
#define ENOTSOCK 38 /* Socket operation on non-socket */
#define EDESTADDRREQ 39 /* Destination address required */
#define EMSGSIZE 40 /* Message too long */
#define EPROTOTYPE 41 /* Protocol wrong type for socket */
#define ENOPROTOOPT 42 /* Protocol not available */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#define EOPNOTSUPP 45 /* Operation not supported */
#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */
#define EADDRINUSE 48 /* Address already in use */
#define EADDRNOTAVAIL 49 /* Can't assign requested address */
#define ENETDOWN 50 /* Network is down */
#define ENETUNREACH 51 /* Network is unreachable */
#define ENETRESET 52 /* Network dropped connection on reset */
#define ECONNABORTED 53 /* Software caused connection abort */
#define ECONNRESET 54 /* Connection reset by peer */
#define ENOBUFS 55 /* No buffer space available */
#define EISCONN 56 /* Socket is already connected */
#define ENOTCONN 57 /* Socket is not connected */
#define ETIMEDOUT 60 /* Operation timed out */
#define ECONNREFUSED 61 /* Connection refused */
#define ELOOP 62 /* Too many levels of symbolic links */
#define ENAMETOOLONG 63 /* File name too long */
#define EHOSTUNREACH 65 /* No route to host */
#define ENOTEMPTY 66 /* Directory not empty */
#define EDQUOT 69 /* Disk quota exceeded */
#define ENOLCK 77 /* No locks available */
#define ENOSYS 78 /* Function not implemented */
#define EILSEQ 84 /* Illegal byte sequence */
#define EOVERFLOW 87 /* Value too large to be stored in data type */
#define ECANCELED 88 /* Operation canceled */
#define EIDRM 89 /* Identifier removed */
#define ENOMSG 90 /* No message of desired type */
#define ENOTSUP 91 /* Not supported */
#define EBADMSG 92 /* Bad message */
#define ENOTRECOVERABLE 93 /* State not recoverable */
#define EOWNERDEAD 94 /* Previous owner died */
#define EPROTO 95 /* Protocol error */

56
src/linux/tinyrt.c Normal file
View File

@ -0,0 +1,56 @@
// See src/tinyrt.h file for the interface this file implements
static RT_Status rt_file_open(RT_File *file, char *name, int rt_flags) {
if((rt_flags & 0x3) == 0) {
return RT_ERROR_BAD_PARAM;
}
int mode = 0;
int flags = 0;
if((rt_flags & 0x03) == 0x03) mode = O_RDWR;
else if(rt_flags & RT_FILE_READ) mode = O_RDONLY;
else if(rt_flags & RT_FILE_WRITE) mode = O_RDWR;
if(rt_flags & RT_FILE_CREATE) flags |= O_CREAT;
if(rt_flags & RT_FILE_EXCLUSIVE) flags |= O_EXCL;
if(rt_flags & RT_FILE_TRUNCATE) flags |= O_TRUNC;
i64 fd = syscall_open(name, flags, mode);
if(-fd == EACCES) return RT_STATUS_FILE_ACCESS;
if(-fd == EEXIST) return RT_STATUS_FILE_EXISTS;
if(-fd == ENOENT) return RT_STATUS_FILE_NOT_EXISTS;
if(-fd == EINVAL) return RT_ERROR_BAD_PARAM;
if(-fd == EISDIR) return RT_STATUS_FILE_DIRECTORY;
// I'm too lazy to fill in the rest so lets leave it at that for now
if(fd < 0) return RT_STATUS_FILE_IO_ERROR;
file->fd = (u64)fd;
file->flags = rt_flags;
return RT_STATUS_OK;
}
static RT_Status rt_file_read(u64 size, void *buffer, RT_File *from, u64 *out_bytes_read) {
i64 bytes_read = syscall_read(from->fd, buffer, size);
if(bytes_read == 0) {
return RT_STATUS_FILE_EOF;
}
if(bytes_read < 0) {
return RT_STATUS_FILE_IO_ERROR;
}
*out_bytes_read = bytes_read;
return RT_STATUS_OK;
}
static RT_Status rt_file_write(RT_File *to, u64 size, void *buffer, u64 *out_bytes_written) {
i64 bytes_written = syscall_write(to->fd, buffer, size);
if(bytes_written < 0) {
return RT_STATUS_FILE_IO_ERROR;
}
*out_bytes_written = bytes_written;
return RT_STATUS_OK;
}
static RT_Status rt_file_close(RT_File *file) {
i64 result = syscall_close(file->fd);
if(result < 0) {
return RT_STATUS_FILE_IO_ERROR;
}
return RT_STATUS_OK;
}

13
src/linux/tinyrt.mf Normal file
View File

@ -0,0 +1,13 @@
# This file contains TinyRT API subsets that are exported
# for this operating system, one name per line. This file
# is used in a build script to generate tinyrt_macro file
# and to resolve higher-level API dependencies
# For example file = 1 means that the file API is
# implemented on this operating system and during building
# a header file will be generated containing definition of
# the form
# #define RT_API_FILE
file = 1

58
src/tinyrt.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include <cia_definitions.h>
// Common errors
#define RT_STATUS_OK 0 // No errors
#define RT_ERROR_NOT_IMPLEMENTED -1 // Function not implemented
#define RT_ERROR_BAD_PARAM -2 // One of the function parameters was wrong
// File API errors
#define RT_STATUS_FILE_ACCESS 1 // No access to the file
#define RT_STATUS_FILE_NO_SPACE 2 // Storage device has no space for the file
#define RT_STATUS_FILE_EXISTS 3 // File exists when shouldn't
#define RT_STATUS_FILE_NOT_EXISTS 4 // File doesn't exist when should
#define RT_STATUS_FILE_DIRECTORY 5 // The file was a directory when shouldn't've been
#define RT_STATUS_FILE_NOT_DIRECTORY 6 // The file wasn't a directory when should've been
#define RT_STATUS_FILE_NAME_TOO_LONG 7 // The filename was too long for the Filesystem
#define RT_STATUS_FILE_LOOP 8 // Too many symlinks followed or a symlink encountered when expected none
#define RT_STATUS_FILE_BUSY 9 // The device is busy if exclusive access is requested
#define RT_STATUS_FILE_TOO_MANY_OPEN 10 // Too many open files in the process
#define RT_STATUS_FILE_NO_MEMORY 11 // No kernel memory or user limit on memory allocation exceeded
#define RT_STATUS_FILE_IO_ERROR 12 // I/O error
#define RT_STATUS_FILE_BAD_FILE 13 // Bad file handle
#define RT_STATUS_FILE_EOF 14 // Read operation reached the end-of-file
// File API flags
#define RT_FILE_READ 0x01
#define RT_FILE_WRITE 0x02
#define RT_FILE_CREATE 0x04
#define RT_FILE_EXCLUSIVE 0x08
#define RT_FILE_TRUNCATE 0x10
typedef i32 RT_Status;
// API implementation flags (managed and used by the layers on top of tinyrt)
static bool _rt_api_file;
static bool _rt_api_tmpfile;
// Initialization & termination of minirt
static RT_Status rt_init();
static RT_Status rt_deinit();
// File API
#if defined(RT_API_FILE)
struct RT_File typedef RT_File;
struct RT_File {
union {
void *handle;
u64 fd;
};
i32 flags;
};
static RT_Status rt_file_open(RT_File *file, char *name, int flags);
static RT_Status rt_file_read(u64 size, void *buffer, RT_File *from, u64 *out_bytes_read);
static RT_Status rt_file_write(RT_File *to, u64 size, void *buffer, u64 *out_bytes_written);
static RT_Status rt_file_close(RT_File *file);
#endif

0
src/windows/tinyrt.mf Normal file
View File