project architecture rework + handle ABI specific code (WIP)

This commit is contained in:
Yatis 2020-10-14 11:45:08 +02:00
parent ac36fce54d
commit aeedfcdb02
75 changed files with 1241 additions and 3819 deletions

View file

@ -0,0 +1,35 @@
#ifndef __ASM_CASIO_TRAPA_H__
# define __ASM_CASIO_TRAPA_H__
/*
** Normally the SH3/SH4 processor provide a "trapa" instruction which allow
** tipping between userland and kernel. But Casio's don't use this method
** (this is why we are always in "privilegied mode" and we can do whatever
** we whant) but use custom calling convention to access the syscall call.
**
** The convention whant that the user jump into the syscall trampoline code
** located at 0x80010070 for fx9860g and 0x80020070 for fxcg20/50.
*/
#ifdef __SUPPORT_CASIO_ABI_FX9860G
# define casio_trapa(id) \
mov.l syscall_table, r2 ;\
mov.l syscall_id, r0 ;\
jmp @r2 ;\
nop ;\
.align 4 ;\
syscall_table: .long 0x80010070 ;\
syscall_id: .long id
#endif
#ifdef __SUPPORT_CASIO_ABI_FXCG50
# define casio_trapa(id) \
mov.l syscall_table, r2 ;\
mov.l syscall_id, r0 ;\
jmp @r2 ;\
nop ;\
.align 4 ;\
syscall_table: .long 0x80020070 ;\
syscall_id: .long id
#endif
#endif /*__ASM__CASIO_TRAPA_H__*/

1
include/asm/unistd.h Normal file
View file

@ -0,0 +1 @@
#include <asm/unistd_32.h>

View file

@ -1,45 +1,13 @@
#ifndef __ASM_UNISTD_32_H__ #ifndef __ASM_UNISTD_32_H__
# define __ASM_UNISTD_32_H__ # define __ASM_UNISTD_32_H__
// Define the number of syscall // ABI redirection
#define __NR_MAX 21 #if defined(__SUPPORT_VHEX_KERNEL)
# include <vhex/unistd_32.h>
// Kernel Test #elif defined(__SUPPORT_CASIO_ABI_FX9860G)
#define __NR_test_syscall 0 # include <fx9860g/unistd_32.h>
#elif defined(__SUPPORT_CASIO_ABI_FXCG50)
// Process # include <fxcg50/unistd_32.h>
#define __NR_exit 1 #endif
#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__*/ #endif /*__ASM_UNISTD_32_H__*/

8
include/bits/confname.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __BITS_CONFNAME_H__
# define __BITS_CONFNAME_H__
//FIXME: this part is probably arch-specific(?)
#define _SC_PAGE_SIZE 0
#define _SC_PAGESIZE _SC_PAGE_SIZE
#endif /*__BITS_CONFNAME_H__*/

9
include/bits/fcntl.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef __BITS_FCNTL_H__
# define __BITS_FCNTL_H__
/* open/fcntl. */
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif /*__BITS_FCNTL_H__*/

26
include/bits/setjmp.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef __BITS_SETJMP_H__
# define __BITS_SETJMP_H__
#include <stddef.h>
#include <stdint.h>
/*
** Custom(?) 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
** different register bank. So to avoid this, it's more simple to restore the
** saved SR first then restore all register (see <src/setjmp/longjmp.S>)
**
** TODO: save process signal mask ?
*/
struct __jmp_buf
{
uint32_t sr;
uint32_t reg[8];
uint32_t gbr;
uint32_t macl;
uint32_t mach;
uint32_t pr;
};
#endif /*__BITS_SETJMP_H__*/

12
include/bits/sigaction.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef __BITS_SIGACTION_H__
# define __BITS_SIGACTION_H__
#include <stddef.h>
#include <stdint.h>
/* Values for the HOW argument to `sigprocmask'. */
#define SIG_BLOCK 0 /* Block signals. */
#define SIG_UNBLOCK 1 /* Unblock signals. */
#define SIG_SETMASK 2 /* Set the set of blocked signals. */
#endif /*__BITS_SIGACTION_H__*/

View file

@ -1,9 +1,13 @@
#ifndef __LIB_BITS_TYPES_FILE_H__ #ifndef __BITS_TYPES_FILE_H__
# define __LIB_BITS_TYPES_FILE_H__ # define __BITS_TYPES_FILE_H__
// opaque definition of the _IO_FILE
struct _IO_FILE; struct _IO_FILE;
/* The opaque type of streams. This is the definition used elsewhere. */ /*
** The opaque type of streams.
** This is the definition used elsewhere.
*/
typedef struct _IO_FILE FILE; typedef struct _IO_FILE FILE;
#endif /*__LIB_BITS_TYPES_FILE_H__*/ #endif /*__BITS_TYPES_FILE_H__*/

View file

@ -1,7 +1,8 @@
#ifndef __LIB_BITS_TYPES___FILE_H__ #ifndef __BITS_TYPES__FILE_H__
# define __LIB_BITS_TYPES___FILE_H__ # define ___LIB_BITS_TYPES__FILE_H__
// define opaque definition of the FILE type
struct _IO_FILE; struct _IO_FILE;
typedef struct _IO_FILE __FILE; typedef struct _IO_FILE __FILE;
#endif /*__LIB_BITS_TYPES___FILE_H__*/ #endif /*__BITS_TYPES__FILE_H__*/

View file

@ -5,8 +5,10 @@
#include <stddef.h> #include <stddef.h>
#include <sys/types.h> #include <sys/types.h>
//TODO: remove me !!! //---
#include <kernel/bits/filesystem.h> // TODO: VFS abstraction ? or ABI-spesific abstraction ?
//---
// Define _IO_FILE // Define _IO_FILE
// TODO: add open flags // TODO: add open flags
@ -16,7 +18,7 @@ struct _IO_FILE
{ {
off_t cursor; off_t cursor;
int permission; int permission;
struct file_operations *file_op; void *file_op;
void *private; void *private;
}; };

View file

@ -1,65 +0,0 @@
#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__*/

File diff suppressed because it is too large Load diff

View file

