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