feat: hello, world!

This commit is contained in:
Jordan ⌨️ 2023-12-10 20:31:11 +01:00
parent c1da9bc218
commit 14ab06110b
26 changed files with 639 additions and 9 deletions

View file

@ -2,21 +2,24 @@
-Wall
-Wextra
-Werror
-D__ck_loader_limine__
-Isrc/libs
-Isrc/kernel/klibs
-Isrc/kernel/archs
-D__ck_toolchain_value=clang
-D__ck_encoding_utf8__
-D__ck_sys_kernel__
-D__ck_freestanding__
-D__ck_loader_value=limine
-D__ck_encoding_value=utf8
-D__ck_arch_x86_64__
-D__ck_bits_64__
-D__ck_toolchain_clang__
-D__ck_bits_value=64
-D__ck_abi_sysv__
-D__ck_abi_value=sysv
-D__ck_sys_value=kernel
-D__ck_loader_limine__
-D__ck_sys_kernel__
-D__ck_encoding_utf8__
-D__ck_abi_sysv__
-D__ck_freestanding__
-D__ck_arch_value=x86_64
-D__ck_bits_64__
-D__ck_bits_value=64
-D__ck_arch_x86_64__
-ffreestanding
-fno-stack-protector
-mno-80387
@ -26,3 +29,4 @@
-mno-sse2
-mno-red-zone
-Dauto=__auto_type
-Isrc/kernel/klibs

19
src/kernel/archs/hal.h Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include <io/stream.h>
void hal_setup(void);
/* --- Assembly function --------------------------------------------------- */
void hal_disable_interrupts(void);
void hal_enable_interrupts(void);
void hal_pause(void);
void hal_panic(void);
/* --- I/O ---------------------------------------------------------------- */
Stream hal_dbg_stream(void);

View file

@ -0,0 +1,19 @@
void hal_disable_interrupts(void)
{
asm volatile("cli");
}
void hal_enable_interrupts(void)
{
asm volatile("sti");
}
void hal_pause(void)
{
asm volatile("pause");
}
void hal_panic(void)
{
asm volatile("int $1");
}

View file

@ -0,0 +1,19 @@
#include <res.h>
#include "e9.h"
Res e9_putc(char c)
{
asm volatile("outb %0, $0xe9" : : "a"(c) : "memory");
return ok$();
}
Res e9_puts(size_t n, char const *s)
{
for (size_t i = 0; i < n; i++)
{
e9_putc(s[i]);
}
return ok$();
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <res.h>
Res e9_putc(char c);
Res e9_puts(size_t n, char const *s);

View file

@ -0,0 +1,16 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "arch (x86_64)",
"enableIf": {
"arch": [
"x86_64"
]
},
"provides": [
"arch"
],
"requires": [
"dbg"
]
}

View file

@ -0,0 +1,14 @@
#include <io/stream.h>
#include "e9.h"
Stream hal_dbg_stream(void)
{
return (Stream){
.write = e9_puts,
};
}
void hal_setup(void)
{
}

View file

@ -1,5 +1,8 @@
#include <dbg/log.h>
_Noreturn int _start()
{
log$("Hello, world!");
for (;;)
;
}

View file

@ -1,5 +1,17 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "exe",
"id": "core"
"id": "core",
"requires": [
"arch",
"dbg",
"stdc-shim"
],
"tools": {
"cc": {
"args": [
"-Isrc/kernel/klibs"
]
}
}
}

View file

