Skip to content
Open
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
66 changes: 63 additions & 3 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 0
persist-credentials: false

- name: disk and QEMU
run: |
Expand Down Expand Up @@ -105,7 +106,7 @@ jobs:
for attempt in 1 2 3; do
apt-get -o Acquire::Check-Valid-Until=false update -qq > /tmp/apt.log 2>&1 \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y -qq git curl ca-certificates \
zstd xz-utils build-essential qemu-system-x86 >> /tmp/apt.log 2>&1 \
zstd xz-utils build-essential qemu-system-x86 ovmf >> /tmp/apt.log 2>&1 \
&& break
[ "$attempt" = 3 ] && { cat /tmp/apt.log; exit 1; }
sleep 20
Expand Down Expand Up @@ -238,6 +239,9 @@ jobs:
sh "$RUNNER_TEMP/rustup-init.sh" -y --profile minimal --default-toolchain stable
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- run: env -u GITHUB_ACTIONS -u CI cargo run -- --build-only
# The image release notes' macOS line (`src/imagerelease.rs`), booted as
# they print it: this runner is the Apple Silicon Mac it names.
- run: env -u GITHUB_ACTIONS -u CI cargo test --test toyos-build -- --release-command

# The declared Windows frontier
# (`issues/build/the-build-system-does-not-compile-on-windows.md`): red
Expand All @@ -250,17 +254,73 @@ jobs:
- *checkout
- run: cargo build -p toyos-build

# The disk image a person downloads, built once and booted under the Linux
# line its notes print (`src/imagerelease.rs`). It compiles and runs
# third-party code out of a cache another such job wrote, so its token only
# reads: the assets go on as an artifact and their digest as an output.
release:
needs: build
runs-on: ubuntu-24.04
# A wedge guard, not a budget.
timeout-minutes: 60
container: *kvm
permissions:
contents: read
env:
GH_TOKEN: ${{ github.token }}
outputs:
digest: ${{ steps.release.outputs.digest }}
steps:
- *deps
- *checkout
- *guest-cache
- id: release
run: cargo run -- --ci release
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: image-release
path: target/image-release/
if-no-files-found: error
retention-days: 1

# The one job that writes releases, publishing on main what `release` booted
# on a night the guest suite passed, once its digest is the one `release`
# answered. No cache and nothing built but the build system, and the token
# only in the publishing step: the checkout keeps no credential, and the
# build step has none.
release-publish:
needs: [build, guest, tcg, release]
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
contents: write
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: image-release
path: target/image-release
- run: cargo build -p toyos-build
- env:
GH_TOKEN: ${{ github.token }}
IMAGE_RELEASE_DIGEST: ${{ needs.release.outputs.digest }}
run: cargo run -- --ci release-publish

