summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2021-03-21 18:38:17 +0000
committerAda Christine <adachristine18@gmail.com>2021-03-21 18:38:17 +0000
commitc359af48545e2427a69eb955b0512706d4afa7e9 (patch)
tree3a58acf219d23f6cca69ec4dae7e3adb6da2b4c5 /kernel
parentb88cfbdfad533629b294797efc196034c61dbb75 (diff)
higher-half stub kernel does the thing
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/entry_efi.c118
-rw-r--r--kernel/kprint.c18
-rw-r--r--kernel/kprint.h5
-rw-r--r--kernel/main.c4
-rw-r--r--kernel/port.c14
-rw-r--r--kernel/port.h5
-rw-r--r--kernel/serial.c41
-rw-r--r--kernel/serial.h5
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);
+