diff options
| -rw-r--r-- | kernel/Makefile | 2 | ||||
| -rw-r--r-- | kernel/entry_efi.c | 118 | ||||
| -rw-r--r-- | kernel/kprint.c | 18 | ||||
| -rw-r--r-- | kernel/kprint.h | 5 | ||||
| -rw-r--r-- | kernel/main.c | 4 | ||||
| -rw-r--r-- | kernel/port.c | 14 | ||||
| -rw-r--r-- | kernel/port.h | 5 | ||||
| -rw-r--r-- | kernel/serial.c | 41 | ||||
| -rw-r--r-- | kernel/serial.h | 5 |
9 files changed, 210 insertions, 2 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 36cca4c..a2cee11 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -16,7 +16,7 @@ LDFLAGS += -z max-page-size=4096 --export-dynamic LOADLIBES := -lgcc SOBJS := -GOBJS := entry_efi.o +GOBJS := entry_efi.o kprint.o serial.o port.o main.o IOBJS := $(SOBJS): CFLAGS += -fPIC diff --git a/kernel/entry_efi.c b/kernel/entry_efi.c index 40e674f..5400a77 100644 --- a/kernel/entry_efi.c +++ b/kernel/entry_efi.c @@ -1,11 +1,127 @@ #include <stdbool.h> +#include <stddef.h> +#include <stdint.h> #include <stdnoreturn.h> #include <boot/entry/entry_efi.h> +#include "serial.h" +#include "kprint.h" + +#define ENTRY_STACK_SIZE 0x2000 +#define align2(x, a) ((x + a - 1) & ~(a - 1)) + +extern void kernel_main(void); + +enum page_range_type +{ + UNUSABLE_MEMORY, + RESERVED_MEMORY, + AVAILABLE_MEMORY +}; + +struct page_range +{ + uint64_t type; + uint64_t base; + size_t size; +}; + +static char entry_heap[0x10000]; +static char *entry_heap_base; +static char *entry_heap_head; + +static struct page_range *system_ranges; +static size_t system_ranges_count; + +static void entry_heap_init(void) +{ + kputs("entry_heap_init() called\r\n"); + + entry_heap_base = entry_heap; + entry_heap_head = entry_heap; +} + +static void *entry_malloc(size_t size) +{ + kputs("entry_malloc() called\r\n"); + + void *buffer; + + size = align2(size, 16); + + if ((entry_heap_head - entry_heap_base + size) > sizeof(entry_heap)) + { + return NULL; + } + else + { + buffer = entry_heap_head; + entry_heap_head += size; + } + + return buffer; +} + +static void parse_memory_ranges(struct efi_memory_map_data *map) +{ + kputs("parse_memory_ranges() called\r\n"); + system_ranges_count = map->size/map->descsize; + system_ranges = entry_malloc(sizeof(*system_ranges) * system_ranges_count); + + for (unsigned int i = 0; i < system_ranges_count; i++) + { + EFI_MEMORY_DESCRIPTOR *desc; + desc = (EFI_MEMORY_DESCRIPTOR *)(map->descsize * i + (char *)map->data); + system_ranges[i].base = desc->PhysicalStart; + system_ranges[i].size = desc->NumberOfPages * EFI_PAGE_SIZE; + + switch (desc->Type) + { + case EfiConventionalMemory: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiLoaderCode: + case EfiLoaderData: + system_ranges[i].type = AVAILABLE_MEMORY; + break; + case SystemMemoryType: + system_ranges[i].type = RESERVED_MEMORY; + break; + default: + system_ranges[i].type = UNUSABLE_MEMORY; + } + } +} + noreturn void kernel_entry(struct efi_boot_data *data) { - (void)data; + serial_init(); + kputs("<hacker voice> i'm in\r\n"); + entry_heap_init(); + + parse_memory_ranges(data->memory_map); + + void *acpi_rsdp = data->acpi_rsdp; + (void)acpi_rsdp; + + // we no longer need any loader data from here on. + // get the entry stack and clean up loader mappings + + char *entry_stack_base = entry_malloc(ENTRY_STACK_SIZE); + char *entry_stack_head = entry_stack_base + ENTRY_STACK_SIZE; + + __asm__("mov %0, %%rsp" :: "r"(entry_stack_head)); + + uint64_t pml4_raw; + __asm__("mov %%cr3, %0" : "=r"(pml4_raw)); + uint64_t *pml4 = (uint64_t *)(pml4_raw & ~((1ULL << 12) - 1)); + pml4[0] = 0; + __asm__("mov %0, %%cr3" :: "r"(pml4_raw)); + + // we can now go to the kernel proper + kernel_main(); + __asm__ ("cli\n\t"); while (true) __asm__ ("hlt\n\t"); } diff --git a/kernel/kprint.c b/kernel/kprint.c new file mode 100644 index 0000000..0a15efd --- /dev/null +++ b/kernel/kprint.c @@ -0,0 +1,18 @@ +#include "kprint.h" +#include "serial.h" + +int kputchar(int c) +{ + return serial_putchar(c); +} + +int kputs(const char *s) +{ + while (*s) + { + kputchar(*s++); + } + + return 0; +} + diff --git a/kernel/kprint.h b/kernel/kprint.h new file mode 100644 index 0000000..5b307a2 --- /dev/null +++ b/kernel/kprint.h @@ -0,0 +1,5 @@ +#pragma once + +int kputchar(int c); +int kputs(const char *s); + diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..2fb2e3e --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,4 @@ +void kernel_main(void) +{ +} + diff --git a/kernel/port.c b/kernel/port.c new file mode 100644 index 0000000..17af396 --- /dev/null +++ b/kernel/port.c @@ -0,0 +1,14 @@ +#include "port.h" + +uint8_t inb(uint16_t port) +{ + uint8_t data; + __asm__ ("inb %1, %0" : "=a"(data) : "d"(port)); + return data; +} + +void outb(uint16_t port, uint8_t data) +{ + __asm__ ("outb %0, %1" :: "a"(data), "d"(port)); +} + diff --git a/kernel/port.h b/kernel/port.h new file mode 100644 index 0000000..cc71973 --- /dev/null +++ b/kernel/port.h @@ -0,0 +1,5 @@ +#include <stdint.h> + +uint8_t inb(uint16_t port); +void outb(uint16_t port, uint8_t data); + diff --git a/kernel/serial.c b/kernel/serial.c new file mode 100644 index 0000000..77f453d --- /dev/null +++ b/kernel/serial.c @@ -0,0 +1,41 @@ +#include "serial.h" +#include "port.h" + +#define PORT 0x3f8 // COM1 + +static int is_transmit_empty(void); + +int serial_init(void) { + outb(PORT + 0, 0x00); // Disable all interrupts + outb(PORT + 2, 0x80); // Enable DLAB (set baud rate divisor) + outb(PORT + -1, 0x03); // Set divisor to 3 (lo byte) 38400 baud + outb(PORT + 0, 0x00); // (hi byte) + outb(PORT + 2, 0x03); // 8 bits, no parity, one stop bit + outb(PORT + 1, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(PORT + 3, 0x0B); // IRQs enabled, RTS/DSR set + outb(PORT + 3, 0x1E); // Set in loopback mode, test the serial chip + outb(PORT + -1, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + if(inb(PORT + -1) != 0xAE) { + return 0; + } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#0 and OUT#2 bits enabled) + outb(PORT + 3, 0x0F); + return -1; +} + +int serial_putchar(int c) +{ + while (is_transmit_empty() == 0); + outb(PORT,(char)c); + return c; +} + +static int is_transmit_empty(void) +{ + return inb(PORT + 5) & 0x20; +} + diff --git a/kernel/serial.h b/kernel/serial.h new file mode 100644 index 0000000..2e22fa6 --- /dev/null +++ b/kernel/serial.h @@ -0,0 +1,5 @@ +#pragma once + +int serial_init(void); +int serial_putchar(int c); + |
