Skip to content

Instantly share code, notes, and snippets.

@Andrej123456789
Created March 17, 2023 19:28
Show Gist options
  • Save Andrej123456789/32af2686f5cbe6335af6e7503fb53c48 to your computer and use it in GitHub Desktop.
Save Andrej123456789/32af2686f5cbe6335af6e7503fb53c48 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "limine.h"
#include "kernel/kernel.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
};
static volatile struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0
};
static volatile struct limine_rsdp_request rsdp_request = {
.id = LIMINE_RSDP_REQUEST,
.revision = 0
};
static volatile struct limine_module_request module_request = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0
};
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0
};
// #define LIMINE_5_LEVEL_PAGING_REQUEST { LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888}
// static volatile limine_5_level_paging_request paging_request = {
// .id = LIMINE_5_LEVEL_PAGING_REQUEST,
// .revision = 0
// };
//#define LIMINE_ENTRY_POINT_REQUEST { LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a }
// extern "C" void _start(void);
// static volatile limine_entry_point_request entry_request = {
// .id = LIMINE_ENTRY_POINT_REQUEST,
// .revision = 0,
// .entry = _start
// };
struct limine_kernel_address_request kernel_address_request = {
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
.revision = 0, .response = NULL
};
// 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");
}
}
bool checkStringEndsWith(const char *str, const char *end)
{
const char *_str = str;
const char *_end = end;
while (*str != 0)
str++;
str--;
while (*end != 0)
end++;
end--;
while (true)
{
if (*str != *end)
return false;
str--;
end--;
if (end == _end || (str == _str && end == _end))
return true;
if (str == _str)
return false;
}
return true;
}
struct limine_file *getFile(const char *name)
{
struct limine_module_response *module_response = module_request.response;
for (size_t i = 0; i < module_response->module_count; i++)
{
struct limine_file *f = module_response->modules[i];
if (checkStringEndsWith(f->path, name))
return f;
}
return NULL;
}
// 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));
struct Framebuffer fb;
{
struct limine_framebuffer *lFb = framebuffer_request.response->framebuffers[0];
fb.BaseAddress = lFb->address;
fb.Width = lFb->width;
fb.Height = lFb->height;
fb.PixelsPerScanLine = lFb->pitch / 4;
fb.BufferSize = lFb->height * lFb->pitch; // lFb->edid_size;
}
if (module_request.response == NULL)
{
asm ("hlt");
}
struct PSF1_FONT font;
{
const char *fName = "zap-light16.psf";
struct limine_file *file = getFile(fName);
if (file == NULL)
{
asm ("hlt");
}
font.psf1_Header = (struct PSF1_HEADER *)file->address;
if (font.psf1_Header->magic[0] != 0x36 || font.psf1_Header->magic[1] != 0x04)
{
asm ("hlt");
}
font.glyphBuffer = (void *)((uint64_t)file->address + sizeof(struct PSF1_HEADER));
}
main(fb, &font);
// We're done, just hang...
hcf();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment