No way it works...
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
_o/
|
||||||
|
build/
|
||||||
|
picolibc/
|
||||||
|
picolibc-install/
|
||||||
115
Makefile
Normal file
115
Makefile
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# Makefile for kernel with picolibc
|
||||||
|
.PHONY: all clean picolibc kernel run help
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
PICOLIBC_INSTALL := $(CURDIR)/picolibc-install
|
||||||
|
BUILD_DIR := build
|
||||||
|
OUT_DIR := $(BUILD_DIR)/out
|
||||||
|
SRC_DIR := src
|
||||||
|
|
||||||
|
# Check if picolibc exists
|
||||||
|
PICOLIBC_EXISTS := $(shell test -d $(PICOLIBC_INSTALL) && echo 1 || echo 0)
|
||||||
|
|
||||||
|
# Compiler and flags
|
||||||
|
CC := gcc
|
||||||
|
AS := nasm
|
||||||
|
LD := ld
|
||||||
|
|
||||||
|
CFLAGS := -m32 -march=i686 -ffreestanding -nostdlib -fno-builtin
|
||||||
|
CFLAGS += -I$(PICOLIBC_INSTALL)/include
|
||||||
|
CFLAGS += -I$(SRC_DIR)/lib
|
||||||
|
CFLAGS += -I$(SRC_DIR)
|
||||||
|
CFLAGS += -Wall -Wextra -O2
|
||||||
|
|
||||||
|
ASFLAGS := -f elf32
|
||||||
|
|
||||||
|
LDFLAGS := -m elf_i386 -nostdlib
|
||||||
|
LDFLAGS += -L$(PICOLIBC_INSTALL)/lib
|
||||||
|
LDFLAGS += -T $(SRC_DIR)/link.ld
|
||||||
|
|
||||||
|
# Get libgcc path for compiler runtime support
|
||||||
|
LIBGCC := $(shell $(CC) -m32 -print-libgcc-file-name)
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
OBJS := $(BUILD_DIR)/kasm.o $(BUILD_DIR)/kc.o $(BUILD_DIR)/duktape.o $(BUILD_DIR)/syscalls.o
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
all: check-picolibc kernel
|
||||||
|
|
||||||
|
# Help target
|
||||||
|
help:
|
||||||
|
@echo "Makefile for kernel with picolibc"
|
||||||
|
@echo ""
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " picolibc - Download and build picolibc"
|
||||||
|
@echo " kernel - Build the kernel (requires picolibc)"
|
||||||
|
@echo " run - Build and run the kernel in QEMU"
|
||||||
|
@echo " clean - Clean build artifacts"
|
||||||
|
@echo " clean-all - Clean everything including picolibc"
|
||||||
|
@echo " help - Show this help message"
|
||||||
|
|
||||||
|
# Build picolibc
|
||||||
|
picolibc:
|
||||||
|
@echo "Building picolibc..."
|
||||||
|
@chmod +x build-picolibc.sh
|
||||||
|
@./build-picolibc.sh
|
||||||
|
|
||||||
|
# Check if picolibc is built
|
||||||
|
check-picolibc:
|
||||||
|
ifneq ($(PICOLIBC_EXISTS),1)
|
||||||
|
@echo "Error: Picolibc not found. Building it now..."
|
||||||
|
@$(MAKE) picolibc
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Create build directories
|
||||||
|
$(BUILD_DIR):
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
$(OUT_DIR): | $(BUILD_DIR)
|
||||||
|
@mkdir -p $(OUT_DIR)
|
||||||
|
|
||||||
|
# Build boot assembly
|
||||||
|
$(BUILD_DIR)/kasm.o: $(SRC_DIR)/boot/kernel.asm | $(BUILD_DIR)
|
||||||
|
@echo "Assembling boot code..."
|
||||||
|
@$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
|
# Build duktape
|
||||||
|
$(BUILD_DIR)/duktape.o: $(SRC_DIR)/lib/duktape.c $(SRC_DIR)/lib/duktape.h | $(BUILD_DIR)
|
||||||
|
@echo "Building Duktape..."
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Build kernel
|
||||||
|
$(BUILD_DIR)/kc.o: $(SRC_DIR)/kernel/kernel.c | $(BUILD_DIR)
|
||||||
|
@echo "Building kernel..."
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Build syscalls
|
||||||
|
$(BUILD_DIR)/syscalls.o: $(SRC_DIR)/lib/syscalls.c | $(BUILD_DIR)
|
||||||
|
@echo "Building syscalls..."
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Link kernel
|
||||||
|
$(OUT_DIR)/kernel: $(OBJS) | $(OUT_DIR)
|
||||||
|
@echo "Linking kernel..."
|
||||||
|
@$(LD) $(LDFLAGS) -o $@ $(OBJS) -lc $(LIBGCC)
|
||||||
|
@echo "Build complete: $@"
|
||||||
|
|
||||||
|
# Main kernel target
|
||||||
|
kernel: check-picolibc $(OUT_DIR)/kernel
|
||||||
|
|
||||||
|
# Run in QEMU
|
||||||
|
run: kernel
|
||||||
|
@echo "Running kernel in QEMU..."
|
||||||
|
@qemu-system-i386 -kernel $(OUT_DIR)/kernel
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
clean:
|
||||||
|
@echo "Cleaning build artifacts..."
|
||||||
|
@rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
|
# Clean everything including picolibc
|
||||||
|
clean-all: clean
|
||||||
|
@echo "Cleaning picolibc..."
|
||||||
|
@rm -rf picolibc picolibc-install
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
56
build-picolibc.sh
Normal file
56
build-picolibc.sh
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script to build picolibc for i686 freestanding environment
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PICOLIBC_DIR="picolibc"
|
||||||
|
BUILD_DIR="build/picolibc"
|
||||||
|
INSTALL_DIR="$(pwd)/picolibc-install"
|
||||||
|
|
||||||
|
echo "=== Building Picolibc for i686 freestanding ==="
|
||||||
|
|
||||||
|
# Check if picolibc exists
|
||||||
|
if [ ! -d "$PICOLIBC_DIR" ]; then
|
||||||
|
echo "Error: Picolibc source not found at $PICOLIBC_DIR"
|
||||||
|
echo "Please clone picolibc manually:"
|
||||||
|
echo " git clone https://github.com/picolibc/picolibc.git"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get current version
|
||||||
|
cd "$PICOLIBC_DIR"
|
||||||
|
CURRENT_VERSION=$(git describe --tags 2>/dev/null || echo "unknown")
|
||||||
|
echo "Using picolibc version: $CURRENT_VERSION"
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Create build directory
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
|
||||||
|
echo "Configuring picolibc with meson..."
|
||||||
|
meson setup "$BUILD_DIR" "$PICOLIBC_DIR" \
|
||||||
|
--cross-file picolibc-i686.txt \
|
||||||
|
--prefix="$INSTALL_DIR" \
|
||||||
|
--wipe \
|
||||||
|
-Dmultilib=false \
|
||||||
|
-Dpicocrt=false \
|
||||||
|
-Dsemihost=false \
|
||||||
|
-Dspecsdir=none \
|
||||||
|
-Dtinystdio=true \
|
||||||
|
-Dio-long-long=true \
|
||||||
|
-Dformat-default=double \
|
||||||
|
-Dtests=false
|
||||||
|
|
||||||
|
echo "Building picolibc..."
|
||||||
|
meson compile -C "$BUILD_DIR"
|
||||||
|
|
||||||
|
echo "Installing picolibc..."
|
||||||
|
meson install -C "$BUILD_DIR"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Picolibc build complete! ==="
|
||||||
|
echo "Installation directory: $INSTALL_DIR"
|
||||||
|
echo ""
|
||||||
|
echo "To use picolibc in your kernel:"
|
||||||
|
echo " Include path: -I$INSTALL_DIR/include"
|
||||||
|
echo " Library path: -L$INSTALL_DIR/lib"
|
||||||
|
echo " Link with: -lc"
|
||||||
18
picolibc-i686.txt
Normal file
18
picolibc-i686.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Meson cross-compilation file for i686-elf with picolibc
|
||||||
|
[binaries]
|
||||||
|
c = 'gcc'
|
||||||
|
ar = 'ar'
|
||||||
|
as = 'as'
|
||||||
|
ld = 'ld'
|
||||||
|
strip = 'strip'
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'none'
|
||||||
|
cpu_family = 'x86'
|
||||||
|
cpu = 'i686'
|
||||||
|
endian = 'little'
|
||||||
|
|
||||||
|
[properties]
|
||||||
|
c_args = ['-m32', '-march=i686']
|
||||||
|
c_link_args = ['-m32']
|
||||||
|
skip_sanity_check = true
|
||||||
47
quickstart.sh
Executable file
47
quickstart.sh
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Quick start script - builds picolibc and kernel, then runs it
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Kernel with Picolibc - Quick Start"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for required tools
|
||||||
|
echo "Checking prerequisites..."
|
||||||
|
|
||||||
|
command -v gcc >/dev/null 2>&1 || { echo "Error: gcc not found"; exit 1; }
|
||||||
|
command -v nasm >/dev/null 2>&1 || { echo "Error: nasm not found"; exit 1; }
|
||||||
|
command -v ld >/dev/null 2>&1 || { echo "Error: ld not found"; exit 1; }
|
||||||
|
command -v qemu-system-i386 >/dev/null 2>&1 || { echo "Error: qemu-system-i386 not found"; exit 1; }
|
||||||
|
|
||||||
|
if ! command -v meson >/dev/null 2>&1; then
|
||||||
|
echo "Warning: meson not found"
|
||||||
|
echo "Install with: pip install --user meson ninja"
|
||||||
|
echo "or: sudo apt install meson ninja-build"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ All prerequisites found"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Build picolibc if not already built
|
||||||
|
if [ ! -d "picolibc-install" ]; then
|
||||||
|
echo "Step 1: Building picolibc (this may take a few minutes)..."
|
||||||
|
./build-picolibc.sh
|
||||||
|
else
|
||||||
|
echo "Step 1: Picolibc already built (skipping)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 2: Building kernel..."
|
||||||
|
make kernel
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 3: Running kernel in QEMU..."
|
||||||
|
echo "(Press Ctrl+A then X to exit QEMU)"
|
||||||
|
echo ""
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
make run
|
||||||
59
scripts/build-with-picolibc.sh
Normal file
59
scripts/build-with-picolibc.sh
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Build script for kernel with picolibc
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
PICOLIBC_INSTALL="$(pwd)/picolibc-install"
|
||||||
|
BUILD_DIR="build"
|
||||||
|
OUT_DIR="$BUILD_DIR/out"
|
||||||
|
|
||||||
|
# Check if picolibc is installed
|
||||||
|
if [ ! -d "$PICOLIBC_INSTALL" ]; then
|
||||||
|
echo "Error: Picolibc not found at $PICOLIBC_INSTALL"
|
||||||
|
echo "Please run ./build-picolibc.sh first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create build directories
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
|
# Compiler flags
|
||||||
|
CFLAGS="-m32 -march=i686 -ffreestanding -nostdlib -fno-builtin"
|
||||||
|
CFLAGS="$CFLAGS -I$PICOLIBC_INSTALL/include"
|
||||||
|
CFLAGS="$CFLAGS -I./src/lib"
|
||||||
|
CFLAGS="$CFLAGS -I./src"
|
||||||
|
CFLAGS="$CFLAGS -Wall -Wextra"
|
||||||
|
|
||||||
|
LDFLAGS="-m elf_i386 -nostdlib"
|
||||||
|
LDFLAGS="$LDFLAGS -L$PICOLIBC_INSTALL/lib"
|
||||||
|
|
||||||
|
echo "=== Building kernel with picolibc ==="
|
||||||
|
|
||||||
|
# Build boot assembly
|
||||||
|
echo "Assembling boot code..."
|
||||||
|
nasm -f elf32 src/boot/kernel.asm -o "$BUILD_DIR/kasm.o"
|
||||||
|
|
||||||
|
# Build duktape with picolibc
|
||||||
|
echo "Building Duktape..."
|
||||||
|
gcc $CFLAGS -c src/lib/duktape.c -o "$BUILD_DIR/duktape.o"
|
||||||
|
|
||||||
|
# Build kernel
|
||||||
|
echo "Building kernel..."
|
||||||
|
gcc $CFLAGS -c src/kernel/kernel.c -o "$BUILD_DIR/kc.o"
|
||||||
|
|
||||||
|
# Link everything together
|
||||||
|
echo "Linking kernel..."
|
||||||
|
ld $LDFLAGS -T src/link.ld -o "$OUT_DIR/kernel" \
|
||||||
|
"$BUILD_DIR/kasm.o" \
|
||||||
|
"$BUILD_DIR/kc.o" \
|
||||||
|
"$BUILD_DIR/duktape.o" \
|
||||||
|
-lc
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Build complete! ==="
|
||||||
|
echo "Kernel binary: $OUT_DIR/kernel"
|
||||||
|
echo ""
|
||||||
|
echo "To run the kernel:"
|
||||||
|
echo " qemu-system-i386 -kernel $OUT_DIR/kernel"
|
||||||
58
scripts/embed_js.py
Executable file
58
scripts/embed_js.py
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Embed JavaScript file as a C string constant
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def escape_c_string(s):
|
||||||
|
"""Escape a string for use in C source code"""
|
||||||
|
result = []
|
||||||
|
for char in s:
|
||||||
|
if char == "\n":
|
||||||
|
result.append("\\n")
|
||||||
|
elif char == "\r":
|
||||||
|
result.append("\\r")
|
||||||
|
elif char == "\t":
|
||||||
|
result.append("\\t")
|
||||||
|
elif char == "\\":
|
||||||
|
result.append("\\\\")
|
||||||
|
elif char == '"':
|
||||||
|
result.append('\\"')
|
||||||
|
elif ord(char) < 32 or ord(char) > 126:
|
||||||
|
result.append(f"\\x{ord(char):02x}")
|
||||||
|
else:
|
||||||
|
result.append(char)
|
||||||
|
return "".join(result)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Usage: embed_js.py <input.js>", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
input_file = sys.argv[1]
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(input_file, "r") as f:
|
||||||
|
js_code = f.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Error: File not found: {input_file}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Generate C header file
|
||||||
|
print("/* Auto-generated file - do not edit */")
|
||||||
|
print("#ifndef EMBEDDED_JS_H")
|
||||||
|
print("#define EMBEDDED_JS_H")
|
||||||
|
print()
|
||||||
|
|
||||||
|
escaped = escape_c_string(js_code)
|
||||||
|
print(f'const char *embedded_js_code = "{escaped}";')
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("#endif /* EMBEDDED_JS_H */")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
77
scripts/run.sh
Executable file
77
scripts/run.sh
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Build and run kernel with picolibc
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
PICOLIBC_INSTALL="$(pwd)/picolibc-install"
|
||||||
|
BUILD_DIR="build"
|
||||||
|
OUT_DIR="$BUILD_DIR/out"
|
||||||
|
|
||||||
|
# Check if picolibc is installed
|
||||||
|
if [ ! -d "$PICOLIBC_INSTALL" ]; then
|
||||||
|
echo "Error: Picolibc not found at $PICOLIBC_INSTALL"
|
||||||
|
echo "Please run: make picolibc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create build directories
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
|
# Copy JavaScript source to build directory
|
||||||
|
cp src/os/index.js build/
|
||||||
|
|
||||||
|
# Generate embedded JavaScript header
|
||||||
|
echo "Generating embedded JavaScript..."
|
||||||
|
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./src/lib"
|
||||||
|
CFLAGS="$CFLAGS -I./src"
|
||||||
|
CFLAGS="$CFLAGS -I$BUILD_DIR"
|
||||||
|
CFLAGS="$CFLAGS -Wall -Wextra"
|
||||||
|
|
||||||
|
LDFLAGS="-m elf_i386 -nostdlib"
|
||||||
|
LDFLAGS="$LDFLAGS -L$PICOLIBC_INSTALL/lib"
|
||||||
|
|
||||||
|
# Get libgcc path
|
||||||
|
LIBGCC=$(gcc -m32 -print-libgcc-file-name)
|
||||||
|
|
||||||
|
echo "=== Building kernel with picolibc ==="
|
||||||
|
|
||||||
|
# Build boot assembly
|
||||||
|
echo "Assembling boot code..."
|
||||||
|
nasm -f elf32 src/boot/kernel.asm -o "$BUILD_DIR/kasm.o"
|
||||||
|
|
||||||
|
# Build duktape
|
||||||
|
echo "Building Duktape..."
|
||||||
|
gcc $CFLAGS -c src/lib/duktape.c -o "$BUILD_DIR/duktape.o"
|
||||||
|
|
||||||
|
# Build kernel
|
||||||
|
echo "Building kernel..."
|
||||||
|
gcc $CFLAGS -c src/kernel/kernel.c -o "$BUILD_DIR/kc.o"
|
||||||
|
|
||||||
|
# Build syscalls
|
||||||
|
echo "Building syscalls..."
|
||||||
|
gcc $CFLAGS -c src/lib/syscalls.c -o "$BUILD_DIR/syscalls.o"
|
||||||
|
|
||||||
|
# Link everything together
|
||||||
|
echo "Linking kernel..."
|
||||||
|
ld $LDFLAGS -T src/link.ld -o "$OUT_DIR/kernel" \
|
||||||
|
"$BUILD_DIR/kasm.o" \
|
||||||
|
"$BUILD_DIR/kc.o" \
|
||||||
|
"$BUILD_DIR/duktape.o" \
|
||||||
|
"$BUILD_DIR/syscalls.o" \
|
||||||
|
-lc "$LIBGCC"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Build complete! ==="
|
||||||
|
echo ""
|
||||||
|
echo "Running kernel in QEMU..."
|
||||||
|
echo "(Press Ctrl+A then X to exit)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
qemu-system-i386 -kernel "$OUT_DIR/kernel"
|
||||||
17
src/boot/kernel.asm
Normal file
17
src/boot/kernel.asm
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
bits 32 ;nasm directive
|
||||||
|
section .text
|
||||||
|
;multiboot spec
|
||||||
|
align 4
|
||||||
|
dd 0x1BADB002 ;magic
|
||||||
|
dd 0x00 ;flags
|
||||||
|
dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
|
||||||
|
|
||||||
|
global start
|
||||||
|
extern kmain ;kmain is defined in the kernel.c file
|
||||||
|
|
||||||
|
start:
|
||||||
|
cli ; stop interrupts
|
||||||
|
|
||||||
|
call kmain
|
||||||
|
|
||||||
|
hlt ; halt the CPU
|
||||||
89
src/kernel/kernel.c
Normal file
89
src/kernel/kernel.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "lib/duktape.h"
|
||||||
|
#include "embedded_js.h"
|
||||||
|
|
||||||
|
#define WHITE_TXT 0x0F
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// Get the address (first argument)
|
||||||
|
uint32_t address = (uint32_t)duk_to_uint32(ctx, 0);
|
||||||
|
|
||||||
|
// Get the value to write (second argument)
|
||||||
|
uint8_t value = (uint8_t)duk_to_uint32(ctx, 1);
|
||||||
|
|
||||||
|
// Write the value to the address
|
||||||
|
uint8_t *ptr = (uint8_t *)address;
|
||||||
|
*ptr = value;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
// Execute embedded JavaScript code from build/index.js
|
||||||
|
duk_push_string(ctx, embedded_js_code);
|
||||||
|
duk_int_t returnCode = duk_peval(ctx);
|
||||||
|
|
||||||
|
if (returnCode != 0)
|
||||||
|
{
|
||||||
|
// Error occurred - display stack trace
|
||||||
|
duk_safe_to_stacktrace(ctx, -1);
|
||||||
|
k_printf((char *)duk_safe_to_string(ctx, -1), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_pop(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int k_printf(char *message, unsigned int line)
|
||||||
|
{
|
||||||
|
char *vidmem = (char *)0xb8000;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
i = (line * 80 * 2);
|
||||||
|
|
||||||
|
while (*message != 0)
|
||||||
|
{
|
||||||
|
if (*message == '\n') // check for a new line
|
||||||
|
{
|
||||||
|
line++;
|
||||||
|
i = (line * 80 * 2);
|
||||||
|
*message++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vidmem[i] = *message;
|
||||||
|
*message++;
|
||||||
|
i++;
|
||||||
|
vidmem[i] = WHITE_TXT;
|
||||||
|
i++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
3779
src/lib/duk_config.h
Normal file
3779
src/lib/duk_config.h
Normal file
File diff suppressed because it is too large
Load Diff
1911
src/lib/duk_source_meta.json
Normal file
1911
src/lib/duk_source_meta.json
Normal file
File diff suppressed because it is too large
Load Diff
101351
src/lib/duktape.c
Normal file
101351
src/lib/duktape.c
Normal file
File diff suppressed because it is too large
Load Diff
1456
src/lib/duktape.h
Normal file
1456
src/lib/duktape.h
Normal file
File diff suppressed because it is too large
Load Diff
33
src/lib/syscalls.c
Normal file
33
src/lib/syscalls.c
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Minimal system stubs for freestanding picolibc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* Exit function - halt the system */
|
||||||
|
void _exit(int status)
|
||||||
|
{
|
||||||
|
(void)status;
|
||||||
|
/* Halt the CPU */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
__asm__ volatile("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get time of day - not supported in freestanding */
|
||||||
|
int gettimeofday(struct timeval *tv, void *tz)
|
||||||
|
{
|
||||||
|
(void)tz;
|
||||||
|
if (tv)
|
||||||
|
{
|
||||||
|
tv->tv_sec = 0;
|
||||||
|
tv->tv_usec = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sbrk - memory allocation (picolibc uses __heap_start and __heap_end from linker script) */
|
||||||
|
/* No need to implement sbrk as picolibc uses the linker symbols directly */
|
||||||
40
src/link.ld
Normal file
40
src/link.ld
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* link.ld
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_FORMAT(elf32-i386)
|
||||||
|
ENTRY(start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x100000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text)
|
||||||
|
*(.text.*)
|
||||||
|
*(.rodata)
|
||||||
|
*(.rodata.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heap for malloc */
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__heap_start = .;
|
||||||
|
. = . + 0x100000; /* 1MB heap */
|
||||||
|
__heap_end = .;
|
||||||
|
|
||||||
|
/* Stack grows downward from high memory */
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__stack_bottom = .;
|
||||||
|
. = . + 0x10000; /* 64KB stack */
|
||||||
|
__stack_top = .;
|
||||||
|
}
|
||||||
36
src/os/index.js
Normal file
36
src/os/index.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
clearScreen();
|
||||||
|
print("Hello World!");
|
||||||
|
|
||||||
|
// writeMemory(0xb8000, 0x48);
|
||||||
|
// writeMemory(0xb8001, 0x0f);
|
||||||
|
|
||||||
|
// writeMemory(0xb8002, 0x65);
|
||||||
|
// writeMemory(0xb8003, 0x0f);
|
||||||
|
|
||||||
|
// writeMemory(0xb8004, 0x6c);
|
||||||
|
// writeMemory(0xb8005, 0x0f);
|
||||||
|
|
||||||
|
// writeMemory(0xb8006, 0x6c);
|
||||||
|
// writeMemory(0xb8007, 0x0f);
|
||||||
|
|
||||||
|
// writeMemory(0xb8008, 0x6f);
|
||||||
|
// writeMemory(0xb8009, 0x0f);
|
||||||
|
|
||||||
|
function clearScreen() {
|
||||||
|
var i = 0;
|
||||||
|
while (i < 80 * 25 * 2) {
|
||||||
|
writeMemory(0xb8000 + i, 0x00);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function printChar(char, offset) {
|
||||||
|
writeMemory(0xb8000 + offset * 2, char.charCodeAt(0));
|
||||||
|
writeMemory(0xb8000 + offset * 2 + 1, 0x0f); // White on black
|
||||||
|
}
|
||||||
|
|
||||||
|
function print(str) {
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
printChar(str.charAt(i), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user