From 8eda325ede02d3fc606a34f7fa3c4922b05a84e4 Mon Sep 17 00:00:00 2001 From: EmulatedSeasons <89668582+EmulatedSeasons@users.noreply.github.com> Date: Thu, 18 Jul 2024 22:25:44 -0400 Subject: Remerged the std stuff into the kernel --- kernel/include/stdio.h | 18 ++++ kernel/include/stdlib.h | 15 ++++ kernel/include/string.h | 20 +++++ kernel/include/sys/cdefs.h | 6 ++ kernel/makefile | 16 ++-- kernel/std/README.txt | 3 + kernel/std/abort.c | 11 +++ kernel/std/memcmp.c | 13 +++ kernel/std/memcpy.c | 9 ++ kernel/std/memmove.c | 14 ++++ kernel/std/memset.c | 8 ++ kernel/std/printf.c | 199 +++++++++++++++++++++++++++++++++++++++++++++ kernel/std/putchar.c | 11 +++ kernel/std/puts.c | 5 ++ kernel/std/strlen.c | 9 ++ 15 files changed, 350 insertions(+), 7 deletions(-) create mode 100644 kernel/include/stdio.h create mode 100644 kernel/include/stdlib.h create mode 100644 kernel/include/string.h create mode 100644 kernel/include/sys/cdefs.h create mode 100644 kernel/std/README.txt create mode 100644 kernel/std/abort.c create mode 100644 kernel/std/memcmp.c create mode 100644 kernel/std/memcpy.c create mode 100644 kernel/std/memmove.c create mode 100644 kernel/std/memset.c create mode 100644 kernel/std/printf.c create mode 100644 kernel/std/putchar.c create mode 100644 kernel/std/puts.c create mode 100644 kernel/std/strlen.c (limited to 'kernel') diff --git a/kernel/include/stdio.h b/kernel/include/stdio.h new file mode 100644 index 0000000..eb4e45b --- /dev/null +++ b/kernel/include/stdio.h @@ -0,0 +1,18 @@ +#ifndef _STDIO_H +#define _STDIO_H 1 + +#define EOF (-1) + +#ifdef __cplusplus +extern "C" { +#endif + +int printf(const char* __restrict, ...); +int putchar(int); +int puts(const char*); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/kernel/include/stdlib.h b/kernel/include/stdlib.h new file mode 100644 index 0000000..1d1ee32 --- /dev/null +++ b/kernel/include/stdlib.h @@ -0,0 +1,15 @@ +#ifndef _STDLIB_H +#define _STDLIB_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((__noreturn__)) +void abort(void); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/kernel/include/string.h b/kernel/include/string.h new file mode 100644 index 0000000..4f6b5bd --- /dev/null +++ b/kernel/include/string.h @@ -0,0 +1,20 @@ +#ifndef _STRING_H +#define _STRING_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int memcmp(const void*, const void*, size_t); +void* memcpy(void* __restrict, const void* __restrict, size_t); +void* memmove(void*, const void*, size_t); +void* memset(void*, int, size_t); +size_t strlen(const char*); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/kernel/include/sys/cdefs.h b/kernel/include/sys/cdefs.h new file mode 100644 index 0000000..1e2c277 --- /dev/null +++ b/kernel/include/sys/cdefs.h @@ -0,0 +1,6 @@ +#ifndef _SYS_CDEFS_H +#define _SYS_CDEFS_H 1 + + + +#endif \ No newline at end of file diff --git a/kernel/makefile b/kernel/makefile index a855808..52f4d00 100644 --- a/kernel/makefile +++ b/kernel/makefile @@ -20,20 +20,22 @@ ifndef SYSROOT $(error No sysroot specified) endif -LIBS = -nostdlib -lc -lgcc +LIBS = -nostdlib -lgcc #Find all the source files +C_SRCS := $(shell find . -type f -name '*.c' -not -path './arch/*') \ + $(shell find $(PWD)/kernel/arch/$(ARCH) -type f -name '*.c') CPP_SRCS := $(shell find . -type f -name '*.cpp' -not -path './arch/*') \ $(shell find $(PWD)/kernel/arch/$(ARCH) -type f -name '*.cpp') HEADERS := $(shell find ./include -type f -name '*.h') ASMFILES := $(shell find . -type f -name '*.asm' -not -path './arch/*') \ $(shell find $(PWD)/kernel/arch/$(ARCH) -type f -name '*.asm') -#OBJS := $(patsubst %.c,%.o,$(C_SOURCES)) -OBJS := $(patsubst %.cpp,%.o,$(CPP_SRCS)) +OBJS := $(patsubst %.c,%.o,$(C_SRCS)) +OBJS += $(patsubst %.cpp,%.o,$(CPP_SRCS)) OBJS += $(patsubst %.asm,%.o,$(ASMFILES)) -#DEPFILES := $(patsubst %.c,%.d,$(C_SOURCES)) +DEPFILES := $(patsubst %.c,%.d,$(C_SOURCES)) DEPFILES := $(patsubst %.cpp,%.d,$(CPP_SRCS)) # LINKLST := crti.o @@ -62,7 +64,7 @@ kernel.bin: ${OBJS} $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ %.o: %.asm - $(info [INFO] Assembling $<) +# $(info [INFO] Assembling $<) $(NASM) $< $(ASMFLAGS) -o $@ -g # crti.o: @@ -71,8 +73,8 @@ kernel.bin: ${OBJS} # crtn.o: # $(NASM) arch/$(ARCH)/crtn.asm $(ASMFLAGS) -o $@ -install-headers: $(HEADERS) - cp -r --preserve=timestamps include/. $(SYSROOT)/usr/include +# install-headers: $(HEADERS) +# cp -r --preserve=timestamps include/. $(SYSROOT)/usr/include clean: $(info [INFO] Cleaning) diff --git a/kernel/std/README.txt b/kernel/std/README.txt new file mode 100644 index 0000000..ef7c787 --- /dev/null +++ b/kernel/std/README.txt @@ -0,0 +1,3 @@ +some libc functions for the kernel + +code based off meaty skeleton from osdev.org diff --git a/kernel/std/abort.c b/kernel/std/abort.c new file mode 100644 index 0000000..83873e8 --- /dev/null +++ b/kernel/std/abort.c @@ -0,0 +1,11 @@ +#include +#include + +__attribute__((__noreturn__)) +void abort(void) { + // TODO: Add proper kernel panic. + printf("kernel: panic: abort()\n"); + asm volatile("hlt"); + while (1) { } + __builtin_unreachable(); +} \ No newline at end of file diff --git a/kernel/std/memcmp.c b/kernel/std/memcmp.c new file mode 100644 index 0000000..93141e1 --- /dev/null +++ b/kernel/std/memcmp.c @@ -0,0 +1,13 @@ +#include + +int memcmp(const void* aptr, const void* bptr, size_t size) { + const unsigned char* a = (const unsigned char*) aptr; + const unsigned char* b = (const unsigned char*) bptr; + for (size_t i = 0; i < size; i++) { + if (a[i] < b[i]) + return -1; + else if (b[i] < a[i]) + return 1; + } + return 0; +} \ No newline at end of file diff --git a/kernel/std/memcpy.c b/kernel/std/memcpy.c new file mode 100644 index 0000000..7e09be7 --- /dev/null +++ b/kernel/std/memcpy.c @@ -0,0 +1,9 @@ +#include + +void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) { + unsigned char* dst = (unsigned char*) dstptr; + const unsigned char* src = (const unsigned char*) srcptr; + for (size_t i=0; i < size; i++) + dst[i] = src[i]; + return dstptr; +} \ No newline at end of file diff --git a/kernel/std/memmove.c b/kernel/std/memmove.c new file mode 100644 index 0000000..98c787f --- /dev/null +++ b/kernel/std/memmove.c @@ -0,0 +1,14 @@ +#include + +void* memmove(void* dstptr, const void* srcptr, size_t size) { + unsigned char* dst = (unsigned char*) dstptr; + const unsigned char* src = (const unsigned char*) srcptr; + if (dst < src) { + for (size_t i = 0; i < size; i++) + dst[i] = src[i]; + } else { + for (size_t i = size; i != 0; i--) + dst[i-1] = src[i-1]; + } + return dstptr; +} \ No newline at end of file diff --git a/kernel/std/memset.c b/kernel/std/memset.c new file mode 100644 index 0000000..67dadfe --- /dev/null +++ b/kernel/std/memset.c @@ -0,0 +1,8 @@ +#include + +void* memset(void* bufptr, int value, size_t size) { + unsigned char* buf = (unsigned char*) bufptr; + for (size_t i = 0; i < size; i++) + buf[i] = (unsigned char) value; + return bufptr; +} \ No newline at end of file diff --git a/kernel/std/printf.c b/kernel/std/printf.c new file mode 100644 index 0000000..0bb5506 --- /dev/null +++ b/kernel/std/printf.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include + +static bool print(const char* data, size_t length) { + const unsigned char* bytes = (const unsigned char*) data; + for (size_t i = 0; i < length; i++) + if (putchar(bytes[i]) == EOF) + return false; + return true; +} + +// for %d and %x. +static const char* itoa(unsigned int num, char* str, unsigned int base) { + int cou = 0; // nt + + if (num == 0) { // 0 + str[cou] = '0'; + str[++cou] = '\0'; + return str; + } + + while (num) + { + unsigned int rem = (num % base); + // brings the number up to ascii 0 + the digit + if (rem > 9) { + str[cou] = rem + '7'; // 7 = 55 + 10(A) = 65 + } else { + str[cou] = rem + '0'; + } + num /= base; + ++cou; + } + + // reverse the string + size_t start = 0; + size_t end = cou - 1; + while (start < end) { + char temp = str[start]; + str[start] = str[end]; + str[end] = temp; + ++start; + --end; + } + + str[cou] = '\0'; + return str; +} + +// have no idea if there's a better way to do this. for %lx +static const char* itoa_u64(unsigned long long num, char* str, int base) { + size_t cou = 0; // nt + + if (num == 0) { // 0 + str[cou] = '0'; + str[++cou] = '\0'; + return str; + } + + while (num) + { + unsigned long long rem = num % base; + // brings the number up to ascii 0 + the digit + if (rem > 9) { + str[cou] = rem + '7'; // 7 = 55 + 10(A) = 65 + } else { + str[cou] = rem + '0'; + } + num /= base; + ++cou; + } + + // reverse the string + size_t start = 0; + size_t end = cou - 1; + while (start < end) { + char temp = str[start]; + str[start] = str[end]; + str[end] = temp; + ++start; + --end; + } + + str[cou] = '\0'; + return str; +} + +int printf(const char* restrict format, ...) { + va_list parameters; + va_start(parameters, format); + + int written = 0; + + while (*format != '\0') { + size_t maxrem = INT_MAX - written; + + if (format[0] != '%' || format[1] == '%') { + if (format[0] == '%') + format++; + size_t amount = 1; + while (format[amount] && format[amount] != '%') + amount++; + if (maxrem < amount) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(format, amount)) + return -1; + format += amount; + written += amount; + continue; + } + + const char* format_begun_at = format++; + + if (*format == 'c') { + format++; + char c = (char) va_arg(parameters, int /* char promotes to int */); + if (!maxrem) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(&c, sizeof(c))) + return -1; + written++; + } else if (*format == 'd') { + format++; + char str[20]; // probably a long enough buffer + unsigned int d = va_arg(parameters, unsigned int); + itoa(d, str, 10); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } else if (*format == 'x') { + format++; + char str[20]; // probably a long enough buffer + unsigned int d = va_arg(parameters, unsigned int); + itoa(d, str, 16); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } else if (*format == 'l') { // for %lx and others that start with l + format++; + if (*format == 'x') { + format++; + char str[20]; // probably a long enough buffer + unsigned long long d = va_arg(parameters, unsigned long long); + itoa_u64(d, str, 16); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } + } else if (*format == 's') { + format++; + const char* str = va_arg(parameters, const char*); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } else { + format = format_begun_at; + size_t len = strlen(format); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(format, len)) + return -1; + written += len; + format += len; + } + } + + va_end(parameters); + return written; +} \ No newline at end of file diff --git a/kernel/std/putchar.c b/kernel/std/putchar.c new file mode 100644 index 0000000..f0f5783 --- /dev/null +++ b/kernel/std/putchar.c @@ -0,0 +1,11 @@ +#include + +//#include +#include + +int putchar(int ic) { + char c = (char) ic; + serial_putchar(c); + //terminal_write(&c, sizeof(c)); + return ic; +} \ No newline at end of file diff --git a/kernel/std/puts.c b/kernel/std/puts.c new file mode 100644 index 0000000..8c8c036 --- /dev/null +++ b/kernel/std/puts.c @@ -0,0 +1,5 @@ +#include + +int puts(const char* string) { + return printf("%s\n", string); +} \ No newline at end of file diff --git a/kernel/std/strlen.c b/kernel/std/strlen.c new file mode 100644 index 0000000..441622a --- /dev/null +++ b/kernel/std/strlen.c @@ -0,0 +1,9 @@ +#include + +size_t strlen(const char* str) { + size_t len = 0; + while (str[len]) { + ++len; + } + return len; +} \ No newline at end of file -- cgit v1.2.3-70-g09d2