Build and tools work on Linux, macOS and BSD as well as Windows
Developed from both Windows and Linux, so nothing in the build should care which host it runs on. It did, in four places. Toolchain: one path instead of two. clang is a cross-compiler by construction, so a single LLVM install targets bare-metal ELF, 16/32-bit code below 1 MB, and Linux/musl userland from any host -- which is how the Windows build already worked. The GNU branch beside it had drifted into passing --no-warn-rwx-segments, a hard error on lld, which is the default linker on both FreeBSD and macOS; and it required a brewed x86_64-elf-gcc before anything built on a Mac at all. GNU is kept as a fallback (USE_GNU=1) but clang+lld is chosen whenever both are present. Host tools use the host's own cc; only mingw needs naming explicitly. tools/mkschfs.c included <sys/sysmacros.h> unconditionally on non-mingw hosts. That header is glibc/musl only -- macOS and the BSDs have neither the header nor a need for it, since major()/minor() come from <sys/types.h> there. Now guarded on __linux__. Ports verified tarballs with `sha256sum -c -`, which does not exist on macOS (shasum), FreeBSD/NetBSD (sha256), or OpenBSD (cksum -a sha256), and each spells its check mode differently. tools/sha256check.sh picks whichever of the five the host has and compares digests itself. nproc is coreutils, so absent on macOS and BSD; falls through to sysctl -n hw.ncpu before defaulting to 4. The PowerShell tools now run under pwsh on any OS: QEMU is found on PATH (the scoop location is a Windows-only fallback), and path literals use forward slashes -- Join-Path $root 'build\x' produces a *filename containing a backslash* on a Unix host. The backslash sweep is limited to known directory prefixes on purpose: bootcheck sends printf 'caf\303\251' to the guest to test UTF-8, and a blanket substitution would have quietly changed what that asserts. Also fixes six tools left booting build/fs.img, which stopped being bootable when SchFS became the root filesystem: crashshot, dispshot, fbshot, splashshot, textshot and ttyshot all take build/schfs.img now, and the -SchFS switches that used to select it are gone. Verified on Windows: full build, and bootcheck green. The Linux, macOS and BSD paths are written from their documented behaviour and are NOT executed here -- this machine has no WSL and no second host.
This commit is contained in:
parent
e04ca28812
commit
cda5908660
15 changed files with 427 additions and 105 deletions
140
Makefile
140
Makefile
|
|
@ -8,7 +8,10 @@ SYSROOT = sysroot
|
|||
# there is no reason to compile one file at a time. Override with `make -j1`
|
||||
# when you want readable output from a failing build.
|
||||
# -----------------------------------------------------------------------
|
||||
NPROC := $(shell nproc 2>/dev/null || echo 4)
|
||||
# nproc is coreutils, so it exists on Linux and under Git Bash but not on
|
||||
# macOS or the BSDs, where the same number comes from sysctl. Falling through
|
||||
# to 4 is a working build either way, just a slower one.
|
||||
NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
MAKEFLAGS += -j$(NPROC)
|
||||
|
||||
# Kernel object files — organized by subsystem
|
||||
|
|
@ -92,31 +95,29 @@ CMDBINS = $(addprefix $(BUILD)/cmd/, $(CMDS))
|
|||
UNAME_S := $(shell uname -s)
|
||||
UNAME_P := $(shell uname -p)
|
||||
|
||||
# Windows, under Git Bash or MSYS2 — WINHOST.
|
||||
# Host platform.
|
||||
#
|
||||
# WINHOST Windows, under Git Bash or MSYS2
|
||||
# MACHOST macOS
|
||||
# BSDHOST FreeBSD / OpenBSD / NetBSD / DragonFly
|
||||
# (else) Linux
|
||||
#
|
||||
# All four are supported hosts: this is developed from both Windows and Linux,
|
||||
# and nothing here should care which.
|
||||
#
|
||||
# Building natively on Windows rather than in WSL, because WSL2 is a real Linux
|
||||
# kernel in a Hyper-V VM and so hard-requires virtualisation; turning that on
|
||||
# puts the Hyper-V hypervisor underneath the whole machine and demotes VMware
|
||||
# to running nested on top of it, which is a real and permanent cost to pay for
|
||||
# a build environment.
|
||||
#
|
||||
# The usual answer is a cross binutils+gcc, which is a day of work that then
|
||||
# rots. clang does not need any of it: it is a cross-compiler by construction,
|
||||
# so one ordinary LLVM install targets both the bare-metal kernel and Linux
|
||||
# userland, and llvm-objcopy/objdump stand in for binutils. Everything else the
|
||||
# build shells out to — perl, sed, dd, sha256sum — comes with Git Bash.
|
||||
ifneq (,$(filter MINGW% MSYS% CYGWIN%,$(UNAME_S)))
|
||||
WINHOST := 1
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
ifeq ($(UNAME_P),aarch64)
|
||||
TOOLPREFIX = x86_64-linux-gnu-
|
||||
else
|
||||
TOOLPREFIX =
|
||||
endif
|
||||
else ifeq ($(UNAME_S),Darwin)
|
||||
TOOLPREFIX = x86_64-elf-
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
MACHOST := 1
|
||||
endif
|
||||
ifneq (,$(filter FreeBSD OpenBSD NetBSD DragonFly,$(UNAME_S)))
|
||||
BSDHOST := 1
|
||||
endif
|
||||
|
||||
QEMU = qemu-system-x86_64
|
||||
|
|
@ -133,10 +134,40 @@ QEMU = qemu-system-x86_64
|
|||
# virtio-gpu wins the display class, stdvga carries the splash and text console.
|
||||
QEMU_DISPLAY = -vga std -device virtio-gpu-pci
|
||||
|
||||
ifdef WINHOST
|
||||
# An explicit --target is what makes clang emit ELF instead of the COFF it
|
||||
# would default to on this host. Without it every object is silently the
|
||||
# wrong format and the first thing to complain is the linker.
|
||||
# -----------------------------------------------------------------------
|
||||
# Cross-compilation: clang everywhere it can be had
|
||||
#
|
||||
# The kernel, the bootloader and the ports all need a compiler targeting
|
||||
# something other than the host -- bare-metal ELF, 16/32-bit code below one
|
||||
# megabyte, and Linux/musl userland respectively. The traditional answer is a
|
||||
# cross binutils+gcc per host, which is a day of work per platform that then
|
||||
# rots, and on macOS means brewing x86_64-elf-* before anything builds at all.
|
||||
#
|
||||
# clang needs none of it: it is a cross-compiler by construction, so one
|
||||
# ordinary LLVM install produces every target from every host. That was already
|
||||
# how the Windows build worked; using it on all four hosts collapses what used
|
||||
# to be two divergent toolchain branches -- one of which had drifted into
|
||||
# passing GNU-ld-only flags to what is nowadays lld on FreeBSD and macOS -- into
|
||||
# a single path that gets exercised on every platform instead of one.
|
||||
#
|
||||
# GNU is kept as a fallback for hosts without clang, but it is the exception.
|
||||
# -----------------------------------------------------------------------
|
||||
HAVE_CLANG := $(shell command -v clang 2>/dev/null)
|
||||
HAVE_LLD := $(shell command -v ld.lld 2>/dev/null)
|
||||
|
||||
ifeq ($(origin USE_GNU), undefined)
|
||||
ifneq (,$(HAVE_CLANG))
|
||||
ifneq (,$(HAVE_LLD))
|
||||
USE_CLANG := 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef USE_CLANG
|
||||
# An explicit --target is what makes clang emit ELF rather than whatever the
|
||||
# host defaults to -- COFF on Windows, Mach-O on macOS. Without it every
|
||||
# object is silently the wrong format and the first thing to complain is the
|
||||
# linker.
|
||||
CC = clang --target=x86_64-elf
|
||||
CC32 = clang --target=i386-elf
|
||||
LD = ld.lld
|
||||
|
|
@ -151,49 +182,66 @@ ifdef WINHOST
|
|||
# and refuses, because for a hosted program that would be a bug. Saying the
|
||||
# base is zero is how you tell it this is not a hosted program.
|
||||
LD_LOWBASE = --image-base=0
|
||||
# Host tools (mkfs, mkschfs, the SchFS suites) are ordinary Windows programs.
|
||||
# They must be built with mingw-w64 rather than clang's default MSVC target:
|
||||
# tools/mkfs.c includes <unistd.h> and <dirent.h>, and the Windows SDK has
|
||||
# neither.
|
||||
HOSTCC = gcc
|
||||
# mingw-w64's gcc warns about things glibc's does not (notably %lld/%zu in
|
||||
# printf against msvcrt). Those warnings are about the host build only and
|
||||
# say nothing about the image, so they must not stop it.
|
||||
HOSTWARN = -Wall
|
||||
# MinGW gcc appends .exe when the -o name has no extension, so a rule
|
||||
# whose target lacks it is never considered built -- mkfs was recompiled on
|
||||
# every single invocation of make, forever, because of this.
|
||||
EXE = .exe
|
||||
# `python3` is not on PATH from the python.org installer; `python` is.
|
||||
PYTHON = python
|
||||
# Compiler for ports/, which build *Linux userland* against musl -- a third
|
||||
# target, distinct from both the kernel (bare-metal ELF) and the host tools
|
||||
# (Windows PE). mingw's gcc cannot do it: it targets Windows, so linking it
|
||||
# against musl gives undefined `stderr` and `__errno_location`.
|
||||
# ports/ build *Linux userland* against musl -- a third target, distinct from
|
||||
# both the kernel (bare-metal ELF) and the host tools (native).
|
||||
#
|
||||
# -nostdlib with the crt files named explicitly, because clang otherwise
|
||||
# reaches for gcc's crtbeginT.o and libgcc, which do not exist on this host.
|
||||
# reaches for gcc's crtbeginT.o and libgcc, which need not exist on any
|
||||
# particular host.
|
||||
MUSLPREFIX = $(abspath $(BUILD))/ports/musl/prefix
|
||||
PORTCC = clang --target=x86_64-unknown-linux-musl -fuse-ld=lld
|
||||
PORTCRT = -nostdlib $(MUSLPREFIX)/lib/crt1.o $(MUSLPREFIX)/lib/crti.o
|
||||
PORTEND = $(MUSLPREFIX)/lib/crtn.o
|
||||
else
|
||||
# GNU fallback. Needs a cross toolchain anywhere the host's own gcc does not
|
||||
# already emit x86_64 ELF -- notably macOS, where TOOLPREFIX has to name a
|
||||
# brewed x86_64-elf-gcc.
|
||||
ifdef MACHOST
|
||||
TOOLPREFIX ?= x86_64-elf-
|
||||
else ifeq ($(UNAME_P),aarch64)
|
||||
TOOLPREFIX ?= x86_64-linux-gnu-
|
||||
else
|
||||
TOOLPREFIX ?=
|
||||
endif
|
||||
CC = $(TOOLPREFIX)gcc
|
||||
CC32 = $(CC) -m32
|
||||
LD = $(TOOLPREFIX)ld
|
||||
OBJCOPY = $(TOOLPREFIX)objcopy
|
||||
OBJDUMP = $(TOOLPREFIX)objdump
|
||||
LDFLAGS = -m elf_x86_64 -nostdlib --no-warn-rwx-segments
|
||||
HOSTCC = gcc
|
||||
HOSTWARN = -Werror -Wall
|
||||
EXE =
|
||||
PYTHON = python3
|
||||
LD_LOWBASE =
|
||||
PORTCC = gcc
|
||||
PORTCC = $(TOOLPREFIX)gcc
|
||||
PORTCRT =
|
||||
PORTEND =
|
||||
endif
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Host tools: mkfs, mkschfs, the SchFS suites, qrtest. Ordinary programs for
|
||||
# the machine doing the building, so they use its native compiler.
|
||||
# -----------------------------------------------------------------------
|
||||
HOSTCC ?= cc
|
||||
|
||||
ifdef WINHOST
|
||||
# mingw-w64's gcc, not clang: clang defaults to an MSVC target here, and
|
||||
# tools/mkfs.c includes <unistd.h> and <dirent.h>, which the Windows SDK
|
||||
# does not have.
|
||||
HOSTCC = gcc
|
||||
# mingw-w64's gcc warns about things glibc's does not (notably %lld/%zu in
|
||||
# printf against msvcrt). Those warnings are about the host build only and
|
||||
# say nothing about the image, so they must not stop it.
|
||||
HOSTWARN = -Wall
|
||||
# MinGW gcc appends .exe when the -o name has no extension, so a rule whose
|
||||
# target lacks it is never considered built -- mkfs was recompiled on every
|
||||
# single invocation of make, forever, because of this.
|
||||
EXE = .exe
|
||||
# `python3` is not on PATH from the python.org installer; `python` is.
|
||||
PYTHON = python
|
||||
else
|
||||
HOSTWARN = -Werror -Wall
|
||||
EXE =
|
||||
PYTHON = python3
|
||||
endif
|
||||
|
||||
# Host tools are generated output and live under build/, per docs/layout.md.
|
||||
# $(EXE) matters: MinGW appends it, and a rule whose target lacks it never
|
||||
# looks satisfied.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ SYSROOT := $(TOPDIR)/sysroot
|
|||
DISTDIR := $(TOPDIR)/dist
|
||||
BUILDROOT := $(TOPDIR)/build/ports
|
||||
|
||||
# Verifying a downloaded tarball. Not `sha256sum -c -`: that command does not
|
||||
# exist on macOS or the BSDs, and each of them spells it differently. The
|
||||
# helper picks whichever of the five possibilities the host actually has.
|
||||
SHA256CHECK := $(TOPDIR)/tools/sha256check.sh
|
||||
|
||||
# Port name is the directory name — no per-port boilerplate needed.
|
||||
PORT := $(notdir $(CURDIR))
|
||||
PORTDIR := $(BUILDROOT)/$(PORT)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ TARBALL := $(DISTDIR)/musl-$(MUSL_VERSION).tar.gz
|
|||
|
||||
$(TARBALL): | $(DISTDIR)
|
||||
curl -fsSL -o $@ $(MUSL_URL)
|
||||
echo "$(MUSL_SHA256) $@" | sha256sum -c -
|
||||
sh $(SHA256CHECK) "$(MUSL_SHA256)" "$@"
|
||||
|
||||
download: $(TARBALL)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ LDFLAGS := -static -L$(MUSL)/lib -lc
|
|||
|
||||
$(TARBALL): | $(DISTDIR)
|
||||
curl -fsSL -o $@ $(TOYBOX_URL)
|
||||
echo "$(TOYBOX_SHA256) $@" | sha256sum -c -
|
||||
sh $(SHA256CHECK) "$(TOYBOX_SHA256)" "$@"
|
||||
|
||||
download: $(TARBALL)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
# the pacing below -- not superstition, just the difference between a reliable
|
||||
# check and a flaky one.
|
||||
#
|
||||
# tools\bootcheck.ps1
|
||||
# tools\bootcheck.ps1 -Tty -Ps
|
||||
# tools/bootcheck.ps1
|
||||
# tools/bootcheck.ps1 -Tty -Ps
|
||||
|
||||
param(
|
||||
[switch]$Fb,
|
||||
|
|
@ -49,16 +49,39 @@ param(
|
|||
# else in this suite touches.
|
||||
[switch]$Ps,
|
||||
[int]$BootSeconds = 20,
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
# The root filesystem. SchFS is the only root there is, so this is not a
|
||||
# choice -- a kernel handed anything else on device 1 panics in forkret().
|
||||
$hdb = Join-Path $root 'build\schfs.img'
|
||||
$log = Join-Path $root 'build\bootcheck.log'
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
$log = Join-Path $root 'build/bootcheck.log'
|
||||
|
||||
Remove-Item -Force $log -ErrorAction SilentlyContinue
|
||||
|
||||
|
|
@ -196,7 +219,7 @@ $usbDevices = if ($Usb) {
|
|||
# there, which failed three USB checks that had nothing wrong with USB.
|
||||
# It also stops the same file being attached twice, once as the root
|
||||
# disk and once as a USB device.
|
||||
"-drive id=usbstick,file=`"$(Join-Path $root 'build\fs.img')`",format=raw,if=none"
|
||||
"-drive id=usbstick,file=`"$(Join-Path $root 'build/fs.img')`",format=raw,if=none"
|
||||
'-device usb-storage,bus=xhci.0,drive=usbstick')
|
||||
} else { @() }
|
||||
|
||||
|
|
|
|||
|
|
@ -9,23 +9,48 @@
|
|||
# shell. screendump writes a PPM; the PNG conversion is optional and skipped if
|
||||
# ImageMagick is not around.
|
||||
#
|
||||
# tools\crashshot.ps1 crash the ramdisk-root build
|
||||
# tools\crashshot.ps1 -SchFS with a SchFS volume attached
|
||||
# tools/crashshot.ps1 crash the ramdisk-root build
|
||||
|
||||
param(
|
||||
[switch]$SchFS,
|
||||
[int]$BootSeconds = 20,
|
||||
[string]$Out = "build\crashscreen.ppm",
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Out = "build/crashscreen.ppm",
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' } else { Join-Path $root 'build\fs.img' }
|
||||
$log = Join-Path $root 'build\crashshot.log'
|
||||
# The root filesystem. SchFS is the only root there is: the kernel mounts
|
||||
# device 1 in forkret() and panics if it is not a SchFS volume, so this is
|
||||
# not a choice and there is no -SchFS switch any more. It used to default to
|
||||
# build/fs.img, which stopped being bootable the moment SchFS became root.
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
$log = Join-Path $root 'build/crashshot.log'
|
||||
$ppm = Join-Path $root $Out
|
||||
$mon = Join-Path $root 'build\qemu-mon.sock'
|
||||
$mon = Join-Path $root 'build/qemu-mon.sock'
|
||||
|
||||
Remove-Item -Force $log, $ppm -ErrorAction SilentlyContinue
|
||||
|
||||
|
|
|
|||
|
|
@ -14,23 +14,48 @@
|
|||
# shell. screendump writes a PPM; the PNG conversion is optional and skipped if
|
||||
# ImageMagick is not around.
|
||||
#
|
||||
# tools\crashshot.ps1 crash the ramdisk-root build
|
||||
# tools\crashshot.ps1 -SchFS with a SchFS volume attached
|
||||
# tools/crashshot.ps1 crash the ramdisk-root build
|
||||
|
||||
param(
|
||||
[switch]$SchFS,
|
||||
[int]$BootSeconds = 20,
|
||||
[string]$Out = "build\dispshot.ppm",
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Out = "build/dispshot.ppm",
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' } else { Join-Path $root 'build\fs.img' }
|
||||
$log = Join-Path $root 'build\crashshot.log'
|
||||
# The root filesystem. SchFS is the only root there is: the kernel mounts
|
||||
# device 1 in forkret() and panics if it is not a SchFS volume, so this is
|
||||
# not a choice and there is no -SchFS switch any more. It used to default to
|
||||
# build/fs.img, which stopped being bootable the moment SchFS became root.
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
$log = Join-Path $root 'build/crashshot.log'
|
||||
$ppm = Join-Path $root $Out
|
||||
$mon = Join-Path $root 'build\qemu-mon.sock'
|
||||
$mon = Join-Path $root 'build/qemu-mon.sock'
|
||||
|
||||
Remove-Item -Force $log, $ppm -ErrorAction SilentlyContinue
|
||||
|
||||
|
|
|
|||
|
|
@ -6,22 +6,49 @@
|
|||
# every byte accepted, and the only symptom is a picture that shears
|
||||
# progressively down the screen. That is a thing you have to look at.
|
||||
#
|
||||
# tools\fbshot.ps1 gradient through mmap
|
||||
# tools\fbshot.ps1 -Mode bars colour bars through write()
|
||||
# tools/fbshot.ps1 gradient through mmap
|
||||
# tools/fbshot.ps1 -Mode bars colour bars through write()
|
||||
|
||||
param(
|
||||
[ValidateSet('fill', 'bars')]
|
||||
[string]$Mode = 'fill',
|
||||
[int]$BootSeconds = 20,
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
$hdb = Join-Path $root 'build\fs.img'
|
||||
$log = Join-Path $root 'build\fbshot.log'
|
||||
$ppm = Join-Path $root "build\fb-$Mode.ppm"
|
||||
# The root filesystem. SchFS is the only root there is: the kernel mounts
|
||||
# device 1 in forkret() and panics if it is not a SchFS volume, so this is
|
||||
# not a choice and there is no -SchFS switch any more. It used to default to
|
||||
# build/fs.img, which stopped being bootable the moment SchFS became root.
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
$log = Join-Path $root 'build/fbshot.log'
|
||||
$ppm = Join-Path $root "build/fb-$Mode.ppm"
|
||||
|
||||
Remove-Item -Force $log, $ppm -ErrorAction SilentlyContinue
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
# counts only first-party code, and separates the code from the comments so the
|
||||
# number means something.
|
||||
#
|
||||
# tools\loc.ps1 the summary table
|
||||
# tools\loc.ps1 -PerFile every file, largest first
|
||||
# tools\loc.ps1 -All include third-party trees, for comparison
|
||||
# tools/loc.ps1 the summary table
|
||||
# tools/loc.ps1 -PerFile every file, largest first
|
||||
# tools/loc.ps1 -All include third-party trees, for comparison
|
||||
#
|
||||
# Comment detection is deliberately simple: it handles // and /* */ for C and
|
||||
# # for scripts, and does not try to understand a // inside a string literal.
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
# El Torito image. The ramdisk root is the point: the ISO carries a complete
|
||||
# userland inside the kernel, so it boots with no hard disk attached at all.
|
||||
#
|
||||
# tools\makeiso.ps1 build it
|
||||
# tools\makeiso.ps1 -Run build it, then boot it under QEMU to check
|
||||
# tools\makeiso.ps1 -Clean force a full rebuild first
|
||||
# tools/makeiso.ps1 build it
|
||||
# tools/makeiso.ps1 -Run build it, then boot it under QEMU to check
|
||||
# tools/makeiso.ps1 -Clean force a full rebuild first
|
||||
#
|
||||
# Afterwards the ISO is schos.iso in the repository root; point a VM's optical
|
||||
# drive at it and boot from CD.
|
||||
|
|
@ -14,9 +14,32 @@
|
|||
param(
|
||||
[switch]$Run,
|
||||
[switch]$Clean,
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
Push-Location $root
|
||||
|
|
@ -117,7 +140,7 @@ Write-Host " RAM: 64 MB is plenty. The old 224 MB floor is gone."
|
|||
if ($Run) {
|
||||
Write-Host ""
|
||||
Write-Host "==> booting the ISO under QEMU, no disk attached" -ForegroundColor Cyan
|
||||
$log = Join-Path $root 'build\isoboot.log'
|
||||
$log = Join-Path $root 'build/isoboot.log'
|
||||
if (Test-Path $log) { Clear-Content $log }
|
||||
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
|
|
|
|||
|
|
@ -55,7 +55,12 @@
|
|||
#define S_ISLNK(m) 0
|
||||
static long readlink(const char *p, char *b, unsigned long n)
|
||||
{ (void)p; (void)b; (void)n; return -1; }
|
||||
#else
|
||||
#elif defined(__linux__)
|
||||
/* glibc and musl both put major()/minor() here, and glibc warns and then
|
||||
errors if you take them from <sys/types.h> instead. Linux only: macOS and
|
||||
the BSDs have no <sys/sysmacros.h> at all and define both in <sys/types.h>,
|
||||
which is already included above -- including it unconditionally is a build
|
||||
failure on every non-Linux Unix. */
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
|
|
|
|||
62
tools/sha256check.sh
Normal file
62
tools/sha256check.sh
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#!/bin/sh
|
||||
# Verify a file's SHA-256 against an expected hex digest, on any host.
|
||||
#
|
||||
# tools/sha256check.sh <expected-hex> <file>
|
||||
#
|
||||
# There is no one checksum command across the supported hosts. Linux and Git
|
||||
# Bash have coreutils' sha256sum; macOS ships shasum(1) and no sha256sum;
|
||||
# FreeBSD and NetBSD ship sha256(1) with a different output format again;
|
||||
# OpenBSD has sha256 too but usually reached through cksum -a sha256. A recipe
|
||||
# that hardcodes any one of them builds on some of the hosts this project
|
||||
# supports and fails on the rest, and the failure arrives only when someone
|
||||
# first runs `make ports` on a Mac.
|
||||
#
|
||||
# Compares digests rather than trusting a -c flag, because the -c input format
|
||||
# differs between the implementations as well.
|
||||
|
||||
set -eu
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "usage: $0 <expected-sha256> <file>" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
expected="$1"
|
||||
file="$2"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "sha256check: no such file: $file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
actual=
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
actual=$(sha256sum "$file" | cut -d' ' -f1)
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
actual=$(shasum -a 256 "$file" | cut -d' ' -f1)
|
||||
elif command -v sha256 >/dev/null 2>&1; then
|
||||
# FreeBSD/NetBSD: -q prints the digest alone.
|
||||
actual=$(sha256 -q "$file")
|
||||
elif command -v cksum >/dev/null 2>&1 && cksum -a sha256 /dev/null >/dev/null 2>&1; then
|
||||
# OpenBSD.
|
||||
actual=$(cksum -a sha256 "$file" | sed 's/.*= *//')
|
||||
elif command -v openssl >/dev/null 2>&1; then
|
||||
actual=$(openssl dgst -sha256 "$file" | sed 's/.*= *//')
|
||||
else
|
||||
echo "sha256check: no usable checksum tool found" >&2
|
||||
echo " looked for: sha256sum, shasum, sha256, cksum, openssl" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Case-insensitive: openssl and sha256 have been known to differ here.
|
||||
expected_lc=$(printf '%s' "$expected" | tr 'A-Z' 'a-z')
|
||||
actual_lc=$(printf '%s' "$actual" | tr 'A-Z' 'a-z')
|
||||
|
||||
if [ "$expected_lc" != "$actual_lc" ]; then
|
||||
echo "sha256check: checksum mismatch for $file" >&2
|
||||
echo " expected: $expected_lc" >&2
|
||||
echo " actual: $actual_lc" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$file: OK"
|
||||
|
|
@ -10,19 +10,42 @@
|
|||
# Same shape as tools/crashshot.ps1: monitor on TCP because QEMU on Windows has
|
||||
# no unix sockets, serial to a logfile so the transcript survives.
|
||||
#
|
||||
# tools\splashshot.ps1 frames every 400ms for 8s
|
||||
# tools\splashshot.ps1 -Every 200 -For 4
|
||||
# tools/splashshot.ps1 frames every 400ms for 8s
|
||||
# tools/splashshot.ps1 -Every 200 -For 4
|
||||
|
||||
param(
|
||||
[int]$Every = 400, # milliseconds between frames
|
||||
[int]$For = 8, # seconds to keep capturing
|
||||
[string]$OutDir = "build\shots",
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$OutDir = "build/shots",
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$log = Join-Path $root 'build\splashshot.log'
|
||||
$log = Join-Path $root 'build/splashshot.log'
|
||||
$dir = Join-Path $root $OutDir
|
||||
|
||||
Remove-Item -Recurse -Force $dir -ErrorAction SilentlyContinue
|
||||
|
|
@ -30,7 +53,11 @@ New-Item -ItemType Directory -Force $dir | Out-Null
|
|||
Remove-Item -Force $log -ErrorAction SilentlyContinue
|
||||
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
$hdb = Join-Path $root 'build\fs.img'
|
||||
# The root filesystem. SchFS is the only root there is: the kernel mounts
|
||||
# device 1 in forkret() and panics if it is not a SchFS volume, so this is
|
||||
# not a choice and there is no -SchFS switch any more. It used to default to
|
||||
# build/fs.img, which stopped being bootable the moment SchFS became root.
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
|
||||
$monPort = 55556 # not crashshot's port, so the two can run back to back
|
||||
|
||||
|
|
@ -42,7 +69,7 @@ $psi.Arguments = @(
|
|||
# developer already has open would otherwise make this fail with "Failed to
|
||||
# get write lock" -- and a capture script is exactly the thing you want to
|
||||
# run without first shutting down what you were looking at. Copying was the
|
||||
# first fix and it meant duplicating build\fs.img, all 153 MB of it, on
|
||||
# first fix and it meant duplicating build/fs.img, all 153 MB of it, on
|
||||
# every run. -snapshot keeps writes in a temporary overlay, so the originals
|
||||
# are untouched either way.
|
||||
"-drive file=`"$hda`",format=raw,index=0,media=disk,file.locking=off"
|
||||
|
|
|
|||
|
|
@ -14,23 +14,48 @@
|
|||
# shell. screendump writes a PPM; the PNG conversion is optional and skipped if
|
||||
# ImageMagick is not around.
|
||||
#
|
||||
# tools\crashshot.ps1 crash the ramdisk-root build
|
||||
# tools\crashshot.ps1 -SchFS with a SchFS volume attached
|
||||
# tools/crashshot.ps1 crash the ramdisk-root build
|
||||
|
||||
param(
|
||||
[switch]$SchFS,
|
||||
[int]$BootSeconds = 20,
|
||||
[string]$Out = "build\textshot.ppm",
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Out = "build/textshot.ppm",
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' } else { Join-Path $root 'build\fs.img' }
|
||||
$log = Join-Path $root 'build\crashshot.log'
|
||||
# The root filesystem. SchFS is the only root there is: the kernel mounts
|
||||
# device 1 in forkret() and panics if it is not a SchFS volume, so this is
|
||||
# not a choice and there is no -SchFS switch any more. It used to default to
|
||||
# build/fs.img, which stopped being bootable the moment SchFS became root.
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
$log = Join-Path $root 'build/crashshot.log'
|
||||
$ppm = Join-Path $root $Out
|
||||
$mon = Join-Path $root 'build\qemu-mon.sock'
|
||||
$mon = Join-Path $root 'build/qemu-mon.sock'
|
||||
|
||||
Remove-Item -Force $log, $ppm -ErrorAction SilentlyContinue
|
||||
|
||||
|
|
|
|||
|
|
@ -7,19 +7,46 @@
|
|||
# framebuffer. So the serial transcript can never tell you whether the escape
|
||||
# parser works -- it contains the raw bytes either way. Only a picture can.
|
||||
#
|
||||
# tools\ttyshot.ps1
|
||||
# tools/ttyshot.ps1
|
||||
|
||||
param(
|
||||
[int]$BootSeconds = 22,
|
||||
[string]$Out = "build\ttyshot.ppm",
|
||||
[string]$Qemu = "$env:USERPROFILE\scoop\apps\qemu\current\qemu-system-x86_64.exe"
|
||||
[string]$Out = "build/ttyshot.ppm",
|
||||
[string]$Qemu = (Find-Qemu)
|
||||
)
|
||||
|
||||
# QEMU, on whichever host this is.
|
||||
#
|
||||
# PowerShell 7 runs on Linux, macOS and the BSDs as well as Windows, so these
|
||||
# scripts are usable from all of them -- but the old default was a hardcoded
|
||||
# scoop path under $env:USERPROFILE, which exists on exactly one of those. PATH
|
||||
# first, because a package-managed qemu is on it everywhere; the scoop location
|
||||
# is only a fallback for the Windows install that does not add itself to PATH.
|
||||
function Find-Qemu {
|
||||
$exe = if ($IsWindows -or $env:OS -eq 'Windows_NT') { 'qemu-system-x86_64.exe' }
|
||||
else { 'qemu-system-x86_64' }
|
||||
$onPath = Get-Command $exe -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return $onPath.Source }
|
||||
if ($env:USERPROFILE) {
|
||||
$scoop = Join-Path (Join-Path $env:USERPROFILE 'scoop/apps/qemu/current') $exe
|
||||
if (Test-Path $scoop) { return $scoop }
|
||||
}
|
||||
foreach ($p in @('/usr/bin', '/usr/local/bin', '/opt/homebrew/bin')) {
|
||||
$c = Join-Path $p $exe
|
||||
if (Test-Path $c) { return $c }
|
||||
}
|
||||
throw "qemu-system-x86_64 not found on PATH. Install QEMU, or pass -Qemu <path>."
|
||||
}
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
$hda = Join-Path $root 'schos.img'
|
||||
$hdb = Join-Path $root 'build\fs.img'
|
||||
$log = Join-Path $root 'build\ttyshot.log'
|
||||
# The root filesystem. SchFS is the only root there is: the kernel mounts
|
||||
# device 1 in forkret() and panics if it is not a SchFS volume, so this is
|
||||
# not a choice and there is no -SchFS switch any more. It used to default to
|
||||
# build/fs.img, which stopped being bootable the moment SchFS became root.
|
||||
$hdb = Join-Path $root 'build/schfs.img'
|
||||
$log = Join-Path $root 'build/ttyshot.log'
|
||||
$ppm = Join-Path $root $Out
|
||||
$monPort = 55571
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue