diff --git a/CMakeLists.txt b/CMakeLists.txt index cbc3219..a26ea07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ffreestanding -nostdlib -lgcc") set(photon_libc_sources "") -set(generic_dirs string) +set(generic_dirs string stdio) foreach (dir ${generic_dirs}) file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/photon/libc/${dir}/*.c) @@ -74,6 +74,7 @@ target_compile_options(c PRIVATE -ffreestanding -nostdlib -nostdinc) target_link_libraries(c crt) target_include_directories(c PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/photon/libc/include) +target_include_directories(c PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/photon/libc/sys/${PLATFORM}/) add_custom_target(sysroot DEPENDS ${photon_libc_headers} diff --git a/photon/libc/include/stdio.h b/photon/libc/include/stdio.h index 0b8c7d3..ccf0589 100644 --- a/photon/libc/include/stdio.h +++ b/photon/libc/include/stdio.h @@ -23,6 +23,8 @@ extern FILE *stdin; extern FILE *stdout; extern FILE *stderr; +extern int fileno(FILE *fp); + #if defined(__cplusplus) } #endif diff --git a/photon/libc/include/time.h b/photon/libc/include/time.h new file mode 100644 index 0000000..c0aa0b3 --- /dev/null +++ b/photon/libc/include/time.h @@ -0,0 +1,11 @@ +#ifndef TIME_H_ +#define TIME_H_ + +#include + +struct timespec { + time_t tv_sec; + long tv_nsec; +}; + +#endif diff --git a/photon/libc/stdio/fileno.c b/photon/libc/stdio/fileno.c new file mode 100644 index 0000000..0cb6a3c --- /dev/null +++ b/photon/libc/stdio/fileno.c @@ -0,0 +1,7 @@ +#include <__fio.h> +#include + +int fileno(FILE *f) +{ + return __fileno(f); +} diff --git a/photon/libc/sys/linux/__fio.h b/photon/libc/sys/linux/__fio.h index 362c0a8..7774336 100644 --- a/photon/libc/sys/linux/__fio.h +++ b/photon/libc/sys/linux/__fio.h @@ -13,6 +13,8 @@ struct __io_file { unsigned int fd; }; +extern int __fileno(struct __io_file *f); + #if defined(__cplusplus) } #endif diff --git a/photon/libc/sys/linux/__syscall.h b/photon/libc/sys/linux/__syscall.h new file mode 100644 index 0000000..c2f0060 --- /dev/null +++ b/photon/libc/sys/linux/__syscall.h @@ -0,0 +1,17 @@ +#ifndef SYS_LINUX___SYSCALL_H_ +#define SYS_LINUX___SYSCALL_H_ + +#include + +extern intptr_t __syscall0(unsigned int id); +extern intptr_t __syscall1(unsigned int id, uintptr_t p0); +extern intptr_t __syscall2(unsigned int id, uintptr_t p0, uintptr_t p1); +extern intptr_t __syscall3(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2); +extern intptr_t __syscall4(unsigned int id, uintptr_t p0, uintptr_t p1, uintptr_t p2, + uintptr_t p3); +extern intptr_t __syscall5(unsigned int id, uintptr_t p0, uintptr_t p1, uintptr_t p2, + uintptr_t p3, uintptr_t p4); +extern intptr_t __syscall6(unsigned int id, uintptr_t p0, uintptr_t p1, uintptr_t p2, + uintptr_t p3, uintptr_t p4, uintptr_t p5); + +#endif diff --git a/photon/libc/sys/linux/fio.c b/photon/libc/sys/linux/fio.c index 150a651..9d2c413 100644 --- a/photon/libc/sys/linux/fio.c +++ b/photon/libc/sys/linux/fio.c @@ -1,4 +1,5 @@ #include "__fio.h" +#include "__syscall.h" struct __io_file __stdin = {}; struct __io_file __stdout = {}; @@ -14,3 +15,8 @@ void __fio_init() __stdout.fd = 1; __stderr.fd = 2; } + +int __fileno(struct __io_file *f) +{ + return f->fd; +} diff --git a/photon/libc/sys/linux/machine/x86_64/syscall.c b/photon/libc/sys/linux/machine/x86_64/syscall.c new file mode 100644 index 0000000..dc54634 --- /dev/null +++ b/photon/libc/sys/linux/machine/x86_64/syscall.c @@ -0,0 +1,108 @@ +#include + +intptr_t __syscall0(uintptr_t id) +{ + intptr_t ret = 0; + asm volatile("mov %1, %%rax; syscall; mov %%rax, %0" + : "=m" (ret) + : "m" (id)); + return ret; +} + +intptr_t __syscall1(uintptr_t id, uintptr_t p0) +{ + intptr_t ret = 0; + asm volatile( + "mov %1, %%rax;" + "mov %2, %%rdi;" + "syscall;" + "mov %%rax, %0" + : "=m" (ret) + : "m" (id), "m" (p0)); + return ret; +} + +intptr_t __syscall2(uintptr_t id, uintptr_t p0, uintptr_t p1) +{ + intptr_t ret = 0; + asm volatile( + "mov %1, %%rax;" + "mov %2, %%rdi;" + "mov %3, %%rsi;" + "syscall;" + "mov %%rax, %0" + : "=m" (ret) + : "m" (id), "m" (p0), "m" (p1)); + return ret; +} + +intptr_t __syscall3(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2) +{ + intptr_t ret = 0; + asm volatile( + "movq %1, %%rax;" + "mov %2, %%rdi;" + "mov %3, %%rsi;" + "mov %4, %%rdx;" + "syscall;" + "mov %%rax, %0" + : "=m" (ret) + : "m" (id), "m" (p0), "m" (p1), "m" (p2)); + return ret; +} + +intptr_t __syscall4(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2, + uintptr_t p3) +{ + intptr_t ret = 0; + asm volatile( + "mov %1, %%rax;" + "mov %2, %%rdi;" + "mov %3, %%rsi;" + "mov %4, %%rdx;" + "mov %5, %%r10;" + "syscall;" + "mov %%rax, %0" + : "=m" (ret) + : "m" (id), "m" (p0), "m" (p1), "m" (p2), "m" (p3)); + return ret; +} + +intptr_t __syscall5(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2, + uintptr_t p3, uintptr_t p4) +{ + intptr_t ret = 0; + asm volatile( + "mov %1, %%rax;" + "mov %2, %%rdi;" + "mov %3, %%rsi;" + "mov %4, %%rdx;" + "mov %5, %%r10;" + "mov %6, %%r8;" + "syscall;" + "mov %%rax, %0" + : "=m" (ret) + : "m" (id), "m" (p0), "m" (p1), "m" (p2), "m" (p3), "m" (p4)); + return ret; +} + +intptr_t __syscall6(uintptr_t id, uintptr_t p0, uintptr_t p1, uintptr_t p2, + uintptr_t p3, uintptr_t p4, uintptr_t p5) +{ + intptr_t ret = 0; + asm volatile( + "mov %1, %%rax;" + "mov %2, %%rdi;" + "mov %3, %%rsi;" + "mov %4, %%rdx;" + "mov %5, %%r10;" + "mov %6, %%r8;" + "mov %7, %%r9;" + "syscall;" + "mov %%rax, %0" + : "=m" (ret) + : "m" (id), "m" (p0), "m" (p1), "m" (p2), "m" (p3), "m" (p4), + "m" (p5)); + return ret; +} + diff --git a/photon/libc/sys/linux/poll.h b/photon/libc/sys/linux/poll.h new file mode 100644 index 0000000..b34fb09 --- /dev/null +++ b/photon/libc/sys/linux/poll.h @@ -0,0 +1,33 @@ +#ifndef SYS_LINUX_POLL_H_ +#define SYS_LINUX_POLL_H_ + +#define POLLIN 0x1 +#define POLLPRI 0x2 +#define POLLOUT 0x4 +#define POLLERR 0x8 +#define POLLHUP 0x10 +#define POLLNVAL 0x20 +#define POLLRDNORM 0x40 +#define POLLRDBAND 0x80 +#define POLLWRNORM 0x100 +#define POLLWRBAND 0x200 + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef unsigned long long nfds_t; + +struct pollfd { + int fd; + short events; + short revents; +}; + +extern int poll(struct pollfd *fds, nfds_t nfds, int timeout); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/photon/libc/sys/linux/_fconst.h b/photon/libc/sys/linux/sys/_fconst.h similarity index 60% rename from photon/libc/sys/linux/_fconst.h rename to photon/libc/sys/linux/sys/_fconst.h index 9696e9c..1733158 100644 --- a/photon/libc/sys/linux/_fconst.h +++ b/photon/libc/sys/linux/sys/_fconst.h @@ -1,5 +1,5 @@ -#ifndef SYS_LINUX__FCONST_H_ -#define SYS_LINUX__FCONST_H_ +#ifndef SYS_LINUX_SYS__FCONST_H_ +#define SYS_LINUX_SYS__FCONST_H_ #define __FILENAME_MAX 1024 diff --git a/photon/libc/sys/linux/sys/stat.h b/photon/libc/sys/linux/sys/stat.h new file mode 100644 index 0000000..9de447e --- /dev/null +++ b/photon/libc/sys/linux/sys/stat.h @@ -0,0 +1,24 @@ +#ifndef SYS_LINUX_SYS_STAT_H_ +#define SYS_LINUX_SYS_STAT_H_ + +#include +#include + +struct stat { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + blksize_t st_blksize; + blkcnt_t st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +}; + +#endif diff --git a/photon/libc/sys/linux/sys/syscall.h b/photon/libc/sys/linux/sys/syscall.h new file mode 100644 index 0000000..02511cd --- /dev/null +++ b/photon/libc/sys/linux/sys/syscall.h @@ -0,0 +1,22 @@ +#ifndef SYS_LINUX_SYSCALL_H_ +#define SYS_LINUX_SYSCALL_H_ + +#define SYS_read 0 +#define SYS_write 1 +#define SYS_open 2 +#define SYS_close 3 +#define SYS_stat 4 +#define SYS_fstat 5 +#define SYS_lstat 6 +#define SYS_poll 7 +#define SYS_lseek 8 +#define SYS_mmap 9 +#define SYS_mprotect 10 +#define SYS_munmap 11 +#define SYS_brk 12 +#define SYS_rt_sigaction 13 +#define SYS_rt_sigprocmask 14 +#define SYS_rt_sigreturn 15 +#define SYS_ioctl 16 + +#endif diff --git a/photon/libc/sys/linux/sys/types.h b/photon/libc/sys/linux/sys/types.h new file mode 100644 index 0000000..2676d28 --- /dev/null +++ b/photon/libc/sys/linux/sys/types.h @@ -0,0 +1,24 @@ +#ifndef SYS_LINUX_SYS_TYPES_H_ +#define SYS_LINUX_SYS_TYPES_H_ + +typedef signed long long blkcnt_t; +typedef signed long long blksize_t; +typedef unsigned long long clock_t; +typedef unsigned int clockid_t; +typedef unsigned long long fsblkcnt_t; +typedef unsigned long long fsfilcnt_t; +typedef unsigned int gid_t; +typedef unsigned int id_t; +typedef unsigned long long ino_t; +typedef unsigned int key_t; +typedef unsigned int mode_t; +typedef unsigned long long nlink_t; +typedef signed long long off_t; +typedef signed int pid_t; +typedef unsigned long long time_t; +typedef unsigned int timer_t; +typedef unsigned int uid_t; +typedef unsigned long useconds_t; +typedef unsigned long long dev_t; + +#endif diff --git a/photon/libc/sys/linux/syscall.c b/photon/libc/sys/linux/syscall.c new file mode 100644 index 0000000..d696e3a --- /dev/null +++ b/photon/libc/sys/linux/syscall.c @@ -0,0 +1,155 @@ +#include "poll.h" +#include "sys/syscall.h" +#include "__syscall.h" +#include "unistd.h" + +ssize_t read(int fd, void *buf, size_t count) +{ + intptr_t res = __syscall3(SYS_read, (uintptr_t)fd, (uintptr_t)buf, + (uintptr_t)count); + if (res < 0) { + return -1; + } + + return (ssize_t)res; +} + +ssize_t write(int fd, const void *buf, size_t count) +{ + intptr_t res = __syscall3(SYS_write, (uintptr_t)fd, (uintptr_t)buf, + (uintptr_t)count); + if (res < 0) { + return -1; + } + + return (ssize_t)res; +} + +int open(const char *pathname, int flags) +{ + intptr_t res = __syscall3(SYS_open, (uintptr_t)pathname, + (uintptr_t)flags, 0); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int close(int fd) +{ + intptr_t res = __syscall1(SYS_close, (uintptr_t)fd); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int stat(const char *pathname, struct stat *statbuf) +{ + intptr_t res = __syscall2(SYS_stat, (uintptr_t)pathname, + (uintptr_t)statbuf); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int fstat(int fd, struct stat *statbuf) +{ + intptr_t res = __syscall2(SYS_fstat, (uintptr_t)fd, + (uintptr_t)statbuf); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int lstat(const char *pathname, struct stat *statbuf) +{ + intptr_t res = __syscall2(SYS_lstat, (uintptr_t)pathname, + (uintptr_t)statbuf); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + intptr_t res = __syscall3(SYS_poll, (uintptr_t)fds, + (uintptr_t)nfds, (uintptr_t)timeout); + if (res < 0) { + return -1; + } + + return (int)res; +} + +off_t lseek(int fd, off_t offset, int whence) +{ + intptr_t res = __syscall3(SYS_lseek, (uintptr_t)fd, + (uintptr_t)offset, (uintptr_t)whence); + if (res < 0) { + return -1; + } + + return (int)res; +} + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) +{ + intptr_t res = __syscall6(SYS_mmap, (uintptr_t)addr, (uintptr_t)len, + (uintptr_t)prot, (uintptr_t)flags, (uintptr_t)fd, (uintptr_t)off); + if (res < 0) { + return NULL; + } + + return (void *)res; +} + +int mprotect(void *addr, size_t len, int prot) +{ + intptr_t res = __syscall3(SYS_mprotect, (uintptr_t)addr, (uintptr_t)len, + (uintptr_t)prot); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int munmap(void *addr, size_t length) +{ + intptr_t res = __syscall2(SYS_munmap, (uintptr_t)addr, (uintptr_t)length); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int brk(void *addr) +{ + intptr_t res = __syscall1(SYS_brk, (uintptr_t)addr); + if (res < 0) { + return -1; + } + + return (int)res; +} + +int ioctl(int fd, unsigned long req, void *arg) +{ + intptr_t res = __syscall3(SYS_ioctl, (uintptr_t)fd, (uintptr_t)req, + (uintptr_t)arg); + if (res < 0) { + return -1; + } + + return (int)res; +} diff --git a/photon/libc/sys/linux/unistd.h b/photon/libc/sys/linux/unistd.h new file mode 100644 index 0000000..18310e1 --- /dev/null +++ b/photon/libc/sys/linux/unistd.h @@ -0,0 +1,27 @@ +#ifndef SYS_LINUX_UNISTD_H_ +#define SYS_LINUX_UNISTD_H_ + +#include +#include + +struct stat; +struct pollfd; + +typedef __intptr_t ssize_t; + +extern ssize_t read(int fd, void *buf, size_t count); +extern ssize_t write(int fd, const void *buf, size_t count); +extern int open(const char *pathname, int flags); +extern int close(int fd); +extern int stat(const char *pathname, struct stat *statbuf); +extern int fstat(int fd, struct stat *statbuf); +extern int lstat(const char *pathname, struct stat *statbuf); +extern off_t lseek(int fd, off_t offset, int whence); +extern void *mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset); +extern int mprotect(void *addr, size_t len, int prot); +extern int munmap(void *addr, size_t length); +extern int brk(void *addr); +extern int ioctl(int fd, unsigned long request, void *arg); + +#endif diff --git a/scripts/create-sysroot.sh b/scripts/create-sysroot.sh index b6b6626..6855bf7 100755 --- a/scripts/create-sysroot.sh +++ b/scripts/create-sysroot.sh @@ -10,8 +10,10 @@ mkdir -p $build_dir/sysroot/usr/include/{sys,machine} cp $source_dir/photon/libc/include/*.h $build_dir/sysroot/usr/include -platform_headers=$(find $source_dir/photon/libc/sys/$platform -type f \( -iname "*.h" ! -iname "__*" \)) -cp -t $build_dir/sysroot/usr/include/sys $platform_headers +platform_headers=$(find $source_dir/photon/libc/sys/$platform -maxdepth 1 -type f \( -iname "*.h" ! -iname "__*" \)) +platform_sys_headers=$(find $source_dir/photon/libc/sys/$platform/sys -maxdepth 1 -type f \( -iname "*.h" ! -iname "__*" \)) +cp -t $build_dir/sysroot/usr/include $platform_headers +cp -t $build_dir/sysroot/usr/include/sys $platform_sys_headers machine_arch_headers=$(find $source_dir/photon/libc/machine/$machine/ \ -type f \( -iname "*.h" ! -iname "__*" \)) diff --git a/tests/start.c b/tests/start.c index b9b1667..09c33b0 100644 --- a/tests/start.c +++ b/tests/start.c @@ -1,7 +1,9 @@ +#include #include -#include int main(int argc, char **argv) { - return 42; + const char *msg = "Hello!\n"; + write(fileno(stdout), msg, 7); + return 0; }