From 6d22fb5b88dc568a8c04946c196a52905b34da0a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 03:51:13 +0000 Subject: [PATCH] Initialize NewOS project: Kernel, Build System, and Boot Image - Created `kernel/` structure with assembly entry point and C main loop. - Implemented basic video driver for Macintosh SE/30 (monochrome framebuffer). - Added `Makefile` using `m68k-linux-gnu` toolchain. - Added `tools/create_image.sh` to generate HFS-formatted `boot.img` with custom Boot Blocks. - Configured environment setup script. --- .gitignore | 6 ++++ Makefile | 28 +++++++++++++++++ include/mac_hardware.h | 29 ++++++++++++++++++ kernel/head.S | 40 ++++++++++++++++++++++++ kernel/main.c | 27 +++++++++++++++++ kernel/video.c | 69 ++++++++++++++++++++++++++++++++++++++++++ linker.ld | 22 ++++++++++++++ tools/create_image.sh | 42 +++++++++++++++++++++++++ tools/setup_env.sh | 16 ++++++++++ 9 files changed, 279 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/mac_hardware.h create mode 100644 kernel/head.S create mode 100644 kernel/main.c create mode 100644 kernel/video.c create mode 100644 linker.ld create mode 100755 tools/create_image.sh create mode 100755 tools/setup_env.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60feb77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*.elf +*.bin +*.img +kernel/ +boot.img diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2fa9d81 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +CC = m68k-linux-gnu-gcc +LD = m68k-linux-gnu-ld +OBJCOPY = m68k-linux-gnu-objcopy + +# Use -fPIC for Position Independent Code since ROM loads us anywhere. +# -msep-data might be needed if we want separate data segment, but -fPIC is standard. +CFLAGS = -m68030 -O2 -Wall -fno-builtin -nostdlib -Iinclude -fPIC +LDFLAGS = -T linker.ld + +all: boot.img + +kernel.elf: kernel/head.o kernel/main.o kernel/video.o + $(LD) $(LDFLAGS) -o $@ $^ + +kernel.bin: kernel.elf + $(OBJCOPY) -O binary $< $@ + +boot.img: kernel.bin tools/create_image.sh + ./tools/create_image.sh + +clean: + rm -f kernel/*.o kernel.elf kernel.bin boot.img + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +%.o: %.S + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/include/mac_hardware.h b/include/mac_hardware.h new file mode 100644 index 0000000..ac6ff0b --- /dev/null +++ b/include/mac_hardware.h @@ -0,0 +1,29 @@ +#ifndef MAC_HARDWARE_H +#define MAC_HARDWARE_H + +// Type definitions +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef int int32_t; + +// Mac Low Memory Globals +// Updated based on SysEqu.a findings +#define ScrnBase (*(volatile uint32_t*)0x824) +// ScreenRow at 0x106? SysEqu.a said 0x106 is ScreenRow. +// Let's verify. 0x106 seems low. But if SysEqu says so. +// Wait, 0x106 is often "MemTop"? No, MemTop is 0x108. +// Let's stick with 0x826 if I can verify it, OR use 0x106 if SysEqu is clear. +// SysEqu: "ScreenRow EQU $106" +#define ScreenRow (*(volatile uint16_t*)0x106) +#define MemTop (*(volatile uint32_t*)0x108) +#define ROMBase (*(volatile uint32_t*)0x2AE) + +// VIA1 Addresses (SE/30) +#define VIA1_BASE 0x50F00000 + +// Video parameters +#define SCREEN_WIDTH 512 +#define SCREEN_HEIGHT 342 + +#endif diff --git a/kernel/head.S b/kernel/head.S new file mode 100644 index 0000000..0fa4307 --- /dev/null +++ b/kernel/head.S @@ -0,0 +1,40 @@ + .global _start + .global _halt + + .text +_start: + /* + * Boot Block Header (standard Mac) + * The first 2 bytes must be 'LK' (0x4C, 0x4B) + * The next 2 bytes are a branch to the code. + */ + + /* Signature 'LK' */ + .byte 0x4C, 0x4B + + /* Branch to Entry (offset will be calculated by assembler) */ + bra.w entry_point + + /* Configuration variables (Boot Block structure) */ + /* 0x04: Entry point for version (unused) */ + .byte 0x00, 0x00 + /* 0x06: Version */ + .byte 0x00, 0x00 + /* ... Padding to standard boot block header size if needed ... */ + +entry_point: + /* Disable interrupts */ + ori.w #0x0700, %sr + + /* Setup Stack - ROM usually provides a stack, but we should be safe */ + /* Let's use the top of memory minus some buffer. MemTop is at 0x108. */ + move.l 0x108, %sp + sub.l #0x1000, %sp /* Leave 4KB buffer */ + + /* Call C kernel (using PC-relative BSR or JSR) */ + /* Since we are -fPIC, we should use bsr if it's close, or load address relative to PC */ + bsr.w kernel_main + +_halt: + stop #0x2700 + bra.s _halt diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..6bb102f --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,27 @@ +#include "mac_hardware.h" + +extern void clear_screen(); +extern void kprint(const char* str); +extern void draw_test_pattern(); + +void kernel_main() { + // 1. Initialize Video + // (Assuming ScrnBase is valid from ROM) + + // 2. Clear Screen + // clear_screen(); // Commented out to avoid clearing if it's already white, let's just draw on top. + + // 3. Print Welcome Message + // kprint("Welcome to NewOS"); + + // Draw something visible immediately + draw_test_pattern(); + + // 4. Infinite Loop (Shell Prompt) + while (1) { + // Blink a pixel or wait for interrupt + volatile int i; + for (i=0; i<100000; i++); + // TODO: Blink cursor + } +} diff --git a/kernel/video.c b/kernel/video.c new file mode 100644 index 0000000..70971e2 --- /dev/null +++ b/kernel/video.c @@ -0,0 +1,69 @@ +#include "mac_hardware.h" + +// Simple 8x8 font bitmap (A subset for "Hello World") +// Minimal font data would be here. For now, let's just draw blocks or simple lines. +// Or we can define a very small font. + +// 8x8 bitmap for 'A' (example) +// 00111100 +// 01100110 +// 01100110 +// 01111110 +// 01100110 +// 01100110 +// 00000000 + +// We need a simple `put_char` function. + +void clear_screen() { + uint32_t *screen = (uint32_t *)ScrnBase; + uint16_t rowBytes = ScreenRow; + uint32_t rows = SCREEN_HEIGHT; + uint32_t stride = rowBytes / 4; // Stride in 32-bit words + + for (uint32_t y = 0; y < rows; y++) { + for (uint32_t x = 0; x < stride; x++) { + screen[y * stride + x] = 0x00000000; // White (0 is white on Mac usually? No, 0 is White, 1 is Black) + // Wait, standard Mac video is 1 bit per pixel. + // 0 = White, 1 = Black usually. + // Let's invert it to be sure we see something. + // 0xFFFFFFFF = Black bar. + // 0xAAAAAAAA = Striped. + } + } +} + +void draw_test_pattern() { + uint32_t *screen = (uint32_t *)ScrnBase; + uint16_t rowBytes = ScreenRow; + + // Draw a black line at the top + for (int i=0; i < (rowBytes/4) * 10; i++) { + screen[i] = 0xFFFFFFFF; + } +} + +// Very minimal font rendering (monochrome) +// x, y are in pixels +void draw_pixel(int x, int y, int color) { + if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; + + uint8_t *screen_byte = (uint8_t *)(ScrnBase + (y * ScreenRow) + (x / 8)); + uint8_t bit = 1 << (7 - (x % 8)); + + if (color) { + *screen_byte |= bit; // Set bit (Black) + } else { + *screen_byte &= ~bit; // Clear bit (White) + } +} + +// Simple "Bitmap Font" - just hardcoding 'H' 'e' 'l' 'l' 'o' for MVP to save space +// In a real OS, we'd include a font.h +const uint8_t FONT_A[8] = {0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00}; +// We will just implement a "Print String" that draws blocks for now if font is missing. + +void kprint(const char* str) { + // Placeholder: Draws a pattern to prove code execution + draw_test_pattern(); +} diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..ca9622e --- /dev/null +++ b/linker.ld @@ -0,0 +1,22 @@ +SECTIONS +{ + . = 0x00000000; /* Boot Blocks are loaded at a specific address, often relocatable. */ + /* + * However, Mac ROMs often load Boot Blocks into a pointer passed in registers. + * Or they might be Position Independent Code (PIC). + * We should compile as PIC if possible, or assume an address. + * Usually Boot Blocks are loaded at heap or stack. + * Safe bet: Compile as PIC (-fPIC). + * But for linker script, we can set 0 and use PC-relative addressing. + */ + + .text : { + *(.text) + } + .data : { + *(.data) + } + .bss : { + *(.bss) + } +} diff --git a/tools/create_image.sh b/tools/create_image.sh new file mode 100755 index 0000000..fa283b8 --- /dev/null +++ b/tools/create_image.sh @@ -0,0 +1,42 @@ +#!/bin/bash +set -e + +echo "Creating boot.img..." + +KERNEL_BIN="kernel.bin" +IMG="boot.img" + +if [ ! -f "$KERNEL_BIN" ]; then + echo "Error: $KERNEL_BIN not found. Run make first." + exit 1 +fi + +# 1. Create a blank 1.44MB floppy image +dd if=/dev/zero of=$IMG bs=1024 count=1440 2>/dev/null + +# 2. Format as HFS (Mac ROM expects HFS volume to check for boot blocks) +# We use 'NewOS' as the volume name. +hformat -l "NewOS" $IMG > /dev/null + +# 3. Install Boot Blocks +# The Mac ROM looks at the first 1024 bytes (Boot Blocks) of the disk. +# Even if HFS is present, the boot blocks are in sectors 0 and 1. +# `hformat` writes a standard boot block. We need to OVERWRITE it with our kernel code. +# +# IMPORTANT: The HFS volume header (MDB) is at sector 2 (offset 1024). +# We MUST NOT overwrite sector 2. +# Our kernel.bin must be <= 1024 bytes for this method. +# If it is larger, we would need to write it to a file and have the boot block load it. +# For MVP (360 bytes), we just overwrite the boot blocks. + +KERNEL_SIZE=$(stat -c%s "$KERNEL_BIN") +if [ "$KERNEL_SIZE" -gt 1024 ]; then + echo "Error: Kernel size ($KERNEL_SIZE bytes) exceeds Boot Block limit (1024 bytes)." + echo "This MVP requires the kernel to fit in the boot blocks." + exit 1 +fi + +# Write our kernel over the first 1024 bytes (preserving the rest of the disk) +dd if=$KERNEL_BIN of=$IMG conv=notrunc bs=1024 count=1 2>/dev/null + +echo "Done. $IMG is ready (HFS formatted with custom Boot Blocks)." diff --git a/tools/setup_env.sh b/tools/setup_env.sh new file mode 100755 index 0000000..eb271c5 --- /dev/null +++ b/tools/setup_env.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +# Update package list +sudo apt-get update + +# Install m68k cross-compiler (Linux target is close enough for bare metal if we use -nostdlib) +sudo apt-get install -y gcc-m68k-linux-gnu binutils-m68k-linux-gnu make + +# Install HFS utilities for disk image manipulation +sudo apt-get install -y hfsutils hfsplus + +# Install hex editor for debugging (optional) +# sudo apt-get install -y hexedit + +echo "Environment setup complete."