Add basic vga kernel module

This commit is contained in:
2025-11-19 21:23:25 +01:00
parent 5ac82c308d
commit f87b00b46f
14 changed files with 108 additions and 52 deletions

2
.gitignore vendored
View File

@@ -2,4 +2,4 @@ _o/
build/
picolibc/
picolibc-install/
lib/
/lib/

View File

@@ -26,16 +26,19 @@ mkdir -p "$OUT_DIR"
# Build TypeScript to JavaScript
cd src/os
echo "Compiling TypeScript to JavaScript..."
bun build --outdir ../../build --target node --bundle kernel/index.ts
bun build --outdir ../../build --target node --bundle src/index.ts
cd ../../
# Generate embedded JavaScript header
echo "Generating embedded JavaScript..."
bun scripts/build_js.js
python3 scripts/embed_js.py build/index.js > "$BUILD_DIR/embedded_js.h"
# Compiler flags
CFLAGS="-m32 -march=i686 -ffreestanding -nostdlib -fno-builtin"
CFLAGS="$CFLAGS -I$PICOLIBC_INSTALL/include"
CFLAGS="$CFLAGS -I./lib/duktape/src"
CFLAGS="$CFLAGS -I./src/lib"
CFLAGS="$CFLAGS -I./src"
CFLAGS="$CFLAGS -I$BUILD_DIR"

9
scripts/build_js.js Executable file
View File

@@ -0,0 +1,9 @@
#! /usr/bin/env bun
import { readFileSync, writeFileSync } from "fs";
writeFileSync(
"build/index.js",
readFileSync("build/index.js", "utf-8")
.replaceAll("let ", "var ")
.replaceAll("const ", "var ")
);

View File

