From af5d8c709b035f5f031ab273bb54ed2354dc7f14 Mon Sep 17 00:00:00 2001 From: Martin Petr Date: Sat, 29 Nov 2025 23:14:51 +0100 Subject: [PATCH] Add typescript kernel loader --- core/src/main.c | 25 +++++++++++--- os/.gitignore | 34 +++++++++++++++++++ os/README.md | 15 ++++++++ os/bun.lock | 25 ++++++++++++++ os/package.json | 12 +++++++ os/src/index.ts | 12 +++++++ os/src/kernel/index.ts | 13 +++++++ os/src/kernel/modules/console/console.kmod.ts | 11 ++++++ os/src/kernel/panic.ts | 12 +++++++ os/src/libs/logger.ts | 7 ++++ os/src/types/global_c_bindings.d.ts | 5 +++ os/tsconfig.json | 29 ++++++++++++++++ scripts/build_c.sh | 2 +- scripts/build_ts.sh | 7 ++++ scripts/process_js.js | 20 +++++++++++ 15 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 os/.gitignore create mode 100644 os/README.md create mode 100644 os/bun.lock create mode 100644 os/package.json create mode 100644 os/src/index.ts create mode 100644 os/src/kernel/index.ts create mode 100644 os/src/kernel/modules/console/console.kmod.ts create mode 100644 os/src/kernel/panic.ts create mode 100644 os/src/libs/logger.ts create mode 100644 os/src/types/global_c_bindings.d.ts create mode 100644 os/tsconfig.json create mode 100755 scripts/build_ts.sh create mode 100755 scripts/process_js.js diff --git a/core/src/main.c b/core/src/main.c index 9e406ee..12750ef 100644 --- a/core/src/main.c +++ b/core/src/main.c @@ -1,6 +1,7 @@ #include "main.h" #include "efi.h" #include "duktape.h" +#include "embedded_js.h" duk_context *ctx; EFI_SYSTEM_TABLE* systemTable; @@ -16,7 +17,7 @@ void ascii_to_utf16(const char *ascii, CHAR16 *utf16) { *utf16 = 0; } -duk_ret_t native_log(duk_context *ctx) { +duk_ret_t native_systable_conout_output_string(duk_context *ctx) { CHAR16 buffer[256]; ascii_to_utf16(duk_safe_to_string(ctx, 0), buffer); systemTable->ConOut->OutputString(systemTable->ConOut, buffer); @@ -24,14 +25,30 @@ duk_ret_t native_log(duk_context *ctx) { return 0; } +duk_ret_t native_systable_conout_clear_screen(duk_context *ctx) { + systemTable->ConOut->ClearScreen(systemTable->ConOut); + return 0; +} + +duk_ret_t native_systable_conout_set_attribute(duk_context *ctx) { + systemTable->ConOut->SetAttribute(systemTable->ConOut, duk_to_uint(ctx, 0)); + return 0; +} + int kernel_main(EFI_SYSTEM_TABLE *st) { systemTable = st; ctx = duk_create_heap_default(); - duk_push_c_function(ctx, native_log, 1); - duk_put_global_string(ctx, "$log"); + duk_push_c_function(ctx, native_systable_conout_output_string, 1); + duk_put_global_string(ctx, "$___native_systable_conout_outputString"); - duk_push_string(ctx, "var a = 1 + 2; $log(a);"); + duk_push_c_function(ctx, native_systable_conout_clear_screen, 0); + duk_put_global_string(ctx, "$___native_systable_conout_clearScreen"); + + duk_push_c_function(ctx, native_systable_conout_set_attribute, 1); + duk_put_global_string(ctx, "$___native_systable_conout_setAttribute"); + + duk_push_string(ctx, EMBEDDED_JS); duk_int_t returnCode = duk_peval(ctx); if (returnCode != 0) diff --git a/os/.gitignore b/os/.gitignore new file mode 100644 index 0000000..a14702c --- /dev/null +++ b/os/.gitignore @@ -0,0 +1,34 @@ +# dependencies (bun install) +node_modules + +# output +out +dist +*.tgz + +# code coverage +coverage +*.lcov + +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# caches +.eslintcache +.cache +*.tsbuildinfo + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/os/README.md b/os/README.md new file mode 100644 index 0000000..b65a829 --- /dev/null +++ b/os/README.md @@ -0,0 +1,15 @@ +# os + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v1.2.20. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime. diff --git a/os/bun.lock b/os/bun.lock new file mode 100644 index 0000000..82a131e --- /dev/null +++ b/os/bun.lock @@ -0,0 +1,25 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "os", + "devDependencies": { + "@types/bun": "latest", + }, + "peerDependencies": { + "typescript": "^5", + }, + }, + }, + "packages": { + "@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="], + + "@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="], + + "bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + } +} diff --git a/os/package.json b/os/package.json new file mode 100644 index 0000000..978288d --- /dev/null +++ b/os/package.json @@ -0,0 +1,12 @@ +{ + "name": "os", + "module": "src/index.ts", + "type": "module", + "private": true, + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5" + } +} diff --git a/os/src/index.ts b/os/src/index.ts new file mode 100644 index 0000000..af28d2f --- /dev/null +++ b/os/src/index.ts @@ -0,0 +1,12 @@ +import { kmain } from "./kernel"; +import { kpanic } from "./kernel/panic"; + +try { + const res = kmain(); + + if (res != 0) { + kpanic("Kernel returned non-zero exit code"); + } +} catch (e) { + kpanic(e instanceof Error ? e.message : String(e)); +} diff --git a/os/src/kernel/index.ts b/os/src/kernel/index.ts new file mode 100644 index 0000000..1a9d1d9 --- /dev/null +++ b/os/src/kernel/index.ts @@ -0,0 +1,13 @@ +import { Logger } from "../libs/logger"; +import { + kmod_console_clearScreen, + kmod_console_outputString, +} from "./modules/console/console.kmod"; + +export function kmain() { + kmod_console_clearScreen(); + + Logger.log("[Kernel] Starting kernel..."); + + return 0; +} diff --git a/os/src/kernel/modules/console/console.kmod.ts b/os/src/kernel/modules/console/console.kmod.ts new file mode 100644 index 0000000..2154918 --- /dev/null +++ b/os/src/kernel/modules/console/console.kmod.ts @@ -0,0 +1,11 @@ +export function kmod_console_clearScreen() { + $___native_systable_conout_clearScreen(); +} + +export function kmod_console_setAttribute(attribute: number) { + $___native_systable_conout_setAttribute(attribute); +} + +export function kmod_console_outputString(string: string) { + $___native_systable_conout_outputString(string); +} diff --git a/os/src/kernel/panic.ts b/os/src/kernel/panic.ts new file mode 100644 index 0000000..c5c494f --- /dev/null +++ b/os/src/kernel/panic.ts @@ -0,0 +1,12 @@ +import { + kmod_console_clearScreen, + kmod_console_outputString, + kmod_console_setAttribute, +} from "./modules/console/console.kmod"; + +export function kpanic(message: string) { + kmod_console_clearScreen(); + kmod_console_setAttribute(0x0c); + kmod_console_outputString("Kernel panic: \\r\\n"); + kmod_console_outputString(message); +} diff --git a/os/src/libs/logger.ts b/os/src/libs/logger.ts new file mode 100644 index 0000000..353d5a9 --- /dev/null +++ b/os/src/libs/logger.ts @@ -0,0 +1,7 @@ +import { kmod_console_outputString } from "../kernel/modules/console/console.kmod"; + +export const Logger = { + log: function (message: string) { + kmod_console_outputString(message + "\\r\\n"); + }, +}; diff --git a/os/src/types/global_c_bindings.d.ts b/os/src/types/global_c_bindings.d.ts new file mode 100644 index 0000000..3b6abd8 --- /dev/null +++ b/os/src/types/global_c_bindings.d.ts @@ -0,0 +1,5 @@ +declare function $___native_systable_conout_outputString(string: string): void; +declare function $___native_systable_conout_clearScreen(): void; +declare function $___native_systable_conout_setAttribute( + attribute: number +): void; diff --git a/os/tsconfig.json b/os/tsconfig.json new file mode 100644 index 0000000..bfa0fea --- /dev/null +++ b/os/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + // Environment setup & latest features + "lib": ["ESNext"], + "target": "ESNext", + "module": "Preserve", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/scripts/build_c.sh b/scripts/build_c.sh index acac3c0..1a111fa 100755 --- a/scripts/build_c.sh +++ b/scripts/build_c.sh @@ -4,7 +4,7 @@ mkdir -p out/img/EFI/BOOT mkdir -p out/lib clang -target x86_64-pc-win32-coff -fno-stack-protector -fshort-wchar -mno-red-zone -Iedk2/MdePkg/Include -Iedk2/MdePkg/Include/X64 -c core/src/efi.c -o out/core/efi.o -clang -target x86_64-pc-win32-coff -fno-stack-protector -fshort-wchar -mno-red-zone -Icore/compat -Icore/lib/duktape/src -Iedk2/MdePkg/Include -Iedk2/MdePkg/Include/X64 -Iedk2/CryptoPkg/Library/Include -c core/src/main.c -o out/core/main.o +clang -target x86_64-pc-win32-coff -fno-stack-protector -fshort-wchar -mno-red-zone -Icore/compat -Icore/lib/duktape/src -Iedk2/MdePkg/Include -Iedk2/MdePkg/Include/X64 -Iedk2/CryptoPkg/Library/Include -Iout -c core/src/main.c -o out/core/main.o clang -target x86_64-pc-win32-coff -fno-stack-protector -fshort-wchar -mno-red-zone -DDUK_F_GENERIC -U_WIN32 -UWIN32 -U_WIN64 -UWIN64 -Icore/compat -Iedk2/MdePkg/Include -Iedk2/MdePkg/Include/X64 -Iedk2/CryptoPkg/Library/Include -c core/lib/duktape/src/duktape.c -o out/lib/duktape.o clang -target x86_64-pc-win32-coff -fno-stack-protector -fshort-wchar -mno-red-zone -Icore/compat -Iedk2/MdePkg/Include -Iedk2/MdePkg/Include/X64 -Iedk2/CryptoPkg/Library/Include -c core/src/compat.c -o out/core/compat.o diff --git a/scripts/build_ts.sh b/scripts/build_ts.sh new file mode 100755 index 0000000..94d3126 --- /dev/null +++ b/scripts/build_ts.sh @@ -0,0 +1,7 @@ +# Build TypeScript to JavaScript +cd os +echo "Compiling TypeScript to JavaScript..." +bun build --outdir ../out/os --target node --bundle src/index.ts +cd .. + +./scripts/process_js.js diff --git a/scripts/process_js.js b/scripts/process_js.js new file mode 100755 index 0000000..e059c45 --- /dev/null +++ b/scripts/process_js.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +const fs = require("fs"); + +const script = fs.readFileSync("out/os/index.js", "utf-8"); +const processed = script + /*.replaceAll("let ", "var ") + .replaceAll("const ", "var ")*/ + .replaceAll("\n`", "\\n`") + .replaceAll("`", "'"); + +fs.writeFileSync( + "out/embedded_js.h", + ` + #ifndef EMBEDDED_JS_H + #define EMBEDDED_JS_H + const char *EMBEDDED_JS = "${processed + .replaceAll('"', '\\"') + .replaceAll("\n", "\\n")}"; + #endif` +);