@ -0,0 +1,46 @@
#include <fmt/fmt.h>
#include <hal.h>
#include <stdarg.h>
#include <sync/spinlock.h>
#include "log.h"
static Spinlock _lock = SPINLOCK_INIT;
static char const *level_names[LOG_EVENT_LENGTH] = {
[LOG_NONE] = "",
[LOG_INFO] = "INFO",
[LOG_WARN] = "WARN",
[LOG_ERROR] = "ERROR",
[LOG_CRIT] = "CRITIC",
};
static char const *level_colors[LOG_EVENT_LENGTH] = {
[LOG_NONE] = "",
[LOG_INFO] = "\e[1;34m",
[LOG_WARN] = "\e[1;33m",
[LOG_ERROR] = "\e[1;31m",
[LOG_CRIT] = "\e[1;35m",
};
void _log(LogEvent event, Loc loc, char const *format, ...)
{
spinlock_acquire(&_lock);
va_list args;
va_start(args, format);
if (event != LOG_NONE)
{
fmt(hal_dbg_stream(), "%s%s\e[0m %s:%d ", level_colors[event], level_names[event], loc.file, loc.line);
}
vfmt(hal_dbg_stream(), format, args);
if (event != LOG_NONE)
{
hal_dbg_stream().write(1, "\n");
}
va_end(args);
spinlock_release(&_lock);
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <io/stream.h>
#include "loc.h"
typedef enum
{
LOG_NONE,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_CRIT,
LOG_EVENT_LENGTH
} LogEvent;
#define log$(...) _log(LOG_INFO, loc$(), __VA_ARGS__)
#define warn$(...) _log(LOG_WARN, loc$(), __VA_ARGS__)
#define error$(...) _log(LOG_ERROR, loc$(), __VA_ARGS__)
#define critical$(...) _log(LOG_CRIT, loc$(), __VA_ARGS__)
#define print$(...) _log(LOG_NONE, (Loc){}, __VA_ARGS__)
void _log(LogEvent event, Loc loc, char const *format, ...);

View file

@ -0,0 +1,14 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "dbg",
"enableIf": {
"freestanding": [
true
]
},
"requires": [
"sync",
"fmt"
]
}

View file

@ -0,0 +1,13 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "stdc-shim",
"props": {
"cpp-root-include": true
},
"enableIf": {
"freestanding": [
true
]
}
}

View file

@ -0,0 +1,51 @@
#include "string.h"
size_t strlen(char const str[static 1])
{
size_t len = 0;
while (*str++)
{
len++;
}
return len;
}
void *memcpy(void *restrict dst, void const *restrict src, size_t n)
{
char *restrict d = dst;
char const *restrict s = src;
while (n--)
{
*d++ = *s++;
}
return dst;
}
void *memset(void *dest, int c, size_t n)
{
char *d = dest;
while (n--)
{
*d++ = c;
}
return dest;
}
int memcmp(const void *s1, const void *s2, size_t n)
{
for (size_t i = 0; i < n; i++)
{
if (((const char *)s1)[i] != ((const char *)s2)[i])
{
return ((const char *)s1)[i] - ((const char *)s2)[i];
}
}
return 0;
}

View file

@ -0,0 +1,11 @@
#pragma once
#include <stddef.h>
size_t strlen(char const s[static 1]);
void *memcpy(void *restrict dest, void const *restrict src, size_t n);
void *memset(void *dest, int c, size_t n);
int memcmp(void const *s1, void const *s2, size_t n);

View file

@ -0,0 +1,10 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "sync",
"enableIf": {
"freestanding": [
true
]
}
}

View file

@ -0,0 +1,30 @@
#include <hal.h>
#include "spinlock.h"
static _Atomic int retain_count = 0;
static void retain_interrupts(void)
{
retain_count++;
}
static void release_interrupt(void)
{
retain_count--;
}
void spinlock_acquire(Spinlock spinlock[static 1])
{
retain_interrupts();
while (atomic_flag_test_and_set(&spinlock->lock))
{
hal_pause();
}
}
void spinlock_release(Spinlock spinlock[static 1])
{
atomic_flag_clear(&spinlock->lock);
release_interrupt();
}

View file

@ -0,0 +1,17 @@
#pragma once
#include <stdatomic.h>
typedef struct
{
volatile atomic_flag lock;
} Spinlock;
#define SPINLOCK_INIT \
(Spinlock) { .lock = ATOMIC_FLAG_INIT }
Spinlock spinlock_new(void);
void spinlock_acquire(Spinlock spinlock[static 1]);
void spinlock_release(Spinlock spinlock[static 1]);

191
src/libs/fmt/fmt.c Normal file
View file