@@ -1,6 +1,6 @@
#include <string.h>
#include <stdint.h>
#include <../lib/duktape/src/duktape.h>
#include <duktape.h>
#include "embedded_js.h"
#define WHITE_TXT 0x0F
@@ -10,15 +10,7 @@ unsigned int k_printf(char *message, unsigned int line);
duk_context *ctx;
duk_ret_t native_print(duk_context *ctx)
{
const char *msg = duk_to_string(ctx, 0);
// k_clear_screen();
k_printf((char *)msg, 0);
return 0;
}
duk_ret_t native_write_memory(duk_context *ctx)
duk_ret_t native_addrw(duk_context *ctx)
{
// Get the address (first argument)
uint32_t address = (uint32_t)duk_to_uint32(ctx, 0);
@@ -38,13 +30,9 @@ void kmain()
// Initialize Duktape heap
ctx = duk_create_heap_default();
// Register native print function
duk_push_c_function(ctx, native_print, DUK_VARARGS);
duk_put_global_string(ctx, "print");
// Register native memory write function
duk_push_c_function(ctx, native_write_memory, 2);
duk_put_global_string(ctx, "writeMemory");
duk_push_c_function(ctx, native_addrw, 2);
duk_put_global_string(ctx, "$addrw");
// Execute embedded JavaScript code from build/index.js
duk_push_string(ctx, embedded_js_code);

View File

@@ -1,33 +0,0 @@
const SCREEN_WIDTH = 80;
const SCREEN_HEIGHT = 25;
const VIDEO_MEMORY_START = 0xb8000;
clearScreen();
print("Welcome to Lints OS!", 0, 0, 0x0a); // Light green on black
function clearScreen(): void {
for (var row = 0; row < SCREEN_HEIGHT; row++) {
for (var col = 0; col < SCREEN_WIDTH; col++) {
const address = VIDEO_MEMORY_START + 2 * (row * SCREEN_WIDTH + col);
writeMemory(address, 0x20); // ASCII space
writeMemory(address + 1, 0x07); // Light grey on black
}
}
}
function writeChar(
row: number,
col: number,
char: string,
color: number
): void {
const address = VIDEO_MEMORY_START + 2 * (row * SCREEN_WIDTH + col);
writeMemory(address, char.charCodeAt(0));
writeMemory(address + 1, color);
}
function print(text: string, row: number, col: number, color: number): void {
for (var i = 0; i < text.length; i++) {
writeChar(row, col + i, text[i]!, color);
}
}

8
src/os/src/index.ts Normal file
View File

@@ -0,0 +1,8 @@
import { kmain } from "./kernel";
import { kpanic } from "./kernel/panic";
try {
kmain();
} catch (e) {
kpanic(e instanceof Error ? e.message : String(e));
}

View File

@@ -0,0 +1,12 @@
import {
kmod_graphics_vga_clear,
kmod_graphics_vga_writeChar,
} from "./modules/graphics/vga";
export function kmain() {
kmod_graphics_vga_clear();
kmod_graphics_vga_writeChar(0, 0, "H", 0x0f);
kmod_graphics_vga_writeChar(1, 0, "i", 0x0f);
throw new Error("Simulated kernel panic");
}

View File

@@ -0,0 +1,3 @@
export const CFG_KMOD_GRAPHICS_VGA_WIDTH = 80;
export const CFG_KMOD_GRAPHICS_VGA_HEIGHT = 25;
export const CFG_KMOD_GRAPGICS_VGA_MEM_ADDR = 0xb8000;

View File

@@ -0,0 +1 @@
export * from "./vga";

View File

@@ -0,0 +1,41 @@
import { charc } from "../../../lib/libts/byte";
import {
CFG_KMOD_GRAPGICS_VGA_MEM_ADDR,
CFG_KMOD_GRAPHICS_VGA_HEIGHT,
CFG_KMOD_GRAPHICS_VGA_WIDTH,
} from "./config";
export function kmod_graphics_vga_getCharAddr(x: number, y: number): number {
return (
CFG_KMOD_GRAPGICS_VGA_MEM_ADDR + (y * CFG_KMOD_GRAPHICS_VGA_WIDTH + x) * 2
);
}
export function kmod_graphics_vga_getColorAddr(x: number, y: number): number {
return (
CFG_KMOD_GRAPGICS_VGA_MEM_ADDR +
(y * CFG_KMOD_GRAPHICS_VGA_WIDTH + x) * 2 +
1
);
}
export function kmod_graphics_vga_clear() {
for (let y = 0; y < CFG_KMOD_GRAPHICS_VGA_HEIGHT; y++) {
for (let x = 0; x < CFG_KMOD_GRAPHICS_VGA_WIDTH; x++) {
kmod_graphics_vga_writeChar(x, y, " ", 0x07);
}
}
}
export function kmod_graphics_vga_writeChar(
x: number,
y: number,
char: string,
color: number
) {
const charAddr = kmod_graphics_vga_getCharAddr(x, y);
const colorAddr = kmod_graphics_vga_getColorAddr(x, y);
$addrw(charAddr, charc(char));
$addrw(colorAddr, color);
}

View File

@@ -0,0 +1,21 @@
import {
kmod_graphics_vga_clear,
kmod_graphics_vga_writeChar,
} from "./modules/graphics/vga";
export function kpanic(reason?: string) {
kmod_graphics_vga_clear();
const l1 = "KERNEL PANIC!";
let l2 = "Unknown: Kernel crashed.";
if (reason) l2 = "Reason: " + reason;
for (let i = 0; i < l1.length; i++) {
kmod_graphics_vga_writeChar(i, 0, l1[i]!, 0x0c);
}
for (let i = 0; i < l2.length; i++) {
kmod_graphics_vga_writeChar(i, 1, l2[i]!, 0x0c);
}
}

View File

@@ -0,0 +1,3 @@
export function charc(char: string): number {
return char.charCodeAt(0);
}

1
src/os/src/types/c/bindings.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
declare function $addrw(address: number, value: number): void;

View File

@@ -1 +0,0 @@
declare function writeMemory(address: number, value: number): void;