@ -4,17 +4,17 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
//TODO: update me !! /* also defined in <stdio.h> */
#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_SET 0 /* Seek from beginning of file. */
#define SEEK_CUR 1 /* Seek from current position. */ #define SEEK_CUR 1 /* Seek from current position. */
#define SEEK_END 2 /* Seek from end of file. */ #define SEEK_END 2 /* Seek from end of file. */
// Functions /*
** Open FILE and return a new file descriptor for it, or -1 on error.
** OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set
** in OFLAG, the third argument is taken as a `mode_t', the mode of the
** created file.
*/
extern int open(const char *pathname, int flags, ...); extern int open(const char *pathname, int flags, ...);
#endif /*__LIB_FCNTL_H__*/ #endif /*__LIB_FCNTL_H__*/

View file

@ -0,0 +1,57 @@
#ifndef __ASM_UNISTD32_FX9860G_H__
# define __ASM_UNISTD32_FX9860G_H__
// File manipulation
#define __NR_Bfile_CreateFile 0x00000434
#define __NR_Bfile_OpenFile 0x0000042c
#define __NR_Bfile_WriteFile 0x00000435
#define __NR_Bfile_ReadFile 0x00000432
#define __NR_Bfile_SeekFile 0x00000431
#define __NR_Bfile_CloseFile 0x0000042d
#define __NR_Bfile_FindFirst 0x0000043b
#define __NR_Bfile_FindNext 0x0000043c
#define __NR_Bfile_FindClose 0x0000043d
#define __NR_Bfile_GetMediaFree 0x0000042e
#define __NR_Bfile_RemoveFile 0x00000439
// Display syscalls
#define __NR_Bdisp_GetVRAM 0x00000135
#define __NR_Bdisp_DrawLine 0x00000030
#define __NR_Bdisp_AllClr_VRAM 0x00000143
#define __NR_Bdisp_Display 0x00000028
#define __NR_Bdisp_PrintMini 0x00000c4f
#define __NR_Bdisp_ClearArea 0x0000014b
#define __NR_Bdisp_ReverseArea 0x0000014d
#define __NR_Bdisp_RestoreDisp 0x00000814
#define __NR_Bdisp_SaveDisp 0x00000813
// Keyboard primitives
#define __NR_Bkey_GetKey 0x0000090f
#define __NR_Bkey_PutKeycode 0x0000024f
#define __NR_BKey_GetKeyWait 0x00000247
// Memory management
#define __NR_Bmem_malloc 0x00000acd
#define __NR_Bmem_realloc 0x00000e6d
#define __NR_Bmem_called 0x00000e6b
#define __NR_Bmem_free 0x00000acc
// USB primitive
#define __NR_USB_Open 0x000002ac // not sure
#define __NR_USB_Close 0x000004a4 // not sure
// SD Card primitives
#define __NR_SDC_Init 0x0000017a // not sure
#define __NR_SDC_Mount 0x0000044b // not sure
#define __NR_SDC_Umount 0x0000044a
// Timer interface
#define __NR_TimerInstall 0x00000118
#define __NR_TimerDeinstall 0x00000119
#define __NR_TimerStart 0x0000011a
#define __NR_TimerStop 0x0000011b
// power management
#define __NR_PowerOff 0x000003f4
#endif /*__ASM_UNISTD32_FX9860G_H__*/

View file

@ -0,0 +1,34 @@
#ifndef __ASM_UNISTD32_FXCG50_H__
# define __ASM_UNISTD32_FXCG50_H__
// File manipulation
#define __NR_BFile_Remove 0x00001db4
#define __NR_BFile_Create 0x00001dae
#define __NR_BFile_Open 0x00001da3
#define __NR_BFile_Close 0x00001da4
#define __NR_BFile_Size 0x00001da6
#define __NR_BFile_Write 0x00001daf
#define __NR_BFile_Read 0x00001dac
#define __NR_BFile_FindFirst 0x00001db7
#define __NR_BFile_FindNext 0x00001db9
#define __NR_BFile_FindClose 0x00001dba
// Keyboard interface
#define __NR_PutKeyCode 0x000012c6
#define __NR_GetKeyWait 0x000012bf
#define __NR_ClearKeyBuffer 0x000012c7
#define __NR_GetVRAMAddress 0x000001e6
// Memory management
#define __NR_Bmem_malloc 0x00001f44
#define __NR_Bmem_free 0x00001f42
#define __NR_Bmem_calloc 0x00001f40
#define __NR_Bmem_realloc 0x00001f46
// Timer interface
#define __NR_Timer_Install 0x000008d9
#define __NR_Timer_Deinstall 0x000008da
#define __NR_Timer_Start 0x000008db
#define __NR_Timer_Stop 0x000008dc
#endif /*__ASM_UNISTD32_FXCG50_H__*/

View file

@ -4,27 +4,23 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
// Real jmp_buf struct /* Get '__jmp_buf' */
// @note: save only r8 ~ r15 and SR / PC registers #include <bits/setjmp.h>
// 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 /* User jmp_buf alias */
typedef struct __jmp_buf jmp_buf[1]; typedef struct __jmp_buf jmp_buf[1];
// Functions /*
** Store the calling environment in ENV, also saving the signal mask.
** Return 0.
*/
extern int setjmp(jmp_buf env); extern int setjmp(jmp_buf env);
/*
** Store the calling environment in ENV, not saving the signal mask.
** Return 0.
*/
extern void longjmp(jmp_buf env, int val); extern void longjmp(jmp_buf env, int val);
#endif /*__LIB_SETJMP_H__*/ #endif /*__LIB_SETJMP_H__*/

View file

@ -5,22 +5,34 @@
#include <stdint.h> #include <stdint.h>
#include <bits/signum.h> #include <bits/signum.h>
// Type of a signal handler /* Type of signal set */
typedef void (*__sighandler_t)(int);
typedef __sighandler_t sighandler_t;
// Type of signal set
typedef uint32_t sigset_t; typedef uint32_t sigset_t;
typedef uint32_t kernel_sigset_t; typedef uint32_t kernel_sigset_t;
// Define sigprocmask() value for "how" argument /* Type of a signal handler.*/
#define SIG_BLOCK 0 typedef void (*__sighandler_t)(int);
#define SIG_UNBLOCK 1 typedef __sighandler_t sighandler_t;
#define SIG_SETMASK 2
// Prototype /*
// TODO: doc ** Get the system-specific definitions of `struct sigaction' and the `SA_*'
** and `SIG_*'. constants.
*/
#include <bits/sigaction.h>
/* Get and/or change the set of blocked signals. */
extern int sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict oldset);
/*
** Send signal SIG to process number PID. If PID is zero, send SIG to all
** processes in the current process's process group. If PID is < -1, send SIG to
** all processes in process group - PID.
*/
extern int kill(pid_t pid, int sig); extern int kill(pid_t pid, int sig);
/*
** Set the handler for the signal SIG to HANDLER, returning the old handler, or
** SIG_ERR on error. By default `signal' has the BSD semantic.
*/
extern void (*signal(int signum, void (*handler)(int)))(int); extern void (*signal(int signum, void (*handler)(int)))(int);
#endif /*__LIB_SIGNAL_H__*/ #endif /*__LIB_SIGNAL_H__*/

