diff --git a/.cache/clangd/index/kernel.c.77F67860B909D538.idx b/.cache/clangd/index/kernel.c.77F67860B909D538.idx new file mode 100644 index 0000000..778b63e Binary files /dev/null and b/.cache/clangd/index/kernel.c.77F67860B909D538.idx differ diff --git a/.cache/clangd/index/kernel.h.2BB7B327DAB1C098.idx b/.cache/clangd/index/kernel.h.2BB7B327DAB1C098.idx new file mode 100644 index 0000000..7144436 Binary files /dev/null and b/.cache/clangd/index/kernel.h.2BB7B327DAB1C098.idx differ diff --git a/.cache/clangd/index/multiboot.h.569D3E05B34DD4E9.idx b/.cache/clangd/index/multiboot.h.569D3E05B34DD4E9.idx new file mode 100644 index 0000000..2be98b5 Binary files /dev/null and b/.cache/clangd/index/multiboot.h.569D3E05B34DD4E9.idx differ diff --git a/.cache/clangd/index/serial.h.C96BAE791DAC37AC.idx b/.cache/clangd/index/serial.h.C96BAE791DAC37AC.idx new file mode 100644 index 0000000..8fed3a5 Binary files /dev/null and b/.cache/clangd/index/serial.h.C96BAE791DAC37AC.idx differ diff --git a/Makefile b/Makefile index 2e3fb71..3437931 100644 --- a/Makefile +++ b/Makefile @@ -4,15 +4,17 @@ AS = nasm BUILDDIR := build INCLUDEDIR := include -CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld - KSRC := $(wildcard kernel/*.asm kernel/*.c) KOBJ := $(addprefix $(BUILDDIR)/, \ $(notdir \ $(patsubst %.asm,%.o, $(patsubst %.c,%.o, $(KSRC))))) KIMG := kernel.bin +CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) +LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld +QEMUFLAGS := -kernel $(BUILDDIR)/$(KIMG) \ + -serial stdio + $(BUILDDIR)/$(KIMG): $(KOBJ) $(CC) $^ -o $@ $(LDFLAGS) $(BUILDDIR)/%.o: */%.asm @@ -27,7 +29,7 @@ $(BUILDDIR)/Hazel.iso: kernel grub-mkrescue -o $(BUILDDIR)/Hazel.iso . qemu: kernel - qemu-system-i386 -kernel $(BUILDDIR)/$(KIMG) + qemu-system-i386 $(QEMUFLAGS) clean: rm build/* boot/*.bin diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..4cc7253 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,20 @@ +[ + { + "arguments": [ + "/home/rami/crossdev/bin/i686-elf-gcc", + "-ffreestanding", + "-Wall", + "-Wextra", + "-Werror", + "-I", + "include", + "-c", + "-o", + "build/kernel.o", + "kernel/kernel.c" + ], + "directory": "/home/rami/hazel", + "file": "/home/rami/hazel/kernel/kernel.c", + "output": "/home/rami/hazel/build/kernel.o" + } +] diff --git a/include/kernel/io.h b/include/kernel/io.h new file mode 100644 index 0000000..4997a73 --- /dev/null +++ b/include/kernel/io.h @@ -0,0 +1,9 @@ +#ifndef HAZEL_IO_H_ +#define HAZEL_IO_H_ + +#include + +uint8_t inb(uint16_t port); +void outb(uint16_t port, uint8_t byte); + +#endif diff --git a/include/kernel/kernel.h b/include/kernel/kernel.h new file mode 100644 index 0000000..77d2237 --- /dev/null +++ b/include/kernel/kernel.h @@ -0,0 +1,15 @@ +#ifndef HAZEL_KERNEL_H_ +#define HAZEL_KERNEL_H_ + +#include +#include + +#define cpu_relax asm volatile ("pause" ::) + +typedef struct { + multiboot_memory_map_t *mem_map; + uint32_t mem_map_len; + log_method_t log_method; +} kernel_ctx_t; + +#endif diff --git a/include/kernel/log.h b/include/kernel/log.h new file mode 100644 index 0000000..de05ef8 --- /dev/null +++ b/include/kernel/log.h @@ -0,0 +1,13 @@ +#ifndef HAZEL_LOG_H_ +#define HAZEL_LOG_H_ + +typedef enum { + LOG_COM1, + LOG_VGA, +} log_method_t; + +#define LOG(x) logs(x); + +void logs(const char *str); + +#endif diff --git a/include/kernel/multiboot.h b/include/kernel/multiboot.h index d14b7d2..5ebf77e 100644 --- a/include/kernel/multiboot.h +++ b/include/kernel/multiboot.h @@ -26,4 +26,21 @@ typedef struct { uint32_t vbeinterfacelength; } multiboot_info_t; +struct multiboot_mmap_entry +{ + uint32_t size; + uint32_t addr_low; + uint32_t addr_high; + uint32_t len_low; + uint32_t len_high; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + + #endif diff --git a/include/kernel/serial.h b/include/kernel/serial.h new file mode 100644 index 0000000..113142b --- /dev/null +++ b/include/kernel/serial.h @@ -0,0 +1,21 @@ +#ifndef HAZEL_SERIAL_H_ +#define HAZEL_SERIAL_H_ + +#include + +#define COM1 0x3F8 +#define COM2 0x2F8 +#define COM3 0x3E8 +#define COM4 0x2E8 +#define COM5 0x5F8 +#define COM6 0x4F8 +#define COM7 0x5E8 +#define COM8 0x4E8 + +#define IS_TRANSMIT_EMPTY(x) (inb(x + 5) & 0x20) + +uint8_t serial_port_init(int port); +void serial_putc(int port, const char c); +void serial_puts(int port, const char *str); + +#endif diff --git a/kernel/io.c b/kernel/io.c new file mode 100644 index 0000000..dcd1403 --- /dev/null +++ b/kernel/io.c @@ -0,0 +1,17 @@ +#include + +uint8_t inb(uint16_t port) { + uint8_t result; + + asm volatile ("in %%dx, %%al" + : "=a" (result) + : "d" (port)); + + return result; +} + +void outb(uint16_t port, uint8_t byte) { + asm volatile ("out %%al, %%dx" + : // no output + : "a" (byte), "d" (port)); +} diff --git a/kernel/kernel.c b/kernel/kernel.c index b9aaedb..363d192 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,10 +1,19 @@ +#include #include +#include + +kernel_ctx_t ctx = {0}; void kernel(multiboot_info_t *info) { - char *vmem = (char *)0xb8000; - vmem[0] = info->flags; - vmem[1] = 0x0f; + if (!(info->flags & (1<<6))) goto halt; + ctx.mem_map = (multiboot_memory_map_t *)info->memmapaddress; + ctx.mem_map_len = info->memmaplength; + if (serial_port_init(COM1)) + ctx.log_method = LOG_COM1; + + LOG("Kernel log being sent to COM1\n"); +halt: asm volatile ("cli" ::); for (;;) {} } diff --git a/kernel/log.c b/kernel/log.c new file mode 100644 index 0000000..cf53c8f --- /dev/null +++ b/kernel/log.c @@ -0,0 +1,15 @@ +#include +#include +#include + +extern kernel_ctx_t ctx; + +void logs(const char *str) { + switch (ctx.log_method) { + case LOG_COM1: + serial_puts(COM1, str); + break; + default: + break; + } +} diff --git a/kernel/serial.c b/kernel/serial.c new file mode 100644 index 0000000..2b50aef --- /dev/null +++ b/kernel/serial.c @@ -0,0 +1,44 @@ +#include +#include +#include + +uint8_t serial_port_init(int port) { + // Test port by seeing if scratch register can store a value + uint8_t old_scratch = inb(port + 7); + outb(port + 7, old_scratch + 1); + if (inb(port + 7) != old_scratch + 1) + return 0; + outb(port + 7, old_scratch); + + outb(port + 1, 0x00); // Disable all interrupts + outb(port + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + outb(port + 1, 0x00); // (hi byte) + outb(port + 3, 0x03); // 8 bits, no parity, one stop bit + outb(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set + outb(port + 4, 0x1E); // Set in loopback mode, test the serial chip + outb(port + 0, 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 + 0) != 0xAE) + return 0; + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + outb(port + 4, 0x0F); + return 1; +} + +void serial_putc(int port, const char c) { + // Poll until transmit is empty + while(!IS_TRANSMIT_EMPTY(port)) cpu_relax; + outb(port, c); +} + +void serial_puts(int port, const char *str) { + while (*str) { + serial_putc(port, str[0]); + str++; + } +}