Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
113
run.ps1
Normal file
113
run.ps1
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Schunix launcher (Windows side).
|
||||
#
|
||||
# Why this exists: without it you have to hand-type a QEMU command line, and a
|
||||
# hand-typed one drifts -- notably onto a stale fs.img, which boots to
|
||||
# "fsinit: invalid file system" because the wrong disk is attached as hdb.
|
||||
#
|
||||
# The build no longer goes through WSL. WSL2 runs a real Linux kernel inside a
|
||||
# Hyper-V VM, so it hard-requires virtualisation, and enabling that puts the
|
||||
# Hyper-V hypervisor underneath the whole machine -- which makes VMware run
|
||||
# nested on top of it and slows the box down permanently. Not a trade worth
|
||||
# making for a build environment.
|
||||
#
|
||||
# Instead it builds natively: clang/lld cross-compile the kernel to bare-metal
|
||||
# ELF, mingw-w64 builds the host tools, and Git Bash supplies make, perl, sed
|
||||
# and dd. See the Toolchain section of the Makefile.
|
||||
#
|
||||
# .\run.ps1 build (native) then boot, windowed
|
||||
# .\run.ps1 -NoBuild boot whatever is already built
|
||||
# .\run.ps1 -Headless no window; serial captured to build\serial.log
|
||||
# .\run.ps1 -Gdb wait for a debugger on :26000 before executing
|
||||
|
||||
# .\run.ps1 -SchFS boot the ramdisk-root kernel with a SchFS volume
|
||||
# attached as hdb; then run cat /proc/schfs
|
||||
|
||||
param(
|
||||
[switch]$NoBuild,
|
||||
[switch]$Headless,
|
||||
[switch]$Gdb,
|
||||
[switch]$SchFS,
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = $PSScriptRoot
|
||||
|
||||
# The two images QEMU needs. These paths are the single source of truth --
|
||||
# keep them in sync with the 'qemu' and 'qemu-schfs' targets in the Makefile.
|
||||
$hda = Join-Path $root 'schunix.img'
|
||||
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' }
|
||||
else { Join-Path $root 'build\fs.img' }
|
||||
|
||||
if (-not $NoBuild) {
|
||||
Write-Host '==> building (native, no WSL)' -ForegroundColor Cyan
|
||||
|
||||
# The three toolchain directories, prepended so the build sees them whether
|
||||
# or not the current shell happened to inherit them: scoop's shims (make),
|
||||
# mingw-w64 (host gcc), and LLVM (clang, ld.lld, llvm-objcopy/objdump).
|
||||
$bash = Join-Path $env:ProgramFiles 'Git\bin\bash.exe'
|
||||
if (-not (Test-Path $bash)) { throw "Git Bash not found at $bash" }
|
||||
$toolPath = @(
|
||||
"$env:USERPROFILE\scoop\shims"
|
||||
"$env:USERPROFILE\scoop\apps\mingw\current\bin"
|
||||
"$env:ProgramFiles\LLVM\bin"
|
||||
) -join ';'
|
||||
$env:PATH = "$toolPath;$env:PATH"
|
||||
|
||||
# -SchFS needs the ramdisk-root kernel: the root filesystem then comes out
|
||||
# of memory, which leaves device 1 free for the SchFS volume. Booting the
|
||||
# normal kernel with a SchFS disk as hdb would leave it with no root.
|
||||
$target = if ($SchFS) { 'make ramroot && make build/schfs.img' } else { 'make' }
|
||||
& $bash -lc "cd /d/DEV/Schunix && $target"
|
||||
if ($LASTEXITCODE -ne 0) { throw "build failed (exit $LASTEXITCODE)" }
|
||||
}
|
||||
|
||||
foreach ($img in @($hda, $hdb)) {
|
||||
if (-not (Test-Path $img)) { throw "missing image: $img (run without -NoBuild)" }
|
||||
}
|
||||
|
||||
# Guard against the exact failure this script exists to prevent: booting against
|
||||
# a stale or empty hdb. Each format has its own magic in its own place.
|
||||
$fs = [System.IO.File]::OpenRead($hdb)
|
||||
try {
|
||||
$buf = New-Object byte[] 4
|
||||
# v1: superblock in block 1 with BSIZE 1024, FSMAGIC 0x10203040.
|
||||
# SchFS: first uberblock in block 1 with SCHFS_BLKSIZE 4096, magic "SchF".
|
||||
$null = $fs.Seek($(if ($SchFS) { 4096 } else { 1024 }), 'Begin')
|
||||
$null = $fs.Read($buf, 0, 4)
|
||||
} finally { $fs.Close() }
|
||||
|
||||
if ($SchFS) {
|
||||
# 0x53636846 little-endian on disk: 46 68 63 53 ("FhcS" byte order).
|
||||
if ($buf[0] -ne 0x46 -or $buf[1] -ne 0x68 -or $buf[2] -ne 0x63 -or $buf[3] -ne 0x53) {
|
||||
throw "$hdb is not a valid SchFS image (bad uberblock magic). Rebuild it: make build/schfs.img"
|
||||
}
|
||||
} else {
|
||||
if ($buf[0] -ne 0x40 -or $buf[1] -ne 0x30 -or $buf[2] -ne 0x20 -or $buf[3] -ne 0x10) {
|
||||
throw "$hdb is not a valid SCHFS image (bad superblock magic). Rebuild it: rm -f build/fs.img && make"
|
||||
}
|
||||
}
|
||||
|
||||
$qemuArgs = @(
|
||||
'-drive', "file=$hda,format=raw,index=0,media=disk"
|
||||
'-drive', "file=$hdb,format=raw,index=1,media=disk"
|
||||
'-m', '1G'
|
||||
'-smp', '2'
|
||||
'-cpu', 'qemu64,+rdtscp'
|
||||
'-machine', 'pc-i440fx-9.2'
|
||||
)
|
||||
|
||||
if ($Headless) {
|
||||
$log = Join-Path $root 'build\serial.log'
|
||||
$qemuArgs += @('-display', 'none', '-serial', "file:$log")
|
||||
Write-Host "==> headless; serial -> $log" -ForegroundColor Cyan
|
||||
} else {
|
||||
$qemuArgs += @('-vga', 'std', '-serial', 'stdio')
|
||||
}
|
||||
|
||||
if ($Gdb) {
|
||||
$qemuArgs += @('-gdb', 'tcp::26000', '-S')
|
||||
Write-Host '==> paused for gdb on localhost:26000' -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
& $Qemu @qemuArgs
|
||||
Loading…
Reference in a new issue