multiboot info, serial ports, logs

This commit is contained in:
rami 2024-06-27 18:36:32 -04:00
parent f6e71429ab
commit e963f0f871
15 changed files with 189 additions and 7 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

20
compile_commands.json Normal file
View File

@ -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"
}
]

9
include/kernel/io.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef HAZEL_IO_H_
#define HAZEL_IO_H_
#include <stdint.h>
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t byte);
#endif

15
include/kernel/kernel.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HAZEL_KERNEL_H_
#define HAZEL_KERNEL_H_
#include <kernel/multiboot.h>
#include <kernel/log.h>
#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

13
include/kernel/log.h Normal file
View File

@ -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

View File

@ -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

21
include/kernel/serial.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef HAZEL_SERIAL_H_
#define HAZEL_SERIAL_H_
#include <stdint.h>
#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

17
kernel/io.c Normal file
View File

@ -0,0 +1,17 @@
#include <kernel/io.h>
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));
}

View File

@ -1,10 +1,19 @@
#include <kernel/kernel.h>
#include <kernel/multiboot.h>
#include <kernel/serial.h>
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 (;;) {}
}

15
kernel/log.c Normal file
View File

@ -0,0 +1,15 @@
#include <kernel/log.h>
#include <kernel/kernel.h>
#include <kernel/serial.h>
extern kernel_ctx_t ctx;
void logs(const char *str) {
switch (ctx.log_method) {
case LOG_COM1:
serial_puts(COM1, str);
break;
default:
break;
}
}

44
kernel/serial.c Normal file
View File

@ -0,0 +1,44 @@
#include <kernel/serial.h>
#include <kernel/io.h>
#include <kernel/kernel.h>
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++;
}
}