initial kernel
This commit is contained in:
107
yak-kernel/main.c
Normal file
107
yak-kernel/main.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <limine.h>
|
||||
|
||||
// The Limine requests can be placed anywhere, but it is important that
|
||||
// the compiler does not optimise them away, so, usually, they should
|
||||
// be made volatile or equivalent.
|
||||
|
||||
static volatile struct limine_terminal_request terminal_request = {
|
||||
.id = LIMINE_TERMINAL_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
// GCC and Clang reserve the right to generate calls to the following
|
||||
// 4 functions even if they are not directly called.
|
||||
// Implement them as the C specification mandates.
|
||||
// DO NOT remove or rename these functions, or stuff will eventually break!
|
||||
// They CAN be moved to a different .c file.
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n) {
|
||||
uint8_t *pdest = (uint8_t *) dest;
|
||||
const uint8_t *psrc = (const uint8_t *) src;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
uint8_t *p = (uint8_t *) s;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
p[i] = (uint8_t) c;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
uint8_t *pdest = (uint8_t *) dest;
|
||||
const uint8_t *psrc = (const uint8_t *) src;
|
||||
|
||||
if (src > dest) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
} else if (src < dest) {
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
pdest[i - 1] = psrc[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
const uint8_t *p1 = (const uint8_t *) s1;
|
||||
const uint8_t *p2 = (const uint8_t *) s2;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (p1[i] != p2[i]) {
|
||||
return p1[i] < p2[i] ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Our quick and dirty strlen() implementation.
|
||||
size_t strlen(const char *str) {
|
||||
size_t ret = 0;
|
||||
while (*str++) {
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Halt and catch fire function.
|
||||
static void hcf(void) {
|
||||
__asm__ ("cli");
|
||||
for (;;) {
|
||||
__asm__ ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
// The following will be our kernel's entry point.
|
||||
// If renaming _start() to something else, make sure to change the
|
||||
// linker script accordingly.
|
||||
void _start(void) {
|
||||
// Ensure we got a terminal
|
||||
if (terminal_request.response == NULL
|
||||
|| terminal_request.response->terminal_count < 1) {
|
||||
hcf();
|
||||
}
|
||||
|
||||
// We should now be able to call the Limine terminal to print out
|
||||
// a simple "Hello World" to screen.
|
||||
const char *hello_msg = "Hello World";
|
||||
|
||||
struct limine_terminal *terminal = terminal_request.response->terminals[0];
|
||||
terminal_request.response->write(terminal, hello_msg, strlen(hello_msg));
|
||||
|
||||
// We're done, just hang...
|
||||
hcf();
|
||||
}
|
||||
Reference in New Issue
Block a user