mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-29 13:03:38 +01:00
Initial commit
This commit is contained in:
commit
8fac0c2272
71 changed files with 6439 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build
|
178
configure
vendored
Executable file
178
configure
vendored
Executable file
|
@ -0,0 +1,178 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
# output file
|
||||||
|
confile='fxlibc.cfg'
|
||||||
|
|
||||||
|
# Build options
|
||||||
|
toolchain=sh-elf
|
||||||
|
prefix=
|
||||||
|
cflags=
|
||||||
|
|
||||||
|
# wanted Makefile
|
||||||
|
makefile='Makefile.default'
|
||||||
|
|
||||||
|
# configuration
|
||||||
|
declare -A config
|
||||||
|
config[__SUPPORT_VHEX_KERNEL]=false
|
||||||
|
config[__DEBUG]=false
|
||||||
|
config[__ENABLE_VALGRIND]=false
|
||||||
|
config[__SUPPORT_CASIO_ABI_FX9860]=false
|
||||||
|
config[__SUPPORT_CASIO_ABI_FXCG50]=false
|
||||||
|
|
||||||
|
#
|
||||||
|
# Help screen
|
||||||
|
#
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
cat << EOF
|
||||||
|
Configuration script for the fx calculator libc.
|
||||||
|
Usage: $0 [OPTION]...
|
||||||
|
|
||||||
|
You should build out-of-tree by creating a build directory and configuring from
|
||||||
|
there.
|
||||||
|
|
||||||
|
Debug the fxlibc
|
||||||
|
--debug enable valgrind flags (-g3)
|
||||||
|
--unit-test check C-functoon validity with Criterion
|
||||||
|
|
||||||
|
Build options:
|
||||||
|
--toolchain=TRIPLET Build with a different toolchain
|
||||||
|
[sh-elf-gcc] (or [gcc] when the '--unit_test' flag is set)
|
||||||
|
--cflags=FLAGS Additional compiler flags at end of command
|
||||||
|
|
||||||
|
ABI support:
|
||||||
|
--vhex-support Enable the Vhex kernel support
|
||||||
|
--casio-support=fx9860|fxcg50
|
||||||
|
enable the support of the Casio' ABI (used by malloc, free, ...)
|
||||||
|
|
||||||
|
fx9860 covers all fx-9860G II-like monochromes models that support add-ins
|
||||||
|
or can be flashed with an OS that does. This includes SH3 and SH4 machines.
|
||||||
|
|
||||||
|
fxcg50 covers just the fx-CG 50; there is some unofficial compatibility with
|
||||||
|
fx-CG 10/20. All of these are SH4-only.
|
||||||
|
|
||||||
|
The 'ABI support' is used to allow some part of the code, in particular the 'unistd'
|
||||||
|
part, I/O management and additionnal feature (process, fs, ...).
|
||||||
|
|
||||||
|
Format:
|
||||||
|
--dyn-lib generate dynamic librairies (Vhex kernel dependant)
|
||||||
|
|
||||||
|
Little note for the generation of dynamic libraries.
|
||||||
|
The superH toolchain currently used (GCC) does not support the '--shared' flags
|
||||||
|
when the archive is build. So we need to create manually an archive that can be
|
||||||
|
used like a shared librairy.
|
||||||
|
|
||||||
|
To do this we need to do several steps:
|
||||||
|
1) build the sources with the PIE mode as if it were a executable without entry point.
|
||||||
|
2) manually extract symbols defined as 'global' from the generated ELF.
|
||||||
|
3) we create "stubs": functions that will have the same name than the wanted
|
||||||
|
shared librairies and will call internal VHEX loader primitives with the
|
||||||
|
librairies name, function address and size, etc....Then the loader will
|
||||||
|
load the shared function and override the "user function (stub)" to force
|
||||||
|
it to jump into the "real" function (trampoline)
|
||||||
|
4) all generated stubs will be compiled and linked throught a static lib that
|
||||||
|
SHOULD be used in the user program which use the "dynamic librairy"
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check mandatory build location
|
||||||
|
# @note:
|
||||||
|
# * You should build out-of-tree by creating a build directory and configuring
|
||||||
|
# from there.
|
||||||
|
#
|
||||||
|
if [ -f 'make/Makefile.default' ]; then
|
||||||
|
echo "error: you should configure from a build directory, like this:" >&2
|
||||||
|
echo " mkdir build && cd build && ../configure [options..]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parsing arguments
|
||||||
|
#
|
||||||
|
for arg; do case "$arg" in
|
||||||
|
--help | -h)
|
||||||
|
help;;
|
||||||
|
|
||||||
|
--debug)
|
||||||
|
config[__DEBUG]=true;;
|
||||||
|
--unit-test)
|
||||||
|
makefile='Malefile.unitest';;
|
||||||
|
|
||||||
|
|
||||||
|
--toolchain=*)
|
||||||
|
toolchain=${arg#*=};;
|
||||||
|
--prefix=*)
|
||||||
|
prefix=${arg#*=};;
|
||||||
|
--cflags=*)
|
||||||
|
cflags=${arg#*=};;
|
||||||
|
|
||||||
|
--vhex-support)
|
||||||
|
config[__SUPPORT_VHEX_KERNEL]=true;;
|
||||||
|
--casio-abi=*)
|
||||||
|
case ${arg#*=} in
|
||||||
|
"fx9860g")
|
||||||
|
config[__SUPPORT_CASIO_ABI_FX9860]=true;;
|
||||||
|
"fcg50")
|
||||||
|
config[__SUPPORT_CASIO_ABI_FXCG50]=true;;
|
||||||
|
*)
|
||||||
|
echo -e "\033[1;33merror\033[0m unreconized target '$arg'"
|
||||||
|
exit 1
|
||||||
|
esac;;
|
||||||
|
|
||||||
|
--dyn-lib)
|
||||||
|
makefile='Makefile.dynlib';;
|
||||||
|
*)
|
||||||
|
echo -e "\033[1;33merror\033[0m unreconized argument '$arg'"
|
||||||
|
exit 1
|
||||||
|
esac; done
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check error
|
||||||
|
#
|
||||||
|
if [ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ] && [ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ]; then
|
||||||
|
echo -e "\033[1;33merror\033[0m too many target"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dump appropriate Makefile
|
||||||
|
# @note:
|
||||||
|
# * We have 3 makefile: normal, dynlib, unit_test
|
||||||
|
#
|
||||||
|
dst='Makefile'
|
||||||
|
src="../make/$makefile"
|
||||||
|
if ! test $src; then
|
||||||
|
echo -e "\033[1;33merror\033[0m target makefile ($src) does not exist !"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
[ -L $src ] && [ "$(readlink $src)" == $dst ] && rm $dst
|
||||||
|
ln -s $src $dst
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate the configuration file
|
||||||
|
#
|
||||||
|
function generate_config()
|
||||||
|
{
|
||||||
|
echo "CONFIG.TOOLCHAIN = $toolchain"
|
||||||
|
[ "$prefix" ] && echo "PREFIX = $prefix"
|
||||||
|
[ "$cflags" ] && echo "CONFIG.CFLAGS = $cflags"
|
||||||
|
|
||||||
|
[ ${config[__DEBUG]} = true ] && echo -n '-g3'
|
||||||
|
[ ${config[__SUPPORT_VHEX_KERNEL]} = true ] && echo -n ' -D __SUPPORT_VHEX_KERNEL'
|
||||||
|
[ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ] && echo -n ' -D ___SUPPORT_CASIO_ABI_FX9860'
|
||||||
|
[ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ] && echo -n ' -D ___SUPPORT_CASIO_ABI_FXCG50'
|
||||||
|
echo ''
|
||||||
|
}
|
||||||
|
generate_config > $confile
|
||||||
|
|
||||||
|
|
||||||
|
echo "Configuration saved in $confile, ready to make!"
|
||||||
|
exit 0
|
45
include/asm/unistd_32.h
Normal file
45
include/asm/unistd_32.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef __ASM_UNISTD_32_H__
|
||||||
|
# define __ASM_UNISTD_32_H__
|
||||||
|
|
||||||
|
// Define the number of syscall
|
||||||
|
#define __NR_MAX 21
|
||||||
|
|
||||||
|
// Kernel Test
|
||||||
|
#define __NR_test_syscall 0
|
||||||
|
|
||||||
|
// Process
|
||||||
|
#define __NR_exit 1
|
||||||
|
#define __NR_fork_execve 2 // (custom)
|
||||||
|
#define __NR_waitpid 3
|
||||||
|
#define __NR_wait 4
|
||||||
|
#define __NR_getpid 5
|
||||||
|
#define __NR_getppid 6
|
||||||
|
#define __NR_getpgid 7
|
||||||
|
#define __NR_setpgid 8
|
||||||
|
|
||||||
|
// Signal
|
||||||
|
#define __NR_signal 9
|
||||||
|
#define __NR_sigreturn 10
|
||||||
|
#define __NR_sigaction 11
|
||||||
|
#define __NR_kill 12
|
||||||
|
#define __NR_sigprogmask 13
|
||||||
|
#define __NR_sigpending 14
|
||||||
|
#define __NR_sigaltstack 15
|
||||||
|
|
||||||
|
// VFS
|
||||||
|
#define __NR_read 16
|
||||||
|
#define __NR_write 17
|
||||||
|
#define __NR_open 18
|
||||||
|
#define __NR_close 19
|
||||||
|
#define __NR_lseek 20
|
||||||
|
#define __NR_pread 21
|
||||||
|
#define __NR_pwrite 22
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
#define __NR_mmap 23
|
||||||
|
#define __NR_munmap 24
|
||||||
|
#define __NR_proc_heap_alloc 25 // (custom)
|
||||||
|
#define __NR_proc_heap_free 26 // (custom)
|
||||||
|
#define __NR_proc_heap_realloc 27 // (custom)
|
||||||
|
|
||||||
|
#endif /*__ASM_UNISTD_32_H__*/
|
50
include/bits/signum.h
Normal file
50
include/bits/signum.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef __LIB_BITS_SIGNUM_H__
|
||||||
|
# define __LIB_BITS_SIGNUM_H__
|
||||||
|
|
||||||
|
// Define the number of signals
|
||||||
|
#define NSIG 32
|
||||||
|
|
||||||
|
// Vhex kernel internal define used to indicate
|
||||||
|
// if the signal is implemented or not
|
||||||
|
#define __SIGUNDEF ((__sighandler_t) -2) /* Not implemented */
|
||||||
|
|
||||||
|
/* Fake signal functions. */
|
||||||
|
#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
|
||||||
|
#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
|
||||||
|
#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
|
||||||
|
|
||||||
|
/* ISO C99 signals. */
|
||||||
|
#define SIGINT 2 /* Interactive attention signal. */
|
||||||
|
#define SIGILL 4 /* Illegal instruction. */
|
||||||
|
#define SIGABRT 6 /* Abnormal termination. */
|
||||||
|
#define SIGFPE 8 /* Erroneous arithmetic operation. */
|
||||||
|
#define SIGSEGV 11 /* Invalid access to storage. */
|
||||||
|
#define SIGTERM 15 /* Termination request. */
|
||||||
|
|
||||||
|
/* Historical signals specified by POSIX. */
|
||||||
|
#define SIGHUP 1 /* Hangup. */
|
||||||
|
#define SIGQUIT 3 /* Quit. */
|
||||||
|
#define SIGTRAP 5 /* Trace/breakpoint trap. */
|
||||||
|
#define SIGKILL 9 /* Killed. */
|
||||||
|
#define SIGBUS 10 /* Bus error. */
|
||||||
|
#define SIGSYS 12 /* Bad system call. */
|
||||||
|
#define SIGPIPE 13 /* Broken pipe. */
|
||||||
|
#define SIGALRM 14 /* Alarm clock. */
|
||||||
|
|
||||||
|
/* New(er) POSIX signals (1003.1-2008, 1003.1-2013). */
|
||||||
|
#define SIGURG 16 /* Urgent data is available at a socket. */
|
||||||
|
#define SIGSTOP 17 /* Stop, unblockable. */
|
||||||
|
#define SIGTSTP 18 /* Keyboard stop. */
|
||||||
|
#define SIGCONT 19 /* Continue. */
|
||||||
|
#define SIGCHLD 20 /* Child terminated or stopped. */
|
||||||
|
#define SIGTTIN 21 /* Background read from control terminal. */
|
||||||
|
#define SIGTTOU 22 /* Background write to control terminal. */
|
||||||
|
#define SIGPOLL 23 /* Pollable event occurred (System V). */
|
||||||
|
#define SIGXCPU 24 /* CPU time limit exceeded. */
|
||||||
|
#define SIGXFSZ 25 /* File size limit exceeded. */
|
||||||
|
#define SIGVTALRM 26 /* Virtual timer expired. */
|
||||||
|
#define SIGPROF 27 /* Profiling timer expired. */
|
||||||
|
#define SIGUSR1 30 /* User-defined signal 1. */
|
||||||
|
#define SIGUSR2 31 /* User-defined signal 2. */
|
||||||
|
|
||||||
|
#endif /*__LIB_BITS_SIGNUM_H__*/
|
9
include/bits/types/FILE.h
Normal file
9
include/bits/types/FILE.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef __LIB_BITS_TYPES_FILE_H__
|
||||||
|
# define __LIB_BITS_TYPES_FILE_H__
|
||||||
|
|
||||||
|
struct _IO_FILE;
|
||||||
|
|
||||||
|
/* The opaque type of streams. This is the definition used elsewhere. */
|
||||||
|
typedef struct _IO_FILE FILE;
|
||||||
|
|
||||||
|
#endif /*__LIB_BITS_TYPES_FILE_H__*/
|
7
include/bits/types/__FILE.h
Normal file
7
include/bits/types/__FILE.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef __LIB_BITS_TYPES___FILE_H__
|
||||||
|
# define __LIB_BITS_TYPES___FILE_H__
|
||||||
|
|
||||||
|
struct _IO_FILE;
|
||||||
|
typedef struct _IO_FILE __FILE;
|
||||||
|
|
||||||
|
#endif /*__LIB_BITS_TYPES___FILE_H__*/
|
23
include/bits/types/struct_FILE.h
Normal file
23
include/bits/types/struct_FILE.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef __FILE_H__
|
||||||
|
# define __FILE_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
//TODO: remove me !!!
|
||||||
|
#include <kernel/bits/filesystem.h>
|
||||||
|
|
||||||
|
// Define _IO_FILE
|
||||||
|
// TODO: add open flags
|
||||||
|
// TODO: add file descriptor ?
|
||||||
|
// TODO: update me !
|
||||||
|
struct _IO_FILE
|
||||||
|
{
|
||||||
|
off_t cursor;
|
||||||
|
int permission;
|
||||||
|
struct file_operations *file_op;
|
||||||
|
void *private;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*__FILE_H__*/
|
9
include/bits/waitflags.h
Normal file
9
include/bits/waitflags.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef __LIB_BITS_WAITFLAGS_H__
|
||||||
|
# define __LIB_BITS_WAITFLAGS_H__
|
||||||
|
|
||||||
|
/* Bits in the third argument to `waitpid'. */
|
||||||
|
#define WNOHANG 1 /* Don't block waiting. */
|
||||||
|
#define WUNTRACED 2 /* Report status of stopped child. */
|
||||||
|
#define WCONTINUED 3 /* Report continued child. */
|
||||||
|
|
||||||
|
#endif /*__LIB_BITS_WAITFLAGS_H__*/
|
35
include/bits/waitstatus.h
Normal file
35
include/bits/waitstatus.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef __LIB_BITS_WAITSTATUS_H__
|
||||||
|
# define __LIB_BITS_WAITSTATUS_H__
|
||||||
|
|
||||||
|
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
|
||||||
|
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||||
|
|
||||||
|
/* If WIFSIGNALED(STATUS), the terminating signal. */
|
||||||
|
#define __WTERMSIG(status) ((status) & 0x7f)
|
||||||
|
|
||||||
|
/* If WIFSTOPPED(STATUS), the signal that stopped the child. */
|
||||||
|
#define __WSTOPSIG(status) __WEXITSTATUS(status)
|
||||||
|
|
||||||
|
/* Nonzero if STATUS indicates normal termination. */
|
||||||
|
#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
|
||||||
|
|
||||||
|
/* Nonzero if STATUS indicates termination by a signal. */
|
||||||
|
#define __WIFSIGNALED(status) \
|
||||||
|
(((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
|
||||||
|
|
||||||
|
/* Nonzero if STATUS indicates the child is stopped. */
|
||||||
|
#define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
|
||||||
|
|
||||||
|
/* Nonzero if STATUS indicates the child continued after a stop. */
|
||||||
|
# define __WIFCONTINUED(status) ((status) == __W_CONTINUED)
|
||||||
|
|
||||||
|
/* Nonzero if STATUS indicates the child dumped core. */
|
||||||
|
#define __WCOREDUMP(status) ((status) & __WCOREFLAG)
|
||||||
|
|
||||||
|
/* Macros for constructing status values. */
|
||||||
|
#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
|
||||||
|
#define __W_STOPCODE(sig) ((sig) << 8 | 0x7f)
|
||||||
|
#define __W_CONTINUED 0xffff
|
||||||
|
#define __WCOREFLAG 0x80
|
||||||
|
|
||||||
|
#endif /*__LIB_BITS_WAITSTATUS_H__*/
|
65
include/display.h
Normal file
65
include/display.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef __LIB_DISPLAY_H__
|
||||||
|
# define __LIB_DISPLAY_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Internal struct used in each draw function
|
||||||
|
typedef struct display_s
|
||||||
|
{
|
||||||
|
uint32_t vram[256];
|
||||||
|
struct font_s *font;
|
||||||
|
struct {
|
||||||
|
size_t width;
|
||||||
|
size_t height;
|
||||||
|
} display;
|
||||||
|
|
||||||
|
// Internal pre-calculated value
|
||||||
|
int nb_char_width;
|
||||||
|
} display_t;
|
||||||
|
|
||||||
|
// Internal struct used to define font structure object.
|
||||||
|
// TODO: move me ?
|
||||||
|
struct font_s
|
||||||
|
{
|
||||||
|
// Bitmap informations
|
||||||
|
struct {
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t height;
|
||||||
|
uint8_t cwidth;
|
||||||
|
uint8_t cheight;
|
||||||
|
uint8_t *raw;
|
||||||
|
} bitmap;
|
||||||
|
|
||||||
|
// Character information
|
||||||
|
struct {
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t height;
|
||||||
|
} font;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal struct used to draw
|
||||||
|
// the ASCII character.
|
||||||
|
struct font_block_s
|
||||||
|
{
|
||||||
|
int16_t height;
|
||||||
|
int16_t width;
|
||||||
|
struct {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
} bitmap;
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw primitives
|
||||||
|
extern int dopen(display_t *disp, const char *fontname);
|
||||||
|
extern void dclear(display_t *disp);
|
||||||
|
extern void dascii(display_t *disp, int row, int colomn, char const c, int mode);
|
||||||
|
extern size_t dprint(display_t *disp, int x, int y, char const *str, ...);
|
||||||
|
extern void dscroll(display_t *disp, int line);
|
||||||
|
extern void dreverse(display_t *disp, int x, int y, int width, int height);
|
||||||
|
extern void drect(display_t *disp, int x, int y, int width, int height);
|
||||||
|
extern void dupdate(display_t *disp);
|
||||||
|
|
||||||
|
#endif /*__LIB_DISPLAY_H__*/
|
4026
include/elf.h
Normal file
4026
include/elf.h
Normal file
File diff suppressed because it is too large
Load diff
156
include/errno.h
Normal file
156
include/errno.h
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
#ifndef __KERNEL_ERRNO_H__
|
||||||
|
# define __KERNEL_ERRNO_H__ 1
|
||||||
|
|
||||||
|
#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 /* I/O error */
|
||||||
|
#define ENXIO 6 /* No such device or address */
|
||||||
|
#define E2BIG 7 /* Argument list too long */
|
||||||
|
#define ENOEXEC 8 /* Exec format error */
|
||||||
|
#define EBADF 9 /* Bad file number */
|
||||||
|
#define ECHILD 10 /* No child processes */
|
||||||
|
#define EAGAIN 11 /* Try again */
|
||||||
|
#define ENOMEM 12 /* Out of memory */
|
||||||
|
#define EACCES 13 /* Permission denied */
|
||||||
|
#define EFAULT 14 /* Bad address */
|
||||||
|
#define ENOTBLK 15 /* Block device required */
|
||||||
|
#define EBUSY 16 /* Device or resource busy */
|
||||||
|
#define EEXIST 17 /* File exists */
|
||||||
|
#define EXDEV 18 /* Cross-device link */
|
||||||
|
#define ENODEV 19 /* No such device */
|
||||||
|
#define ENOTDIR 20 /* Not a directory */
|
||||||
|
#define EISDIR 21 /* Is a directory */
|
||||||
|
#define EINVAL 22 /* Invalid argument */
|
||||||
|
#define ENFILE 23 /* File table overflow */
|
||||||
|
#define EMFILE 24 /* Too many open files */
|
||||||
|
#define ENOTTY 25 /* Not a typewriter */
|
||||||
|
#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 /* Math argument out of domain of func */
|
||||||
|
#define ERANGE 34 /* Math result not representable */
|
||||||
|
|
||||||
|
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||||
|
#define ENAMETOOLONG 36 /* File name too long */
|
||||||
|
#define ENOLCK 37 /* No record locks available */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This error code is special: arch syscall entry code will return
|
||||||
|
* -ENOSYS if users try to call a syscall that doesn't exist. To keep
|
||||||
|
* failures of syscalls that really do exist distinguishable from
|
||||||
|
* failures due to attempts to use a nonexistent syscall, syscall
|
||||||
|
* implementations should refrain from returning -ENOSYS.
|
||||||
|
*/
|
||||||
|
#define ENOSYS 38 /* Invalid system call number */
|
||||||
|
|
||||||
|
#define ENOTEMPTY 39 /* Directory not empty */
|
||||||
|
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||||
|
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||||
|
#define ENOMSG 42 /* No message of desired type */
|
||||||
|
#define EIDRM 43 /* Identifier removed */
|
||||||
|
#define ECHRNG 44 /* Channel number out of range */
|
||||||
|
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||||
|
#define EL3HLT 46 /* Level 3 halted */
|
||||||
|
#define EL3RST 47 /* Level 3 reset */
|
||||||
|
#define ELNRNG 48 /* Link number out of range */
|
||||||
|
#define EUNATCH 49 /* Protocol driver not attached */
|
||||||
|
#define ENOCSI 50 /* No CSI structure available */
|
||||||
|
#define EL2HLT 51 /* Level 2 halted */
|
||||||
|
#define EBADE 52 /* Invalid exchange */
|
||||||
|
#define EBADR 53 /* Invalid request descriptor */
|
||||||
|
#define EXFULL 54 /* Exchange full */
|
||||||
|
#define ENOANO 55 /* No anode */
|
||||||
|
#define EBADRQC 56 /* Invalid request code */
|
||||||
|
#define EBADSLT 57 /* Invalid slot */
|
||||||
|
|
||||||
|
#define EDEADLOCK EDEADLK
|
||||||
|
|
||||||
|
#define EBFONT 59 /* Bad font file format */
|
||||||
|
#define ENOSTR 60 /* Device not a stream */
|
||||||
|
#define ENODATA 61 /* No data available */
|
||||||
|
#define ETIME 62 /* Timer expired */
|
||||||
|
#define ENOSR 63 /* Out of streams resources */
|
||||||
|
#define ENONET 64 /* Machine is not on the network */
|
||||||
|
#define ENOPKG 65 /* Package not installed */
|
||||||
|
#define EREMOTE 66 /* Object is remote */
|
||||||
|
#define ENOLINK 67 /* Link has been severed */
|
||||||
|
#define EADV 68 /* Advertise error */
|
||||||
|
#define ESRMNT 69 /* Srmount error */
|
||||||
|
#define ECOMM 70 /* Communication error on send */
|
||||||
|
#define EPROTO 71 /* Protocol error */
|
||||||
|
#define EMULTIHOP 72 /* Multihop attempted */
|
||||||
|
#define EDOTDOT 73 /* RFS specific error */
|
||||||
|
#define EBADMSG 74 /* Not a data message */
|
||||||
|
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||||
|
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||||
|
#define EBADFD 77 /* File descriptor in bad state */
|
||||||
|
#define EREMCHG 78 /* Remote address changed */
|
||||||
|
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||||
|
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||||
|
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||||
|
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||||
|
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||||
|
#define EILSEQ 84 /* Illegal byte sequence */
|
||||||
|
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||||
|
#define ESTRPIPE 86 /* Streams pipe error */
|
||||||
|
#define EUSERS 87 /* Too many users */
|
||||||
|
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||||
|
#define EDESTADDRREQ 89 /* Destination address required */
|
||||||
|
#define EMSGSIZE 90 /* Message too long */
|
||||||
|
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||||
|
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||||
|
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||||
|
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||||
|
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||||
|
#define ENOTSUP EOPNOTSUPP /* Not supported (may be the same value as [EOPNOTSUPP]) */
|
||||||
|
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||||
|
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||||
|
#define EADDRINUSE 98 /* Address already in use */
|
||||||
|
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||||
|
#define ENETDOWN 100 /* Network is down */
|
||||||
|
#define ENETUNREACH 101 /* Network is unreachable */
|
||||||
|
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||||
|
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||||
|
#define ECONNRESET 104 /* Connection reset by peer */
|
||||||
|
#define ENOBUFS 105 /* No buffer space available */
|
||||||
|
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||||
|
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||||
|
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||||
|
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||||
|
#define ETIMEDOUT 110 /* Connection timed out */
|
||||||
|
#define ECONNREFUSED 111 /* Connection refused */
|
||||||
|
#define EHOSTDOWN 112 /* Host is down */
|
||||||
|
#define EHOSTUNREACH 113 /* No route to host */
|
||||||
|
#define EALREADY 114 /* Operation already in progress */
|
||||||
|
#define EINPROGRESS 115 /* Operation now in progress */
|
||||||
|
#define ESTALE 116 /* Stale file handle */
|
||||||
|
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||||
|
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||||
|
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||||
|
#define EISNAM 120 /* Is a named type file */
|
||||||
|
#define EREMOTEIO 121 /* Remote I/O error */
|
||||||
|
#define EDQUOT 122 /* Quota exceeded */
|
||||||
|
|
||||||
|
#define ENOMEDIUM 123 /* No medium found */
|
||||||
|
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||||
|
#define ECANCELED 125 /* Operation Canceled */
|
||||||
|
#define ENOKEY 126 /* Required key not available */
|
||||||
|
#define EKEYEXPIRED 127 /* Key has expired */
|
||||||
|
#define EKEYREVOKED 128 /* Key has been revoked */
|
||||||
|
#define EKEYREJECTED 129 /* Key was rejected by service */
|
||||||
|
|
||||||
|
/* for robust mutexes */
|
||||||
|
#define EOWNERDEAD 130 /* Owner died */
|
||||||
|
#define ENOTRECOVERABLE 131 /* State not recoverable */
|
||||||
|
|
||||||
|
#define ERFKILL 132 /* Operation not possible due to RF-kill */
|
||||||
|
|
||||||
|
#define EHWPOISON 133 /* Memory page has hardware error */
|
||||||
|
|
||||||
|
#endif /* __KERNEL_ERRNO_H__ */
|
20
include/fcntl.h
Normal file
20
include/fcntl.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef __LIB_FCNTL_H__
|
||||||
|
# define __LIB_FCNTL_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//TODO: update me !!
|
||||||
|
#define O_RDONLY 0
|
||||||
|
#define O_WRONLY 1
|
||||||
|
#define O_RDWR 2
|
||||||
|
|
||||||
|
//TODO: define also in <stdio.h>
|
||||||
|
#define SEEK_SET 0 /* Seek from beginning of file. */
|
||||||
|
#define SEEK_CUR 1 /* Seek from current position. */
|
||||||
|
#define SEEK_END 2 /* Seek from end of file. */
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
extern int open(const char *pathname, int flags, ...);
|
||||||
|
|
||||||
|
#endif /*__LIB_FCNTL_H__*/
|
30
include/setjmp.h
Normal file
30
include/setjmp.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef __LIB_SETJMP_H__
|
||||||
|
# define __LIB_SETJMP_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Real jmp_buf struct
|
||||||
|
// @note: save only r8 ~ r15 and SR / PC registers
|
||||||
|
// The SR register is saved first because the longjump can be involved with
|
||||||
|
// differentregister bank. So to avoid this it's more simple to restore the
|
||||||
|
// saved SR first then restore all register (see <lib/libc/setjmp/longjmp.S>)
|
||||||
|
struct __jmp_buf
|
||||||
|
{
|
||||||
|
uint32_t sr;
|
||||||
|
uint32_t reg[8];
|
||||||
|
uint32_t gbr;
|
||||||
|
uint32_t macl;
|
||||||
|
uint32_t mach;
|
||||||
|
uint32_t pr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// User jmp_buf alias
|
||||||
|
typedef struct __jmp_buf jmp_buf[1];
|
||||||
|
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
extern int setjmp(jmp_buf env);
|
||||||
|
extern void longjmp(jmp_buf env, int val);
|
||||||
|
|
||||||
|
#endif /*__LIB_SETJMP_H__*/
|
26
include/signal.h
Normal file
26
include/signal.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef __LIB_SIGNAL_H__
|
||||||
|
# define __LIB_SIGNAL_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <bits/signum.h>
|
||||||
|
|
||||||
|
// Type of a signal handler
|
||||||
|
typedef void (*__sighandler_t)(int);
|
||||||
|
typedef __sighandler_t sighandler_t;
|
||||||
|
|
||||||
|
// Type of signal set
|
||||||
|
typedef uint32_t sigset_t;
|
||||||
|
typedef uint32_t kernel_sigset_t;
|
||||||
|
|
||||||
|
// Define sigprocmask() value for "how" argument
|
||||||
|
#define SIG_BLOCK 0
|
||||||
|
#define SIG_UNBLOCK 1
|
||||||
|
#define SIG_SETMASK 2
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
// TODO: doc
|
||||||
|
extern int kill(pid_t pid, int sig);
|
||||||
|
extern void (*signal(int signum, void (*handler)(int)))(int);
|
||||||
|
|
||||||
|
#endif /*__LIB_SIGNAL_H__*/
|
78
include/stdio.h
Normal file
78
include/stdio.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef __LIB_STDIO_H__
|
||||||
|
# define __LIB_STDIO_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* *printf() familly - formatted output conversion. */
|
||||||
|
extern int printf(const char *restrict format, ...);
|
||||||
|
extern int dprintf(int fd, const char *restrict format, ...);
|
||||||
|
extern int sprintf(char *restrict str, const char *restrict format, ...);
|
||||||
|
extern int snprintf(char *restrict str, size_t size, const char *restrict format, ...);
|
||||||
|
|
||||||
|
extern int vdprintf(int fd, const char *restrict format, va_list ap);
|
||||||
|
extern int vsprintf(char *restrict str, const char *restrict format, va_list ap);
|
||||||
|
extern int vsnprintf(char *restrict str, size_t size, const char *restrict format, va_list ap);
|
||||||
|
|
||||||
|
/* putx() - display char / string */
|
||||||
|
extern int putchar(int c);
|
||||||
|
extern int puts(const char *s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Internal part
|
||||||
|
// TODO: move me ?
|
||||||
|
//---
|
||||||
|
#define PRINTF_INTERNAL_BUFFER_SIZE 32
|
||||||
|
|
||||||
|
struct printf_opt
|
||||||
|
{
|
||||||
|
// Internal buffer to avoid syscall flux
|
||||||
|
char buffer[PRINTF_INTERNAL_BUFFER_SIZE];
|
||||||
|
size_t buffer_cursor;
|
||||||
|
|
||||||
|
// Common part
|
||||||
|
int counter;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
// *dprintf part
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
// *sprintf part
|
||||||
|
char *str;
|
||||||
|
size_t str_size;
|
||||||
|
|
||||||
|
// For string / fd common support
|
||||||
|
void (*disp_char)(struct printf_opt *opt, char n);
|
||||||
|
void (*disp_fflush)(struct printf_opt *opt);
|
||||||
|
|
||||||
|
// Printf-options
|
||||||
|
struct {
|
||||||
|
uint8_t diez : 1;
|
||||||
|
uint8_t zero : 1;
|
||||||
|
uint8_t minus : 1;
|
||||||
|
uint8_t space : 1;
|
||||||
|
uint8_t plus : 1;
|
||||||
|
uint8_t const : 3;
|
||||||
|
} flags;
|
||||||
|
int width;
|
||||||
|
int precision;
|
||||||
|
int uppercase;
|
||||||
|
int lenght;
|
||||||
|
|
||||||
|
// Internal format management.
|
||||||
|
char sign;
|
||||||
|
char base[2];
|
||||||
|
char format[32];
|
||||||
|
int digits;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal symbols used to define all actions possibility
|
||||||
|
extern void (*action[26])(struct printf_opt *opt, char n);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*__LIB_STDIO_H__*/
|
30
include/stdlib.h
Normal file
30
include/stdlib.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef __LIB_STDLIB_H__
|
||||||
|
# define __LIB_STDLIB_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define HEAP_BLOCK_MIN (16)
|
||||||
|
struct heap_block
|
||||||
|
{
|
||||||
|
uint16_t status; /* status of the block (1=used,0=free) */
|
||||||
|
uint16_t size; /* size of the block (without block header) */
|
||||||
|
} __attribute__((packed, aligned(2)));
|
||||||
|
|
||||||
|
struct heap_page
|
||||||
|
{
|
||||||
|
void *brk; /* break (address of the limit area) */
|
||||||
|
size_t size; /* Page size (without header) */
|
||||||
|
struct heap_page *next; /* Next heap page */
|
||||||
|
struct heap_block heap; /* Start of block informations */
|
||||||
|
} __attribute__((packed, aligned(4)));
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
extern void *malloc(size_t size);
|
||||||
|
extern void *calloc(size_t nmemb, size_t size);
|
||||||
|
extern void *realloc(void *ptr, size_t size);
|
||||||
|
extern void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||||
|
extern void free(void *ptr);
|
||||||
|
|
||||||
|
#endif /*__LIB_STDLIB_H__*/
|
32
include/string.h
Normal file
32
include/string.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef __STRING_H__
|
||||||
|
# define __STRING_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* memset() - fill memory with a constant byte. */
|
||||||
|
extern void *memset(void *s, int c, size_t n);
|
||||||
|
extern void *memcpy(void *dest, const void *src, size_t n);
|
||||||
|
|
||||||
|
/* strcat() - concatenate two string */
|
||||||
|
extern char *strcat(char *dest, char const *src);
|
||||||
|
|
||||||
|
/* strcmp() - compare two strings */
|
||||||
|
extern int strcmp(const char *s1, const char *s2);
|
||||||
|
extern int strncmp(const char *s1, const char *s2, size_t n);
|
||||||
|
|
||||||
|
/* strcpy(), strncpy() - copy a string. */
|
||||||
|
extern char *strncpy(char *dest, char const *str, size_t size);
|
||||||
|
extern char *strcpy(char *dest, char const *src);
|
||||||
|
|
||||||
|
/* strlen - calculate the lenght of a string. */
|
||||||
|
extern size_t strnlen(char const *str, size_t maxlen);
|
||||||
|
extern size_t strlen(char const *str);
|
||||||
|
|
||||||
|
/* strrchr() - find the last occurent of a byte */
|
||||||
|
extern char *strrchr(const char *s, int c);
|
||||||
|
|
||||||
|
/* strdup() - dump string */
|
||||||
|
extern char *strdup(const char *s);
|
||||||
|
|
||||||
|
#endif /*__STRING_H__*/
|
44
include/sys/mman.h
Normal file
44
include/sys/mman.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef __LIB_SYS_MMAN_H__
|
||||||
|
# define __LIB_SYS_MMAN_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef __KERNEL_MEMORY_H__
|
||||||
|
// mapping flags
|
||||||
|
// Protection (unused)
|
||||||
|
#define PROT_READ 0x1 /* Page can be read. */
|
||||||
|
#define PROT_WRITE 0x2 /* Page can be written. */
|
||||||
|
#define PROT_EXEC 0x4 /* Page can be executed. */
|
||||||
|
#define PROT_NONE 0x0 /* Page can not be accessed. */
|
||||||
|
|
||||||
|
// Mapping flags
|
||||||
|
#define MAP_SHARED 0x01 /* Share changes. */
|
||||||
|
#define MAP_PRIVATE 0x02 /* Changes are private. */
|
||||||
|
#define MAP_ANONYMOUS 0x20 /* Don't use a file. */
|
||||||
|
#define MAP_ANON MAP_ANONYMOUS /* Don't use a file. */
|
||||||
|
#define MAP_FILE 0 /* Ignored. */
|
||||||
|
#define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */
|
||||||
|
#define MAP_DENYWRITE 0x00800 /* ETXTBSY. */
|
||||||
|
#define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */
|
||||||
|
#define MAP_LOCKED 0x02000 /* Lock the mapping. */
|
||||||
|
#define MAP_NORESERVE 0x04000 /* Don't check for reservations. */
|
||||||
|
#define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */
|
||||||
|
#define MAP_NONBLOCK 0x10000 /* Do not block on IO. */
|
||||||
|
#define MAP_STACK 0x20000 /* Allocation is for a stack. */
|
||||||
|
#define MAP_HUGETLB 0x40000 /* Create huge page mapping. */
|
||||||
|
#define MAP_SYNC 0x80000 /* Perform synchronous page
|
||||||
|
faults for the mapping. */
|
||||||
|
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED but do not unmap
|
||||||
|
underlying mapping. */
|
||||||
|
#define MAP_UNINITIALIZED 0x200000 /* Don't clear anonymous page */
|
||||||
|
|
||||||
|
// Value returned when mmap value
|
||||||
|
#define MAP_FAILED ((void*) -1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
extern void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
|
||||||
|
extern int munmap(void *addr, size_t length);
|
||||||
|
|
||||||
|
#endif /*__LIB_SYS_MMAN_H__*/
|
1
include/sys/signal.h
Normal file
1
include/sys/signal.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include <signal.h>
|
41
include/sys/stat.h
Normal file
41
include/sys/stat.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef __KERNEL_FS_STAT_H__
|
||||||
|
# define __KERNEL_FS_STAT_H__
|
||||||
|
|
||||||
|
/* File types. */
|
||||||
|
#define __S_IFMT 0170000 /* These bits determine file type. */
|
||||||
|
#define __S_IFDIR 0040000 /* Directory. */
|
||||||
|
#define __S_IFCHR 0020000 /* Character device. */
|
||||||
|
#define __S_IFBLK 0060000 /* Block device. */
|
||||||
|
#define __S_IFREG 0100000 /* Regular file. */
|
||||||
|
#define __S_IFIFO 0010000 /* FIFO. */
|
||||||
|
#define __S_IFLNK 0120000 /* Symbolic link. */
|
||||||
|
#define __S_IFSOCK 0140000 /* Socket. */
|
||||||
|
|
||||||
|
/* Protection bits. */
|
||||||
|
#define __S_ISUID 0004000 /* Set user ID on execution. */
|
||||||
|
#define __S_ISGID 0002000 /* Set group ID on execution. */
|
||||||
|
#define __S_ISVTX 0001000 /* Save swapped text after use (sticky). */
|
||||||
|
#define __S_IREAD 0000400 /* Read by owner. */
|
||||||
|
#define __S_IWRITE 0000200 /* Write by owner. */
|
||||||
|
#define __S_IEXEC 0000100 /* Execute by owner. */
|
||||||
|
|
||||||
|
|
||||||
|
#define S_IRUSR __S_IREAD /* Read by owner. */
|
||||||
|
#define S_IWUSR __S_IWRITE /* Write by owner. */
|
||||||
|
#define S_IXUSR __S_IEXEC /* Execute by owner. */
|
||||||
|
/* Read, write, and execute by owner. */
|
||||||
|
#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)
|
||||||
|
|
||||||
|
#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */
|
||||||
|
#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */
|
||||||
|
#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */
|
||||||
|
/* Read, write, and execute by group. */
|
||||||
|
#define S_IRWXG (S_IRWXU >> 3)
|
||||||
|
|
||||||
|
#define S_IROTH (S_IRGRP >> 3) /* Read by others. */
|
||||||
|
#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */
|
||||||
|
#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */
|
||||||
|
/* Read, write, and execute by others. */
|
||||||
|
#define S_IRWXO (S_IRWXG >> 3)
|
||||||
|
|
||||||
|
#endif /*__KERNEL_FS_STAT_H__*/
|
12
include/sys/syscall.h
Normal file
12
include/sys/syscall.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef __LIB_SYS_SYSCALL_H__
|
||||||
|
# define __LIB_SYS_SYSCALL_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// include Vhex kernel real syscall
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
|
||||||
|
//TODO include Casio's syscall !!
|
||||||
|
|
||||||
|
#endif /*__LIB_SYS_SYSCALL_H__*/
|
25
include/sys/types.h
Normal file
25
include/sys/types.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef __TYPES_H__
|
||||||
|
# define __TYPES_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Define properly off_t type.
|
||||||
|
# ifndef __off_t_defined
|
||||||
|
typedef uint32_t off_t;
|
||||||
|
# define __off_t_defined
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// Define properly ssize_t type.
|
||||||
|
#ifndef __ssize_t_defined
|
||||||
|
typedef int32_t ssize_t;
|
||||||
|
# define __ssize_t_defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define alias
|
||||||
|
typedef int32_t pid_t;
|
||||||
|
typedef int16_t mode_t;
|
||||||
|
typedef uint16_t dev_t;
|
||||||
|
typedef uint16_t umode_t;
|
||||||
|
|
||||||
|
#endif /*__TYPES_H__*/
|
24
include/sys/wait.h
Normal file
24
include/sys/wait.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef __LIB_SYS_WAIT_H__
|
||||||
|
# define __LIB_SYS_WAIT_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <bits/waitflags.h>
|
||||||
|
#include <bits/waitstatus.h>
|
||||||
|
|
||||||
|
/* Macros for the `waitpid`'s wstatus argument. */
|
||||||
|
#define WEXITSTATUS(status) __WEXITSTATUS(status)
|
||||||
|
#define WTERMSIG(status) __WTERMSIG(status)
|
||||||
|
#define WSTOPSIG(status) __WSTOPSIG(status)
|
||||||
|
#define WIFEXITED(status) __WIFEXITED(status)
|
||||||
|
#define WIFSIGNALED(status) __WIFSIGNALED(status)
|
||||||
|
#define WIFSTOPPED(status) __WIFSTOPPED(status)
|
||||||
|
#define WIFCONTINUED(status) __WIFCONTINUED(status)
|
||||||
|
#define WCOREDUMP(status) __WCOREDUMP(status)
|
||||||
|
|
||||||
|
// Wait process
|
||||||
|
extern pid_t waitpid(pid_t pid, int *wstatus, int options);
|
||||||
|
extern pid_t wait(int *wstatus);
|
||||||
|
|
||||||
|
#endif /*__LIB_SYS_WAIT_H__*/
|
1
include/syscall.h
Normal file
1
include/syscall.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include <sys/syscall.h>
|
62
include/threads.h
Normal file
62
include/threads.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#ifndef __LIB_PTHREAD_H__
|
||||||
|
# define __LIB_PTHREAD_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Define Mutex type
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
mtx_plain = 0,
|
||||||
|
mtx_recursive = 1,
|
||||||
|
mtx_timed = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define mutex structure
|
||||||
|
#define MTX_WATERMARK (0xdeadbeef)
|
||||||
|
struct __mtx_s
|
||||||
|
{
|
||||||
|
uint32_t __watermark;
|
||||||
|
uint16_t lock;
|
||||||
|
uint8_t type;
|
||||||
|
} __attribute__((packed, aligned(4)));
|
||||||
|
typedef struct __mtx_s mtx_t;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mutex functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// Creates a new mutex object with type __TYPE.
|
||||||
|
// @note: If successful the new object is pointed by __MUTEX.
|
||||||
|
extern int mtx_init(mtx_t *__mutex, int __type);
|
||||||
|
|
||||||
|
// Block the current thread until the mutex pointed to by __MUTEX is unlocked.
|
||||||
|
// In that case current thread will not be blocked.
|
||||||
|
extern int mtx_lock(mtx_t *__mutex);
|
||||||
|
|
||||||
|
// Try to lock the mutex pointed by __MUTEX without blocking.
|
||||||
|
// @note: If the mutex is free the current threads takes control of it,
|
||||||
|
// otherwise it returns immediately.
|
||||||
|
extern int mtx_trylock(mtx_t *__mutex);
|
||||||
|
|
||||||
|
// Unlock the mutex pointed by __MUTEX.
|
||||||
|
// @note: It may potentially awake other threads waiting on this mutex.
|
||||||
|
extern int mtx_unlock (mtx_t *__mutex);
|
||||||
|
|
||||||
|
// Destroy the mutex object pointed by __MUTEX.
|
||||||
|
extern void mtx_destroy(mtx_t *__mutex);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Atomic operations
|
||||||
|
//
|
||||||
|
|
||||||
|
// Save the current SR register and set the SR.BIT bit up (start atomic operations)
|
||||||
|
// @note: return the saved SR register (if has been saved), 0xffffffff otherwise.
|
||||||
|
extern uint32_t __thread_atomic_start(void);
|
||||||
|
|
||||||
|
// Restore the saved SR register
|
||||||
|
// @note: return the restored SR register or -1 otherwise.
|
||||||
|
extern uint32_t __thread_atomic_stop(void);
|
||||||
|
#endif /*__LIB_PTHREAD_H__*/
|
36
include/unistd.h
Normal file
36
include/unistd.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef __LIB_UNISTD_H__
|
||||||
|
# define __LIB_UNISTD_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
// TODO: move me
|
||||||
|
#define STDIN_FILENO 0
|
||||||
|
#define STDOUT_FILENO 1
|
||||||
|
#define STDERR_FILENO 2
|
||||||
|
|
||||||
|
//TODO: move me
|
||||||
|
#define _SC_PAGE_SIZE 0
|
||||||
|
#define _SC_PAGESIZE _SC_PAGE_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
// Process part
|
||||||
|
extern pid_t getpid(void);
|
||||||
|
extern pid_t getpgid(void);
|
||||||
|
extern pid_t getppid(void);
|
||||||
|
extern int setpgid(pid_t pid, pid_t pgid);
|
||||||
|
|
||||||
|
// CUSTOM function (fork() + exeve()) !
|
||||||
|
extern pid_t fork_execve(const char *pathname, char **argv, char **envp);
|
||||||
|
|
||||||
|
// File part
|
||||||
|
extern ssize_t write(int fd, const void *buf, size_t count);
|
||||||
|
extern ssize_t read(int fd, void *buf, size_t count);
|
||||||
|
extern off_t lseek(int fd, off_t offset, int whence);
|
||||||
|
extern int close(int fd);
|
||||||
|
|
||||||
|
// System part
|
||||||
|
extern long sysconf(int name);
|
||||||
|
|
||||||
|
#endif /*__LIB_UNISTD_H__*/
|
168
make/Makefile.default
Normal file
168
make/Makefile.default
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#! /usr/bin/make -f
|
||||||
|
#---
|
||||||
|
#
|
||||||
|
# fxlibc project Makefile
|
||||||
|
#
|
||||||
|
# This makefile is grandly inspired by the Gint unikernel
|
||||||
|
# projet, many thanks to Lephenixnoir !
|
||||||
|
#
|
||||||
|
# Build architecture:
|
||||||
|
# build/
|
||||||
|
# |-- objects/
|
||||||
|
# | |-- string_strlen.o
|
||||||
|
# | |-- string_strcmp.o
|
||||||
|
# | ...
|
||||||
|
# | `-- signal_kill.o
|
||||||
|
# |-- debug/
|
||||||
|
# | |-- fxlibc.map (ELF link map informations)
|
||||||
|
# | ...
|
||||||
|
# | `-- otherinfo.txt
|
||||||
|
# |-- Makefile
|
||||||
|
# |-- fxlibc.cfg
|
||||||
|
# `-- bin/
|
||||||
|
# |-- fxlibc_stubs.a (workaround for the shared librairie, see documentation note)
|
||||||
|
# |-- fxlibc.so (shared librairy)
|
||||||
|
# `-- fxlibc.a (static librairy)
|
||||||
|
#---
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Build configuration
|
||||||
|
#---
|
||||||
|
|
||||||
|
# Require configuration file (if you want to clean up and lost the file, you
|
||||||
|
# can either reconfigure or just delete the build directory)
|
||||||
|
CONFIG := fxlibc.cfg
|
||||||
|
ifeq "$(wildcard $(CONFIG))" ""
|
||||||
|
$(error "config file $(CONFIG) does not exist (reconfigure or wipe directory)")
|
||||||
|
endif
|
||||||
|
include $(CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
# Compiler flags, assembler flags, dependency generation, archiving
|
||||||
|
header := -I ../include
|
||||||
|
cflags := $(machine) -ffreestanding -nostdlib -Wall -Wextra -std=c11 -Os \
|
||||||
|
-fstrict-volatile-bitfields $(header) $(CONFIG.CFLAGS)
|
||||||
|
|
||||||
|
# color definition
|
||||||
|
red := \033[1;31m
|
||||||
|
green := \033[1;32m
|
||||||
|
blue := \033[1;34m
|
||||||
|
white := \033[1;37m
|
||||||
|
nocolor := \033[1;0m
|
||||||
|
|
||||||
|
# This is a workaround to force a newline when the "eval" keyword is involved
|
||||||
|
define n
|
||||||
|
# Force newline character
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
# Define all directory used to stored informations
|
||||||
|
dir_objects := objects
|
||||||
|
dir_bin := bin
|
||||||
|
|
||||||
|
# Output configurations
|
||||||
|
name := fxlibc
|
||||||
|
target := $(dir_bin)/$(name).a
|
||||||
|
|
||||||
|
# automated variable
|
||||||
|
src :=
|
||||||
|
directory := $(shell find ../src/ -not -path "*/\.*" -type d)
|
||||||
|
$(foreach path,$(directory),$(eval \
|
||||||
|
src += $(wildcard $(path)/*.c) $n\
|
||||||
|
src += $(wildcard $(path)/*.S) $n\
|
||||||
|
src += $(wildcard $(path)/*.s) $n\
|
||||||
|
))
|
||||||
|
obj := $(patsubst .._src_%,$(dir_objects)/%.o,$(subst /,_,$(basename $(src))))
|
||||||
|
|
||||||
|
# check if any file have been found
|
||||||
|
ifeq ($(obj),)
|
||||||
|
$(error "source file does not exist (reconfigure or wipe directory)")
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Toolchain
|
||||||
|
#---
|
||||||
|
gcc = $(CONFIG.TOOLCHAIN)-gcc
|
||||||
|
as = $(CONFIG.TOOLCHAIN)-as
|
||||||
|
ld = $(CONFIG.TOOLCHAIN)-ld
|
||||||
|
ar = $(CONFIG.TOOLCHAIN)-ar
|
||||||
|
objcopy = $(CONFIG.TOOLCHAIN)-objcopy
|
||||||
|
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Version management
|
||||||
|
#---
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Build rules
|
||||||
|
#---
|
||||||
|
all: $(target)
|
||||||
|
|
||||||
|
# linker part
|
||||||
|
$(target): $(obj) | $(dir_bin)
|
||||||
|
$(ar) crs $@ $^
|
||||||
|
|
||||||
|
# Directory management
|
||||||
|
$(dir_bin) $(dir_objects):
|
||||||
|
@ printf "Create $(blue)$@$(nocolor) directory\n"
|
||||||
|
@ mkdir -p $@
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Automated rules
|
||||||
|
#---
|
||||||
|
define rule-src
|
||||||
|
$(patsubst .._src_%,$(dir_objects)/%.o,$(subst /,_,$(basename $1))): $1 | $(dir_objects)
|
||||||
|
@ printf "compiling $(white)$$<$(nocolor)..."
|
||||||
|
@ $(gcc) $(cflags) -o $$@ -c $$< -lgcc
|
||||||
|
@ printf "$(green)[ok]$(nocolor)\n"
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(foreach source,$(src),$(eval \
|
||||||
|
$(call rule-src,$(source))) \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Debugging rules
|
||||||
|
#---
|
||||||
|
help:
|
||||||
|
@ echo 'make [options]...'
|
||||||
|
@ echo ''
|
||||||
|
@ echo 'Options:'
|
||||||
|
@ echo ' * disasm use objdump to display the content of the archive'
|
||||||
|
@ echo ' * debug display source files name and objects name'
|
||||||
|
@ echo ' * elf_sec display ELF section of the archive'
|
||||||
|
__debug:
|
||||||
|
@ echo 'src: $(src)'
|
||||||
|
@ echo ''
|
||||||
|
@ echo 'obj: $(obj)'
|
||||||
|
@ echo ''
|
||||||
|
@ echo 'directory: $(dir_bin) $(dir_output) $(dir_objects)'
|
||||||
|
|
||||||
|
disasm:
|
||||||
|
@ $(objdump) -D $(target) | less
|
||||||
|
|
||||||
|
elf_sec:
|
||||||
|
@ $(objdump) -h $(target) | less
|
||||||
|
|
||||||
|
.PHONY: help __debug disasm elf_sec
|
||||||
|
|
||||||
|
|
||||||
|
#---
|
||||||
|
# clean rules
|
||||||
|
#---
|
||||||
|
clean:
|
||||||
|
rm -rf $(dir_objects)
|
||||||
|
|
||||||
|
fclean: clean
|
||||||
|
rm -rf $(dir_bin)
|
||||||
|
|
||||||
|
re: fclean clean
|
||||||
|
|
||||||
|
.PHONY: clean fclean re
|
54
src/setjmp/longjmp.S
Normal file
54
src/setjmp/longjmp.S
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
.text
|
||||||
|
.global _longjmp
|
||||||
|
.type _longjmp, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** void longjmp(jmp_buf env, int val)
|
||||||
|
** @note: TODO
|
||||||
|
*/
|
||||||
|
_longjmp:
|
||||||
|
! save the context into unbankable register
|
||||||
|
mov r4, r8
|
||||||
|
|
||||||
|
! check the returned value validity
|
||||||
|
tst r5, r5
|
||||||
|
bf/s int_block
|
||||||
|
mov r5, r9
|
||||||
|
mov #1, r9
|
||||||
|
|
||||||
|
! block interrupt
|
||||||
|
int_block:
|
||||||
|
stc sr, r1
|
||||||
|
mov #0x10, r2
|
||||||
|
shll8 r2
|
||||||
|
shll16 r2
|
||||||
|
or r2, r1
|
||||||
|
ldc r1, sr
|
||||||
|
|
||||||
|
context_switch:
|
||||||
|
! load the old SR regsiter first to force register bank switch
|
||||||
|
! (if needed) then move the context and the returned value into
|
||||||
|
! non-saved (by the setjmp context) registers.
|
||||||
|
ldc.l @r8+, sr
|
||||||
|
mov r8, r4
|
||||||
|
mov r9, r0
|
||||||
|
|
||||||
|
! restore all old registers
|
||||||
|
mov.l @r4+, r8
|
||||||
|
mov.l @r4+, r9
|
||||||
|
mov.l @r4+, r10
|
||||||
|
mov.l @r4+, r11
|
||||||
|
mov.l @r4+, r12
|
||||||
|
mov.l @r4+, r13
|
||||||
|
mov.l @r4+, r14
|
||||||
|
mov.l @r4+, r15
|
||||||
|
ldc.l @r4+, gbr
|
||||||
|
lds.l @r4+, macl
|
||||||
|
lds.l @r4+, mach
|
||||||
|
lds.l @r4+, pr
|
||||||
|
|
||||||
|
! return to the old place
|
||||||
|
rts
|
||||||
|
nop
|
43
src/setjmp/setjmp.S
Normal file
43
src/setjmp/setjmp.S
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.text
|
||||||
|
.global _setjmp
|
||||||
|
.type _setjmp, @function
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** int setjmp(jmp_buf env)
|
||||||
|
** @note: TODO
|
||||||
|
*/
|
||||||
|
_setjmp:
|
||||||
|
! block interrupt
|
||||||
|
stc sr, r1
|
||||||
|
mov r1, r3
|
||||||
|
mov #0x10, r2
|
||||||
|
shll8 r2
|
||||||
|
shll16 r2
|
||||||
|
or r2, r1
|
||||||
|
ldc r1, sr
|
||||||
|
|
||||||
|
! save current context
|
||||||
|
! @note: r3 is the saved SR regsiter
|
||||||
|
add #52, r4
|
||||||
|
sts.l pr, @-r4
|
||||||
|
sts.l mach, @-r4
|
||||||
|
sts.l macl, @-r4
|
||||||
|
stc.l gbr, @-r4
|
||||||
|
mov.l r15, @-r4
|
||||||
|
mov.l r14, @-r4
|
||||||
|
mov.l r13, @-r4
|
||||||
|
mov.l r12, @-r4
|
||||||
|
mov.l r11, @-r4
|
||||||
|
mov.l r10, @-r4
|
||||||
|
mov.l r9, @-r4
|
||||||
|
mov.l r8, @-r4
|
||||||
|
mov.l r3, @-r4
|
||||||
|
|
||||||
|
! restore sr
|
||||||
|
ldc r3, sr
|
||||||
|
|
||||||
|
! return
|
||||||
|
rts
|
||||||
|
mov #0, r0
|
||||||
|
|
15
src/signal/kill.S
Normal file
15
src/signal/kill.S
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _kill
|
||||||
|
.type _kill, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** TODO: doc
|
||||||
|
*/
|
||||||
|
_kill:
|
||||||
|
trapa #__NR_kill
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
15
src/signal/signal.S
Normal file
15
src/signal/signal.S
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _signal
|
||||||
|
.type _signal, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** TODO: doc
|
||||||
|
*/
|
||||||
|
_signal:
|
||||||
|
trapa #__NR_signal
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/stdio/dprintf.c
Normal file
12
src/stdio/dprintf.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int dprintf(int fd, const char *restrict format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
ret = vdprintf(fd, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return (ret);
|
||||||
|
}
|
188
src/stdio/internal/printf_actions.c
Normal file
188
src/stdio/internal/printf_actions.c
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Define all actions
|
||||||
|
static void action_str(struct printf_opt *op, char n);
|
||||||
|
static void action_ptr(struct printf_opt *op, char n);
|
||||||
|
static void action_int(struct printf_opt *op, char n);
|
||||||
|
static void action_uint(struct printf_opt *op, char n);
|
||||||
|
static void action_char(struct printf_opt *op, char n);
|
||||||
|
|
||||||
|
// Define all actions which can be used
|
||||||
|
void (*action[26])(struct printf_opt *opt, char n) = {
|
||||||
|
NULL, NULL, action_char, action_int,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
action_int, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, action_uint, action_ptr,
|
||||||
|
NULL, NULL, action_str, NULL,
|
||||||
|
action_uint, NULL, NULL, action_uint,
|
||||||
|
NULL, NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Disp part
|
||||||
|
//---
|
||||||
|
static void base_to_str(struct printf_opt *opt, uint32_t num, int base, int digits)
|
||||||
|
{
|
||||||
|
char *hexa = (opt->uppercase == 1) ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||||
|
|
||||||
|
opt->digits = 0;
|
||||||
|
while (num != 0 || opt->digits < digits)
|
||||||
|
{
|
||||||
|
opt->format[opt->digits++] = hexa[num % base];
|
||||||
|
num = num / base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disp_format(struct printf_opt *opt)
|
||||||
|
{
|
||||||
|
// display pre symbols
|
||||||
|
if (opt->sign != '\0')
|
||||||
|
(*opt->disp_char)(opt, opt->sign);
|
||||||
|
if (opt->base[0] != '\0')
|
||||||
|
(*opt->disp_char)(opt, opt->base[0]);
|
||||||
|
if (opt->base[1] != '\0')
|
||||||
|
(*opt->disp_char)(opt, opt->base[1]);
|
||||||
|
|
||||||
|
// padding
|
||||||
|
if (opt->flags.minus == 1 && opt->width > opt->digits)
|
||||||
|
{
|
||||||
|
int total = opt->digits + (opt->sign != '\0') +
|
||||||
|
(opt->base[0] != '\0') + (opt->base[1] != '\0');
|
||||||
|
total = opt->width - total;
|
||||||
|
while (--total >= 0)
|
||||||
|
(*opt->disp_char)(opt, (opt->flags.zero == 1) ? '0' : ' ');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display number
|
||||||
|
int saved_digits = opt->digits;
|
||||||
|
while (--opt->digits >= 0)
|
||||||
|
(*opt->disp_char)(opt, opt->format[opt->digits]);
|
||||||
|
|
||||||
|
// padding
|
||||||
|
if (opt->flags.minus == 0 && opt->width > saved_digits)
|
||||||
|
{
|
||||||
|
int total = saved_digits + (opt->sign != '\0') +
|
||||||
|
(opt->base[0] != '\0') + (opt->base[1] != '\0');
|
||||||
|
total = opt->width - total;
|
||||||
|
while (--total >= 0)
|
||||||
|
(*opt->disp_char)(opt, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Args part
|
||||||
|
//---
|
||||||
|
static uint32_t get_arg_i(struct printf_opt *opt)
|
||||||
|
{
|
||||||
|
switch (opt->lenght)
|
||||||
|
{
|
||||||
|
case 0: return ((signed char)va_arg(opt->ap, int));
|
||||||
|
case 1: return ((short int)va_arg(opt->ap, int));
|
||||||
|
case 2: return (va_arg(opt->ap, long int));
|
||||||
|
case 3: return (va_arg(opt->ap, long long int));
|
||||||
|
case 4: return (va_arg(opt->ap, intmax_t));
|
||||||
|
case 5: return (va_arg(opt->ap, size_t));
|
||||||
|
case 6: return (va_arg(opt->ap, ptrdiff_t));
|
||||||
|
}
|
||||||
|
return (va_arg(opt->ap, int));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_arg_u(struct printf_opt *opt)
|
||||||
|
{
|
||||||
|
switch (opt->lenght)
|
||||||
|
{
|
||||||
|
case 0: return ((unsigned char)va_arg(opt->ap, int));
|
||||||
|
case 1: return ((unsigned short int)va_arg(opt->ap, int));
|
||||||
|
case 2: return (va_arg(opt->ap, unsigned long int));
|
||||||
|
case 3: return (va_arg(opt->ap, unsigned long long int));
|
||||||
|
case 4: return (va_arg(opt->ap, intmax_t));
|
||||||
|
case 5: return (va_arg(opt->ap, size_t));
|
||||||
|
case 6: return (va_arg(opt->ap, ptrdiff_t));
|
||||||
|
}
|
||||||
|
return (va_arg(opt->ap, unsigned int));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Actions part.
|
||||||
|
//---
|
||||||
|
static void action_str(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
(void)n;
|
||||||
|
str = va_arg(opt->ap, const char *);
|
||||||
|
while (*str != '\0')
|
||||||
|
(*opt->disp_char)(opt, *(str++));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_char(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
n = (char)va_arg(opt->ap, int);
|
||||||
|
(*opt->disp_char)(opt, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_ptr(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
(void)n;
|
||||||
|
opt->sign = '@';
|
||||||
|
opt->base[0] = '0';
|
||||||
|
opt->base[1] = 'x';
|
||||||
|
base_to_str(opt, (uint32_t)va_arg(opt->ap, void*), 16, 8);
|
||||||
|
disp_format(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_int(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
int64_t num;
|
||||||
|
|
||||||
|
// Get data and check negative value
|
||||||
|
// FIXME: max negative value can not be reversed
|
||||||
|
(void)n;
|
||||||
|
num = get_arg_i(opt);
|
||||||
|
if (num < 0) {
|
||||||
|
opt->sign = '-';
|
||||||
|
num = -num;
|
||||||
|
} else if (opt->flags.space == 1 || opt->flags.plus == 1) {
|
||||||
|
opt->sign = (opt->flags.plus == 1) ? '+' : ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate / display number
|
||||||
|
base_to_str(opt, num, 10, 1);
|
||||||
|
disp_format(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_uint(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
uint32_t num;
|
||||||
|
int base;
|
||||||
|
|
||||||
|
// Get appropriate base
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 'o': base = 8; break;
|
||||||
|
case 'x': base = 16; break;
|
||||||
|
default: base = 10; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display extra symbols if needed
|
||||||
|
if (opt->flags.diez == 1)
|
||||||
|
{
|
||||||
|
if (n == 'o') {
|
||||||
|
opt->base[0] = '0';
|
||||||
|
} else if (n == 'x') {
|
||||||
|
opt->base[0] = '0';
|
||||||
|
opt->base[1] = (opt->uppercase == 1) ? 'X' : 'x';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get number
|
||||||
|
num = get_arg_u(opt);
|
||||||
|
|
||||||
|
// Generate / display number
|
||||||
|
base_to_str(opt, num, base, 1);
|
||||||
|
disp_format(opt);
|
||||||
|
}
|
40
src/stdio/internal/printf_common.c
Normal file
40
src/stdio/internal/printf_common.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//TODO: precision handling
|
||||||
|
int printf_common(struct printf_opt *opt, const char *restrict format)
|
||||||
|
{
|
||||||
|
extern int printf_get_options(struct printf_opt *opt, const char *restrict format);
|
||||||
|
int saved_p;
|
||||||
|
int p;
|
||||||
|
|
||||||
|
p = -1;
|
||||||
|
opt->counter = 0;
|
||||||
|
opt->buffer_cursor = 0;
|
||||||
|
while (format[++p] != '\0')
|
||||||
|
{
|
||||||
|
// Check printable char
|
||||||
|
if (format[p] != '%' || format[p + 1] == '%') {
|
||||||
|
(*opt->disp_char)(opt, (format[p] != '%') ? format[p] : format[++p]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get options
|
||||||
|
saved_p = p;
|
||||||
|
p = p + printf_get_options(opt, &format[p + 1]);
|
||||||
|
|
||||||
|
// Check arg validity
|
||||||
|
if (((format[p + 1] >= 'a' && format[p + 1] <= 'z') ||
|
||||||
|
(format[p + 1] >= 'A' && format[p + 1] <= 'Z')) &&
|
||||||
|
action[(format[p + 1] | 0x20) - 'a'] != NULL) {
|
||||||
|
(*action[(format[p + 1] | 0x20) - 'a'])(opt, format[p + 1] | 0x20);
|
||||||
|
p = p + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default, print the %
|
||||||
|
(*opt->disp_char)(opt, '%');
|
||||||
|
p = saved_p;
|
||||||
|
}
|
||||||
|
(*opt->disp_fflush)(opt);
|
||||||
|
return (opt->counter);
|
||||||
|
}
|
105
src/stdio/internal/printf_options.c
Normal file
105
src/stdio/internal/printf_options.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static int get_flags(struct printf_opt *opt, const char *restrict format)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = -1;
|
||||||
|
opt->flags.diez = 0;
|
||||||
|
opt->flags.zero = 0;
|
||||||
|
opt->flags.minus = 0;
|
||||||
|
opt->flags.space = 0;
|
||||||
|
opt->flags.plus = 0;
|
||||||
|
while (format[++i] != '\0')
|
||||||
|
{
|
||||||
|
switch (format[i])
|
||||||
|
{
|
||||||
|
case '#': opt->flags.diez = 1; break;
|
||||||
|
case '0': opt->flags.zero = 1; break;
|
||||||
|
case '-': opt->flags.minus = 1; break;
|
||||||
|
case ' ': opt->flags.space = 1; break;
|
||||||
|
case '+': opt->flags.plus = 1; break;
|
||||||
|
default: return (i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_width(struct printf_opt *opt, const char *restrict format)
|
||||||
|
{
|
||||||
|
// Check dynamic width
|
||||||
|
if (format[0] == '*') {
|
||||||
|
opt->width = va_arg(opt->ap, int);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check error
|
||||||
|
int i = -1;
|
||||||
|
opt->width = 0;
|
||||||
|
if (format[0] == '0')
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
// Get static width
|
||||||
|
while (format[++i] >= '0' && format[i] <= '9')
|
||||||
|
opt->width = (opt->width * 10) + (format[i] - '0');
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_precision(struct printf_opt *opt, const char *restrict format)
|
||||||
|
{
|
||||||
|
// Check if precision is specified
|
||||||
|
if (format[0] != '.')
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
// Check dynamic precision
|
||||||
|
if (format[1] == '*') {
|
||||||
|
opt->precision = va_arg(opt->ap, int);
|
||||||
|
return (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get static precision
|
||||||
|
int i = 0;
|
||||||
|
opt->precision = 0;
|
||||||
|
while (format[++i] >= '0' && format[i] <= '9')
|
||||||
|
opt->precision = (opt->precision * 10) + (format[i] - '0');
|
||||||
|
|
||||||
|
// Check default precision
|
||||||
|
if (i == 0)
|
||||||
|
opt->precision = 1;
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_lenght(struct printf_opt *opt, const char *restrict format)
|
||||||
|
{
|
||||||
|
opt->lenght = -1;
|
||||||
|
switch (format[0])
|
||||||
|
{
|
||||||
|
case 'h': opt->lenght = (format[1] == 'h') ? 1 : 0; break;
|
||||||
|
case 'l': opt->lenght = (format[1] == 'l') ? 3 : 2; break;
|
||||||
|
case 'j': opt->lenght = 4; break;
|
||||||
|
case 'z': opt->lenght = 5; break;
|
||||||
|
case 't': opt->lenght = 6; break;
|
||||||
|
default: return (0);
|
||||||
|
}
|
||||||
|
return ((opt->lenght == 1 || opt->lenght == 3) ? 2 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int printf_get_options(struct printf_opt *opt, const char *restrict format)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Wipe internal format infos
|
||||||
|
opt->sign = '\0';
|
||||||
|
opt->base[0] = '\0';
|
||||||
|
opt->base[1] = '\0';
|
||||||
|
|
||||||
|
// Get generals opetions
|
||||||
|
i = get_flags(opt, &format[0]);
|
||||||
|
i += get_width(opt, &format[i]);
|
||||||
|
i += get_precision(opt, &format[i]);
|
||||||
|
i += get_lenght(opt, &format[i]);
|
||||||
|
|
||||||
|
// Check upper case actions
|
||||||
|
opt->uppercase = (format[i] == 'X') ? 1 : 0;
|
||||||
|
return (i);
|
||||||
|
}
|
13
src/stdio/printf.c
Normal file
13
src/stdio/printf.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int printf(const char *restrict format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
ret = vdprintf(STDOUT_FILENO, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return (ret);
|
||||||
|
}
|
11
src/stdio/putc.c
Normal file
11
src/stdio/putc.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int putc(int c)
|
||||||
|
{
|
||||||
|
char n;
|
||||||
|
|
||||||
|
n = (char)c;
|
||||||
|
write(STDOUT_FILENO, &n, 1);
|
||||||
|
return (n);
|
||||||
|
}
|
13
src/stdio/puts.c
Normal file
13
src/stdio/puts.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int puts(const char *s)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
size = strlen(s);
|
||||||
|
n = write(STDOUT_FILENO, s, size);
|
||||||
|
return (-(n == size));
|
||||||
|
}
|
11
src/stdio/snprintf.c
Normal file
11
src/stdio/snprintf.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int snprintf(char *restrict str, size_t size, const char *restrict format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
size = vsnprintf(str, size, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return (size);
|
||||||
|
}
|
12
src/stdio/sprintf.c
Normal file
12
src/stdio/sprintf.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int sprintf(char *restrict str, const char *restrict format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
size = vsnprintf(str, 65535, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return (size);
|
||||||
|
}
|
35
src/stdio/vdprintf.c
Normal file
35
src/stdio/vdprintf.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// if the writte syscall do not return the same
|
||||||
|
// number of bytes that requested, stop the function !
|
||||||
|
static void disp_fflush(struct printf_opt *opt)
|
||||||
|
{
|
||||||
|
if (opt->buffer_cursor != 0) {
|
||||||
|
opt->counter += write(opt->fd, opt->buffer, opt->buffer_cursor);
|
||||||
|
opt->buffer_cursor = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disp_char(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
// Check if we should force flush the internal buffer
|
||||||
|
if (opt->buffer_cursor >= PRINTF_INTERNAL_BUFFER_SIZE)
|
||||||
|
disp_fflush(opt);
|
||||||
|
|
||||||
|
// Save char
|
||||||
|
opt->buffer[opt->buffer_cursor++] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vdprintf(int fd, const char *restrict format, va_list ap)
|
||||||
|
{
|
||||||
|
extern int printf_common(struct printf_opt *opt, const char *restrict format);
|
||||||
|
struct printf_opt opt;
|
||||||
|
|
||||||
|
opt.fd = fd;
|
||||||
|
opt.disp_char = &disp_char;
|
||||||
|
opt.disp_fflush = &disp_fflush;
|
||||||
|
va_copy(opt.ap, ap);
|
||||||
|
return (printf_common(&opt, format));
|
||||||
|
}
|
29
src/stdio/vsnprintf.c
Normal file
29
src/stdio/vsnprintf.c
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void disp_char(struct printf_opt *opt, char n)
|
||||||
|
{
|
||||||
|
// Check write possibility
|
||||||
|
if (opt->buffer_cursor < opt->str_size - 1) {
|
||||||
|
opt->str[opt->buffer_cursor] = n;
|
||||||
|
opt->buffer_cursor = opt->buffer_cursor + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disp_fflush(struct printf_opt *opt)
|
||||||
|
{
|
||||||
|
opt->str[opt->buffer_cursor] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsnprintf(char *restrict str, size_t size, const char *restrict format, va_list ap)
|
||||||
|
{
|
||||||
|
extern int printf_common(struct printf_opt *opt, const char *restrict format);
|
||||||
|
struct printf_opt opt;
|
||||||
|
|
||||||
|
opt.str = str;
|
||||||
|
opt.str_size = size;
|
||||||
|
opt.disp_char = &disp_char;
|
||||||
|
opt.disp_fflush = &disp_fflush;
|
||||||
|
va_copy(opt.ap, ap);
|
||||||
|
return (printf_common(&opt, format) + 1);
|
||||||
|
}
|
||||||
|
|
6
src/stdio/vsprintf.c
Normal file
6
src/stdio/vsprintf.c
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int vsprintf(char *restrict str, const char *restrict format, va_list ap)
|
||||||
|
{
|
||||||
|
return (vsnprintf(str, 65535, format, ap));
|
||||||
|
}
|
16
src/stdlib/calloc.c
Normal file
16
src/stdlib/calloc.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void *calloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0 || nmemb == 0)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
void *ret = malloc(nmemb * size);
|
||||||
|
if (ret == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
memset(ret, 0x00, size);
|
||||||
|
return (ret);
|
||||||
|
}
|
17
src/stdlib/free.S
Normal file
17
src/stdlib/free.S
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _free
|
||||||
|
.type _free, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** @note: the MMU is used by Casio so we
|
||||||
|
** can not implement brk or skr because
|
||||||
|
** of non continuous heap.
|
||||||
|
*/
|
||||||
|
_free:
|
||||||
|
trapa #__NR_proc_heap_free
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
16
src/stdlib/malloc.S
Normal file
16
src/stdlib/malloc.S
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _malloc
|
||||||
|
.type _malloc, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** @note: We can not implement brk or skr
|
||||||
|
** because the MMU is used by Casio.
|
||||||
|
*/
|
||||||
|
_malloc:
|
||||||
|
trapa #__NR_proc_heap_alloc
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
46
src/stdlib/realloc.S
Normal file
46
src/stdlib/realloc.S
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _realloc
|
||||||
|
.type _realloc, @function
|
||||||
|
|
||||||
|
.extern _malloc
|
||||||
|
.extern _free
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
/*
|
||||||
|
** void *realloc(void ptr, size_t size)
|
||||||
|
**
|
||||||
|
** @note: the MMU is used by Casio so we
|
||||||
|
** can not implement brk or skr because
|
||||||
|
** of non continuous heap.
|
||||||
|
*/
|
||||||
|
_realloc:
|
||||||
|
! Check malloc part
|
||||||
|
tst r4, r4 ! if ptr == NULL...
|
||||||
|
bf.s check_free ! ...if not, jump at <check_free>
|
||||||
|
mov.l .malloc, r0 ! get malloc() address
|
||||||
|
jmp @r0 ! call malloc(size)
|
||||||
|
mov r5, r4 ! (db) send size
|
||||||
|
|
||||||
|
! Check free
|
||||||
|
check_free:
|
||||||
|
tst r5, r5 ! if size == 0...
|
||||||
|
bf.s call_realloc ! ...if not, jump at <call_realloc>
|
||||||
|
mov.l .free, r0 ! get free() address
|
||||||
|
sts.l pr, @-r15 ! save pr register
|
||||||
|
jmp @r0 ! call free(ptr)
|
||||||
|
nop ! (db) nop
|
||||||
|
rts ! return...
|
||||||
|
xor r0, r0 ! (db) ...NULL
|
||||||
|
|
||||||
|
|
||||||
|
! Call realloc
|
||||||
|
call_realloc:
|
||||||
|
trapa #__NR_proc_heap_realloc
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.malloc: .long _malloc
|
||||||
|
.free: .long _free
|
||||||
|
.end
|
8
src/stdlib/reallocarray.c
Normal file
8
src/stdlib/reallocarray.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
//FIXME: check safe !!!!
|
||||||
|
//FIXME: Check underflow !!
|
||||||
|
void *reallocarray(void *ptr, size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
return (realloc(ptr, nmemb * size));
|
||||||
|
}
|
8
src/string/memcpy.c
Normal file
8
src/string/memcpy.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void *memcpy(void *dest, const void *src, size_t count)
|
||||||
|
{
|
||||||
|
for (size_t i = 0 ; i < count ; i = i + 1)
|
||||||
|
((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
|
||||||
|
return (dest);
|
||||||
|
}
|
9
src/string/memset.c
Normal file
9
src/string/memset.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
//TODO: update me :(
|
||||||
|
void *memset(void *s, int c, size_t n)
|
||||||
|
{
|
||||||
|
while ((int)--n >= 0)
|
||||||
|
((uint8_t*)s)[n] = c;
|
||||||
|
return (s);
|
||||||
|
}
|
17
src/string/strcat.c
Normal file
17
src/string/strcat.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *strcat(char *dest, char const *src)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t start;
|
||||||
|
|
||||||
|
if (src == NULL || dest == NULL)
|
||||||
|
return (0);
|
||||||
|
i = -1;
|
||||||
|
start = -1;
|
||||||
|
while (dest[++start] != '\0');
|
||||||
|
while (src[++i] != '\0')
|
||||||
|
dest[start + i] = src[i];
|
||||||
|
dest[i + start] = '\0';
|
||||||
|
return (dest);
|
||||||
|
}
|
31
src/string/strchr.c
Normal file
31
src/string/strchr.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
//TODO: asm ?
|
||||||
|
char *strchr(const char *s1, int c)
|
||||||
|
{
|
||||||
|
int i = -1;
|
||||||
|
while (s1[++i] != '\0' && s1[i] != c);
|
||||||
|
return ((s1[i] == '\0') ? NULL : (void*)&s1[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: asm ?
|
||||||
|
char *strchrnul(const char *s1, int c)
|
||||||
|
{
|
||||||
|
int i = -1;
|
||||||
|
while (s1[++i] != '\0' && s1[i] != c);
|
||||||
|
return ((void*)&s1[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO asm ?
|
||||||
|
char *strrchr(const char *s1, int c)
|
||||||
|
{
|
||||||
|
void *saved;
|
||||||
|
|
||||||
|
saved = NULL;
|
||||||
|
for (int i = 0 ; s1[i] != '\0' ; i++)
|
||||||
|
{
|
||||||
|
if (s1[i] == c)
|
||||||
|
saved = (void *)&s1[i];
|
||||||
|
}
|
||||||
|
return (saved);
|
||||||
|
}
|
22
src/string/strcmp.c
Normal file
22
src/string/strcmp.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int strcmp(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
if (s1 == NULL || s2 == NULL)
|
||||||
|
return (0);
|
||||||
|
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
|
||||||
|
{
|
||||||
|
s1 += 1;
|
||||||
|
s2 += 1;
|
||||||
|
}
|
||||||
|
return (*s1 - *s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int strncmp(const char *s1, const char *s2, size_t n)
|
||||||
|
{
|
||||||
|
if (s1 == NULL || s2 == NULL || n == 0)
|
||||||
|
return (0);
|
||||||
|
size_t i = -1;
|
||||||
|
while (++i < n - 1 && s1[i] != '\0' && s2[i] != '\0' && s1[i] == s2[i]);
|
||||||
|
return (s1[i] - s2[i]);
|
||||||
|
}
|
27
src/string/strcpy.c
Normal file
27
src/string/strcpy.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *strcpy(char *dest, char const *src)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (src == NULL || dest == NULL)
|
||||||
|
return (0);
|
||||||
|
i = -1;
|
||||||
|
while (src[++i] != '\0')
|
||||||
|
dest[i] = src[i];
|
||||||
|
dest[i] = '\0';
|
||||||
|
return (dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strncpy(char *dest, char const *str, size_t size)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (str == NULL || dest == NULL)
|
||||||
|
return (0);
|
||||||
|
i = -1;
|
||||||
|
while (++i < size && str[i] != '\0')
|
||||||
|
dest[i] = str[i];
|
||||||
|
dest[i] = '\0';
|
||||||
|
return (dest);
|
||||||
|
}
|
22
src/string/strdup.c
Normal file
22
src/string/strdup.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
char *strdup(const char *s)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
void *dump;
|
||||||
|
|
||||||
|
// Check error
|
||||||
|
if (s == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
// Check len
|
||||||
|
len = strlen(s);
|
||||||
|
if (len == 0)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
// Dump string and return
|
||||||
|
dump = malloc(len);
|
||||||
|
memcpy(dump, s, len);
|
||||||
|
return (dump);
|
||||||
|
}
|
23
src/string/strlen.c
Normal file
23
src/string/strlen.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
size_t strlen(char const *str)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (str == NULL)
|
||||||
|
return (0);
|
||||||
|
i = -1;
|
||||||
|
while (str[++i] != '\0');
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strnlen(char const *str, size_t maxlen)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (str == NULL)
|
||||||
|
return (0);
|
||||||
|
i = -1;
|
||||||
|
while (str[++i] != '\0' && (size_t)i < maxlen);
|
||||||
|
return (i);
|
||||||
|
}
|
88
src/threads/atomic.S
Normal file
88
src/threads/atomic.S
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
.text
|
||||||
|
.global ___thread_atomic_start
|
||||||
|
.global ___thread_atomic_stop
|
||||||
|
|
||||||
|
.type ___thread_atomic_start, @function
|
||||||
|
.type ___thread_atomic_stop, @function
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
// Save the current SR register and set the SR.BIT bit up (start atomic operations)
|
||||||
|
// @note: return the saved SR register (if has been saved), 0xffffffff otherwise.
|
||||||
|
___thread_atomic_start:
|
||||||
|
! Check if the calculator is currently
|
||||||
|
! into an atomic operation and update
|
||||||
|
! atomic counter.
|
||||||
|
mov.l atomic_counter, r1 ! r1 = atomic counter address
|
||||||
|
mov.l @r1, r2 ! r2 = atomic counter data
|
||||||
|
tst r2, r2 ! if atomic counter == 0...
|
||||||
|
add #1, r2 ! update atomic counter data
|
||||||
|
mov.l r2, @r1 ! update atomic counter.
|
||||||
|
bf.s atomic_start_exit ! ...if not, jump <atomic_start_exit>
|
||||||
|
mov #-1, r0 ! (db) return 0xffffffff
|
||||||
|
|
||||||
|
! Block interrupt if needed.
|
||||||
|
stc sr, r1 ! get SR register.
|
||||||
|
mov r1, r0 ! save current SR register.
|
||||||
|
mov.l bl_mask, r2 ! get SR.BL mask.
|
||||||
|
or r2, r1 ! set SR.BL = 1 and SR.IMASK = 0b1111.
|
||||||
|
ldc r1, sr ! update SR register.
|
||||||
|
|
||||||
|
! Save "old" SR register.
|
||||||
|
mov.l sr_save, r1 ! r1 = sr_save address
|
||||||
|
mov.l r0, @r1 ! save "old" SR register data.
|
||||||
|
|
||||||
|
atomic_start_exit:
|
||||||
|
rts ! exit.
|
||||||
|
nop ! (db) nop.
|
||||||
|
|
||||||
|
// Restore the saved SR register
|
||||||
|
// @note: return the restored SR register or -1 otherwise.
|
||||||
|
___thread_atomic_stop:
|
||||||
|
|
||||||
|
! Check if the calculator is currently
|
||||||
|
! into an atomic operation and update
|
||||||
|
! atomic counter if pssible.
|
||||||
|
mov.l atomic_counter, r1 ! r1 = atomic counter address
|
||||||
|
mov.l @r1, r0 ! r0 = atomic counter data
|
||||||
|
tst r0, r0 ! if atomic counter == 0...
|
||||||
|
bt atomic_end_error ! ...if yes, jump at <atomic_end_error>
|
||||||
|
cmp/eq #1, r0 ! if atomic counter == 1...
|
||||||
|
add #-1, r0 ! update atomic counter data
|
||||||
|
mov.l r0, @r1 ! update atomic counter
|
||||||
|
bf atomic_end_error ! ...if not, jump at <atomic_end_error>
|
||||||
|
|
||||||
|
! Restore saved SR register data.
|
||||||
|
mov.l sr_save, r1 ! get sr_save address
|
||||||
|
mov.l @r1, r0 ! r0 = "old" SR register data
|
||||||
|
ldc r0, sr ! restore SR register.
|
||||||
|
bra atomic_end_exit ! return the resotred SR register.
|
||||||
|
nop ! (db) nop
|
||||||
|
|
||||||
|
atomic_end_error:
|
||||||
|
mov #-1, r0 ! return 0xffffffff
|
||||||
|
|
||||||
|
atomic_end_exit:
|
||||||
|
rts ! exit.
|
||||||
|
nop ! (db) nop.
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
bl_mask: .long 0x100000f0
|
||||||
|
sr_save: .long ___thread_atomic_sr_save
|
||||||
|
atomic_counter: .long ___thread_atomic_counter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##---
|
||||||
|
## Global part.
|
||||||
|
##---
|
||||||
|
.data
|
||||||
|
.global ___thread_atomic_sr_save
|
||||||
|
.global ___thread_atomic_counter
|
||||||
|
|
||||||
|
.type ___thread_atomic_sr_save, @object
|
||||||
|
.type ___thread_atomic_counter, @object
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
___thread_atomic_sr_save: .long 0x00000000
|
||||||
|
___thread_atomic_counter: .long 0x00000000
|
109
src/threads/mutex.c
Normal file
109
src/threads/mutex.c
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include <threads.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Creates a new mutex object with type __TYPE.
|
||||||
|
// @note: If successful the new object is pointed by __MUTEX.
|
||||||
|
int mtx_init (mtx_t *__mutex, int __type)
|
||||||
|
{
|
||||||
|
// Check if the mutext is already initialized
|
||||||
|
if (__mutex->__watermark == MTX_WATERMARK)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
// Initialize mutex
|
||||||
|
__mutex->__watermark = MTX_WATERMARK;
|
||||||
|
__mutex->type = __type;
|
||||||
|
__mutex->lock = 0;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block the current thread until the mutex pointed to by __MUTEX is unlocked.
|
||||||
|
// In that case current thread will not be blocked.
|
||||||
|
int mtx_lock(mtx_t *__mutex)
|
||||||
|
{
|
||||||
|
// Check mutex validity
|
||||||
|
if (__mutex->__watermark != MTX_WATERMARK)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
// Wait util the mutex is unlocked
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Check if the mutex is unlock
|
||||||
|
__thread_atomic_start();
|
||||||
|
if (__mutex->lock == 0)
|
||||||
|
break;
|
||||||
|
__thread_atomic_stop();
|
||||||
|
|
||||||
|
// TODO: force kernel schedule
|
||||||
|
__asm__ volatile ("sleep");
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: handle mutex type !!
|
||||||
|
(void)__mutex->type;
|
||||||
|
|
||||||
|
// Lock the mutex
|
||||||
|
__mutex->lock = 1;
|
||||||
|
|
||||||
|
// Stop atomic operations
|
||||||
|
__thread_atomic_stop();
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to lock the mutex pointed by __MUTEX without blocking.
|
||||||
|
// @note: If the mutex is free the current threads takes control of it,
|
||||||
|
// otherwise it returns immediately.
|
||||||
|
int mtx_trylock(mtx_t *__mutex)
|
||||||
|
{
|
||||||
|
// Check mutex validity
|
||||||
|
if (__mutex->__watermark != MTX_WATERMARK)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
// Start atomic operations
|
||||||
|
__thread_atomic_start();
|
||||||
|
|
||||||
|
// Check if the mutex is already free
|
||||||
|
int ret = -1;
|
||||||
|
if (__mutex->lock == 0)
|
||||||
|
{
|
||||||
|
//TODO: handle mutex type !!
|
||||||
|
(void)__mutex->type;
|
||||||
|
|
||||||
|
// lock the mutex and change the return value
|
||||||
|
__mutex->lock = 1;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop atomic operation and return
|
||||||
|
__thread_atomic_stop();
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock the mutex pointed by __MUTEX.
|
||||||
|
// @note: It may potentially awake other threads waiting on this mutex.
|
||||||
|
int mtx_unlock(mtx_t *__mutex)
|
||||||
|
{
|
||||||
|
// Check mutex validity
|
||||||
|
if (__mutex->__watermark != MTX_WATERMARK)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
// Start atomic operation
|
||||||
|
__thread_atomic_start();
|
||||||
|
|
||||||
|
// Check if the mutex is realy used and unluck if needed
|
||||||
|
int ret = -1;
|
||||||
|
if (__mutex->lock != 0) {
|
||||||
|
__mutex->lock = 0;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop atomic operation and return
|
||||||
|
__thread_atomic_stop();
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the mutex object pointed by __MUTEX.
|
||||||
|
// TODO: check if the mutex is in use ?
|
||||||
|
void mtx_destroy(mtx_t *__mutex)
|
||||||
|
{
|
||||||
|
__mutex->__watermark = 0x00000000;
|
||||||
|
__mutex->type = -1;
|
||||||
|
}
|
12
src/unistd/close.S
Normal file
12
src/unistd/close.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _close
|
||||||
|
.type _close, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_close:
|
||||||
|
trapa #__NR_close
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/fork_execve.S
Normal file
12
src/unistd/fork_execve.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _fork_execve
|
||||||
|
.type _fork_execve, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_fork_execve:
|
||||||
|
trapa #__NR_fork_execve
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/getpgid.S
Normal file
12
src/unistd/getpgid.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _getpgid
|
||||||
|
.type _getpgid, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_getpgid:
|
||||||
|
trapa #__NR_getpgid
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/getpid.S
Normal file
12
src/unistd/getpid.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _getpid
|
||||||
|
.type _getpid, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_getpid:
|
||||||
|
trapa #__NR_getpid
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/getppid.S
Normal file
12
src/unistd/getppid.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _getppid
|
||||||
|
.type _getppid, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_getppid:
|
||||||
|
trapa #__NR_getppid
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/lseek.S
Normal file
12
src/unistd/lseek.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _lseek
|
||||||
|
.type _lseek, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_lseek:
|
||||||
|
trapa #__NR_lseek
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/open.S
Normal file
12
src/unistd/open.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _open
|
||||||
|
.type _open, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_open:
|
||||||
|
trapa #__NR_open
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/read.S
Normal file
12
src/unistd/read.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _read
|
||||||
|
.type _read, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_read:
|
||||||
|
trapa #__NR_read
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/setpgid.S
Normal file
12
src/unistd/setpgid.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _setpgid
|
||||||
|
.type _setpgid, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_setpgid:
|
||||||
|
trapa #__NR_setpgid
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/wait.S
Normal file
12
src/unistd/wait.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _wait
|
||||||
|
.type _wait, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_wait:
|
||||||
|
trapa #__NR_wait
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/waitpid.S
Normal file
12
src/unistd/waitpid.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _waitpid
|
||||||
|
.type _waitpid, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_waitpid:
|
||||||
|
trapa #__NR_waitpid
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
12
src/unistd/write.S
Normal file
12
src/unistd/write.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <asm/unistd_32.h>
|
||||||
|
.text
|
||||||
|
.global _write
|
||||||
|
.type _write, @function
|
||||||
|
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
_write:
|
||||||
|
trapa #__NR_write
|
||||||
|
rts
|
||||||
|
nop
|
||||||
|
.end
|
Loading…
Reference in a new issue