diff --git a/.gitignore b/.gitignore
index 199ca10..b3c0522 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,11 @@ dist/
.#*
*~
\#*\#
+
+# Build output under projects/ -- these are programs that run on SchOS, and
+# their binaries were tracked by accident.
+projects/schcom/schcom
+projects/schcom/schcom-demo
+
+# A built ISO dropped next to the site for download.html. 62 MB; not source.
+docs/Website/releases/
diff --git a/Makefile b/Makefile
index e7be12c..65fd31c 100644
--- a/Makefile
+++ b/Makefile
@@ -107,7 +107,7 @@ KERN_NOENTRY = $(filter-out $(BUILD)/kernel/arch/x86_64/entry.o, $(KERNOBJS))
# Third-party software does NOT go here — see ports/.
# -----------------------------------------------------------------------
ULIB = $(addprefix $(BUILD)/lib/, start.o glue.o usys.o)
-CMDS = init schinit schinitd fbinfo shmtest socktest inputtest nettest reflink schattr ping chvt pcitest vgpud
+CMDS = schinit schinitd fbinfo shmtest socktest inputtest nettest reflink schattr ping chvt pcitest vgpud
CMDBINS = $(addprefix $(BUILD)/cmd/, $(CMDS))
# -----------------------------------------------------------------------
diff --git a/cmd/init/main.c b/cmd/init/main.c
deleted file mode 100644
index a5f68e7..0000000
--- a/cmd/init/main.c
+++ /dev/null
@@ -1,134 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// SchOS — minimal init (PID 1)
-
-#include "types.h"
-#include "user.h"
-#include "fcntl.h"
-
-static void
-xputs(int fd, const char *s)
-{
- int n = 0;
- while (s[n]) n++;
- write(fd, (void *)s, n);
-}
-
-int
-main(void)
-{
- if (getpid() != 1)
- exit();
-
- // Open console as fd 0; dup to fd 1 (stdout) and fd 2 (stderr).
- if (open("console", O_RDWR) < 0) {
- mknod("console", 1, 1);
- open("console", O_RDWR);
- }
- dup(0);
- dup(0);
-
- // --- /dev ------------------------------------------------------------
- // Minor numbers under major 1 follow Linux's mem-major layout where it
- // costs nothing (null=2, zero=5, full=7, random=8, urandom=9).
- // /dev/hole (was minor 4) is gone: it backed an abandoned experiment and
- // nothing has referenced it since.
- mkdir("/dev");
- mknod("/dev/console", 1, 1);
- mknod("/dev/null", 1, 2);
- mknod("/dev/keyboard", 1, 3);
- mknod("/dev/zero", 1, 5);
- mknod("/dev/full", 1, 7);
- mknod("/dev/random", 1, 8);
- mknod("/dev/urandom", 1, 9);
- mknod("/dev/fb0", 2, 0);
- mknod("/dev/mouse", 3, 1);
- mknod("/dev/tty", 1, 1); // alias for console — must pass TCGETS ioctl
- mknod("/dev/ttyS0", 4, 64);
- mknod("/dev/stdin", 1, 1);
- mknod("/dev/stdout", 1, 1);
- mknod("/dev/stderr", 1, 1);
-
- // Raw input events, Linux evdev layout (kernel/dev/input.c). /dev/keyboard
- // and /dev/mouse above are the old character-and-position interfaces; these
- // are the ones with key releases and button transitions, which is what a
- // game or a compositor needs and what neither of the others can express.
- mkdir("/dev/input");
- mknod("/dev/input/event0", 7, 0); // keyboard
- mknod("/dev/input/event1", 7, 1); // mouse
-
- // Raw disks (kernel/dev/disk.c). The minor is the IDE device number, so
- // hda is the disk the kernel booted from and hdb the second channel.
- //
- // Created unconditionally, the same way every other node here is: opening
- // one when no drive is there fails with ENXIO, which is a better answer
- // than a missing path, and it keeps this list a description of the device
- // model rather than of one machine's hardware.
- mknod("/dev/hda", 8, 0);
- mknod("/dev/hdb", 8, 1);
-
- // --- /proc -----------------------------------------------------------
- // Synthesised status files, major 6 (kernel/dev/procfs.c). These are the
- // global ones; per-process /proc// directories need synthetic
- // directory support in the filesystem, which does not exist yet.
- mkdir("/proc");
- // /proc is a real filesystem now (kernel/fs/procfs.c), not a handful of
- // mknod'd nodes: it has to be, because one directory per process cannot be
- // created ahead of time. This is what makes `ps` and `top` work.
- //
- // The mknod'd global files below still happen, and are simply covered by
- // the mount. They stay for now so that a failure here degrades to the old
- // behaviour instead of losing /proc entirely.
- mount("proc", "/proc", "proc", 0, 0);
- mknod("/proc/meminfo", 6, 1);
- mknod("/proc/uptime", 6, 2);
- mknod("/proc/cpuinfo", 6, 3);
- mknod("/proc/version", 6, 4);
- mknod("/proc/stat", 6, 5);
- mknod("/proc/loadavg", 6, 6);
- mknod("/proc/mounts", 6, 7);
- mknod("/proc/filesystems", 6, 8);
- // SchFS volume summary: label, generation, free space, and the root
- // directory. Reachable whether or not the volume is mounted into the
- // namespace, which is what makes it useful when a mount has gone wrong.
- mknod("/proc/schfs", 6, 9);
- // Write 'c' here to crash on purpose. The crash screen is otherwise the
- // one part of the system that can only be seen by having a bug.
- mknod("/proc/sysrq", 6, 10);
- mknod("/proc/pci", 6, 11);
- mknod("/proc/interrupts", 6, 12);
-
- mkdir("/sys");
-
- xputs(1, "\nSchOS\n");
- xputs(1, "init: ready (pid 1)\n");
-
- for (;;) {
- int pid = fork();
- if (pid < 0) {
- xputs(2, "init: fork failed\n");
- sleep(100);
- continue;
- }
-
- if (pid == 0) {
- // exec.c auto-enables Linux ABI for musl binaries (entry >= 0x100000).
- // Do NOT call enable_linux_abi() here — it corrupts SchOS syscall
- // numbers for the exec/exit calls that follow in this child.
- // Standardized naming: the shell is always /bin/sh, regardless of
- // which implementation backs it (dash, mksh, etc.) — no ksh/mksh/
- // other aliases are looked up here.
- static char *argv[] = { "sh", 0 };
- exec("/bin/sh", argv);
- xputs(2, "init: no shell found; place sh in /bin\n");
- exit();
- }
-
- // Reap zombies; the loop restarts the shell when it exits.
- int wpid;
- while ((wpid = wait()) >= 0 && wpid != pid)
- ;
- // Brief pause before restarting so we don't spin on a missing shell.
- sleep(100);
- }
- return 0;
-}
diff --git a/docs/README.md b/docs/README.md
index 8e122b9..c80ca3e 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -55,7 +55,12 @@ files are.
**Trying to build it** → [guides/building.md](guides/building.md).
-**Wondering what happens next** → [plan/1.0.md](plan/1.0.md), which is the finish line, then [plan/README.md](plan/README.md) for the order.
+**Wondering what happens next** → [plan/1.0.md](plan/1.0.md), which is the finish
+line *and* the register of everything half-built. Then
+[plan/README.md](plan/README.md) for the order.
+
+**About to start something new** → the register, first. Nothing new starts while
+it has rows in it, and a row leaves only by being finished or deleted.
**Something is broken and it feels familiar** → [history/](history/). There is a
good chance it is in there.
@@ -84,7 +89,7 @@ good chance it is in there.
| | |
|---|---|
| [README](plan/README.md) | The three current decisions and the order they happen in. |
-| [1.0.md](plan/1.0.md) | **The finish line.** What 1.0 contains, and what is explicitly deferred past it. |
+| [1.0.md](plan/1.0.md) | **The finish line, and the freeze.** What 1.0 contains, what is deferred, and the register of every half-built thing in the tree. |
| [foundations.md](plan/foundations.md) | The kernel work everything else is blocked on. |
| [wayland.md](plan/wayland.md) | The GUI stack, and what gets deleted to make room. |
| [hybrid.md](plan/hybrid.md) | Moving drivers out of the kernel. |
diff --git a/docs/Website/Assets/usb.svg b/docs/Website/Assets/usb.svg
new file mode 100644
index 0000000..1b35037
--- /dev/null
+++ b/docs/Website/Assets/usb.svg
@@ -0,0 +1,27 @@
+
diff --git a/docs/Website/README.md b/docs/Website/README.md
index 9c83e51..cd286b3 100644
--- a/docs/Website/README.md
+++ b/docs/Website/README.md
@@ -1,19 +1,42 @@
# The website
-Five files and a folder of marks. No build step, no dependencies, no
+Six files and a folder of marks. No build step, no dependencies, no
framework — open `index.html` and it works, including from a `file://` URL.
```
index.html the front page
+download.html get it, write it to a stick, or build it
docs.html the documentation reader
style.css the palette, transcribed from include/theme.h
app.js the front page: the boot log types, sections fade in
docs.js the Markdown renderer and the doc index
Assets/ shift.svg (logo), uberblock.svg (SchFS), guru.svg (PSOGM),
- pride.svg
+ usb.svg (downloads), pride.svg
```
+## The download page
+
+`download.html` links to `releases/schos.iso`, a path relative to this
+directory. **Nothing puts a file there** — the ISO is 62 MB and does not belong
+in the repository — so the link is dead until a build is dropped next to the
+site:
+
+```sh
+make iso
+mkdir -p docs/Website/releases && cp schos.iso docs/Website/releases/
+```
+
+The page is written so that this is the only thing that needs doing, and so that
+nothing on it is a promise the tree cannot keep. In particular the support table
+says **one real machine, under test** rather than listing hardware, because one
+Chromebox is the entire bare-metal record and a compatibility list would be
+fiction. When that changes, change the table; do not soften the wording.
+
+The `dd` command is split across two lines on purpose. It was one long line
+first, and the card clipped it at `conv=` — a destructive command that can
+scroll half of itself out of view is a good way to take somebody's disk.
+
## The docs reader
`docs.html` renders the Markdown in `docs/` in the site's own theme, with the
diff --git a/docs/Website/docs.html b/docs/Website/docs.html
index 676be54..b97210a 100644
--- a/docs/Website/docs.html
+++ b/docs/Website/docs.html
@@ -21,6 +21,7 @@
diff --git a/docs/Website/download.html b/docs/Website/download.html
new file mode 100644
index 0000000..aedd9c6
--- /dev/null
+++ b/docs/Website/download.html
@@ -0,0 +1,226 @@
+
+
+
+
+
+Download — SchOS
+
+
+
+
+
+
+
+
+ SchOS ships as one bootable ISO. It boots on UEFI, runs entirely from
+ RAM, and touches nothing on the machine unless you tell it to — there is
+ no installer yet, and that is the point of trying it this way.
+
+ schos.iso · about 62 MB · UEFI x86-64 · nothing is written
+ to your disks
+
+
+
+
+
Before you do
+
This has booted on exactly one real machine
+
+ Everything below QEMU is honest reporting rather than a compatibility
+ list. SchOS drives real hardware, and it has been run on a very small
+ number of it.
+
+
+
QEMU / OVMF
boots
+
Asus Chromebox Guado CN62
under test
+
Anything else
unknown
+
+
+ If it does not boot, the kernel log is on the screen from its first line
+ — that is deliberate, and it is there because of this machine. A photo of
+ where it stops is a genuinely useful bug report.
+
+
+
+
+
+
+
+
Writing it
+
Two ways onto a stick
+
+ Ventoy first, because it is the one that does not cost you the stick. An
+ ISO copied onto a Ventoy drive sits next to every other ISO on it, and the
+ drive stays an ordinary drive.
+
+
+
+
+ recommended
+
Ventoy
+
+ Copy the file. That is the whole procedure — Ventoy finds it and offers
+ it in its menu at boot, and the stick remains usable for everything
+ else.
+
+
$ cp schos.iso /run/media/you/Ventoy/
+
+ This is how SchOS is actually tested on hardware. No optical drive has
+ been involved at any point.
+
+
+
+
+ destructive
+
dd
+
+ Writes the image over the whole device. Check the device name
+ twice — there is no confirmation and no undo, and the wrong letter
+ takes a disk with it.
+
+ of= is the whole device, not a partition — sdX
+ and never sdX1.
+
+
+
+
+
+
+
+
+
First boot
+
What actually happens
+
+ Written out because a system you have never seen before gives you no way to
+ tell "working" from "stuck", and the difference is worth knowing in advance.
+
+
+
+
+ 1
+
The loader
+
+ A splash, and F8 for boot options. It is a PE/COFF loader built
+ with clang and lld-link; there is no BIOS path, so the firmware has to
+ be in UEFI mode.
+
+
+
+ 2
+
The kernel log
+
+ On screen, from the first line that can draw. Cores, the PCI bus, the
+ network card, the filesystem. If it stops, it stops somewhere you can
+ read.
+
+
+
+ 3
+
A shell
+
+ schinit starts one on the console and a second on
+ tty2. mksh is /bin/sh, with
+ zsh beside it and the real toybox userland behind both.
+
+
+
+ 4
+
Six terminals
+
+ AltGr+F1…F6 switches between them — the one
+ chord a Linux host does not take for itself — or chvt N
+ from a shell.
+
+
+
+
+
+ Nothing is written to your disks and nothing persists. The root
+ filesystem is in RAM; the machine is exactly as you left it after a reboot,
+ including the parts of it you were hoping to keep. There is no installer —
+ 1.0 is where that starts.
+
+
+
+
+
+
+
Or build it
+
Clone it, build it, boot it
+
+ The toolchain is one file. On NixOS shell.nix brings the whole
+ thing in; elsewhere it is clang, lld, GNU make and a host compiler — see
+ the build guide.
+
+
+
$ git clone <the repository> schos && cd schos
+$ nix-shell # NixOS only; elsewhere see the build guide
+$ make iso # produces schos.iso
+$ make qemu # or just run it, without a stick
+
+
+ make qemu is the one to reach for first. Everything on this
+ page works there, it takes seconds rather than a reboot, and a serial
+ console beats a photograph of a screen.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/Website/index.html b/docs/Website/index.html
index 6c80330..7b8e43e 100644
--- a/docs/Website/index.html
+++ b/docs/Website/index.html
@@ -25,6 +25,7 @@
What it hasHybridNumbers
+ DownloadDocs
@@ -42,8 +43,8 @@
and runs unmodified musl and toybox on top.