# One standing issue, found by title and commented on; a dispatch is somebody
# watching the run, so only the schedule files.
nightly-red:
needs: [host, build, guest, tcg, audio, portability-linux, portability-macos]
needs: [host, build, guest, tcg, audio, portability-linux, portability-macos, release, release-publish]
if: ${{ !cancelled() && github.event_name == 'schedule' }}
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- *checkout
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- env:
GH_TOKEN: ${{ github.token }}
NEEDS: ${{ toJSON(needs) }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
# No submodules: `cargo publish` walks the repository's vcs state, and an
# initialised but empty `rust/` breaks that walk.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false

- id: auth
uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ assets/*.sf2
phosphor-icons
.cargo/config.toml
.build-locks/
# The std fork's `library/` and licence files, fetched where `rust/` holds no source
# (`src/licence.rs`).
.licence-fork/
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ image = { version = "0.25", default-features = false, features = ["jpeg"] }
# (`src/fingerprint.rs`). Already resolved here through a dev-dependency, so
# nothing new is fetched — but `cargo run` did not compile it before this.
sha2 = "0.10"
# The image release's compressed asset, which every stock macOS and Linux
# unpacks (`src/imagerelease.rs`).
flate2 = { version = "1", default-features = false, features = ["rust_backend"] }

[dev-dependencies]
toyos-cc = { path = "toyos-cc" }
Expand Down Expand Up @@ -198,7 +201,6 @@ toyos-xhci = { path = "toyos-xhci" }
# the guest's volume is compared with a third party's decoding of the committed
# archive, never with `userland/pkg`'s own. The archive itself is committed
# under `tests/fixtures` and no test fetches anything.
flate2 = { version = "1", default-features = false, features = ["rust_backend"] }
tar = "0.4"

[profile.release]
Expand Down
6 changes: 2 additions & 4 deletions bootloader/src/floor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ use alloc::vec::Vec;
use toyos_update::floor::{self, Read, Scope, Stored};
use uefi::prelude::*;
use uefi::table::runtime::{VariableAttributes, VariableVendor};
use uefi::{guid, CString16};
use uefi::{CString16, Guid};

/// Whose images this loader's floor holds, as its build decided.
const SCOPE: Scope = Scope::from_word(env!("TOYOS_IMAGE_FLOOR"));

/// The vendor every floor is under: `33BE3D4A-30E6-49F5-8050-F169D93A20FB`,
/// minted for this and used for nothing else.
const VENDOR: VariableVendor = VariableVendor(guid!("33be3d4a-30e6-49f5-8050-f169d93a20fb"));
const VENDOR: VariableVendor = VariableVendor(Guid::parse_or_panic(floor::VENDOR));

/// The only attributes the floor is written with.
const ATTRIBUTES: VariableAttributes =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
status: open
kind: defect
opened: 2026-09-27
---

# The loader writes the first disk carrying its log GUID, not the one it booted from

`loaderlog::volume_handle` (`bootloader/src/loaderlog.rs`) takes the first
filesystem on the machine whose GPT partition's unique GUID is the log
partition's, and `loader.log` and the attempt records are written there. Every
copy of one image carries the same partition unique GUIDs, and the image
release (`src/imagerelease.rs`) is written byte for byte to every stick made
from it. With two sticks of one release plugged in, the loader can write the
log partition of the stick it did not boot from: a disk it was not given, and
one that carries no TOYOS-DATA partition. The release notes name this as the
one such disk a boot may write.

Owner: the bootloader.

**Exit condition.** The loader writes only the device it booted from: the log
volume is looked up on the device of the loaded image's own handle, and a boot
with two copies of one image attached writes the other copy's bytes not at
all.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
status: open
kind: tooling
opened: 2026-09-27
---

# A toolchain release takes GitHub's Latest badge from the image release

`gh release create` in `src/release.rs` names no `--latest`, so GitHub marks
each new toolchain release Latest: every release this repository has published
is a toolchain's, and the newest carries the badge. The image release
(`src/imagerelease.rs`) is created `--latest`, and the next toolchain release
takes the badge back, so `/releases/latest` names a toolchain rather than the
image a person downloads until the next image release.

Not changed beside the image release because `src/release.rs` is one of the
trees the toolchain's tag hashes (`TREES`): editing it publishes a toolchain.

**Exit condition.** A toolchain release is created `--latest=false`, and
`/releases/latest` names the newest image release whenever there is one.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
status: open
kind: tooling
opened: 2026-09-28
---

# The toolchain install unpacks an asset no digest vouches for

`release::install` (`src/release.rs`) downloads the `toyos-toolchain.tar.zst`
asset of the release its tree's tag names, unpacks it into `rust/build` and
links it as rustup's `toyos`, and checks nothing about its bytes: the tag is
the hash of the tarball's inputs (`TREES`), not of the tarball. Every guest
job and the image release's boot job compile and boot with what it installs.

A job holding this repository's `contents: write` token can replace a
release asset, so any code such a job runs can replace the toolchain every
later job installs, and through it the image the release publishes. The
nightly's `build` job holds that token while it bootstraps the toolchain, and
the image release's publish job while it publishes.

Owner: the release module (`src/release.rs`).

**Exit condition.** `install` unpacks only an asset whose SHA-256 is one that
no job holding a write token can rewrite — committed to the tree it installs
for — and refuses any other by name.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
status: expected-red
kind: defect
opened: 2026-09-27
---

# The kernel dies at boot on the edk2 firmware QEMU ships

Booted with `edk2-x86_64-code.fd` and `edk2-i386-vars.fd` from Homebrew's QEMU
11.1.1 (`/opt/homebrew/share/qemu/`), the kernel panics right after the
physical memory manager comes up:

[kernel 0.000 cpu0 boot] pmm: the firmware map calls 2140844032 bytes usable in 110 entries; managed=2017460224 withheld=94371840 unaligned=29011968, and the three sum to it; frames=962 reserved_frames=45 base=0x200000 span=1022
[kernel 0.000 cpu0 boot] EARLY PANIC: panicked at library/alloc/src/alloc.rs:659:9:
memory allocation of 4096 bytes failed

The same image under the same command line with `ovmf/OVMF_CODE-pure-efi.fd`
and `ovmf/OVMF_VARS-pure-efi.fd` in their place reaches the desktop
(`compositor: ready`). Two things the firmwares hand over differ in the two
logs: the memory map, 110 entries against 95, and the GOP framebuffer, at
`0x80000000` against `0xc0000000`. On the firmware that boots, the line after
`pmm:` is the framebuffer's mapping, `mmio: 0xc0000000+0x400000 PAT
WriteCombining`.

The command line is `imagerelease::Host::MacosAppleSilicon`'s
(`src/imagerelease.rs`) with `-display none`, over a copy of a
`target/bootable.img`.

`release_command_boots` (`cargo test --test toyos-build -- --release-command`,
which the nightly's `portability-macos` runs) boots that line, and is disabled
in `src/redlist.rs` while this stands.

**Exit condition.** `release_command_boots` is green on the dev host with the
firmware Homebrew's QEMU ships, and its row leaves `src/redlist.rs`.
Loading
Loading