@ -0,0 +1,191 @@
#include <stdint.h>
#include <string.h>
#include "fmt.h"
static char *strrev(char *str)
{
int start;
int end;
char tmp;
end = strlen(str) - 1;
start = 0;
while (start < end)
{
tmp = str[start];
str[start] = str[end];
str[end] = tmp;
start++;
end--;
}
return str;
}
static char *itoa(int64_t value, char *str, int base)
{
int i = 0;
bool isNegative = false;
if (value == 0)
{
str[i++] = '0';
str[i] = '\0';
return str;
}
if (value < 0 && base == 10)
{
isNegative = true;
value = -value;
}
while (value != 0)
{
int rem = value % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
value = value / base;
}
if (isNegative)
{
str[i++] = '-';
}
str[i] = '\0';
return strrev(str);
}
char *utoa(uint64_t value, char *str, int base)
{
int i = 0;
if (value == 0)
{
str[i++] = '0';
str[i] = '\0';
return str;
}
while (value != 0)
{
int rem = value % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
value = value / base;
}
str[i] = '\0';
return strrev(str);
}
Res fmt(Stream stream, char const fmt[static 1], ...)
{
va_list args;
va_start(args, fmt);
Res res = vfmt(stream, fmt, args);
va_end(args);
return res;
}
Res vfmt(Stream stream, char const fmt[static 1], va_list args)
{
const char *s = fmt;
while (*s)
{
if (*s == '%')
{
switch (*++s)
{
case 'd':
{
s++;
char buf[100];
int64_t value = va_arg(args, int64_t);
itoa(value, buf, 10);
stream.write(strlen(buf), buf);
break;
}
case 'u':
{
s++;
char buf[100];
uint64_t value = va_arg(args, int64_t);
utoa(value, buf, 10);
stream.write(strlen(buf), buf);
break;
}
case 'p':
{
s++;
char buf[100];
uint64_t value = va_arg(args, uint64_t);
utoa(value, buf, 16);
stream.write(2, "0x");
for (size_t i = 0; i < 16 - strlen(buf); i++)
{
stream.write(1, "0");
}
stream.write(strlen(buf), buf);
break;
}
case 'x':
{
s++;
char buf[100];
uint64_t value = va_arg(args, uint64_t);
utoa(value, buf, 16);
stream.write(strlen(buf), buf);
break;
}
case 's':
{
s++;
char *value = va_arg(args, char *);
stream.write(strlen(value), value);
break;
}
case 'c':
{
s++;
char value = va_arg(args, int);
stream.write(1, &value);
break;
}
case '%':
{
s++;
stream.write(1, "%");
break;
}
default:
{
return err$(RES_INVAL);
}
}
}
else
{
char sub[2] = {*s++, '\0'};
stream.write(1, sub);
}
}
return uok$(0);
}

8
src/libs/fmt/fmt.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include <io/stream.h>
#include <res.h>
#include <stdarg.h>
Res fmt(Stream stream, char const fmt[static 1], ...);
Res vfmt(Stream stream, char const fmt[static 1], va_list args);

View file

@ -0,0 +1,5 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "fmt"
}

View file

@ -0,0 +1,5 @@
{
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
"type": "lib",
"id": "io"
}

9
src/libs/io/stream.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#include "res.h"
typedef struct
{
Res (*write)(size_t n, char const buf[static n]);
Res (*read)(size_t n, char buf[static n]);
} Stream;

18
src/libs/loc.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include <stddef.h>
typedef struct
{
char const *file;
const char *full;
const char *func;
size_t line;
} Loc;
#define loc$() ((Loc){ \
.file = __FILE_NAME__, \
.full = __FILE__, \
.func = __func__, \
.line = __LINE__, \
})

56
src/libs/res.h Normal file
View file

@ -0,0 +1,56 @@
#pragma once
#include <stddef.h>
#include "loc.h"
#include "utils.h"
#define RES_TYPE(F) \
F(RES_OK) \
F(RES_INVAL) \
F(RES_NOMEM) \
F(RES_BADALIGN) \
F(RES_NOENT)
enum res_type
{
RES_TYPE(make_enum$)
};
static char const *res_type_str[] = {RES_TYPE(make_str$)};
typedef struct
{
enum res_type type;
Loc loc;
union
{
size_t uvalue;
ptrdiff_t ivalue;
};
} Res;
#define ok$() \
(Res) { .type = RES_OK, .uvalue = 0, .loc = loc$() }
#define uok$(u) \
(Res) { .type = RES_OK, .uvalue = (u), .loc = loc$() }
#define iok$(i) \
(Res) { .type = RES_OK, .ivalue = (i), .loc = loc$() }
#define err$(t) \
(Res) { .type = (t), .uvalue = 0, .loc = loc$() }
#define try$(EXPR) \
({ \
Res __result = (Res)(EXPR); \
if (__result.type != RES_OK) \
return __result; \
__result.ivalue; \
})
static inline char const *res_to_str(Res res)
{
return res_type_str[res.type];
}

9
src/libs/utils.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#define max$(a, b) (((a) > (b)) ? (a) : (b))
#define min$(a, b) (((a) < (b)) ? (a) : (b))
#define make_enum$(enum) enum,
#define make_str$(str) #str,