Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.o
*.elf
*.bin
*.img
kernel/
boot.img
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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 $@ $<
29 changes: 29 additions & 0 deletions include/mac_hardware.h
Original file line number Diff line number Diff line change
@@ -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
40 changes: 40 additions & 0 deletions kernel/head.S
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions kernel/main.c
Original file line number Diff line number Diff line change
@@ -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
}
}
69 changes: 69 additions & 0 deletions kernel/video.c
Original file line number Diff line number Diff line change
@@ -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();
}
22 changes: 22 additions & 0 deletions linker.ld
Original file line number Diff line number Diff line change
@@ -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)
}
}
42 changes: 42 additions & 0 deletions tools/create_image.sh
Original file line number Diff line number Diff line change
@@ -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)."
16 changes: 16 additions & 0 deletions tools/setup_env.sh
Original file line number Diff line number Diff line change
@@ -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."