Add basic vga kernel module
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,4 +2,4 @@ _o/
|
||||
build/
|
||||
picolibc/
|
||||
picolibc-install/
|
||||
lib/
|
||||
/lib/
|
||||
@@ -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
9
scripts/build_js.js
Executable 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 ")
|
||||
);
|
||||
@@ -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);
|
||||
|
||||
@@ -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
8
src/os/src/index.ts
Normal 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));
|
||||
}
|
||||
12
src/os/src/kernel/index.ts
Normal file
12
src/os/src/kernel/index.ts
Normal 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");
|
||||
}
|
||||
3
src/os/src/kernel/modules/graphics/config.ts
Normal file
3
src/os/src/kernel/modules/graphics/config.ts
Normal 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;
|
||||
1
src/os/src/kernel/modules/graphics/graphics.kmod.ts
Normal file
1
src/os/src/kernel/modules/graphics/graphics.kmod.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./vga";
|
||||
41
src/os/src/kernel/modules/graphics/vga.ts
Normal file
41
src/os/src/kernel/modules/graphics/vga.ts
Normal 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);
|
||||
}
|
||||
21
src/os/src/kernel/panic.ts
Normal file
21
src/os/src/kernel/panic.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
3
src/os/src/lib/libts/byte.ts
Normal file
3
src/os/src/lib/libts/byte.ts
Normal 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
1
src/os/src/types/c/bindings.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare function $addrw(address: number, value: number): void;
|
||||
1
src/os/types/kernel/functions.d.ts
vendored
1
src/os/types/kernel/functions.d.ts
vendored
@@ -1 +0,0 @@
|
||||
declare function writeMemory(address: number, value: number): void;
|
||||
Reference in New Issue
Block a user