From 2f0539665155cc4878ce4cc77913dbaf3b8ec4a3 Mon Sep 17 00:00:00 2001 From: Tom-on64 Date: Wed, 25 Mar 2026 18:17:42 +0100 Subject: [PATCH] Added and made kernel use it --- docs/errors.txt | 32 +++++++++++ kernel/include/errno.h | 35 ++++++++++++ kernel/include/idt.h | 2 +- kernel/include/paging.h | 10 ++-- kernel/include/pmm.h | 2 +- kernel/include/serial.h | 1 + kernel/makefile | 2 +- kernel/src/bootloader.c | 18 +++--- kernel/src/gdt.c | 7 +-- kernel/src/idt.c | 16 ++++-- kernel/src/isr.c | 18 +++--- kernel/src/kernel.c | 13 ++--- kernel/src/paging.c | 121 ++++++++++++++++++---------------------- kernel/src/pmm.c | 34 +++++------ kernel/src/serial.c | 13 ++++- 15 files changed, 189 insertions(+), 135 deletions(-) create mode 100644 docs/errors.txt create mode 100644 kernel/include/errno.h diff --git a/docs/errors.txt b/docs/errors.txt new file mode 100644 index 0000000..a9e482b --- /dev/null +++ b/docs/errors.txt @@ -0,0 +1,32 @@ +Error handling +============== + +Functions that can fail must have a way of telling the caller that something +went wrong and preferably what went wrong. The simplest and cleanest way of +indicating an error is a return code. Error codes are defined in the +header alongside some helpfull macros. + +Error codes have identifiers like these: ENOMEM, ENOENT, EALIGN, ... +They are defined as positive values, however all functions should return a +negative integer on error, so it would look something like 'return -EFAULT;'. +Also theres SUCCESS which is just 0. You can use it, but don't need to. + +If you are returning a pointer/address, the highest address is almost certainly +unused, so returning '(void*)-EINVAL', should work just fine. This is quite an +eyesore, so there are three macros for working with these "errno-in-pointer"s. +IS_ERR(ptr) just returns 1 if the pointer is an errno. Otherwise 0. +ERR_PTR(err) does that void* cast mentioned above so it would be ERR_PTR(-EINVAL). +PTR_ERR(ptr) is the inverse of ERR_PTR(), as it converts a errno-in-pointer to +an errno value. PTR_ERR(ERR_PTR(-EIO)) == -EIO + + +Here are some usage examples: + int pag_init(void) { + if (...) return -ENOMEM; // Not enough memory + + void* paddr = pmm_alloc(); + if (IS_ERR(paddr)) return PTR_ERR(paddr); // Pass the error down + + return SUCCESS; + } + diff --git a/kernel/include/errno.h b/kernel/include/errno.h new file mode 100644 index 0000000..aa6bc47 --- /dev/null +++ b/kernel/include/errno.h @@ -0,0 +1,35 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +#include + +#define ERRNO_MAX 4095 + +#define IS_ERR(_ptr) ((uintptr_t)(_ptr) >= (uintptr_t)(-ERRNO_MAX)) + +#define ERR_PTR(_err) ((void*)(_err)) +#define PTR_ERR(_ptr) ((int)(intptr_t)(_ptr)) + +// TODO: Add correct errno.h numbers +enum { + SUCCESS = 0, + ENOMEM, // Cannot allocate memory + EPERM, // Operation not permitted + ENOENT, // No entry (no such file or directory) + EIO, // Input/Output error + ENXIO, // No such device or address + EAGAIN, // Resource temporarly busy + EACCES, // Permission denied + EFAULT, // Bad address + ENODEV, // No such device + EINVAL, // Invalid argument + EDOM, // Numerical argument out of domain + ERANGE, // Numerical result out of range + ENOSYS, // Function not implemented + ENOTSUP, // Not supported + EILLSEQ, // Illegal byte sequence + EOVERFLOW, // + EALIGN, // Not aligned +}; + +#endif diff --git a/kernel/include/idt.h b/kernel/include/idt.h index fe9bc7a..c3770ce 100644 --- a/kernel/include/idt.h +++ b/kernel/include/idt.h @@ -32,6 +32,6 @@ struct idt_pointer { } __packed; int idt_init(void); -void idt_set_gate(uint8_t i, void* handler, uint8_t flags); +void idt_set_gate(uint8_t i, void* handler, uint8_t flags, uint8_t ist); #endif diff --git a/kernel/include/paging.h b/kernel/include/paging.h index ec1f35c..e6be24b 100644 --- a/kernel/include/paging.h +++ b/kernel/include/paging.h @@ -41,11 +41,11 @@ static inline bool pag_is_user_addr(void* vaddr) { return (uintptr_t)vaddr < 0x0 // NOTE: All uint64_t* are VIRTUAL addresses int pag_init(void); uint64_t* pag_get_pte(uint64_t* pml4, void* vaddr); -void pag_map(uint64_t* pml4, void* vaddr, void* paddr, uint64_t flags); -void pag_map_region(uint64_t* pml4, void* vaddr, void* paddr, size_t count, uint64_t flags); -void pag_unmap(uint64_t* pml4, void* vaddr); -void pag_unmap_region(uint64_t* pml4, void* vaddr, size_t count); -void pag_protect(uint64_t* pml4, void* vaddr, uint64_t flags); +int pag_map(uint64_t* pml4, void* vaddr, void* paddr, uint64_t flags); +int pag_map_region(uint64_t* pml4, void* vaddr, void* paddr, size_t count, uint64_t flags); +int pag_unmap(uint64_t* pml4, void* vaddr); +int pag_unmap_region(uint64_t* pml4, void* vaddr, size_t count); +int pag_protect(uint64_t* pml4, void* vaddr, uint64_t flags); void* pag_get_phys(uint64_t* pml4, void* vaddr); void pag_set_pml4(uint64_t* pml4); uint64_t* pag_get_pml4(void); diff --git a/kernel/include/pmm.h b/kernel/include/pmm.h index d08bead..62d0141 100644 --- a/kernel/include/pmm.h +++ b/kernel/include/pmm.h @@ -5,6 +5,6 @@ int pmm_init(void); void* pmm_alloc(void); -void pmm_free(void*); +int pmm_free(void*); #endif diff --git a/kernel/include/serial.h b/kernel/include/serial.h index a580b29..8d35981 100644 --- a/kernel/include/serial.h +++ b/kernel/include/serial.h @@ -18,6 +18,7 @@ int serial_rcvd(int dev); char serial_recv(int dev); void serial_write(int dev, char* buf, size_t len); void serial_puts(int dev, char* s); +void serial_cls(int dev); int debugf(char* fmt, ...); int vdebugf(char* fmt, va_list args); diff --git a/kernel/makefile b/kernel/makefile index 1fe1d31..7033b09 100644 --- a/kernel/makefile +++ b/kernel/makefile @@ -18,7 +18,7 @@ $(OUT): $(OBJS_C) $(OBJS_S) $(BIN)/%.c.o: $(SRC)/%.c $(SSP) @mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -DSTACK_CHK_GUARD=$(shell cat $(SSP)) -I$(INC) -c -o $@ $< + $(CC) $(CCFLAGS) -DSTACK_CHK_GUARD="$$(cat $(SSP))" -I$(INC) -c -o $@ $< $(BIN)/%.s.o: $(SRC)/%.s @mkdir -p $(dir $@) diff --git a/kernel/src/bootloader.c b/kernel/src/bootloader.c index 631d345..6c785d9 100644 --- a/kernel/src/bootloader.c +++ b/kernel/src/bootloader.c @@ -1,14 +1,12 @@ #include #include #include +#include -/* - * This defines our expected Limine version - */ +// This defines our expected Limine version static volatile uint64_t lim_base_revision[] = LIMINE_BASE_REVISION(4); -struct bootloader bootloader = { 0 }; - +// Limine requests static struct limine_paging_mode_request lim_paging_req = { .id = LIMINE_PAGING_MODE_REQUEST_ID, .revision = 4, .mode = LIMINE_PAGING_MODE_X86_64_4LVL, }; @@ -28,6 +26,9 @@ static struct limine_framebuffer_request lim_fbuf_req = static struct limine_executable_file_request lim_exe_req = { .id = LIMINE_EXECUTABLE_FILE_REQUEST_ID, .revision = 4 }; +// Bootloader data struct +struct bootloader bootloader = { 0 }; + int boot_init(void) { if (LIMINE_BASE_REVISION_SUPPORTED(lim_base_revision) == false) panic("Unsupported Limine base revision."); @@ -38,10 +39,7 @@ int boot_init(void) { struct limine_framebuffer_response* lim_fbuf_res = lim_fbuf_req.response; struct limine_executable_file_response* lim_exe_res = lim_exe_req.response; - if (lim_paging_res->mode != LIMINE_PAGING_MODE_X86_64_4LVL) { - debugf("[boot] Expected 4 level paging.\n"); - return 1; - } + if (lim_paging_res->mode != LIMINE_PAGING_MODE_X86_64_4LVL) panic("Expected 4 level paging."); bootloader.hhdm_offset = lim_hhdm_res->offset; bootloader.kernel_phys_base = lim_kaddr_res->physical_base; bootloader.kernel_virt_base = lim_kaddr_res->virtual_base; @@ -58,6 +56,6 @@ int boot_init(void) { bootloader.fb_entries = lim_fbuf_res->framebuffers; bootloader.fb_entry_count = lim_fbuf_res->framebuffer_count; - return 0; + return SUCCESS; } diff --git a/kernel/src/gdt.c b/kernel/src/gdt.c index 5154595..cd99707 100644 --- a/kernel/src/gdt.c +++ b/kernel/src/gdt.c @@ -1,7 +1,6 @@ -#include "paging.h" -#include "pmm.h" #include #include +#include #include static struct gdt_entries gdt; @@ -105,8 +104,6 @@ int gdt_init(void) { memset(&tss, 0, sizeof(tss)); tss_load(&tss); - debugf("[gdt] GDT loaded.\n"); - - return 0; + return SUCCESS; } diff --git a/kernel/src/idt.c b/kernel/src/idt.c index 6ccf945..8740b8f 100644 --- a/kernel/src/idt.c +++ b/kernel/src/idt.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -7,25 +9,27 @@ __align(16) // performace static struct idt_entry idt[IDT_ENTRIES]; static struct idt_pointer idtp; -void idt_set_gate(uint8_t i, void* handler, uint8_t attrib) { +void idt_set_gate(uint8_t i, void* handler, uint8_t attrib, uint8_t ist) { size_t addr = (size_t)handler; idt[i].offset_low = (uint16_t)addr; idt[i].selector = GDT_KERNEL_CODE; - idt[i].ist = 0; - idt[i].__reserved = 0; + idt[i].ist = ist & 7; idt[i].attrib = attrib; idt[i].offset_mid = (uint16_t)(addr >> 16); idt[i].offset_high = (uint32_t)(addr >> 32); + idt[i].__reserved = 0; } int idt_init(void) { + memset(idt, 0, sizeof(idt)); + idtp.size = sizeof(idt) - 1; - idtp.offset = (size_t)&idt; + idtp.offset = (uintptr_t)&idt; // Load IDT instruction + cli(); __asm__ volatile ("lidt %0" : : "m"(idtp)); - debugf("[idt] IDT initalized.\n"); - return 0; + return SUCCESS; } diff --git a/kernel/src/isr.c b/kernel/src/isr.c index e512067..0aa2faf 100644 --- a/kernel/src/isr.c +++ b/kernel/src/isr.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -64,24 +65,23 @@ void pic_remap(void) { int isr_init(void) { memset(irq_handlers, 0, sizeof(irq_handlers)); - if (idt_init() != 0) { - debugf("[isr] Could not load IDT."); - return 1; - } + idt_init(); for (int i = 0; i < 48; i++) { // First 32 IRSs are exceptions (traps) and the next 16 are hardware interrupts - idt_set_gate(i, isr_redirect_table[i], IDT_FLAG_INT); + idt_set_gate(i, isr_redirect_table[i], i < 32 ? IDT_FLAG_TRAP : IDT_FLAG_INT, 0); } - idt_set_gate(0x03, isr_redirect_table[3], IDT_FLAG_USER); // Allow breakpoints - idt_set_gate(0x80, isr128, IDT_FLAG_USER); // Syscall + + idt_set_gate(0x02, isr_redirect_table[2], IDT_FLAG_TRAP, 2); // Use IST2 for NMIs + idt_set_gate(0x03, isr_redirect_table[3], IDT_FLAG_USER, 0); // Allow breakpoints + idt_set_gate(0x08, isr_redirect_table[8], IDT_FLAG_TRAP, 1); // Use IST1 for Double Faults + idt_set_gate(0x80, isr128, IDT_FLAG_USER, 0); // Syscall pic_remap(); // TODO: apic_init(); sti(); - debugf("[isr] ISR initialized.\n"); - return 0; + return SUCCESS; } void isr_register(uint8_t i, isr_handler_ptr handler) { diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index 0cb60b9..02bf234 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -13,10 +12,10 @@ __noreturn void _start(void) { // Serial console for debugging - if (serial_init(COM1) != 0) panic("Failed to initialize Serial driver."); + if (serial_init(COM1) < 0) panic("Failed to initialize Serial driver."); // Load structures from bootloader - if (boot_init() != 0) panic("Failed to parse bootloader structures."); + if (boot_init() < 0) panic("Failed to parse bootloader structures."); // The most important function in the world. splash(); @@ -28,12 +27,12 @@ void _start(void) { debugf("[kernel] CPUID_GETVENDORID: %s\n", s); // System init - if (gdt_init() != 0) panic("Failed to initalize GDT."); - if (isr_init() != 0) panic("Failed to initalize ISRs."); + if (gdt_init() < 0) panic("Failed to initalize GDT."); + if (isr_init() < 0) panic("Failed to initalize ISRs."); // Memory management - if (pmm_init() != 0) panic("Failed to initalize Physical Memory Manager."); - if (pag_init() != 0) panic("Failed to initalize Paging."); + if (pmm_init() < 0) panic("Failed to initalize Physical Memory Manager."); + if (pag_init() < 0) panic("Failed to initalize Paging."); // Patiently wait for things to do :) while (1); diff --git a/kernel/src/paging.c b/kernel/src/paging.c index 5391354..339ee4e 100644 --- a/kernel/src/paging.c +++ b/kernel/src/paging.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -12,19 +13,17 @@ uint64_t* pag_kernel_pml4 = NULL; int pag_init(void) { pag_kernel_pml4 = TO_VIRT(pmm_alloc()); - if (pag_kernel_pml4 == NULL) { - debugf("[pag] Failed to allocate kernel PML4. Not enough memory.\n"); - return 1; - } + if (IS_ERR(pag_kernel_pml4)) return PTR_ERR(pag_kernel_pml4); memset(pag_kernel_pml4, 0, PAGE_SIZE); - pag_map_region( + int ret = pag_map_region( pag_kernel_pml4, (void*)bootloader.kernel_virt_base, (void*)bootloader.kernel_phys_base, dceil(bootloader.executable->size, PAGE_SIZE), PTE_FLAG_WRITE | PTE_FLAG_PRESENT ); + if (ret != SUCCESS) return ret; for (size_t i = 0; i < bootloader.mm_entry_count; i++) { struct limine_memmap_entry* entry = bootloader.mm_entries[i]; @@ -48,115 +47,106 @@ int pag_init(void) { continue; } - pag_map_region( + ret = pag_map_region( pag_kernel_pml4, (void*)(entry->base + bootloader.hhdm_offset), (void*)entry->base, dceil(entry->length, PAGE_SIZE), flags | PTE_FLAG_PRESENT ); + if (ret != SUCCESS) return ret; } - debugf("[pag] Switching to kernel PML4 at %p.\n", pag_kernel_pml4); pag_set_pml4(pag_kernel_pml4); - debugf("[pag] Paging initialized.\n"); return 0; } uint64_t* pag_get_pte(uint64_t* pml4, void* vaddr) { uintptr_t v = (uintptr_t)vaddr; - if (v % PAGE_SIZE != 0) { - debugf("[pag] Could not get PTE from non-aligned virtual address %p.\n", vaddr); - return NULL; - } + if (v % PAGE_SIZE != 0) return ERR_PTR(-EALIGN); uint64_t* pdpt = pag_get_next_tab(pml4, PML4_IDX(v)); - if (pdpt == NULL) { - debugf("[pag] Could not get PTE. %p was not found in PML4.\n"); - return NULL; - } + if (IS_ERR(pdpt)) return pdpt; + uint64_t* pd = pag_get_next_tab(pdpt, PDPT_IDX(v)); - if (pd == NULL) { - debugf("[pag] Could not get PTE. %p was not found in PDPT.\n"); - return NULL; - } + if (IS_ERR(pd)) return pd; + uint64_t* pt = pag_get_next_tab(pd, PD_IDX(v)); - if (pt == NULL) { - debugf("[pag] Could not get PTE. %p was not found in PD.\n"); - return NULL; - } + if (IS_ERR(pt)) return pt; return &pt[PT_IDX(v)]; } uint64_t* pag_new_pte(uint64_t* pml4, void* vaddr) { uintptr_t v = (uintptr_t)vaddr; - if (v % PAGE_SIZE != 0) { - debugf("[pag] Could not create PTE for non-aligned virtual address %p.\n", vaddr); - return NULL; - } + if (v % PAGE_SIZE != 0) return ERR_PTR(-EALIGN); uint64_t* pdpt = pag_new_next_tab(pml4, PML4_IDX(v)); - if (pdpt == NULL) { - debugf("[pag] Failed to create PDPT. Not enough memory.\n"); - return NULL; - } + if (IS_ERR(pdpt)) return pdpt; + uint64_t* pd = pag_new_next_tab(pdpt, PDPT_IDX(v)); - if (pd == NULL) { - debugf("[pag] Failed to create PD. Not enough memory.\n"); - if (pdpt != NULL) pmm_free(pdpt); - return NULL; - } + if (IS_ERR(pd)) return pd; + uint64_t* pt = pag_new_next_tab(pd, PD_IDX(v)); - if (pt == NULL) { - debugf("[pag] Failed to create PT. Not enough memory.\n"); - if (pd != NULL) pmm_free(pd); - if (pdpt != NULL) pmm_free(pdpt); - return NULL; - } + if (IS_ERR(pt)) return pt; return &pt[PT_IDX(v)]; } -void pag_map(uint64_t* pml4, void* vaddr, void* paddr, uint64_t flags) { +int pag_map(uint64_t* pml4, void* vaddr, void* paddr, uint64_t flags) { uintptr_t p = (uintptr_t)paddr; - if (p % PAGE_SIZE != 0) { - debugf("[pag] Could not map %p to %p. Physical address is not aligned.\n", paddr, vaddr); - return; - } - - uint64_t* page = pag_new_pte(pml4, vaddr); - *page = PTE_ADDR(p) | flags | PTE_FLAG_PRESENT; + if (p % PAGE_SIZE != 0) return -EALIGN; + + uint64_t* pte = pag_new_pte(pml4, vaddr); + if (IS_ERR(pte)) return PTR_ERR(pte); + + *pte = PTE_ADDR(p) | flags | PTE_FLAG_PRESENT; pag_invalidate(vaddr); + + return SUCCESS; } -void pag_map_region(uint64_t* pml4, void* vaddr, void* paddr, size_t count, uint64_t flags) { +int pag_map_region(uint64_t* pml4, void* vaddr, void* paddr, size_t count, uint64_t flags) { for (size_t i = 0; i < count; i++) { - pag_map(pml4, vaddr + i * PAGE_SIZE, paddr + i * PAGE_SIZE, flags); + int ret = pag_map(pml4, vaddr + i * PAGE_SIZE, paddr + i * PAGE_SIZE, flags); + if (ret != SUCCESS) return ret; } + return SUCCESS; } // TODO: This is a pmm memory leak. If all pages in a PT are unmapped, remove // that PT from it's PD. This applies to PDs & PDPTs too. -void pag_unmap(uint64_t* pml4, void* vaddr) { +int pag_unmap(uint64_t* pml4, void* vaddr) { uint64_t* pte = pag_get_pte(pml4, vaddr); + if (IS_ERR(pte)) return PTR_ERR(pte); + *pte = 0; pag_invalidate(vaddr); + + return SUCCESS; } -void pag_unmap_region(uint64_t* pml4, void* vaddr, size_t count) { +int pag_unmap_region(uint64_t* pml4, void* vaddr, size_t count) { for (size_t i = 0; i < count; i++) { - pag_unmap(pml4, vaddr + i * PAGE_SIZE); + int ret = pag_unmap(pml4, vaddr + i * PAGE_SIZE); + if (ret != SUCCESS) return ret; } + return SUCCESS; } -void pag_protect(uint64_t* pml4, void* vaddr, uint64_t flags) { +int pag_protect(uint64_t* pml4, void* vaddr, uint64_t flags) { uint64_t* pte = pag_get_pte(pml4, vaddr); + if (IS_ERR(pte)) return PTR_ERR(pte); + *pte = PTE_ADDR(*pte) | flags | PTE_FLAG_PRESENT; + + return SUCCESS; } void* pag_get_phys(uint64_t* pml4, void* vaddr) { uint64_t* pte = pag_get_pte(pml4, vaddr); + if (IS_ERR(pte)) return pte; + return (void*)PTE_ADDR(*pte); } @@ -171,21 +161,20 @@ uint64_t* pag_get_pml4(void) { } uint64_t* pag_get_next_tab(uint64_t* tab, offset_t index) { - if (index >= 512 || tab == NULL) return NULL; - else if (tab[index] & PTE_FLAG_PRESENT) return TO_VIRT(tab[index] & PTE_ADDR_MASK); - else return NULL; + if (tab == NULL || IS_ERR(tab)) return ERR_PTR(-EFAULT); + if (index >= 512) return ERR_PTR(-EINVAL); + + if (tab[index] & PTE_FLAG_PRESENT) return TO_VIRT(PTE_ADDR(tab[index])); + else return ERR_PTR(-ENOENT); } uint64_t* pag_new_next_tab(uint64_t* tab, offset_t index) { - if (tab == NULL) return NULL; uint64_t* vaddr = pag_get_next_tab(tab, index); - if (vaddr != NULL) return vaddr; + if (!IS_ERR(vaddr)) return vaddr; + if (PTR_ERR(vaddr) != -ENOENT) return vaddr; void* paddr = pmm_alloc(); - if (!paddr) { - debugf("[pag] Failed to allocate page for new table.\n"); - return NULL; - } + if (IS_ERR(paddr)) return paddr; vaddr = TO_VIRT(paddr); memset(vaddr, 0, PAGE_SIZE); diff --git a/kernel/src/pmm.c b/kernel/src/pmm.c index 3b2c7b2..a311e95 100644 --- a/kernel/src/pmm.c +++ b/kernel/src/pmm.c @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -10,7 +11,6 @@ uint64_t* pmm_head = NULL; size_t pmm_total_mem = 0; int pmm_init(void) { - debugf("[pmm] Physical memory map:\n"); // We're gonna use the loop to also print the memmap for (size_t i = 0; i < bootloader.mm_entry_count; i++) { struct limine_memmap_entry* entry = bootloader.mm_entries[i]; @@ -39,37 +39,29 @@ int pmm_init(void) { } debugf("[pmm] %d bytes of available memory.\n", pmm_total_mem); + if (pmm_total_mem == 0) return -ENOMEM; - return 0; + return SUCCESS; } void* pmm_alloc() { - if (pmm_head == NULL) { - debugf("[pmm] Could not allocate page, not enough memory.\n"); - return NULL; - } + if (pmm_head == NULL) return ERR_PTR(-ENOMEM); + uint64_t* addr = pmm_head; - if ((uintptr_t)addr % PAGE_SIZE != 0) { - debugf("[pmm] Tried to allocate non-aligned page.\n"); - // It may fix itself if a page gets freed - // panic("pmm_head corrupted."); - return NULL; - } + if ((uintptr_t)addr % PAGE_SIZE != 0) panic("pmm_head corrupted."); pmm_head = (uint64_t*)(*addr); + return TO_PHYS(addr); } -void pmm_free(void* page) { - if (page == NULL) { - debugf("[pmm] Tried to free NULL.\n"); - return; - } - if ((uintptr_t)page % PAGE_SIZE != 0) { - debugf("[pmm] Tried to free non-aligned page.\n"); - return; - } +int pmm_free(void* page) { + if (page == NULL || IS_ERR(page)) return -EFAULT; + if ((uintptr_t)page % PAGE_SIZE != 0) return -EALIGN; + uint64_t* addr = TO_VIRT(page); *addr = (uint64_t)pmm_head; pmm_head = addr; + + return SUCCESS; } diff --git a/kernel/src/serial.c b/kernel/src/serial.c index faed72c..b00d8a2 100644 --- a/kernel/src/serial.c +++ b/kernel/src/serial.c @@ -1,3 +1,4 @@ +#include "errno.h" #include #include #include @@ -11,13 +12,15 @@ int serial_init(int dev) { outb(dev + 3, 0x03); // 8 bits, no parity, one stop bit outb(dev + 2, 0xC7); // Enable FIFO, clear them, with 14 byte threshold outb(dev + 4, 0x0B); // IRQs enabled, RTS/DSR set + outb(dev + 4, 0x1E); // Set in loopback mode, test the serial chip outb(dev + 0, 0xAE); // Test serial chip (send byte 0xAE and check if it returns) - - if (inb(dev + 0) != 0xAE) return 1; + if (inb(dev + 0) != 0xAE) return -ENODEV; + outb(dev + 4, 0x0F); // non-loopback, IRQs enabled, OUT#1 and OUT#2 bits enabled - debugf("\x1b[H\x1b[JSerial display initiated!\n\n"); + serial_cls(COM1); + serial_puts(COM1, "Serial display (COM1)\n\n"); return 0; } @@ -54,6 +57,10 @@ void serial_puts(int dev, char* s) { serial_write(dev, s, len); } +void serial_cls(int dev) { + serial_write(dev, "\x1b[H\x1b[J", 6); +} + int debugf(char* fmt, ...) { va_list args; va_start(args, fmt);