#include #include #include // 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(); }