diff --git a/src/kernel/hal/mod.h b/src/kernel/hal/mod.h index 4930024..5c3529f 100644 --- a/src/kernel/hal/mod.h +++ b/src/kernel/hal/mod.h @@ -11,3 +11,5 @@ Writer hal_writer(void); void hal_brkpoint(void); DTBNode* hal_dtb_root(void); + +size_t page_size(void); diff --git a/src/kernel/hal/rv32/boot.c b/src/kernel/hal/rv32/boot.c index 46f1573..e51dd46 100644 --- a/src/kernel/hal/rv32/boot.c +++ b/src/kernel/hal/rv32/boot.c @@ -1,17 +1,18 @@ #include +#include +#include #include #include #include -#include -#include +#include +#include #include "exception.h" -#include "mem.h" extern char __bss[], __bss_end[]; extern void kmain(void); -static uint8_t early_heap[kib$(20)]; +static uint8_t early_heap[kib$(32)]; static DTBNode* dtb_root = NULL; void rv32_start(__attribute__((unused)) size_t hartid, uintptr_t dtb) { @@ -20,7 +21,17 @@ void rv32_start(__attribute__((unused)) size_t hartid, uintptr_t dtb) { BumpAllocator alloc = bump_allocator_create((void*)early_heap, sizeof(early_heap)); dtb_root = dtb_init(dtb, &alloc.base); - mem_init(); + handover_init(dtb_root, &alloc.base); + handover_append(handover(), (HandoverRecord){ + .tag = HANDOVER_LOADER, + .start = (uintptr_t)early_heap, + .size = sizeof(early_heap), + }); + + for (size_t i = 0; i < handover()->count; i++) { + debug$("%s (start: %x, len: %x)", handover_tag_name(handover()->records[i].tag), handover()->records[i].start, handover()->records[i].size); + } + kmain(); } diff --git a/src/kernel/hal/rv32/hal.c b/src/kernel/hal/rv32/hal.c index 2bc6762..4ae210c 100644 --- a/src/kernel/hal/rv32/hal.c +++ b/src/kernel/hal/rv32/hal.c @@ -9,3 +9,7 @@ void hal_putc(int ch) { void hal_brkpoint(void) { __asm__ volatile("ebreak"); } + +size_t page_size(void) { + return 4096; +} diff --git a/src/kernel/hal/rv32/manifest.json b/src/kernel/hal/rv32/manifest.json index be6e981..348c2ad 100644 --- a/src/kernel/hal/rv32/manifest.json +++ b/src/kernel/hal/rv32/manifest.json @@ -7,5 +7,5 @@ "sys": ["kernel"] }, "provides": ["hal-impl"], - "requires": ["dtb"] + "requires": ["dtb", "pmm", "handover-dtb"] } diff --git a/src/kernel/hal/rv32/mem.c b/src/kernel/hal/rv32/mem.c deleted file mode 100644 index fed1c7a..0000000 --- a/src/kernel/hal/rv32/mem.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include - -#include "mem.h" - -void mem_init(void) { - DTBNode* root = hal_dtb_root(); - if (root == NULL) { - error$("No DTB found"); - hal_brkpoint(); - } - - DTBNode* mem = dtb_lookup(root, "memory"); - if (mem == NULL) { - error$("No memory node found in DTB"); - hal_brkpoint(); - } - - RegValue reg_val = dtb_lookup_reg(mem); - if (reg_val.len == 0) { - warn$("Memory node size is larger than 4GB. Defaulting to 4GB"); - reg_val.len = align_down$(gib$(4) - 1, 4096); - } - - debug$("Memory node found at %x with size %x", reg_val.addr, reg_val.len); - - DTBNode* reserved = dtb_lookup(root, "reserved-memory"); - if (reserved == NULL) { - error$("No reserved memory node found in DTB"); - hal_brkpoint(); - } - - DTBNode* child = reserved->children; - - while (child != NULL) { - RegValue reg = dtb_lookup_reg(child); - debug$("Reserved memory node with name %s found at %x with size %x", child->name, reg.addr, reg.len); - - child = child->next; - } -} diff --git a/src/kernel/hal/rv32/mem.h b/src/kernel/hal/rv32/mem.h deleted file mode 100644 index c73eda1..0000000 --- a/src/kernel/hal/rv32/mem.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void mem_init(void); diff --git a/src/kernel/libs/libc/stdio.h b/src/kernel/libs/libc/stdio.h index d3514f2..6df95d5 100644 --- a/src/kernel/libs/libc/stdio.h +++ b/src/kernel/libs/libc/stdio.h @@ -3,3 +3,8 @@ #include #define printf(...) _log(LOG_INFO, loc$(), __VA_ARGS__) + +#define fprintf(TYPE, ...) _log(TYPE, loc$(), __VA_ARGS__) + +#define stdio LOG_INFO +#define stderr LOG_ERROR diff --git a/src/kernel/pmm/manifest.json b/src/kernel/pmm/manifest.json new file mode 100644 index 0000000..93a8fb8 --- /dev/null +++ b/src/kernel/pmm/manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "pmm" +} diff --git a/src/kernel/pmm/mod.c b/src/kernel/pmm/mod.c new file mode 100644 index 0000000..e0038fe --- /dev/null +++ b/src/kernel/pmm/mod.c @@ -0,0 +1,14 @@ +#include "mod.h" +#include +#include + +Pmm* pmm = NULL; + +void pmm_init(size_t start, size_t len) { + (void)start; + (void)len; + if (pmm != NULL) { + error$("PMM already initialized"); + hal_brkpoint(); + } +} diff --git a/src/kernel/pmm/mod.h b/src/kernel/pmm/mod.h new file mode 100644 index 0000000..268c503 --- /dev/null +++ b/src/kernel/pmm/mod.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +typedef struct _Page { + struct _Page* next; + uintptr_t addr; +} Page; + +typedef struct { + size_t total_pages; + size_t free_pages; + Page* freelist; +} Pmm; + +void pmm_init(size_t start, size_t len); diff --git a/src/libs/handover/base/manifest.json b/src/libs/handover/base/manifest.json new file mode 100644 index 0000000..2f5bb4b --- /dev/null +++ b/src/libs/handover/base/manifest.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "handover" +} diff --git a/src/libs/handover/base/mod.c b/src/libs/handover/base/mod.c new file mode 100644 index 0000000..a1bb5f6 --- /dev/null +++ b/src/libs/handover/base/mod.c @@ -0,0 +1,158 @@ +#include +#include +#include + +#include "mod.h" + +char const* handover_tag_name(HandoverTag tag) { + switch (tag) { +#define TAG(NAME, VALUE) \ + case HANDOVER_##NAME: \ + return #NAME; + HANDOVER_TAGS(TAG) +#undef TAG + } + return "UNKNOWN"; +} + +bool handover_mergeable(uint32_t tag) { + switch (tag) { + case HANDOVER_FREE: + case HANDOVER_LOADER: + case HANDOVER_KERNEL: + case HANDOVER_RESERVED: + return true; + + default: + return false; + } +} + +bool handover_overlap(HandoverRecord lhs, HandoverRecord rhs) { + return lhs.start < rhs.start + rhs.size && rhs.start < lhs.start + lhs.size; +} + +bool handover_just_before(HandoverRecord lhs, HandoverRecord rhs) { + return lhs.start + lhs.size == rhs.start; +} + +bool handover_just_after(HandoverRecord lhs, HandoverRecord rhs) { + return lhs.start == rhs.start + rhs.size; +} + +HandoverRecord handover_half_under(HandoverRecord self, HandoverRecord other) { + if (handover_overlap(self, other) && + self.start < other.start) { + return (HandoverRecord){ + .tag = self.tag, + .flags = 0, + .start = self.start, + .size = other.start - self.start, + }; + } + + return (HandoverRecord){0}; +} + +HandoverRecord handover_half_over(HandoverRecord self, HandoverRecord other) { + if (handover_overlap(self, other) && + self.start + self.size > other.start + other.size) { + return (HandoverRecord){ + .tag = self.tag, + .flags = 0, + .start = other.start + other.size, + .size = self.start + self.size - other.start - other.size, + }; + } + + return (HandoverRecord){0}; +} + +void handover_insert(HandoverPayload* payload, size_t index, HandoverRecord record) { + for (size_t i = payload->count; i > index; i--) { + payload->records[i] = payload->records[i - 1]; + } + + payload->records[index] = record; + payload->count++; +} + +void handover_remove(HandoverPayload* payload, size_t index) { + for (size_t i = index; i < payload->count - 1; i++) { + payload->records[i] = payload->records[i + 1]; + } + + payload->count--; +} + +void handover_append(HandoverPayload* payload, HandoverRecord record) { + if (record.size == 0) { + return; + } + + for (size_t i = 0; i < payload->count; i++) { + HandoverRecord other = payload->records[i]; + + if (record.tag == other.tag && handover_just_after(record, other) && handover_mergeable(record.tag)) { + handover_remove(payload, i); + other.size += record.size; + handover_append(payload, other); + return; + } + + if (record.tag == other.tag && handover_just_before(record, other) && handover_mergeable(record.tag)) { + handover_remove(payload, i); + other.start -= record.size; + other.size += record.size; + handover_append(payload, other); + return; + } + + if (handover_overlap(record, other)) { + if ((handover_mergeable(record.tag) && !handover_mergeable(other.tag)) || other.tag == HANDOVER_FREE) { + handover_remove(payload, i); + + HandoverRecord lower = handover_half_under(other, record); + HandoverRecord upper = handover_half_over(other, record); + + handover_append(payload, record); + handover_append(payload, lower); + handover_append(payload, upper); + return; + } else if (!handover_mergeable(record.tag) && handover_mergeable(other.tag)) { + handover_remove(payload, i); + + HandoverRecord lower = handover_half_under(record, other); + HandoverRecord upper = handover_half_over(record, other); + + handover_append(payload, other); + handover_append(payload, lower); + handover_append(payload, upper); + return; + } else { + fprintf(stderr, "handover: record %s (start: %x, len: %x) collides with %s (start: %x, len: %x)\n", handover_tag_name(record.tag), record.start, record.size, handover_tag_name(other.tag), other.start, other.size); + abort(); + } + } + + if (record.start < other.start) { + handover_insert(payload, i, record); + return; + } + } + + payload->records[payload->count++] = record; +} + +char const* handover_str(HandoverPayload const* payload, uint32_t offset) { + return (char const*)payload + offset; +} + +size_t handover_add_string(HandoverPayload* handover, char const* str) { + size_t len = strlen(str) + 1; + size_t offset = handover->size - len; + memset((void*)((uintptr_t)handover + offset), 0, len); + memcpy((void*)((uintptr_t)handover + offset), str, len); + handover->size -= len; + return offset; +} diff --git a/src/libs/handover/base/mod.h b/src/libs/handover/base/mod.h new file mode 100644 index 0000000..cedc194 --- /dev/null +++ b/src/libs/handover/base/mod.h @@ -0,0 +1,159 @@ +#pragma once + +#include +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + +#ifdef __ck_bits_64__ +# define KERNEL_BASE 0xffffffff80000000; +# define UPPER_HALF 0xffff800000000000; +#else +# define KERNEL_BASE 0xc0000000; +# define UPPER_HALF 0xc0000000; +#endif //!__ck_bits_64__ + +#define HANDOVER_COOLBOOT 0xc001b001 +#define HANDOVER_SECTION ".handover" + +#define HANDOVER_TAGS(TAG) \ + TAG(FREE, 0x00000000) \ + TAG(MAGIC, HANDOVER_COOLBOOT) \ + TAG(SELF, 0xa24f988d) \ + TAG(STACK, 0xf65b391b) \ + TAG(KERNEL, 0xbfc71b20) \ + TAG(LOADER, 0xf1f80c26) \ + TAG(FILE, 0xcbc36d3b) \ + TAG(RSDP, 0x8ef29c18) \ + TAG(FDT, 0xb628bbc1) \ + TAG(FB, 0xe2d55685) \ + TAG(CMDLINE, 0x435140c4) \ + TAG(RESERVED, 0xb8841d2d) \ + TAG(END, 0xffffffff) + +typedef enum { + +#define TAG(NAME, VALUE) HANDOVER_##NAME = VALUE, + HANDOVER_TAGS(TAG) +#undef TAG +} HandoverTag; + +typedef struct +{ + uint32_t tag; + uint32_t flags; + uintptr_t start; + size_t size; + + union { + struct + { + uint16_t width; + uint16_t height; + uint16_t pitch; + +#define HANDOVER_RGBX8888 0x7451 +#define HANDOVER_BGRX8888 0xd040 + uint16_t format; + } fb; + + struct + { + uint32_t name; + uint32_t meta; + } file; + + uint64_t more; + }; +} HandoverRecord; + +typedef struct +{ + uint32_t magic, agent, size, count; + HandoverRecord records[]; +} HandoverPayload; + +typedef struct +{ + uint32_t tag; + uint32_t flags; + uint64_t more; +} HandoverRequest; + +typedef void HandoverEntry( + uint64_t magic, + HandoverPayload const* payload +); + +/* --- Header Utilities ----------------------------------------------------- */ + +#define HANDOVER_REQ_START \ + { \ + .tag = HANDOVER_MAGIC \ + } + +#define HANDOVER_REQ_END \ + { \ + .tag = HANDOVER_END \ + } + +#define WITH_FB \ + { \ + .tag = HANDOVER_FB \ + } + +#define WITH_ACPI \ + { \ + .tag = HANDOVER_RSDP \ + } + +#define WITH_FDT \ + { \ + .tag = HANDOVER_FDT \ + } + +#define WITH_FILES \ + { \ + .tag = HANDOVER_FILE \ + } + +#define WITH_CMDLINE \ + { \ + .tag = HANDOVER_CMDLINE \ + } + +#define HANDOVER(...) \ + __attribute__((section(HANDOVER_SECTION), used)) static HandoverRequest handover_header[] = { \ + {.tag = HANDOVER_MAGIC}, \ + __VA_ARGS__ __VA_OPT__(, ){.tag = HANDOVER_END}, \ + }; + +/* --- Utilities ------------------------------------------------------------ */ + +char const* handover_tag_name(HandoverTag tag); + +bool handover_mergeable(uint32_t tag); + +bool handover_overlap(HandoverRecord lhs, HandoverRecord rhs); + +bool handover_just_before(HandoverRecord lhs, HandoverRecord rhs); + +bool handover_just_after(HandoverRecord lhs, HandoverRecord rhs); + +HandoverRecord handover_half_under(HandoverRecord self, HandoverRecord other); + +HandoverRecord handover_half_over(HandoverRecord self, HandoverRecord other); + +void handover_insert(HandoverPayload* payload, size_t index, HandoverRecord record); + +void handover_remove(HandoverPayload* payload, size_t index); + +void handover_append(HandoverPayload* payload, HandoverRecord record); + +char const* handover_str(HandoverPayload const* payload, uint32_t offset); + +size_t handover_add_string(HandoverPayload* handover, char const* str); + +#pragma GCC diagnostic pop diff --git a/src/libs/handover/dtb/manifest.json b/src/libs/handover/dtb/manifest.json new file mode 100644 index 0000000..4db94fc --- /dev/null +++ b/src/libs/handover/dtb/manifest.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "handover-dtb", + "requires": [ + "dtb", + "handover" + ] +} diff --git a/src/libs/handover/dtb/mod.c b/src/libs/handover/dtb/mod.c new file mode 100644 index 0000000..cc16ba3 --- /dev/null +++ b/src/libs/handover/dtb/mod.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "handover/base/mod.h" +#include "logger/mod.h" +#include "mod.h" + +static DTBNode* dtb_root = NULL; +static HandoverPayload* payload = NULL; + +static void handover_mmap(void) { + if (dtb_root == NULL) { + fprintf(stderr, "No DTB found"); + abort(); + } + + DTBNode* mem = dtb_lookup(dtb_root, "memory"); + if (mem == NULL) { + fprintf(stderr, "No memory node found in DTB"); + abort(); + } + + RegValue reg_val = dtb_lookup_reg(mem); + + if (reg_val.len == 0) { + printf("WARNING: Memory node size is larger than 4GB. Defaulting to 4GB"); + reg_val.len = align_down$(gib$(4) - 1, 4096); + } + + handover_append(payload, (HandoverRecord){ + .tag = HANDOVER_FREE, + .start = reg_val.addr, + .size = reg_val.len, + }); + + DTBNode* reserved = dtb_lookup(dtb_root, "reserved-memory"); + if (reserved == NULL) { + fprintf(stderr, "No reserved memory node found in DTB"); + abort(); + } + + DTBNode* child = reserved->children; + while (child != NULL) { + RegValue reg = dtb_lookup_reg(child); + handover_append(payload, (HandoverRecord){ + .tag = HANDOVER_RESERVED, + .start = reg.addr, + .size = reg.len, + }); + child = child->next; + } +} + +void handover_init(DTBNode* dtb, Allocator* alloc) { + if (dtb_root != NULL) { + fprintf(stderr, "Handover is already initialized"); + abort(); + } + + dtb_root = dtb; + + payload = alloc->alloc(alloc, kib$(16)); + if (payload == NULL) { + fprintf(stderr, "Failed to allocate memory for handover payload"); + abort(); + } + + payload->count = 0; + payload->magic = HANDOVER_MAGIC; + + handover_mmap(); +} + +HandoverPayload* handover(void) { + return payload; +} diff --git a/src/libs/handover/dtb/mod.h b/src/libs/handover/dtb/mod.h new file mode 100644 index 0000000..47c6c67 --- /dev/null +++ b/src/libs/handover/dtb/mod.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include + +void handover_init(DTBNode* dtb, Allocator* alloc); + +HandoverPayload* handover(void); diff --git a/src/libs/helpers/misc.h b/src/libs/helpers/misc.h new file mode 100644 index 0000000..f315d4e --- /dev/null +++ b/src/libs/helpers/misc.h @@ -0,0 +1,4 @@ +#pragma once + +#define GENERATE_ENUM(ENUM) ENUM, +#define GENERATE_STRING(STRING) #STRING,