diff options
author | Danny Holman <dholman@gymli.org> | 2024-05-27 13:53:52 -0500 |
---|---|---|
committer | Danny Holman <dholman@gymli.org> | 2024-05-27 13:53:52 -0500 |
commit | aaf7355c5ededfcdc877c7f2989fb1ba02dfb848 (patch) | |
tree | 0c4588650fe1fc1fa1af2972353a2bc920cf1e68 /libk | |
parent | 41cff28f5447b5f669db62ce2a73be98bc5bce37 (diff) |
libk: create a subset libc for kernel use
Create a subset of the C library for use inside the kernel.
Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to 'libk')
-rw-r--r-- | libk/io.c | 78 | ||||
-rw-r--r-- | libk/stack_protector.c | 11 | ||||
-rw-r--r-- | libk/string.c | 133 |
3 files changed, 222 insertions, 0 deletions
diff --git a/libk/io.c b/libk/io.c new file mode 100644 index 0000000..eedc171 --- /dev/null +++ b/libk/io.c @@ -0,0 +1,78 @@ +#include <libk/io.h> +#include <libk/string.h> +#include <kernel/video/framebuffer.h> +#include <kernel/tty/tty_vga.h> + +char* convert(unsigned int num, int base) { + static char rep[] = "0123456789ABCDEF"; + static char buffer[50]; + char *ptr; + + ptr = &buffer[49]; + *ptr = '\0'; + + do { + *--ptr = rep[num%base]; + num /= base; + } while (num != 0); + + return ptr; +} + +int vkprintf(const char *fmt, va_list args) { + char *s; + int i; + + char buffer[4096]; + memset(buffer, 0, 4096); + for (size_t n = 0; n < strlen(fmt); n++) { + if (fmt[n] != '%') { + buffer[strlen(buffer)] = fmt[n]; + continue; + } else { + n++; + } + + switch (fmt[n]) { + case 'c': + i = va_arg(args, int); + buffer[strlen(buffer)] = i; + break; + case 's': + s = va_arg(args, char*); + strcat(buffer, s); + break; + case 'd': + i = va_arg(args, int); + if (i < 0) { + i = -i; + strcat(buffer, "-"); + } + strcat(buffer, convert(i, 10)); + break; + case 'o': + i = va_arg(args, unsigned int); + strcat(buffer, convert(i, 10)); + break; + case 'x': + i = va_arg(args, unsigned int); + strcat(buffer, convert(i, 16)); + break; + } + } + //tty_write(buffer, strlen(buffer)); + fb_write(buffer, strlen(buffer)); + memset(buffer, 0, 4096); + return 0; +} + +int kprintf(const char *fmt, ...) { + va_list args; + int done; + + va_start(args, fmt); + done = vkprintf(fmt, args); + va_end(args); + + return done; +} diff --git a/libk/stack_protector.c b/libk/stack_protector.c new file mode 100644 index 0000000..78d0302 --- /dev/null +++ b/libk/stack_protector.c @@ -0,0 +1,11 @@ +#include <kernel/panic.h> +#include <stdint.h> +#include <stddef.h> + +#define STACK_CHK_GUARD 0x32E3429E + +uintptr_t __stack_chk_guard = STACK_CHK_GUARD; + +__attribute__((noreturn)) void __stack_chk_fail(void) { + panic("STACK SMASHING IN KERNEL ADDRESS SPACE"); +} diff --git a/libk/string.c b/libk/string.c new file mode 100644 index 0000000..be59397 --- /dev/null +++ b/libk/string.c @@ -0,0 +1,133 @@ +#include <libk/string.h> + +int memcmp(const void *str1, const void *str2, size_t n) { + unsigned char const *p1 = str1; + unsigned char const *p2 = str2; + int ret = 0; + + if (str1 == str2) + return 0; + + while (n > 0) { + if (*p1 != *p2) { + ret = (*p1 > *p2)?1:-1; + break; + } + n--; + p1++; + p2++; + } + return ret; +} + +void* memcpy(void* __restrict dest, const void* __restrict src, size_t n) { + if (dest == src) + return dest; + + unsigned char *pdest = dest; + unsigned char const *psrc = src; + for (size_t i = 0; i < n; i++) + pdest[i] = psrc[i]; + return dest; +} + +char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) { + for (size_t i = 0; i < n; i++) { + if (src[i] == '\0') + break; + dest[i] = src[i]; + } + return dest; +} + +char* strcpy(char* __restrict dest, const char* __restrict src) { + return (char*)memcpy(dest, src, strlen(src)); +} + +char* strcat(char* __restrict dest, const char* __restrict src) { + return (char*)memcpy(&dest[strlen(dest)], src, strlen(src)); +} + +char* strncat(char* __restrict dest, const char* __restrict src, size_t n) { + return (char*)memcpy(&dest[strlen(dest)], src, n); +} + +void* memmove(void* __restrict dest, const void* __restrict src, size_t n) { + if (dest == src) + return dest; + + unsigned char const *psrc = src; + unsigned char buffer[n]; + + for (size_t i = 0; i < n; i++) + buffer[i] = psrc[i]; + return memcpy(dest, (void*)buffer, n); +} + +void* memset(void *str, int c, size_t n) { + unsigned char *p = str; + for (size_t i = 0; i < n; i++) + p[i] = (unsigned char)c; + return str; +} + +int strncmp(const char *str1, const char *str2, size_t n) { + return memcmp(str1, str2, n); +} + +int strcmp(const char *str1, const char *str2) { + size_t str1_sz = strlen(str1); + size_t str2_sz = strlen(str2); + if (str1_sz > str2_sz) + return memcmp(str1, str2, str2_sz); + return memcmp(str1, str2, str1_sz); +} + +size_t strlen(const char *str) { + size_t i = 0; + while (str[i] != '\0') + i++; + return i; +} + +int _is_delim(char c, const char *delim) { + while (*delim != '\0') { + if (c == *delim) + return 1; + delim++; + } + return 0; +} + +char* strtok(char* __restrict str, const char* __restrict delim) { + static char *old_str; + + if (str == NULL) + str = old_str; + + while (1) { + if (_is_delim(*str, delim)) { + str++; + continue; + } + + if (*str == '\0') + return NULL; + break; + } + + char *ret = str; + while (1) { + if (*str == '\0') { + old_str = str; + return ret; + } + + if (_is_delim(*str, delim)) { + *str = '\0'; + old_str = str + 1; + return ret; + } + str++; + } +} |