build system refresh
This commit is contained in:
1
rlibc/.gitignore
vendored
Normal file
1
rlibc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.a
|
||||
10
rlibc/include/stdio.h
Normal file
10
rlibc/include/stdio.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef RLIBC_STDIO_H
|
||||
#define RLIBC_STDIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
char getchar(void);
|
||||
|
||||
#endif
|
||||
8
rlibc/include/stdlib.h
Normal file
8
rlibc/include/stdlib.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef RLIBC_STDLIB_H
|
||||
#define RLIBC_STDLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void* malloc(size_t size);
|
||||
|
||||
#endif
|
||||
15
rlibc/include/string.h
Normal file
15
rlibc/include/string.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef RLIBC_STRING_H
|
||||
#define RLIBC_STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *memcpy(void *restrict dest, const void *restrict src, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
|
||||
size_t strlen(const char *s);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
char* strcat(char *dest, const char* src);
|
||||
|
||||
#endif
|
||||
8
rlibc/include/sys/types.h
Normal file
8
rlibc/include/sys/types.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef RLIBC_SYS_TYPES_H
|
||||
#define RLIBC_SYS_TYPES_H
|
||||
|
||||
typedef long off_t;
|
||||
|
||||
typedef int ssize_t;
|
||||
|
||||
#endif
|
||||
17
rlibc/include/sys/video.h
Normal file
17
rlibc/include/sys/video.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef USER_VIDEO_H
|
||||
#define USER_VIDEO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define FBIOGET_INFO 0x1
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t pitch;
|
||||
uint32_t bpp;
|
||||
uint32_t fb_size;
|
||||
} fb_info_t;
|
||||
|
||||
|
||||
#endif
|
||||
46
rlibc/include/syscall.h
Normal file
46
rlibc/include/syscall.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef RLIBC_SYSCALL_H
|
||||
#define RLIBC_SYSCALL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define SYS_EXIT 1
|
||||
#define SYS_READ 3
|
||||
#define SYS_WRITE 4
|
||||
#define SYS_OPEN 5
|
||||
#define SYS_CLOSE 6
|
||||
#define SYS_BRK 12
|
||||
#define SYS_SBRK 13
|
||||
#define SYS_PTY 20
|
||||
#define SYS_FORK 21
|
||||
#define SYS_EXEC 22
|
||||
#define SYS_DUP2 23
|
||||
#define SYS_LSEEK 24
|
||||
#define SYS_WAIT 25
|
||||
#define SYS_MMAP 26
|
||||
#define SYS_IOCTL 27
|
||||
|
||||
int open(const char* path);
|
||||
int write(int fd, const void *buf, size_t count);
|
||||
int read(int fd, void *buf, size_t count);
|
||||
int close(int fd);
|
||||
|
||||
int lseek(int fd, size_t offset, int whence);
|
||||
|
||||
void* mmap(int fd);
|
||||
|
||||
void exit(int status) __attribute__((noreturn));
|
||||
|
||||
void* sbrk(int32_t increment);
|
||||
int brk(void *addr);
|
||||
|
||||
int pty(int* slave);
|
||||
|
||||
int fork();
|
||||
int exec(const char* path);
|
||||
int dup2(int src, int dst);
|
||||
int waitpid(int pid, int* status);
|
||||
|
||||
int ioctl(int fd, uint32_t request, void* arg);
|
||||
|
||||
#endif
|
||||
15
rlibc/include/unistd.h
Normal file
15
rlibc/include/unistd.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef RLIBC_UNISTD_H
|
||||
#define RLIBC_UNISTD_H
|
||||
|
||||
#include <syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
#endif
|
||||
20
rlibc/makefile
Normal file
20
rlibc/makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
CC = i686-elf-gcc
|
||||
AR = i686-elf-ar
|
||||
CFLAGS = -ffreestanding -O2 -Wall -Wextra -Iinclude
|
||||
TARGET = rlibc.a
|
||||
|
||||
SRCS = $(shell find src -name "*.c")
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(AR) rcs $@ $(OBJS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET) compile_commands.json
|
||||
|
||||
.PHONY: all clean
|
||||
74
rlibc/src/malloc.c
Normal file
74
rlibc/src/malloc.c
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#define ALIGN(size) (((size) + 3) & ~3)
|
||||
#define HEADER_SIZE sizeof(struct Header)
|
||||
|
||||
struct Header {
|
||||
size_t size;
|
||||
int is_free;
|
||||
struct Header* next;
|
||||
};
|
||||
|
||||
static struct Header* free_list_head = NULL;
|
||||
|
||||
static struct Header* find_free_block(struct Header** last, size_t size) {
|
||||
struct Header* current = free_list_head;
|
||||
while (current && !(current->is_free && current->size >= size)) {
|
||||
*last = current;
|
||||
current = current->next;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
static struct Header* request_space(struct Header* last, size_t size) {
|
||||
struct Header* block = sbrk(0);
|
||||
void* request = sbrk(size + HEADER_SIZE);
|
||||
|
||||
if (request == (void*)-1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
last->next = block;
|
||||
}
|
||||
|
||||
block->size = size;
|
||||
block->next = NULL;
|
||||
block->is_free = 0;
|
||||
return block;
|
||||
}
|
||||
|
||||
void* malloc(size_t size) {
|
||||
if (size <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = ALIGN(size);
|
||||
|
||||
if (free_list_head == NULL) {
|
||||
struct Header* block = request_space(NULL, size);
|
||||
if (!block) return NULL;
|
||||
free_list_head = block;
|
||||
return (void*)(block + 1);
|
||||
}
|
||||
|
||||
struct Header* last = free_list_head;
|
||||
struct Header* block = find_free_block(&last, size);
|
||||
|
||||
if (block) {
|
||||
block->is_free = 0;
|
||||
} else {
|
||||
block = request_space(last, size);
|
||||
if (!block) return NULL;
|
||||
}
|
||||
|
||||
return (void*)(block + 1);
|
||||
}
|
||||
|
||||
void free(void* ptr) {
|
||||
if (!ptr) return;
|
||||
|
||||
struct Header* block = (struct Header*)ptr - 1;
|
||||
block->is_free = 1;
|
||||
}
|
||||
122
rlibc/src/stdio.c
Normal file
122
rlibc/src/stdio.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void utoa(unsigned int value, char *buf, int base) {
|
||||
char temp[32];
|
||||
int i = 0;
|
||||
|
||||
// Handle zero explicitly
|
||||
if (value == 0) {
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert digits in reverse order
|
||||
while (value > 0) {
|
||||
int remainder = value % base;
|
||||
if (remainder < 10) {
|
||||
temp[i++] = '0' + remainder;
|
||||
} else {
|
||||
temp[i++] = 'a' + (remainder - 10);
|
||||
}
|
||||
value /= base;
|
||||
}
|
||||
|
||||
// Reverse the string into the output destination buffer
|
||||
int j = 0;
|
||||
while (i > 0) {
|
||||
buf[j++] = temp[--i];
|
||||
}
|
||||
buf[j] = '\0';
|
||||
}
|
||||
|
||||
/* Helper function to convert a signed integer to a string */
|
||||
static void itoa(int value, char *buf, int base) {
|
||||
if (value < 0 && base == 10) {
|
||||
*buf++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
utoa((unsigned int)value, buf, base);
|
||||
}
|
||||
|
||||
int printf(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
int written_total = 0;
|
||||
char num_buf[32]; // Stack-allocated scratchpad for string conversions
|
||||
|
||||
while (*format != '\0') {
|
||||
if (*format == '%') {
|
||||
format++; // Move past '%'
|
||||
|
||||
switch (*format) {
|
||||
case 'c': {
|
||||
char c = (char)va_arg(args, int);
|
||||
write(1, &c, 1);
|
||||
written_total++;
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *s = va_arg(args, char *);
|
||||
if (!s) s = "(null)";
|
||||
// Find length manually without dragging headers
|
||||
int len = 0;
|
||||
while (s[len] != '\0') len++;
|
||||
write(1, s, len);
|
||||
written_total += len;
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
case 'i': {
|
||||
int n = va_arg(args, int);
|
||||
itoa(n, num_buf, 10);
|
||||
int len = 0;
|
||||
while (num_buf[len] != '\0') len++;
|
||||
write(1, num_buf, len);
|
||||
written_total += len;
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
unsigned int x = va_arg(args, unsigned int);
|
||||
utoa(x, num_buf, 16);
|
||||
int len = 0;
|
||||
while (num_buf[len] != '\0') len++;
|
||||
write(1, num_buf, len);
|
||||
written_total += len;
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
write(1, "%", 1);
|
||||
written_total++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Unknown conversion, print verbatim
|
||||
write(1, format - 1, 2);
|
||||
written_total += 2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Standard text character
|
||||
write(1, format, 1);
|
||||
written_total++;
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return written_total;
|
||||
}
|
||||
|
||||
char getchar(void) {
|
||||
char c;
|
||||
int res = read(0, &c, 1);
|
||||
|
||||
if (res <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (char)c;
|
||||
}
|
||||
8
rlibc/src/strcat.c
Normal file
8
rlibc/src/strcat.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
char* strcat(char* dest, const char* src) {
|
||||
char* start = dest + strlen(dest);
|
||||
strcpy(start, src);
|
||||
return dest;
|
||||
}
|
||||
68
rlibc/src/string.c
Normal file
68
rlibc/src/string.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <string.h>
|
||||
|
||||
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Copy memory area: safely handles overlapping regions */
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
if (d < s) {
|
||||
// Copy forward
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
} else if (d > s) {
|
||||
// Copy backward to prevent overwriting uncopied data
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
d[i - 1] = s[i - 1];
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Fill memory block with a constant byte */
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
p[i] = (unsigned char)c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Calculate the length of a string */
|
||||
size_t strlen(const char *s) {
|
||||
size_t len = 0;
|
||||
while (s[len] != '\0') {
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Compare two strings */
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
|
||||
/* Copy a string from src to dest */
|
||||
char *strcpy(char *dest, const char *src) {
|
||||
size_t i = 0;
|
||||
while (src[i] != '\0') {
|
||||
dest[i] = src[i];
|
||||
i++;
|
||||
}
|
||||
dest[i] = '\0';
|
||||
return dest;
|
||||
}
|
||||
63
rlibc/src/strtok.c
Normal file
63
rlibc/src/strtok.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <string.h>
|
||||
|
||||
static size_t kernel_strspn(const char *s, const char *accept) {
|
||||
const char *p;
|
||||
const char *a;
|
||||
size_t count = 0;
|
||||
|
||||
for (p = s; *p != '\0'; ++p) {
|
||||
for (a = accept; *a != '\0'; ++a) {
|
||||
if (*p == *a)
|
||||
break;
|
||||
}
|
||||
if (*a == '\0')
|
||||
return count;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static char *kernel_strpbrk(const char *s, const char *accept) {
|
||||
while (*s != '\0') {
|
||||
const char *a = accept;
|
||||
while (*a != '\0') {
|
||||
if (*s == *a) {
|
||||
return (char *)s;
|
||||
}
|
||||
a++;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strtok_r(char *str, const char *delim, char **saveptr) {
|
||||
char *token;
|
||||
|
||||
if (str == NULL) {
|
||||
str = *saveptr;
|
||||
}
|
||||
|
||||
if (str == NULL || *str == '\0') {
|
||||
*saveptr = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str += kernel_strspn(str, delim);
|
||||
if (*str == '\0') {
|
||||
*saveptr = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = str;
|
||||
str = kernel_strpbrk(token, delim);
|
||||
|
||||
if (str == NULL) {
|
||||
*saveptr = NULL;
|
||||
} else {
|
||||
*str = '\0';
|
||||
*saveptr = str + 1;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
84
rlibc/src/syscall.c
Normal file
84
rlibc/src/syscall.c
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <syscall.h>
|
||||
|
||||
static inline int syscall1(int num, uint32_t arg1) {
|
||||
int ret;
|
||||
asm volatile (
|
||||
"int $0x80"
|
||||
: "=a"(ret)
|
||||
: "a"(num), "b"(arg1)
|
||||
: "memory"
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int syscall3(int num, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
|
||||
int ret;
|
||||
asm volatile (
|
||||
"int $0x80"
|
||||
: "=a"(ret)
|
||||
: "a"(num), "b"(arg1), "c"(arg2), "d"(arg3)
|
||||
: "memory"
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void exit(int status) {
|
||||
syscall1(SYS_EXIT, (uint32_t)status);
|
||||
while(1);
|
||||
}
|
||||
|
||||
int open(const char* path) {
|
||||
return syscall3(SYS_OPEN, (uint32_t)path, 0, 0);
|
||||
}
|
||||
|
||||
int write(int fd, const void* buf, size_t cnt) {
|
||||
return syscall3(SYS_WRITE, (uint32_t)fd, (uint32_t)buf, (uint32_t)cnt);
|
||||
}
|
||||
|
||||
int read(int fd, void* buf, size_t cnt) {
|
||||
return syscall3(SYS_READ, (uint32_t)fd, (uint32_t)buf, (uint32_t)cnt);
|
||||
}
|
||||
|
||||
int lseek(int fd, size_t offset, int whence) {
|
||||
return syscall3(SYS_LSEEK, (uint32_t)fd, offset, whence);
|
||||
}
|
||||
|
||||
int close(int fd) {
|
||||
return syscall1(SYS_CLOSE, fd);
|
||||
}
|
||||
|
||||
int pty(int* slave) {
|
||||
return syscall1(SYS_PTY, (uint32_t)slave);
|
||||
}
|
||||
|
||||
int fork() {
|
||||
return syscall1(SYS_FORK, 0);
|
||||
}
|
||||
|
||||
int exec(const char* path) {
|
||||
return syscall1(SYS_EXEC, (uint32_t)path);
|
||||
}
|
||||
|
||||
int dup2(int src, int dst) {
|
||||
return syscall3(SYS_DUP2, src, dst, 0);
|
||||
}
|
||||
|
||||
int waitpid(int pid, int* status) {
|
||||
return syscall3(SYS_WAIT, pid, (uint32_t)status, 0);
|
||||
}
|
||||
|
||||
void* sbrk(int32_t increment) {
|
||||
return (void*)syscall1(SYS_SBRK, increment);
|
||||
}
|
||||
|
||||
int brk(void *addr) {
|
||||
return syscall1(SYS_BRK, (uint32_t)addr);
|
||||
}
|
||||
|
||||
void* mmap(int fd) {
|
||||
return (void*)syscall1(SYS_MMAP, fd);
|
||||
}
|
||||
|
||||
int ioctl(int fd, uint32_t request, void* arg) {
|
||||
return syscall3(SYS_IOCTL, fd, request, (uint32_t)arg);
|
||||
}
|
||||
Reference in New Issue
Block a user