Hello world over serial

This commit is contained in:
2025-12-16 23:09:13 +01:00
parent c4c1939637
commit 13fee12f59
23 changed files with 2272 additions and 5 deletions

View File

@@ -1,5 +1,11 @@
#include <limine/limine.h>
#include <amd64/init.h>
#include <sys/debug.h>
void bootmain(void) {
amd64_init();
DEBUG("Hello from amd64!\n");
for (;;);
}

46
kernel/amd64/debug.c Normal file
View File

@@ -0,0 +1,46 @@
#include <libk/std.h>
#include <libk/string.h>
#include <libk/printf.h>
#include <sys/debug.h>
#include <amd64/debug.h>
#include <amd64/io.h>
#define PORT_COM1 0x03F8
#define BUFFER_SIZE 1024
static bool amd64_debug_serial_tx_empty(void) {
return (bool)(amd64_io_inb(PORT_COM1 + 5) & 0x20);
}
static void amd64_debug_serial_write(char x) {
while (!amd64_debug_serial_tx_empty());
amd64_io_outb(PORT_COM1, (uint8_t)x);
}
void debugprintf(const char *fmt, ...) {
char buffer[BUFFER_SIZE];
memset(buffer, 0, sizeof(buffer));
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
buffer[sizeof(buffer) - 1] = '\0';
const char *p = buffer;
while (*p) {
amd64_debug_serial_write(*p);
p++;
}
}
void amd64_debug_init(void) {
amd64_io_outb(PORT_COM1 + 1, 0x00);
amd64_io_outb(PORT_COM1 + 3, 0x80);
amd64_io_outb(PORT_COM1 + 0, 0x03);
amd64_io_outb(PORT_COM1 + 1, 0x00);
amd64_io_outb(PORT_COM1 + 3, 0x03);
amd64_io_outb(PORT_COM1 + 2, 0xC7);
amd64_io_outb(PORT_COM1 + 4, 0x0B);
}

6
kernel/amd64/debug.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _KERNEL_AMD64_DEBUG_H
#define _KERNEL_AMD64_DEBUG_H
void amd64_debug_init(void);
#endif // _KERNEL_AMD64_DEBUG_H

View File

@@ -1,3 +1,4 @@
cflags += --target=x86_64-pc-none-elf
ldflags += --target=x86_64-pc-none-elf
ldflags += --target=x86_64-pc-none-elf \
-Wl,-zmax-page-size=0x1000

105
kernel/amd64/init.c Normal file
View File

@@ -0,0 +1,105 @@
#include <libk/std.h>
#include <libk/string.h>
#include <amd64/init.h>
#include <amd64/tss.h>
#include <amd64/debug.h>
#define GDT_KCODE 0x08
#define GDT_KDATA 0x10
#define GDT_UCODE 0x18
#define GDT_UDATA 0x20
#define GDT_TSS 0x28
#define TSS 0x80
#define TSS_PRESENT 0x89
#define KSTACK_SIZE (8*1024)
struct gdt_entry {
uint16_t limitlow;
uint16_t baselow;
uint8_t basemid;
uint8_t access;
uint8_t gran;
uint8_t basehigh;
} __attribute__((packed));
struct gdt_ptr {
uint16_t limit;
uint64_t base;
} __attribute__((packed));
struct gdt_extended {
struct gdt_entry old[5];
struct gdt_entry tsslow;
struct gdt_entry tsshigh;
} __attribute__((packed));
__attribute__((aligned(16))) static volatile uint8_t kernel_stack[KSTACK_SIZE];
__attribute__((aligned(16))) static volatile struct gdt_extended gdt;
static void amd64_gdt_set(volatile struct gdt_entry *ent, uint32_t base,
uint32_t limit, uint8_t acc, uint8_t gran) {
ent->baselow = (base & 0xFFFF);
ent->basemid = (base >> 16) & 0xFF;
ent->basehigh = (base >> 24) & 0xFF;
ent->limitlow = (limit & 0xFFFF);
ent->gran = ((limit >> 16) & 0x0F) | (gran & 0xF0);
ent->access = acc;
}
static void amd64_gdt_init(void) {
volatile struct tss *tss = amd64_get_tss();
memset((void *)&gdt, 0, sizeof(gdt));
memset((void *)kernel_stack, 0, sizeof(kernel_stack));
memset((void *)tss, 0, sizeof(*tss));
tss->iopb_off = sizeof(*tss);
tss->rsp0 = (uint64_t)((uintptr_t)kernel_stack + sizeof(kernel_stack));
uint64_t tssbase = (uint64_t)&tss;
uint64_t tsslimit = sizeof(*tss) - 1;
amd64_gdt_set(&gdt.old[0], 0, 0, 0, 0);
amd64_gdt_set(&gdt.old[1], 0, 0xFFFFF, 0x9A, 0xA0);
amd64_gdt_set(&gdt.old[2], 0, 0xFFFFF, 0x92, 0xC0);
amd64_gdt_set(&gdt.old[3], 0, 0xFFFFF, 0xFA, 0xA0);
amd64_gdt_set(&gdt.old[4], 0, 0xFFFFF, 0xF2, 0xC0);
amd64_gdt_set(&gdt.tsslow, (tssbase & 0xFFFFFFFF), tsslimit, TSS_PRESENT | TSS, 0);
uint32_t tssbasehigh = (tssbase >> 32);
gdt.tsshigh.limitlow = (tssbasehigh & 0xFFFF);
gdt.tsshigh.baselow = (tssbasehigh >> 16) & 0xFFFF;
gdt.tsshigh.basemid = 0;
gdt.tsshigh.basehigh = 0;
gdt.tsshigh.access = 0;
gdt.tsshigh.gran = 0;
struct gdt_ptr gdtr;
gdtr.limit = sizeof(gdt) - 1;
gdtr.base = (uint64_t)&gdt;
__asm__ volatile("lgdt %0" :: "m"(gdtr) : "memory");
__asm__ volatile(
"pushq %[kcode]\n"
"lea 1f(%%rip), %%rax\n"
"pushq %%rax\n"
"lretq\n"
"1:\n"
"movw %[kdata], %%ax\n"
"movw %%ax, %%ds\n"
"movw %%ax, %%es\n"
"movw %%ax, %%ss\n"
:
: [kcode] "i"(GDT_KCODE), [kdata] "i"(GDT_KDATA)
: "rax", "memory"
);
__asm__ volatile("ltr %0" :: "r"((uint16_t)GDT_TSS));
}
void amd64_init(void) {
amd64_gdt_init();
amd64_debug_init();
}