View file

@ -10,7 +10,6 @@ extern int printf(const char *restrict format, ...);
extern int dprintf(int fd, 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 sprintf(char *restrict str, const char *restrict format, ...);
extern int snprintf(char *restrict str, size_t size, 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 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 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); extern int vsnprintf(char *restrict str, size_t size, const char *restrict format, va_list ap);
@ -19,60 +18,4 @@ extern int vsnprintf(char *restrict str, size_t size, const char *restrict forma
extern int putchar(int c); extern int putchar(int c);
extern int puts(const char *s); 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__*/ #endif /*__LIB_STDIO_H__*/

View file

@ -4,27 +4,28 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
//---
#define HEAP_BLOCK_MIN (16) // Dynamic memory management
struct heap_block //---
{ /* Allocate SIZE bytes of memory. */
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 *malloc(size_t size);
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern void *calloc(size_t nmemb, size_t size); extern void *calloc(size_t nmemb, size_t size);
/*
** Re-allocate the previously allocated block in PTR, making the new block
** SIZE bytes long.
*/
extern void *realloc(void *ptr, size_t size); extern void *realloc(void *ptr, size_t size);
/*
** Re-allocate the previously allocated block in PTR, making the new block large
** enough for NMEMB elements of SIZE bytes each.
*/
extern void *reallocarray(void *ptr, size_t nmemb, size_t size); extern void *reallocarray(void *ptr, size_t nmemb, size_t size);
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free(void *ptr); extern void free(void *ptr);
#endif /*__LIB_STDLIB_H__*/ #endif /*__LIB_STDLIB_H__*/

View file

@ -37,8 +37,22 @@
#define MAP_FAILED ((void*) -1) #define MAP_FAILED ((void*) -1)
#endif #endif
// Prototype /*
** Map addresses starting near ADDR and extending for LEN bytes. from
** OFFSET into the file FD describes according to PROT and FLAGS. If ADDR
** is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
** set in FLAGS, the mapping will be at ADDR exactly (which must be
** page-aligned); otherwise the system chooses a convenient nearby address.
** The return value is the actual mapping address chosen or MAP_FAILED
** for errors (in which case `errno' is set). A successful `mmap' call
** deallocates any previous mapping for the affected region.
*/
extern void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); extern void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
/*
** Deallocate any mapping for the region starting at ADDR and extending LEN bytes.
** Returns 0 if successful, -1 for errors (and sets errno).
*/
extern int munmap(void *addr, size_t length); extern int munmap(void *addr, size_t length);
#endif /*__LIB_SYS_MMAN_H__*/ #endif /*__LIB_SYS_MMAN_H__*/

View file

@ -19,7 +19,6 @@
#define __S_IWRITE 0000200 /* Write by owner. */ #define __S_IWRITE 0000200 /* Write by owner. */
#define __S_IEXEC 0000100 /* Execute by owner. */ #define __S_IEXEC 0000100 /* Execute by owner. */
#define S_IRUSR __S_IREAD /* Read by owner. */ #define S_IRUSR __S_IREAD /* Read by owner. */
#define S_IWUSR __S_IWRITE /* Write by owner. */ #define S_IWUSR __S_IWRITE /* Write by owner. */
#define S_IXUSR __S_IEXEC /* Execute by owner. */ #define S_IXUSR __S_IEXEC /* Execute by owner. */

View file

@ -1,12 +1,18 @@
#ifndef __LIB_SYS_SYSCALL_H__ #ifndef __SYSCALL_H__
# define __LIB_SYS_SYSCALL_H__ # define __SYSCALL_H__
#include <stddef.h> /*
#include <stdint.h> ** This file should list the numbers of the system calls the system knows.
** But instead of duplicating this we use the information available
** from the kernel sources.
*/
#include <asm/unistd.h>
// include Vhex kernel real syscall /*
#include <asm/unistd_32.h> ** The Linux kernel header file defines macros __NR_*, but some
** programs expect the traditional form SYS_*. <bits/syscall.h>
** defines SYS_* macros for __NR_* macros of known names.
*/
#include <bits/syscall.h>
//TODO include Casio's syscall !! #endif
#endif /*__LIB_SYS_SYSCALL_H__*/

View file

@ -17,6 +17,7 @@ typedef int32_t ssize_t;
#endif #endif
// Define alias // Define alias
//FIXME: potential conflict with the real glibc(?)
typedef int32_t pid_t; typedef int32_t pid_t;
typedef int16_t mode_t; typedef int16_t mode_t;
typedef uint16_t dev_t; typedef uint16_t dev_t;

View file

@ -4,7 +4,14 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
/*
** This will define the `W*' macros for the flag bits to `waitpid', `wait3',
** and `wait4'.
*/
#include <bits/waitflags.h> #include <bits/waitflags.h>
/* This will define all the `__W*' macros.*/
#include <bits/waitstatus.h> #include <bits/waitstatus.h>
/* Macros for the `waitpid`'s wstatus argument. */ /* Macros for the `waitpid`'s wstatus argument. */
@ -17,8 +24,26 @@
#define WIFCONTINUED(status) __WIFCONTINUED(status) #define WIFCONTINUED(status) __WIFCONTINUED(status)
#define WCOREDUMP(status) __WCOREDUMP(status) #define WCOREDUMP(status) __WCOREDUMP(status)
// Wait process /*
** Wait for a child matching PID to die.
** - If PID is greater than 0, match any process whose process ID is PID.
** - If PID is (pid_t) -1, match any process.
** - If PID is (pid_t) 0, match any process with the same process group as the
** current process.
** - If PID is less than -1, match any process whose process group is the absolute
** value of PID.
** - If the WNOHANG bit is set in OPTIONS, and that child is not already dead,
** return (pid_t) 0. If successful, return PID and store the dead child's
** status in STAT_LOC.
** - Return (pid_t) -1 for errors. If the WUNTRACED bit is set in OPTIONS,
** return status for stopped children; otherwise don't.
*/
extern pid_t waitpid(pid_t pid, int *wstatus, int options); extern pid_t waitpid(pid_t pid, int *wstatus, int options);
/*
** Wait for a child to die. When one does, put its status in *STAT_LOC
** and return its process ID. For errors, return (pid_t) -1.
*/
extern pid_t wait(int *wstatus); extern pid_t wait(int *wstatus);
#endif /*__LIB_SYS_WAIT_H__*/ #endif /*__LIB_SYS_WAIT_H__*/

View file

@ -4,15 +4,19 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
//---
// Warnig, this part is experimental and reserved for Vhex
//---
// Define Mutex type // Define Mutex type
enum enum {
{
mtx_plain = 0, mtx_plain = 0,
mtx_recursive = 1, mtx_recursive = 1,
mtx_timed = 2 mtx_timed = 2
}; };
// Define mutex structure // Define mutex structure
// @note: This is a custom implementation
#define MTX_WATERMARK (0xdeadbeef) #define MTX_WATERMARK (0xdeadbeef)
struct __mtx_s struct __mtx_s
{ {
@ -23,40 +27,52 @@ struct __mtx_s
typedef struct __mtx_s mtx_t; typedef struct __mtx_s mtx_t;
// //---
// Mutex functions // Mutex functions
// //---
// Creates a new mutex object with type __TYPE. /*
// @note: If successful the new object is pointed by __MUTEX. ** 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); 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. ** 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); 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, ** Try to lock the mutex pointed by __MUTEX without blocking.
// otherwise it returns immediately. ** @note: If the mutex is free the current threads takes control of it,
** otherwise it returns immediately.
*/
extern int mtx_trylock(mtx_t *__mutex); extern int mtx_trylock(mtx_t *__mutex);
// Unlock the mutex pointed by __MUTEX. /*
// @note: It may potentially awake other threads waiting on this 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); extern int mtx_unlock (mtx_t *__mutex);
// Destroy the mutex object pointed by __MUTEX. /* Destroy the mutex object pointed by __MUTEX. */
extern void mtx_destroy(mtx_t *__mutex); extern void mtx_destroy(mtx_t *__mutex);
// //---
// Atomic operations // Atomic operations
// //---
/*
// Save the current SR register and set the SR.BIT bit up (start 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. ** @note: return the saved SR register (if has been saved), 0xffffffff otherwise.
*/
extern uint32_t __thread_atomic_start(void); extern uint32_t __thread_atomic_start(void);
// Restore the saved SR register /*
// @note: return the restored SR register or -1 otherwise. ** Restore the saved SR register
** @note: return the restored SR register or -1 otherwise.
*/
extern uint32_t __thread_atomic_stop(void); extern uint32_t __thread_atomic_stop(void);
#endif /*__LIB_PTHREAD_H__*/ #endif /*__LIB_PTHREAD_H__*/

View file

@ -5,32 +5,90 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.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 // Process part
///---
/* Get the process ID of the calling process. */
extern pid_t getpid(void); 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()) ! /* Get the process group ID of the calling process. */
extern pid_t getpgid(void);
/* Get the process ID of the calling process's parent. */
extern pid_t getppid(void);
/*
** Set the process group ID of the process matching PID to PGID.
** If PID is zero, the current process's process group ID is set.
** If PGID is zero, the process ID of the process is used.
*/
extern int setpgid(pid_t __pid, pid_t __pgid);
// CUSTOM syscall for Vhex (fork() + exeve()) !
//TODO: move me !!
extern pid_t fork_execve(const char *pathname, char **argv, char **envp); extern pid_t fork_execve(const char *pathname, char **argv, char **envp);
//---
// File part // 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); /* Standard file descriptors. */
extern off_t lseek(int fd, off_t offset, int whence); #define STDIN_FILENO 0 /* Standard input. */
extern int close(int fd); #define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
/*
** Write N bytes of BUF to FD.
** Return the number written, or -1.
*/
extern ssize_t write(int __fd, const void *__buf, size_t __nbytes);
/*
** Read NBYTES into BUF from FD.
** Return the number read, -1 for errors or 0 for EOF.
*/
extern ssize_t read(int __fd, void *__buf, size_t __nbytes);
/*
** Read NBYTES into BUF from FD at the given position OFFSET without
** changing the file pointer.
** Return the number read, -1 for errors or 0 for EOF.
*/
extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, off_t __offset);
/*
** Write N bytes of BUF to FD at the given position OFFSET without
** changing the file pointer.
** Return the number written, or -1.
*/
extern ssize_t pwrite (int __fd, const void *__buf, size_t __n, off_t __offset);
/* Values for the WHENCE argument to lseek. */
#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. */
/*
** Move FD's file position to OFFSET bytes from the beginning of the file
** (if WHENCE is SEEK_SET), the current position (if WHENCE is SEEK_CUR),
** or the end of the file (if WHENCE is SEEK_END).
** Return the new file position.
*/
extern __off_t lseek (int __fd, off_t __offset, int __whence);
/* Close the file descriptor FD */
extern int close(int __fd);
//---
// System part // System part
extern long sysconf(int name); //---
/*
** Get the `_PC_*' symbols for the NAME argument to `pathconf' and `fpathconf';
** the `_SC_*' symbols for the NAME argument to `sysconf'; and the `_CS_*'
** symbols for the NAME argument to `confstr'.
*/
#include <bits/confname.h>
/* Get the value of the system variable NAME. */
extern long int sysconf(int __name);
#endif /*__LIB_UNISTD_H__*/ #endif /*__LIB_UNISTD_H__*/

45
include/vhex/unistd_32.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef __ASM_UNISTD32_VHEX_H__
# define __ASM_UNISTD32_VHEX_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_UNISTD32_VHEX_H__*/

View file

@ -33,8 +33,8 @@
# * handle versionning # * handle versionning
#--- #---
MAJOR := 0 MAJOR := 0
MINOR := 1 MINOR := 2
PATCH := 1 PATCH := 0
EXTRAVERSION := -alpha EXTRAVERSION := -alpha

View file

@ -0,0 +1,21 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _open
.type _open, @function
.align 2
/*
** extern int open(const char *pathname, int flags, ...);
** Open FILE and return a new file descriptor for it, or -1 on error.
** OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set
** in OFLAG, the third argument is taken as a `mode_t', the mode of the
** created file.
*/
_open:
trapa #__NR_open
rts
nop
.end
#endif

View file

@ -6,7 +6,8 @@
.align 2 .align 2
/* /*
** void longjmp(jmp_buf env, int val) ** void longjmp(jmp_buf env, int val)
** @note: TODO ** Store the calling environment in ENV, not saving the signal mask.
** Return 0.
*/ */
_longjmp: _longjmp:
! save the context into unbankable register ! save the context into unbankable register

View file

@ -5,7 +5,10 @@
.align 2 .align 2
/* /*
** int setjmp(jmp_buf env) ** int setjmp(jmp_buf env)
** @note: TODO ** Store the calling environment in ENV, also saving the signal mask.
** Return 0.
**
** TODO: hande signal mask
*/ */
_setjmp: _setjmp:
! block interrupt ! block interrupt
@ -40,4 +43,4 @@ _setjmp:
! return ! return
rts rts
mov #0, r0 mov #0, r0
.end

View file

@ -0,0 +1,20 @@
#include __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _kill
.type _kill, @function
.align 2
/*
** extern int kill(pid_t pid, int sig);
** Send signal SIG to process number PID. If PID is zero, send SIG to all
** processes in the current process's process group. If PID is < -1, send SIG to
** all processes in process group - PID.
*/
_kill:
trapa #__NR_kill
rts
nop
.end
#endif

View file

@ -0,0 +1,19 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _signal
.type _signal, @function
.align 2
/*
** extern void (*signal(int signum, void (*handler)(int)))(int);
** Set the handler for the signal SIG to HANDLER, returning the old handler, or
** SIG_ERR on error. By default `signal' has the BSD semantic.
*/
_signal:
trapa #__NR_signal
rts
nop
.end
#endif

View file

@ -1,15 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _kill
.type _kill, @function
.align 2
/*
** TODO: doc
*/
_kill:
trapa #__NR_kill
rts
nop
.end

View file

@ -1,15 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _signal
.type _signal, @function
.align 2
/*
** TODO: doc
*/
_signal:
trapa #__NR_signal
rts
nop
.end

View file

@ -0,0 +1,58 @@
#ifndef _SRC_STDIO_PRINTF_H__
# define _SRC_STDIO_PRINTF_H__
#include <stddef.h>
#include <stdint.h>
//---
// Internal printf() part
//---
#define PRINTF_INTERNAL_BUFFER_SIZE 32
// internal structure used by any printf function familly
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 /*_SRC_STDIO_PRINTF_H__*/

View file

@ -0,0 +1,23 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _free
.type _free, @function
.align 2
/*
** extern void free(void *ptr)
** Custom syscall which free a block allocated by `malloc', `realloc' or `calloc'.
**
** @note:
** The MMU is used by Casio so we cannot implement brk or skr for technical
** reason (non-continius heap, no shared page, ...), so all memory management
** is performed by the Vhex kernel.
*/
_free:
trapa #__NR_proc_heap_free
rts
nop
.end
#endif

View file

@ -0,0 +1,23 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _malloc
.type _malloc, @function
.align 2
/*
** extern void *malloc(size_t size);
** Allocate SIZE bytes of memory.
**
** @note:
** The MMU is used by Casio so we cannot implement brk or skr for technical
** reason (non-continius heap, no shared page, ...), so all memory management
** is performed by the Vhex kernel.
*/
_malloc:
trapa #__NR_proc_heap_alloc
rts
nop
.end
#endif

View file

@ -0,0 +1,43 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _realloc
.type _realloc, @function
.align 2
/*
** extern void *realloc(void ptr, size_t size)
**
** @note:
** The MMU is used by Casio so we cannot implement brk or skr for technical
** reason (non-continius heap, no shared page, ...), so all memory management
** is performed by the Vhex kernel.
*/
_realloc:
! Check if the PTR is NULL
! In this case, realloc() work like malloc(), so lets call it
tst r4, r4
bf check_free
mov r5, r4
trapa #__NR_proc_head_alloc
rts
nop
! Check is the size is NULL
! In this case, realloc() work like free(), so lets call it
! then return NULL pointer
check_free:
tst r5, r5
bf call_realloc
trapa #__NR_proc_heap_free
rts
xor r0, r0
! Call realloc
call_realloc:
trapa #__NR_proc_heap_realloc
rts
nop
.end
#endif

View file

@ -2,15 +2,28 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
/*
** The calloc() function allocates memory for an array of nmemb elements of size
** bytes each and returns a pointer to the allocated memory. The memory is set
** to zero. If nmemb or size is 0, then calloc() returns either NULL, or a
** unique pointer value that can later be successfully passed to free(). If the
** multiplication of nmemb and size would result in integer overflow, then
** calloc() returns an error. By contrast, an integer overflow would not be
** detected in the following call to malloc(), with the result that an incorrectly
** sized block of memory would be allocated: `malloc(nmemb * size);`
*/
void *calloc(size_t nmemb, size_t size) void *calloc(size_t nmemb, size_t size)
{ {
// check error
if (size == 0 || nmemb == 0) if (size == 0 || nmemb == 0)
return (NULL); return (NULL);
// Try to allowate the area
void *ret = malloc(nmemb * size); void *ret = malloc(nmemb * size);
if (ret == NULL) if (ret == NULL)
return (NULL); return (NULL);
// wipe the area
memset(ret, 0x00, size); memset(ret, 0x00, size);
return (ret); return (ret);
} }

View file

@ -1,17 +0,0 @@
#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

View file

@ -1,16 +0,0 @@
#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

View file

@ -1,46 +0,0 @@
#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

View file

@ -1,7 +1,18 @@
#include <stdlib.h> #include <stdlib.h>
//FIXME: check safe !!!! /*
//FIXME: Check underflow !! ** The reallocarray() function changes the size of the memory block pointed to
** by ptr to be large enough for an array of nmemb elements, each of which is
** size bytes. It is equivalent to the call: `realloc(ptr, nmemb * size);`
**
** However, unlike that realloc() call, reallocarray() fails safely in the case
** where the multiplication would overflow. If such an overflow occurs,
** reallocarray() returns NULL, sets errno to ENOMEM, and leaves the original
** block of memory unchanged.
**
** FIXME: check safe !!!!
** FIXME: Check underflow !!
*/
void *reallocarray(void *ptr, size_t nmemb, size_t size) void *reallocarray(void *ptr, size_t nmemb, size_t size)
{ {
return (realloc(ptr, nmemb * size)); return (realloc(ptr, nmemb * size));

View file

@ -1,5 +1,13 @@
#include <string.h> #include <string.h>
/*
** The memcpy() function copies n bytes from memory area src to memory area dest.
** The memory areas must not overlap. Use memmove(3) if the memory areas do
** overlap.
**
** TODO: use DMA ?
** TODO: use DSP ?
*/
void *memcpy(void *dest, const void *src, size_t count) void *memcpy(void *dest, const void *src, size_t count)
{ {
for (size_t i = 0 ; i < count ; i = i + 1) for (size_t i = 0 ; i < count ; i = i + 1)

View file

@ -1,6 +1,12 @@
#include <string.h> #include <string.h>
//TODO: update me :( /*
** The memset() function fills the first n bytes of the memory area pointed to
** by s with the constant byte c.
**
** TODO: use DMA !
** TODO: use DSP ?
*/
void *memset(void *s, int c, size_t n) void *memset(void *s, int c, size_t n)
{ {
while ((int)--n >= 0) while ((int)--n >= 0)

View file

@ -1,5 +1,16 @@
#include <string.h> #include <string.h>
/*
** The strcat() function appends the src string to the dest string,
** overwriting the terminating null byte ('\0') at the end of dest, and then
** adds a terminating null byte. The strings may not overlap, and the dest
** string must have enough space for the result. If dest is not large enough,
** program behavior is unpredictable; buffer overruns are a favorite avenue for
** attacking secure programs.
**
** TODO: use the DMA !
** TODO: look at the DSP ?
*/
char *strcat(char *dest, char const *src) char *strcat(char *dest, char const *src)
{ {
size_t i; size_t i;
@ -15,3 +26,25 @@ char *strcat(char *dest, char const *src)
dest[i + start] = '\0'; dest[i + start] = '\0';
return (dest); return (dest);
} }
/*
** The strncat() function is similar, except that:
** * it will use at most n bytes from src; and
** * src does not need to be null-terminated if it contains n or more bytes.
**
** As with strcat(), the resulting string in dest is always null-terminated.
**
** If src contains n or more bytes, strncat() writes n+1 bytes to dest (n from
** src plus the terminating null byte). Therefore, the size of dest must be at
** least strlen(dest)+n+1.
*/
char *strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return (dest);
}

View file

@ -1,6 +1,9 @@
#include <string.h> #include <string.h>
//TODO: asm ? /*
** The strchr() function returns a pointer to the first occurrence of the
** character c in the strings.
*/
char *strchr(const char *s1, int c) char *strchr(const char *s1, int c)
{ {
int i = -1; int i = -1;
@ -8,7 +11,11 @@ char *strchr(const char *s1, int c)
return ((s1[i] == '\0') ? NULL : (void*)&s1[i]); return ((s1[i] == '\0') ? NULL : (void*)&s1[i]);
} }
//TODO: asm ? /*
** The strchrnul() function is like strchr() except that if c is not found in
** s, then it returns a pointer to the null byte at the end of s, rather
** than NULL.
*/
char *strchrnul(const char *s1, int c) char *strchrnul(const char *s1, int c)
{ {
int i = -1; int i = -1;
@ -16,14 +23,16 @@ char *strchrnul(const char *s1, int c)
return ((void*)&s1[i]); return ((void*)&s1[i]);
} }
//TODO asm ? /*
** The strrchr() function returns a pointer to the last occurrence of the
** character c in the strings.
*/
char *strrchr(const char *s1, int c) char *strrchr(const char *s1, int c)
{ {
void *saved; void *saved;
saved = NULL; saved = NULL;
for (int i = 0 ; s1[i] != '\0' ; i++) for (int i = 0 ; s1[i] != '\0' ; i++) {
{
if (s1[i] == c) if (s1[i] == c)
saved = (void *)&s1[i]; saved = (void *)&s1[i];
} }

View file

@ -1,17 +1,34 @@
#include <string.h> #include <string.h>
/*
** The strcmp() function compares the two strings s1 and s2. The locale is not
** taken into account (for a locale-aware comparison, see strcoll(3)).
** The comparison is done using unsigned characters.
**
** strcmp() returns an integer indicating the result of the comparison, as follows:
** * 0, if the s1 and s2 are equal;
** * a negative value if s1 is less than s2;
** * a positive value if s1 is greater than s2.
**
** TODO: quad-word access !
*/
int strcmp(const char *s1, const char *s2) int strcmp(const char *s1, const char *s2)
{ {
if (s1 == NULL || s2 == NULL) if (s1 == NULL || s2 == NULL)
return (0); return (0);
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) {
{
s1 += 1; s1 += 1;
s2 += 1; s2 += 1;
} }
return (*s1 - *s2); return (*s1 - *s2);
} }
/*
** The strncmp() function is similar, except it compares only the first (at most)
** n bytes of s1 and s2.
**
** TODO: quad-word access !
*/
int strncmp(const char *s1, const char *s2, size_t n) int strncmp(const char *s1, const char *s2, size_t n)
{ {
if (s1 == NULL || s2 == NULL || n == 0) if (s1 == NULL || s2 == NULL || n == 0)

View file

@ -1,5 +1,14 @@
#include <string.h> #include <string.h>
/*
** The strcpy() function copies the string pointed to by src, including the
** terminating null byte ('\0'), to the buffer pointed to by dest.
** The strings may not overlap, and the destination string dest must be
** large enough to receive the copy. Beware of buffer overruns!
**
** TODO: use quad-word access and/or DMA !
** TODO: look at the DSP ?
*/
char *strcpy(char *dest, char const *src) char *strcpy(char *dest, char const *src)
{ {
size_t i; size_t i;
@ -13,6 +22,11 @@ char *strcpy(char *dest, char const *src)
return (dest); return (dest);
} }
/*
** The strncpy() function is similar, except that at most n bytes of src are
** copied. Warning: If there is no null byte among the first n bytes of src, the
** string placed in dest will not be null-terminated.
*/
char *strncpy(char *dest, char const *str, size_t size) char *strncpy(char *dest, char const *str, size_t size)
{ {
size_t i; size_t i;

View file

@ -1,6 +1,11 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/*
** The strdup() function returns a pointer to a new string which is a
** duplicate of the string s. Memory for the new string is obtained with
** malloc(), and can be freed with free().
*/
char *strdup(const char *s) char *strdup(const char *s)
{ {
size_t len; size_t len;
@ -15,8 +20,45 @@ char *strdup(const char *s)
if (len == 0) if (len == 0)
return (NULL); return (NULL);
// Dump string and return // try to allocate the new area
dump = malloc(len); dump = malloc(len);
if (dump == NULL)
return (NULL);
// dump the area and return
memcpy(dump, s, len); memcpy(dump, s, len);
return (dump); return (dump);
} }
/*
** The strndup() function is similar, but copies at most n bytes. If s is longer
** than n, only n bytes are copied, and a terminating null byte ('\0') is added.
*/
char *strndump(const char *s, size_t n)
{
size_t len;
char *dump;
// Check error
if (s == NULL)
return (NULL);
// Check len
len = strnlen(s, n);
if (len == 0)
return (NULL);
// try to allocate the new area
dump = malloc(len);
if (dump == NULL)
return (NULL);
// dump the area, set the null byte and return
memcpy(dump, s, len);
dump[len - 1] = '\0';
return (dump);
}
//TODO: strdupa()
//TODO: strndupa()

View file

@ -1,5 +1,11 @@
#include <string.h> #include <string.h>
/*
** The strlen() function calculates the length of the string pointed to by s,
** excluding the terminating null byte ('\0').
**
** TODO: use quad-word access !
*/
size_t strlen(char const *str) size_t strlen(char const *str)
{ {
size_t i; size_t i;
@ -11,6 +17,14 @@ size_t strlen(char const *str)
return (i); return (i);
} }
/*
** The strnlen() function returns the number of bytes in the string pointed to
** by s, excluding the terminating null byte ('\0'), but at most maxlen.
** In doing this, strnlen() looks only at the first maxlen characters in the
** string pointed to by s and never beyond s+maxlen.
**
** TODO: use quad-word access !
*/
size_t strnlen(char const *str, size_t maxlen) size_t strnlen(char const *str, size_t maxlen)
{ {
size_t i; size_t i;

View file

@ -0,0 +1,19 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _wait
.type _wait, @function
.align 2
/*
** extern pid_t wait(int *wstatus);
** Wait for a child to die. When one does, put its status in *STAT_LOC
** and return its process ID. For errors, return (pid_t) -1.
*/
_wait:
trapa #__NR_wait
rts
nop
.end
#endif

View file

@ -0,0 +1,29 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _waitpid
.type _waitpid, @function
.align 2
/*
** extern pid_t waitpid(pid_t pid, int *wstatus, int options);
** Wait for a child matching PID to die.
** - If PID is greater than 0, match any process whose process ID is PID.
** - If PID is (pid_t) -1, match any process.
** - If PID is (pid_t) 0, match any process with the same process group as the
** current process.
** - If PID is less than -1, match any process whose process group is the absolute
** value of PID.
** - If the WNOHANG bit is set in OPTIONS, and that child is not already dead,
** return (pid_t) 0. If successful, return PID and store the dead child's
** status in STAT_LOC.
** - Return (pid_t) -1 for errors. If the WUNTRACED bit is set in OPTIONS,
** return status for stopped children; otherwise don't.
*/
_waitpid:
trapa #__NR_waitpid
rts
nop
.end
#endif

View file

@ -6,64 +6,72 @@
.type ___thread_atomic_stop, @function .type ___thread_atomic_stop, @function
.align 2 .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. ** extern uint32_t __thread_atomic_start(void)
** Save the current SR register and set the SR.BIT bit up to start an atomic
** context (interrupt is blocked).
** Return the saved SR register (only if the we enter into an atomic context),
** 0xffffffff otherwise.
*/
___thread_atomic_start: ___thread_atomic_start:
! Check if the calculator is currently ! Check if the user is currently into an atomic operation
! into an atomic operation and update ! and update atomic counter.
! atomic counter. mov.l atomic_counter, r1
mov.l atomic_counter, r1 ! r1 = atomic counter address mov.l @r1, r2
mov.l @r1, r2 ! r2 = atomic counter data tst r2, r2
tst r2, r2 ! if atomic counter == 0... add #1, r2
add #1, r2 ! update atomic counter data mov.l r2, @r1
mov.l r2, @r1 ! update atomic counter. bf.s atomic_start_exit
bf.s atomic_start_exit ! ...if not, jump <atomic_start_exit> mov #-1, r0
mov #-1, r0 ! (db) return 0xffffffff
! Block interrupt if needed. ! Block interrupt if needed.
stc sr, r1 ! get SR register. stc sr, r1
mov r1, r0 ! save current SR register. mov r1, r0
mov.l bl_mask, r2 ! get SR.BL mask. mov.l bl_mask, r2
or r2, r1 ! set SR.BL = 1 and SR.IMASK = 0b1111. or r2, r1
ldc r1, sr ! update SR register. ldc r1, sr
! Save "old" SR register. ! Save "old" SR register.
mov.l sr_save, r1 ! r1 = sr_save address mov.l sr_save, r1
mov.l r0, @r1 ! save "old" SR register data. mov.l r0, @r1
atomic_start_exit: atomic_start_exit:
rts ! exit. rts
nop ! (db) nop. nop
// Restore the saved SR register /*
// @note: return the restored SR register or -1 otherwise. ** extern uint32_t __thread_atomic_stop(void)
** Decreate the internal "atomic context counter" and if the counter is 0,
** restore the saved SR register status.
** Return the restored SR register (if restored) or -1 otherwise.
*/
___thread_atomic_stop: ___thread_atomic_stop:
! Check if the calculator is currently ! Check if the device is currently into an atomic operation
! into an atomic operation and update ! and update atomic counter and, if needed, restore the SR
! atomic counter if pssible. ! regsiter
mov.l atomic_counter, r1 ! r1 = atomic counter address mov.l atomic_counter, r1
mov.l @r1, r0 ! r0 = atomic counter data mov.l @r1, r0
tst r0, r0 ! if atomic counter == 0... tst r0, r0
bt atomic_end_error ! ...if yes, jump at <atomic_end_error> bt atomic_end_error
cmp/eq #1, r0 ! if atomic counter == 1... cmp/eq #1, r0
add #-1, r0 ! update atomic counter data add #-1, r0
mov.l r0, @r1 ! update atomic counter mov.l r0, @r1
bf atomic_end_error ! ...if not, jump at <atomic_end_error> bf atomic_end_error
! Restore saved SR register data. ! Restore saved SR register data.
mov.l sr_save, r1 ! get sr_save address mov.l sr_save, r1
mov.l @r1, r0 ! r0 = "old" SR register data mov.l @r1, r0
ldc r0, sr ! restore SR register. ldc r0, sr
bra atomic_end_exit ! return the resotred SR register. bra atomic_end_exit
nop ! (db) nop nop
atomic_end_error: atomic_end_error:
mov #-1, r0 ! return 0xffffffff mov #-1, r0
atomic_end_exit: atomic_end_exit:
rts ! exit. rts
nop ! (db) nop. nop
.align 4 .align 4
bl_mask: .long 0x100000f0 bl_mask: .long 0x100000f0
@ -72,7 +80,6 @@ atomic_counter: .long ___thread_atomic_counter
##--- ##---
## Global part. ## Global part.
##--- ##---

View file

@ -0,0 +1,20 @@
#ifdef __SUPPORT_CASIO_ABI_FX9860G
#include <asm/unistd_32.h>
#include <asm-casio/__trapa.h>
.text
.global _close
.type _close, @function
.align 2
/*
** int close(int fd)
** close() closes a file descriptor, so that it no longer refers to any file
** and may be reused.
*/
_close:
casio_trapa(__NR_close)
rts
nop
.end
#endif

View file

@ -0,0 +1,19 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _close
.type _close, @function
.align 2
/*
** int close(int fd)
** close() closes a file descriptor, so that it no longer refers to any file
** and may be reused.
*/
_close:
trapa #__NR_close
rts
nop
.end
#endif

View file

@ -0,0 +1,24 @@
#include __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _fork_execve
.type _fork_execve, @function
.align 2
/*
** pid_t fork_execve(const char *pathname, char **argv, char **envp);
** Custom syscall used to create a new process based on the new command passed
** using the `argv` and `envp` parametter. This sycall is equivalent of fork()
** and execve() combined.
**
** This custom syscall exist because the Vhex kernel doesn't have access to the
** MMU, so we cannot ensure that the memory requested by the potential new
** process is enough when execve() is involved by the user.
*/
_fork_execve:
trapa #__NR_fork_execve
rts
nop
.end
#endif

View file

@ -1,3 +1,4 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h> #include <asm/unistd_32.h>
.text .text
.global _getpgid .global _getpgid
@ -5,8 +6,13 @@
.align 2 .align 2
/*
** extern pid_t getpgid(void);
** Get the process group ID of the calling process.
*/
_getpgid: _getpgid:
trapa #__NR_getpgid trapa #__NR_getpgid
rts rts
nop nop
.end .end
#endif

View file

@ -1,3 +1,4 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h> #include <asm/unistd_32.h>
.text .text
.global _getpid .global _getpid
@ -5,8 +6,13 @@
.align 2 .align 2
/*
** extern pid_t getpid(void);
** Get the process ID of the calling process.
*/
_getpid: _getpid:
trapa #__NR_getpid trapa #__NR_getpid
rts rts
nop nop
.end .end
#endif

View file

@ -1,3 +1,4 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h> #include <asm/unistd_32.h>
.text .text
.global _getppid .global _getppid
@ -5,8 +6,13 @@
.align 2 .align 2
/*
** extern pid_t getpgid(void);
** Get the parent process ID of the calling process.
*/
_getppid: _getppid:
trapa #__NR_getppid trapa #__NR_getppid
rts rts
nop nop
.end .end
#endif

View file

@ -0,0 +1,21 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _lseek
.type _lseek, @function
.align 2
/*
** extern off_t lseek(int fd, off_t offset, int whence)
** Move FD's file position to OFFSET bytes from the beginning of the file
** (if WHENCE is SEEK_SET), the current position (if WHENCE is SEEK_CUR),
** or the end of the file (if WHENCE is SEEK_END).
** Return the new file position.
*/
_lseek:
trapa #__NR_lseek
rts
nop
.end
#endif

View file

@ -0,0 +1,19 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _read
.type _read, @function
.align 2
/*
** extern ssize_t write(int __fd, const void *__buf, size_t __nbytes);
** Write N bytes of BUF to FD.
** Return the number written, or -1.
*/
_read:
trapa #__NR_read
rts
nop
.end
#endif

View file

@ -0,0 +1,20 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _setpgid
.type _setpgid, @function
.align 2
/*
** extern int setpgid(pid_t __pid, pid_t __pgid);
** Set the process group ID of the process matching PID to PGID.
** If PID is zero, the current process's process group ID is set.
** If PGID is zero, the process ID of the process is used.
*/
_setpgid:
trapa #__NR_setpgid
rts
nop
.end
#endif

View file

@ -0,0 +1,19 @@
#ifdef __SUPPORT_VHEX_KERNEL
#include <asm/unistd_32.h>
.text
.global _write
.type _write, @function
.align 2
/*
** extern ssize_t write(int __fd, const void *__buf, size_t __nbytes);
** Write N bytes of BUF to FD.
** Return the number written, or -1.
*/
_write:
trapa #__NR_write
rts
nop
.end
#endif

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _close
.type _close, @function
.align 2
_close:
trapa #__NR_close
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _fork_execve
.type _fork_execve, @function
.align 2
_fork_execve:
trapa #__NR_fork_execve
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _lseek
.type _lseek, @function
.align 2
_lseek:
trapa #__NR_lseek
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _open
.type _open, @function
.align 2
_open:
trapa #__NR_open
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _read
.type _read, @function
.align 2
_read:
trapa #__NR_read
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _setpgid
.type _setpgid, @function
.align 2
_setpgid:
trapa #__NR_setpgid
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _wait
.type _wait, @function
.align 2
_wait:
trapa #__NR_wait
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _waitpid
.type _waitpid, @function
.align 2
_waitpid:
trapa #__NR_waitpid
rts
nop
.end

View file

@ -1,12 +0,0 @@
#include <asm/unistd_32.h>
.text
.global _write
.type _write, @function
.align 2
_write:
trapa #__NR_write
rts
nop
.end