build: replace hosted target with static linux and add kernel target

Co-authored-by: aider (openrouter/moonshotai/kimi-k2.6) <aider@aider.chat>
This commit is contained in:
2026-05-04 10:48:51 +03:00
parent fcbc810db8
commit 23451c8e85
4 changed files with 279 additions and 8 deletions
+9 -8
View File
@@ -2,21 +2,22 @@ CC = clang
CFLAGS = -Wall -Wextra -g -std=c11
COMMON_SRCS = forth_core.c forth_dict.c forth_words.c forth_interp.c main.c
HOSTED_SRCS = $(COMMON_SRCS) platform_hosted.c
FREESTANDING_SRCS = $(COMMON_SRCS) platform_freestanding.c
LINUX_SRCS = $(COMMON_SRCS) platform_linux.c
KERNEL_SRCS = $(COMMON_SRCS) platform_kernel.c kernel_entry.S
KERNEL_LD = kernel.ld
TARGET = forth
FREESTANDING_TARGET = forth_freestanding
KERNEL_TARGET = forth.kernel
all: $(TARGET)
$(TARGET): $(HOSTED_SRCS) forth.h
$(CC) $(CFLAGS) -D_POSIX_C_SOURCE=200809L -o $@ $(HOSTED_SRCS)
$(TARGET): $(LINUX_SRCS) forth.h
$(CC) $(CFLAGS) -static -nostdlib -ffreestanding -fno-stack-protector -o $@ $(LINUX_SRCS)
$(FREESTANDING_TARGET): $(FREESTANDING_SRCS) forth.h
$(CC) $(CFLAGS) -ffreestanding -nostdlib -fno-stack-protector -o $@ $(FREESTANDING_SRCS)
$(KERNEL_TARGET): $(KERNEL_SRCS) forth.h $(KERNEL_LD)
$(CC) $(CFLAGS) -ffreestanding -nostdlib -fno-stack-protector -mno-red-zone -o $@ $(KERNEL_SRCS) -T$(KERNEL_LD) -Wl,--build-id=none
clean:
rm -f $(TARGET) $(FREESTANDING_TARGET)
rm -f $(TARGET) $(KERNEL_TARGET)
.PHONY: all clean
+30
View File
@@ -0,0 +1,30 @@
ENTRY(_start)
SECTIONS
{
. = 0x100000;
.text : ALIGN(4K)
{
*(.multiboot2)
*(.text)
}
.rodata : ALIGN(4K)
{
*(.rodata)
}
.data : ALIGN(4K)
{
*(.data)
}
.bss : ALIGN(4K)
{
__bss_start = .;
*(.bss)
*(COMMON)
__bss_end = .;
}
}
+98
View File
@@ -0,0 +1,98 @@
# Multiboot2 header and x86_64 long-mode bootstrap
.section .multiboot2, "a"
.align 8
multiboot_header:
.long 0xe85250d6
.long 0
.long multiboot_header_end - multiboot_header
.long -(0xe85250d6 + 0 + (multiboot_header_end - multiboot_header))
.align 8
.word 0
.word 0
.long 8
multiboot_header_end:
.section .bss, "aw", @nobits
.align 4096
pml4:
.space 4096
pdpt:
.space 4096
pd:
.space 4096
.align 16
stack_bottom:
.space 16384
stack_top:
.section .text
.code32
.global _start
.type _start, @function
_start:
movl $stack_top, %esp
movl $pdpt, %eax
orl $0x03, %eax
movl %eax, pml4
movl $pd, %eax
orl $0x03, %eax
movl %eax, pdpt
movl $0x00000083, %eax
movl $pd, %edi
movl $512, %ecx
1:
movl %eax, (%edi)
addl $0x200000, %eax
addl $8, %edi
loop 1b
movl $pml4, %eax
movl %eax, %cr3
movl %cr4, %eax
orl $0x20, %eax
movl %eax, %cr4
movl $0xC0000080, %ecx
rdmsr
orl $0x100, %eax
wrmsr
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0
lgdt gdt64_pointer
ljmp $0x08, $long_mode_start
.code64
long_mode_start:
movabsq $stack_top, %rax
movq %rax, %rsp
movabsq $__bss_start, %rdi
movabsq $__bss_end, %rcx
subq %rdi, %rcx
xorq %rax, %rax
rep stosb
call kernel_main
cli
1:
hlt
jmp 1b
.section .rodata
.align 8
gdt64:
.quad 0x0000000000000000
.quad 0x00209A0000000000
gdt64_pointer:
.word gdt64_pointer - gdt64 - 1
.quad gdt64
+142
View File
@@ -0,0 +1,142 @@
#include "forth.h"
#include <stdint.h>
#include <stdarg.h>
// VGA text-mode buffer
static uint16_t* vga_buffer = (uint16_t*)0xB8000;
static int vga_row = 0;
static int vga_col = 0;
static void vga_putchar(char c) {
if (c == '\n') {
vga_col = 0;
vga_row++;
} else {
int idx = vga_row * 80 + vga_col;
vga_buffer[idx] = (uint16_t)((0x0F << 8) | (unsigned char)c);
vga_col++;
if (vga_col >= 80) {
vga_col = 0;
vga_row++;
}
}
if (vga_row >= 25) {
vga_row = 0;
vga_col = 0;
}
}
static inline void outb(uint16_t port, uint8_t val) {
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
__asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static void serial_init(void) {
outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x80);
outb(0x3F8 + 0, 0x01);
outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x03);
outb(0x3F8 + 2, 0xC7);
outb(0x3F8 + 4, 0x0B);
}
void forth_putchar(char c) {
vga_putchar(c);
while ((inb(0x3F8 + 5) & 0x20) == 0) { }
outb(0x3F8, (uint8_t)c);
}
int forth_getchar(void) {
if ((inb(0x3F8 + 5) & 1) == 0) {
return FORTH_EOF;
}
return inb(0x3F8);
}
void forth_fflush(void) {
}
void forth_panic(void) {
__asm__ volatile ("cli; hlt");
__builtin_unreachable();
}
int64_t forth_strtoll(const char* str, char** endptr, int base) {
const char* s = str;
int neg = 0;
int64_t val = 0;
while (forth_isspace(*s)) s++;
if (*s == '-') { neg = 1; s++; }
else if (*s == '+') { s++; }
while (*s >= '0' && *s <= '9') {
val = val * base + (*s - '0');
s++;
}
if (endptr) *endptr = (char*)s;
return neg ? -val : val;
}
static void print_str(const char* s) {
while (*s) forth_putchar(*s++);
}
static void print_int(long long v) {
char buf[32];
int i = 30;
int neg = 0;
if (v < 0) { neg = 1; v = -v; }
buf[31] = '\0';
if (v == 0) {
buf[i--] = '0';
} else {
while (v > 0 && i >= 0) {
buf[i--] = '0' + (v % 10);
v /= 10;
}
}
if (neg) buf[i--] = '-';
print_str(&buf[i + 1]);
}
void forth_printf(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
while (*fmt) {
if (*fmt == '%' && *(fmt + 1)) {
fmt++;
if (*fmt == 's') {
print_str(va_arg(ap, const char*));
} else if (*fmt == 'c') {
forth_putchar((char)va_arg(ap, int));
} else if (*fmt == '%') {
forth_putchar('%');
} else if (*fmt == 'l') {
if (*(fmt + 1) == 'l' && (*(fmt + 2) == 'd' || *(fmt + 2) == 'i' || *(fmt + 2) == 'u')) {
fmt += 2;
print_int(va_arg(ap, long long));
}
} else if (*fmt == 'd' || *fmt == 'i' || *fmt == 'u') {
print_int(va_arg(ap, int));
} else {
forth_putchar('%');
forth_putchar(*fmt);
}
} else {
forth_putchar(*fmt);
}
fmt++;
}
va_end(ap);
}
void kernel_main(void) {
serial_init();
forth_run();
forth_panic();
}