6
kernel/amd64/init.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _KERNEL_AMD64_INIT_H
#define _KERNEL_AMD64_INIT_H
void amd64_init(void);
#endif // _KERNEL_AMD64_INIT_H

54
kernel/amd64/io.c Normal file
View File

@@ -0,0 +1,54 @@
#include <libk/std.h>
#include <amd64/io.h>
void amd64_io_outb(uint16_t port, uint8_t v) {
__asm__ volatile("outb %1, %0" :: "dN"(port), "a"(v));
}
void amd64_io_outw(uint16_t port, uint16_t v) {
__asm__ volatile("outw %%ax, %%dx" :: "a"(v), "d"(port));
}
void amd64_io_outl(uint16_t port, uint32_t v) {
__asm__ volatile("outl %%eax, %%dx" :: "d"(port), "a"(v));
}
void amd64_io_outsw(uint16_t port, const void *addr, int cnt) {
__asm__ volatile(
"cld; rep outsw"
: "+S"(addr), "+c"(cnt)
: "d"(port)
: "memory", "cc"
);
}
uint8_t amd64_io_inb(uint16_t port) {
uint8_t r;
__asm__ volatile("inb %1, %0" : "=a"(r) : "dN"(port));
return r;
}
uint16_t amd64_io_inw(uint16_t port) {
uint16_t r;
__asm__ volatile("inw %%dx, %%ax" : "=a"(r) : "d"(port));
return r;
}
uint32_t amd64_io_inl(uint16_t port) {
uint32_t r;
__asm__ volatile("inl %%dx, %%eax" : "=a"(r) : "d"(port));
return r;
}
void amd64_io_insw(uint16_t port, void *addr, int cnt) {
__asm__ volatile(
"cld; rep insw"
: "+D"(addr), "+c"(cnt)
: "d"(port)
: "memory", "cc"
);
}
void amd64_io_wait(void) {
amd64_io_outb(0x80, 0);
}

16
kernel/amd64/io.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef _KERNEL_AMD64_IO_H
#define _KERNEL_AMD64_IO_H
#include <libk/std.h>
void amd64_io_outb(uint16_t port, uint8_t v);
void amd64_io_outw(uint16_t port, uint16_t v);
void amd64_io_outl(uint16_t port, uint32_t v);
void amd64_io_outsw(uint16_t port, const void *addr, int cnt);
uint8_t amd64_io_inb(uint16_t port);
uint16_t amd64_io_inw(uint16_t port);
uint32_t amd64_io_inl(uint16_t port);
void amd64_io_insw(uint16_t port, void *addr, int cnt);
void amd64_io_wait(void);
#endif // _KERNEL_AMD64_IO_H

View File

@@ -1,3 +1,11 @@
c += amd64/bootmain.c
c += amd64/bootmain.c \
amd64/init.c \
amd64/tss.c \
amd64/io.c \
amd64/debug.c
o += amd64/bootmain.o
o += amd64/bootmain.o \
amd64/init.o \
amd64/tss.o \
amd64/io.o \
amd64/debug.o

8
kernel/amd64/tss.c Normal file
View File

@@ -0,0 +1,8 @@
#include <libk/std.h>
#include <amd64/tss.h>
__attribute__((aligned(16))) static volatile struct tss tss;
volatile struct tss *amd64_get_tss(void) {
return &tss;
}

20
kernel/amd64/tss.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef _KERNEL_AMD64_TSS_H
#define _KERNEL_AMD64_TSS_H
#include <libk/std.h>
struct tss {
uint32_t resv0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
uint16_t resv3;
uint16_t iopb_off;
} __attribute__((packed));
volatile struct tss *amd64_get_tss(void);
#endif // _KERNEL_AMD64_TSS_H