summaryrefslogtreecommitdiff
path: root/kernel/libc
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-30 22:12:14 +0100
committerAnton Kling <anton@kling.gg>2023-10-31 00:18:38 +0100
commit8a9208612eec8ddae4c418485d848ecfa0613699 (patch)
tree2f4b29200c2f0c19ae52f45bdb9b38a41b356e30 /kernel/libc
parentca76600acc8bf7a02346efa5bd8f17072210ec01 (diff)
Meta: Move kernel and userland to their own folders.
This is to allow both the kernel and the userland to share certain header files and to make the folder structure a bit more clear.
Diffstat (limited to 'kernel/libc')
-rw-r--r--kernel/libc/exit/assert.c12
-rw-r--r--kernel/libc/include/assert.h19
-rw-r--r--kernel/libc/include/errno.h85
-rw-r--r--kernel/libc/include/limits.h1
-rw-r--r--kernel/libc/include/stdio.h9
-rw-r--r--kernel/libc/include/stdlib.h0
-rw-r--r--kernel/libc/include/string.h19
-rw-r--r--kernel/libc/include/time.h6
-rw-r--r--kernel/libc/include/types.h27
-rw-r--r--kernel/libc/stdio/print.c97
-rw-r--r--kernel/libc/string/copy.c26
-rw-r--r--kernel/libc/string/isequal.c15
-rw-r--r--kernel/libc/string/memcmp.c12
-rw-r--r--kernel/libc/string/memcpy.c20
-rw-r--r--kernel/libc/string/memset.c9
-rw-r--r--kernel/libc/string/strcat.c6
-rw-r--r--kernel/libc/string/strcmp.c8
-rw-r--r--kernel/libc/string/strcpy.c8
-rw-r--r--kernel/libc/string/strlcpy.c21
-rw-r--r--kernel/libc/string/strlen.c8
-rw-r--r--kernel/libc/string/strncpy.c11
21 files changed, 419 insertions, 0 deletions
diff --git a/kernel/libc/exit/assert.c b/kernel/libc/exit/assert.c
new file mode 100644
index 0000000..b48773a
--- /dev/null
+++ b/kernel/libc/exit/assert.c
@@ -0,0 +1,12 @@
+#include <assert.h>
+#include <log.h>
+#include <stdio.h>
+#include <log.h>
+
+void aFailed(char *f, int l) {
+ kprintf("Assert failed\n");
+ kprintf("%s : %d\n", f, l);
+ dump_backtrace(10);
+ for (;;)
+ ;
+}
diff --git a/kernel/libc/include/assert.h b/kernel/libc/include/assert.h
new file mode 100644
index 0000000..90a0be4
--- /dev/null
+++ b/kernel/libc/include/assert.h
@@ -0,0 +1,19 @@
+#include <log.h>
+#include <stdio.h>
+
+#define assert(expr) \
+ { \
+ if (!(expr)) \
+ aFailed(__FILE__, __LINE__); \
+ }
+
+#define ASSERT_BUT_FIXME_PROPOGATE(expr) \
+ { \
+ if (!(expr)) \
+ kprintf("Performing assert that should have been a propogated error."); \
+ assert(expr); \
+ }
+
+void aFailed(char *f, int l);
+#define ASSERT_NOT_REACHED \
+ { assert(0) }
diff --git a/kernel/libc/include/errno.h b/kernel/libc/include/errno.h
new file mode 100644
index 0000000..1ad1004
--- /dev/null
+++ b/kernel/libc/include/errno.h
@@ -0,0 +1,85 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+#define E2BIG 1 // Argument list too long.
+#define EACCES 2 // Permission denied.
+#define EADDRINUSE 3 // Address in use.
+#define EADDRNOTAVAIL 4 // Address not available.
+#define EAFNOSUPPORT 5 // Address family not supported.
+#define EAGAIN 6 // Resource unavailable, try again.
+#define EALREADY 7 // Connection already in progress.
+#define EBADF 8 // Bad file descriptor.
+#define EBADMSG 9 // Bad message.
+#define EBUSY 10 // Device or resource busy.
+#define ECANCELED 11 // Operation canceled.
+#define ECHILD 12 // No child processes.
+#define ECONNABORTED 13 // Connection aborted.
+#define ECONNREFUSED 14 // Connection refused.
+#define ECONNRESET 15 // Connection reset.
+#define EDEADLK 16 // Resource deadlock would occur.
+#define EDESTADDRREQ 17 // Destination address required.
+#define EDOM 18 // Mathematics argument out of domain of function.
+#define EDQUOT 19 // Reserved.
+#define EEXIST 20 // File exists.
+#define EFAULT 21 // Bad address.
+#define EFBIG 22 // File too large.
+#define EHOSTUNREACH 23 // Host is unreachable.
+#define EIDRM 24 // Identifier removed.
+#define EILSEQ 25 // Illegal byte sequence.
+#define EINPROGRESS 26 // Operation in progress.
+#define EINTR 27 // Interrupted function.
+#define EINVAL 28 // Invalid argument.
+#define EIO 29 // I/O error.
+#define EISCONN 30 // Socket is connected.
+#define EISDIR 31 // Is a directory.
+#define ELOOP 32 // Too many levels of symbolic links.
+#define EMFILE 33 // File descriptor value too large.
+#define EMLINK 34 // Too many links.
+#define EMSGSIZE 35 // Message too large.
+#define EMULTIHOP 36 // Reserved.
+#define ENAMETOOLONG 37 // Filename too long.
+#define ENETDOWN 38 // Network is down.
+#define ENETRESET 39 // Connection aborted by network.
+#define ENETUNREACH 40 // Network unreachable.
+#define ENFILE 41 // Too many files open in system.
+#define ENOBUFS 42 // No buffer space available.
+#define ENODATA 43 // No message is available on the STREAM head read queue.
+#define ENODEV 44 // No such device.
+#define ENOENT 45 // No such file or directory.
+#define ENOEXEC 46 // Executable file format error.
+#define ENOLCK 47 // No locks available.
+#define ENOLINK 48 // Reserved.
+#define ENOMEM 49 // Not enough space.
+#define ENOMSG 50 // No message of the desired type.
+#define ENOPROTOOPT 51 // Protocol not available.
+#define ENOSPC 52 // No space left on device.
+#define ENOSR 53 // No STREAM resources.
+#define ENOSTR 54 // Not a STREAM.
+#define ENOSYS 55 // Functionality not supported.
+#define ENOTCONN 56 // The socket is not connected.
+#define ENOTDIR 57 // Not a directory or a symbolic link to a directory.
+#define ENOTEMPTY 58 // Directory not empty.
+#define ENOTRECOVERABLE 59 // State not recoverable.
+#define ENOTSOCK 60 // Not a socket.
+#define ENOTSUP 61 // Not supported (may be the same value as.
+#define ENOTTY 62 // Inappropriate I/O control operation.
+#define ENXIO 63 // No such device or address.
+#define EOPNOTSUPP ENOTSUP // Operation not supported on socket.
+#define EOVERFLOW 65 // Value too large to be stored in data type.
+#define EOWNERDEAD 66 // Previous owner died.
+#define EPERM 67 // Operation not permitted.
+#define EPIPE 68 // Broken pipe.
+#define EPROTO 69 // Protocol error.
+#define EPROTONOSUPPORT 70 // Protocol not supported.
+#define EPROTOTYPE 71 // Protocol wrong type for socket.
+#define ERANGE 72 // Result too large.
+#define EROFS 73 // Read-only file system.
+#define ESPIPE 74 // Invalid seek.
+#define ESRCH 75 // No such process.
+#define ESTALE 76 // Reserved.
+#define ETIME 77 // Stream ioctl() timeout.
+#define ETIMEDOUT 78 // Connection timed out.
+#define ETXTBSY 79 // Text file busy.
+#define EWOULDBLOCK EAGAIN // Operation would block.
+#define EXDEV 81 // Cross-device link.
+#endif
diff --git a/kernel/libc/include/limits.h b/kernel/libc/include/limits.h
new file mode 100644
index 0000000..05022ec
--- /dev/null
+++ b/kernel/libc/include/limits.h
@@ -0,0 +1 @@
+#define PATH_MAX 256
diff --git a/kernel/libc/include/stdio.h b/kernel/libc/include/stdio.h
new file mode 100644
index 0000000..f2bbb32
--- /dev/null
+++ b/kernel/libc/include/stdio.h
@@ -0,0 +1,9 @@
+#ifndef STDIO_H
+#define STDIO_H
+
+void putc(const char c);
+int puts(char *str);
+void delete_characther(void);
+int kprintf(const char *format, ...);
+
+#endif
diff --git a/kernel/libc/include/stdlib.h b/kernel/libc/include/stdlib.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kernel/libc/include/stdlib.h
diff --git a/kernel/libc/include/string.h b/kernel/libc/include/string.h
new file mode 100644
index 0000000..7cee4b2
--- /dev/null
+++ b/kernel/libc/include/string.h
@@ -0,0 +1,19 @@
+#ifndef STRING_H
+#define STRING_H
+#include <stddef.h>
+#include <stdint.h>
+
+unsigned long strlen(const char *s);
+void *memcpy(void *dest, const void *src, uint32_t n);
+void *memset(void *dst, const unsigned char c, uint32_t n);
+int memcmp(const void *s1, const void *s2, uint32_t n);
+char *strcpy(char *d, const char *s);
+int strcmp(const char *s1, const char *s2);
+int isequal(const char *s1, const char *s2);
+int isequal_n(const char *s1, const char *s2, uint32_t n);
+char *copy_and_allocate_string(const char *s);
+char *copy_and_allocate_user_string(const char *s);
+char *strncpy(char *dest, const char *src, size_t n);
+size_t strlcpy(char *dst, const char *src, size_t dsize);
+char *strcat(char *s1, const char *s2);
+#endif
diff --git a/kernel/libc/include/time.h b/kernel/libc/include/time.h
new file mode 100644
index 0000000..4e356d1
--- /dev/null
+++ b/kernel/libc/include/time.h
@@ -0,0 +1,6 @@
+#include <types.h>
+
+struct timespec {
+ time_t tv_sec; // Seconds.
+ long tv_nsec; // Nanoseconds.
+};
diff --git a/kernel/libc/include/types.h b/kernel/libc/include/types.h
new file mode 100644
index 0000000..ffcf281
--- /dev/null
+++ b/kernel/libc/include/types.h
@@ -0,0 +1,27 @@
+#ifndef TYPES_H
+#define TYPES_H
+typedef unsigned int ino_t;
+
+typedef int mode_t;
+
+typedef int nlink_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int id_t;
+
+typedef int blkcnt_t;
+typedef int off_t;
+
+typedef int dev_t;
+typedef unsigned int fsblkcnt_t;
+typedef unsigned int fsfilcnt_t;
+typedef unsigned int ino_t;
+//typedef unsigned int size_t;
+
+typedef int blksize_t;
+typedef int pid_t;
+typedef int ssize_t;
+
+//typedef int clock_t;
+typedef int time_t;
+#endif
diff --git a/kernel/libc/stdio/print.c b/kernel/libc/stdio/print.c
new file mode 100644
index 0000000..8174983
--- /dev/null
+++ b/kernel/libc/stdio/print.c
@@ -0,0 +1,97 @@
+#include "../../drivers/serial.h"
+#include "../include/assert.h"
+#include "../include/stdio.h"
+#include <stdarg.h>
+
+#define TAB_SIZE 8
+
+const char HEX_SET[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+inline void putc(const char c) { write_serial(c); }
+
+int kprint_hex(uint64_t num) {
+ int c = 2;
+
+ if (num == 0) {
+ putc('0');
+ c++;
+ return c;
+ }
+
+ char str[16] = {0};
+ int i = 0;
+ for (; num != 0 && i < 16; i++, num /= 16)
+ str[i] = HEX_SET[(num % 16)];
+
+ c += i;
+ for (i--; i >= 0; i--)
+ putc(str[i]);
+
+ return c;
+}
+
+int kprint_int(int num) {
+ int c = 0;
+ if (0 == num) {
+ putc('0');
+ c++;
+ return c;
+ }
+ char str[10];
+ int i = 0;
+ for (; num != 0 && i < 10; i++, num /= 10)
+ str[i] = (num % 10) + '0';
+
+ c += i;
+ for (i--; i >= 0; i--)
+ putc(str[i]);
+ return c;
+}
+
+int kprintf(const char *format, ...) {
+ int c = 0;
+ va_list list;
+ va_start(list, format);
+
+ const char *s = format;
+ for (; *s; s++) {
+ if ('%' != *s) {
+ putc(*s);
+ c++;
+ continue;
+ }
+
+ char flag = *(s + 1);
+ if ('\0' == flag)
+ break;
+
+ switch (flag) {
+ case 'c':
+ putc((char)va_arg(list, int));
+ c++;
+ break;
+ case 'd':
+ c += kprint_int(va_arg(list, int));
+ break;
+ case 's':
+ for (char *string = va_arg(list, char *); *string; putc(*string++), c++)
+ ;
+ break;
+ case 'x':
+ c += kprint_hex(va_arg(list, const uint32_t));
+ break;
+ case '%':
+ putc('%');
+ c++;
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+ s++;
+ }
+ return c;
+}
+
+int puts(char *str) { return kprintf("%s\n", str); }
diff --git a/kernel/libc/string/copy.c b/kernel/libc/string/copy.c
new file mode 100644
index 0000000..277c808
--- /dev/null
+++ b/kernel/libc/string/copy.c
@@ -0,0 +1,26 @@
+#include <assert.h>
+#include <kmalloc.h>
+#include <stddef.h>
+#include <string.h>
+
+char *copy_and_allocate_string(const char *s) {
+ size_t l = strlen(s);
+ char *r = kmalloc(l + 1);
+ if (!r)
+ return NULL;
+ return strncpy(r, s, l);
+}
+
+char *copy_and_allocate_user_string(const char *s) {
+ size_t len;
+ if (!is_valid_user_c_string(s, &len))
+ return NULL;
+ size_t real_len = strlen(s);
+ assert(real_len == len);
+ len = real_len;
+ char *r = kmalloc(len + 1);
+ if (!r)
+ return NULL;
+ strlcpy(r, s, len);
+ return r;
+}
diff --git a/kernel/libc/string/isequal.c b/kernel/libc/string/isequal.c
new file mode 100644
index 0000000..cdbd3cc
--- /dev/null
+++ b/kernel/libc/string/isequal.c
@@ -0,0 +1,15 @@
+#include "../include/string.h"
+
+int isequal(const char *s1, const char *s2) {
+ for(;*s1;s1++,s2++)
+ if(*s1 != *s2)
+ return 0;
+ return 1;
+}
+
+int isequal_n(const char *s1, const char *s2, uint32_t n) {
+ for(;*s1 && n;s1++,s2++,n--)
+ if(*s1 != *s2)
+ return 0;
+ return 1;
+}
diff --git a/kernel/libc/string/memcmp.c b/kernel/libc/string/memcmp.c
new file mode 100644
index 0000000..72c680a
--- /dev/null
+++ b/kernel/libc/string/memcmp.c
@@ -0,0 +1,12 @@
+#include "../include/string.h"
+
+int memcmp(const void *s1, const void *s2, uint32_t n)
+{
+ int return_value = 0;
+
+ for(uint32_t i = 0;i < n;i++)
+ if(((unsigned char *)(s1))[i] != ((unsigned char *)(s2))[i])
+ return_value++;
+
+ return return_value;
+}
diff --git a/kernel/libc/string/memcpy.c b/kernel/libc/string/memcpy.c
new file mode 100644
index 0000000..5c04407
--- /dev/null
+++ b/kernel/libc/string/memcpy.c
@@ -0,0 +1,20 @@
+#include "../include/string.h"
+
+void *
+memcpy(void *dest, const void *src, uint32_t n) {
+ unsigned char *d = dest;
+ const unsigned char *s = src;
+
+ for (; n >= 8; n -= 8, d += 8, s += 8)
+ *(uint64_t *)d = *(uint64_t *)s;
+
+ for (; n >= 4; n -= 4, d += 4, s += 4)
+ *(uint32_t *)d = *(uint32_t *)s;
+
+ for (; n >= 2; n -= 2, d += 2, s += 2)
+ *(uint16_t *)d = *(uint16_t *)s;
+
+ for (; n; n--)
+ *d++ = *s++;
+ return dest;
+}
diff --git a/kernel/libc/string/memset.c b/kernel/libc/string/memset.c
new file mode 100644
index 0000000..a446eb4
--- /dev/null
+++ b/kernel/libc/string/memset.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+void *memset(void *dst, const unsigned char c, uint32_t n) {
+ uintptr_t d = (uintptr_t)dst;
+ for (uint32_t i = 0; i < n; i++, d++)
+ *(unsigned char *)d = c;
+
+ return (void *)d;
+}
diff --git a/kernel/libc/string/strcat.c b/kernel/libc/string/strcat.c
new file mode 100644
index 0000000..78a9ec6
--- /dev/null
+++ b/kernel/libc/string/strcat.c
@@ -0,0 +1,6 @@
+#include <string.h>
+
+char *strcat(char *s1, const char *s2) {
+ strcpy(s1 + strlen(s1), s2);
+ return s1;
+}
diff --git a/kernel/libc/string/strcmp.c b/kernel/libc/string/strcmp.c
new file mode 100644
index 0000000..d7039e2
--- /dev/null
+++ b/kernel/libc/string/strcmp.c
@@ -0,0 +1,8 @@
+#include "../include/string.h"
+
+int strcmp(const char *s1, const char *s2)
+{
+ for(;*s1 == *s2 && *s1; s1++, s2++)
+ ;
+ return *s1 - *s2;
+}
diff --git a/kernel/libc/string/strcpy.c b/kernel/libc/string/strcpy.c
new file mode 100644
index 0000000..fa1e336
--- /dev/null
+++ b/kernel/libc/string/strcpy.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+char *strcpy(char *d, const char *s) {
+ char *s1 = d;
+ for (; (*d++ = *s++);)
+ ;
+ return s1;
+}
diff --git a/kernel/libc/string/strlcpy.c b/kernel/libc/string/strlcpy.c
new file mode 100644
index 0000000..43d0e58
--- /dev/null
+++ b/kernel/libc/string/strlcpy.c
@@ -0,0 +1,21 @@
+#include <stddef.h>
+#include <string.h>
+
+// Copy string src to buffer dst of size dsize. At most dsize-1
+// chars will be copied. Always NUL terminates (unless dsize == 0).
+// Returns strlen(src); if retval >= dsize, truncation occurred.
+size_t strlcpy(char *dst, const char *src, size_t dsize) {
+ size_t n = dsize;
+ const char *osrc = src;
+ for (; n; n--) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ if (n == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+ return src - osrc - 1;
+}
diff --git a/kernel/libc/string/strlen.c b/kernel/libc/string/strlen.c
new file mode 100644
index 0000000..4346383
--- /dev/null
+++ b/kernel/libc/string/strlen.c
@@ -0,0 +1,8 @@
+#include "../include/string.h"
+
+unsigned long strlen(const char *s)
+{
+ const char * tmp = s;
+ for(;*tmp++;);
+ return (tmp - s)-1;
+}
diff --git a/kernel/libc/string/strncpy.c b/kernel/libc/string/strncpy.c
new file mode 100644
index 0000000..a886895
--- /dev/null
+++ b/kernel/libc/string/strncpy.c
@@ -0,0 +1,11 @@
+#include <stddef.h>
+#include <string.h>
+
+// FIXME: Something is weird with this function
+char *strncpy(char *dest, const char *src, size_t n) {
+ char *r = dest;
+ for (; n && (*dest = *src); n--, src++, dest++)
+ ;
+ *dest = '\0';
+ return r;
+}