- PS/2 keyboard driver: IRQ1 handler, scancode set 1 translation, ring buffer, shift key support - SYS_READ (fd=0): non-blocking keyboard read for stdin - SYS_YIELD: calls schedule_tick directly (no nested INT 0x80) - SYS_EXEC: loads binary from CPIO initrd, replaces process image - User-space libc: crt0.S (C runtime startup), syscalls.h (inline syscall wrappers, basic string functions) - Shell app (sh): readline with echo/backspace, builtins (cd, env, help, exit), fork+exec for external commands - Updated build_apps.sh: C app support with crt0 linking, libc include path, .bss section in objcopy Tested: shell boots, keyboard input works, hello-world runs via fork+exec, env shows CWD, exit cleanly terminates.
148 lines
3.7 KiB
C
148 lines
3.7 KiB
C
/**
|
|
* @file syscalls.h
|
|
* @brief User-space system call wrappers for ClaudeOS.
|
|
*
|
|
* Provides inline functions that invoke INT 0x80 with the appropriate
|
|
* system call numbers and arguments.
|
|
*/
|
|
|
|
#ifndef USERSPACE_SYSCALLS_H
|
|
#define USERSPACE_SYSCALLS_H
|
|
|
|
typedef unsigned int uint32_t;
|
|
typedef int int32_t;
|
|
|
|
/* System call numbers (must match kernel's syscall.h) */
|
|
#define SYS_EXIT 0
|
|
#define SYS_WRITE 1
|
|
#define SYS_READ 2
|
|
#define SYS_FORK 3
|
|
#define SYS_GETPID 4
|
|
#define SYS_YIELD 5
|
|
#define SYS_WAITPID 6
|
|
#define SYS_EXEC 7
|
|
#define SYS_GETENV 8
|
|
#define SYS_SETENV 9
|
|
|
|
static inline int32_t syscall0(int num) {
|
|
int32_t ret;
|
|
__asm__ volatile("int $0x80" : "=a"(ret) : "a"(num));
|
|
return ret;
|
|
}
|
|
|
|
static inline int32_t syscall1(int num, uint32_t arg1) {
|
|
int32_t ret;
|
|
__asm__ volatile("int $0x80" : "=a"(ret) : "a"(num), "b"(arg1));
|
|
return ret;
|
|
}
|
|
|
|
static inline int32_t syscall2(int num, uint32_t arg1, uint32_t arg2) {
|
|
int32_t ret;
|
|
__asm__ volatile("int $0x80" : "=a"(ret)
|
|
: "a"(num), "b"(arg1), "c"(arg2));
|
|
return ret;
|
|
}
|
|
|
|
static inline int32_t syscall3(int num, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
|
|
int32_t ret;
|
|
__asm__ volatile("int $0x80" : "=a"(ret)
|
|
: "a"(num), "b"(arg1), "c"(arg2), "d"(arg3));
|
|
return ret;
|
|
}
|
|
|
|
static inline void exit(int code) {
|
|
syscall1(SYS_EXIT, (uint32_t)code);
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
static inline int32_t write(int fd, const void *buf, uint32_t len) {
|
|
return syscall3(SYS_WRITE, (uint32_t)fd, (uint32_t)buf, len);
|
|
}
|
|
|
|
static inline int32_t read(int fd, void *buf, uint32_t len) {
|
|
return syscall3(SYS_READ, (uint32_t)fd, (uint32_t)buf, len);
|
|
}
|
|
|
|
static inline int32_t fork(void) {
|
|
return syscall0(SYS_FORK);
|
|
}
|
|
|
|
static inline int32_t getpid(void) {
|
|
return syscall0(SYS_GETPID);
|
|
}
|
|
|
|
static inline void yield(void) {
|
|
syscall0(SYS_YIELD);
|
|
}
|
|
|
|
static inline int32_t waitpid(int32_t pid) {
|
|
return syscall1(SYS_WAITPID, (uint32_t)pid);
|
|
}
|
|
|
|
static inline int32_t exec(const char *path) {
|
|
return syscall1(SYS_EXEC, (uint32_t)path);
|
|
}
|
|
|
|
static inline int32_t getenv(const char *key, char *buf, uint32_t bufsize) {
|
|
return syscall3(SYS_GETENV, (uint32_t)key, (uint32_t)buf, bufsize);
|
|
}
|
|
|
|
static inline int32_t setenv(const char *key, const char *value) {
|
|
return syscall2(SYS_SETENV, (uint32_t)key, (uint32_t)value);
|
|
}
|
|
|
|
/* Basic string operations for user-space */
|
|
static inline uint32_t strlen(const char *s) {
|
|
uint32_t len = 0;
|
|
while (s[len]) len++;
|
|
return len;
|
|
}
|
|
|
|
static inline int strcmp(const char *a, const char *b) {
|
|
while (*a && *a == *b) { a++; b++; }
|
|
return (unsigned char)*a - (unsigned char)*b;
|
|
}
|
|
|
|
static inline int strncmp(const char *a, const char *b, uint32_t n) {
|
|
while (n && *a && *a == *b) { a++; b++; n--; }
|
|
return n ? ((unsigned char)*a - (unsigned char)*b) : 0;
|
|
}
|
|
|
|
static inline char *strcpy(char *dst, const char *src) {
|
|
char *d = dst;
|
|
while ((*d++ = *src++));
|
|
return dst;
|
|
}
|
|
|
|
static inline char *strncpy(char *dst, const char *src, uint32_t n) {
|
|
char *d = dst;
|
|
while (n && (*d++ = *src++)) n--;
|
|
while (n--) *d++ = '\0';
|
|
return dst;
|
|
}
|
|
|
|
static inline void *memset(void *s, int c, uint32_t n) {
|
|
unsigned char *p = (unsigned char *)s;
|
|
while (n--) *p++ = (unsigned char)c;
|
|
return s;
|
|
}
|
|
|
|
static inline void *memcpy(void *dst, const void *src, uint32_t n) {
|
|
unsigned char *d = (unsigned char *)dst;
|
|
const unsigned char *s = (const unsigned char *)src;
|
|
while (n--) *d++ = *s++;
|
|
return dst;
|
|
}
|
|
|
|
/** Print a string to stdout. */
|
|
static inline void puts(const char *s) {
|
|
write(1, s, strlen(s));
|
|
}
|
|
|
|
/** Print a single character to stdout. */
|
|
static inline void putchar(char c) {
|
|
write(1, &c, 1);
|
|
}
|
|
|
|
#endif /* USERSPACE_SYSCALLS_H */
|