Boot stick and boot loader
FAQ › EUZOS Desktop › Boot stick and boot loader · Nederlands
What is it?
EUZOS starts from a FAT32 volume with a fixed layout: a UEFI boot loader of its own (\EFI\BOOT\BOOTX64.EFI on x86-64, BOOTAA64.EFI on ARM64) that loads the kernel (\EOS\KX64.ELF, or \EOS\KAA64.ELF on ARM64) plus all files in \EOS\FW\ (firmware and settings) into memory, and jumps to it. That volume is a USB stick (made with make image) or, after an installation, the EFI system partition (ESP) of the internal disk. The kernel calls whichever one it booted from the boot volume; the console commands still say stick for both.
When EUZOS starts from a USB stick, a choice screen comes first: Try EUZOS or Install on this PC. Holding I while switching on skips the choice and goes straight to the installer. A trial kernel can be started once (try) and then made permanent (commit).
How do I…?
How do I make an EUZOS stick?
On the development Mac: make image (EUZOS Desktop, test build) writes the image with the boot loader, kernel, programs, firmware and a signed release manifest (\EOS\MANIFEST.TXT + \EOS\MANIFEST.SIG). Without that signed manifest the stick still boots, but cannot install (the choice screen says so). See docs/INSTALLING.md, "Where the files come from". A running EUZOS can also write a new stick from a release on the network: install <url> <disk> (see Installer).
What do I see when the stick boots?
- The boot loader prints lines starting with
[EUZOS-boot](display mode, ACPI, which kernel it loaded) and draws coloured bars at the top. - The kernel shows the boot screen: the EUZOS logo with a calm animation and a status line. Esc shows the boot text; Esc again (or another key) returns to the boot screen. An error line or a panic shows the text at once.
- Booted from a USB stick (x86-64 only): the choice screen "Welcome to EUZOS" with Try EUZOS ("From the stick; nothing on this PC changes") and Install on this PC ("On the internal drive; everything on it will be erased"). After 10 seconds without a choice it becomes Try; a tap, click or arrow key stops the countdown.
- Try continues to the normal login screen.
How do I go straight to the installer (the I key)?
Hold I (or i) while switching on. The boot loader does not wait for it: it only looks at what is already in the firmware's keyboard buffer (at most 64 keys) just before leaving the firmware. If there is an I, it passes the flag BOOT_INSTALL to the kernel, which skips the choice screen and opens the installer at the disk step. Without I the boot is just as fast as before.
Why is the choice screen in the kernel and not in the boot loader?
It must work with a finger (the Panasonic CF-33 and FZ-G1 tablets only have a touchscreen, and their UEFI has no touch), it must be graphical in all languages and both themes, and it needs the on-screen keyboard. All of that exists only in the kernel. The boot loader only passes on the I key.
How do I switch the choice screen off?
Put choice=no (legacy keuze=nee) in \EOS\FW\INSTALL.TXT on the stick (for example a test stick that must always continue booting). The screen also does not appear when booting from the internal disk, on ARM64, or on an installation stick (automatic=yes, legacy automatisch=ja, see Installer).
Since 27-10-2026 EUZOS writes English config file names, keys, values and confirmation words (for example
WIPE-…,environment=inPROFILE.TXT); the old Dutch names (marked legacy here) are still read and accepted (docs/ENGLISH.md).
Why does my PC boot the stick even though EUZOS is installed on the SSD?
After an installation the internal disk is first in the UEFI BootOrder, so the firmware boots the SSD even with a stick plugged in. The boot loader on the internal disk therefore looks for an EUZOS stick on USB (it must have \EFI\BOOT\BOOTX64.EFI, \EOS\KX64.ELF and \EOS\MANIFEST.TXT); if it finds one, it starts the stick's boot loader (LoadImage/StartImage), and the stick boots as if the firmware had chosen it. Switch this off with stick=no (legacy value stick=nee) in \EOS\FW\BOOT.TXT on the internal disk (legacy name OPSTART.TXT, still read).
How do I see which volume EUZOS booted from?
stick lists the USB storage devices, then the boot volume (USB stick or internal SATA/NVMe disk), its sector and cluster size, how it was chosen (the boot partition GUID from the boot loader, or the label EUZOS with an old boot loader), and the sizes of EOS/KX64.ELF, EOS/KX64TRY.ELF and EOS/TRY.TXT.
How do I test a new kernel without risk?
- Put the new kernel on the boot volume as
\EOS\KX64TRY.ELF(over SSH:ssh euzos 'put EOS/KX64TRY.ELF' < kernel; the Mac scripttools/trial.shbuilds, uploads and does the rest). try: writes the marker\EOS\TRY.TXTand reboots.- The boot loader sees
TRY.TXT, deletes it first, and boots the trial kernel once. If that kernel hangs or crashes, the next boot takes the committed kernel again. - If the trial kernel works:
commit(run from the trial kernel).
A trial kernel that panics, faults, or has a lock stuck for 20 seconds writes a report to \EOS\HANG.TXT and reboots by itself into the committed kernel; the next kernel puts HANG.TXT in its log and deletes it.
What does commit check?
That KX64TRY.ELF is a valid kernel for this machine (ELF64, little-endian, position-independent, right architecture, at least 64 KiB), and, for a build with a build ID other than dev, that the trial kernel is the kernel running now. Then it copies the current KX64.ELF to KX64OLD.ELF, writes the trial kernel over KX64.ELF and reads it back.
What if the committed kernel does not load?
The boot loader tries kernels in order: (the trial kernel, once, if TRY.TXT was there) → KX64.ELF → KX64OLD.ELF (the backup made by commit). The first one that reads and loads wins; a broken file gives a message, not a crash. If none loads: "no usable kernel on the stick".
How do I put a file on the boot volume or delete one?
fetch <url> <path>: fetch over HTTPS and write only if<url>.sigis a valid signature with the key in\EOS\FW\SIGNPUB.TXT, and the version is not older than the one remembered in\EOS\FW\FETCH.TXT(anti-rollback; the legacyHAAL.TXTis still read, and per name the highest version of the two counts).- Over SSH:
put <path>with the data on stdin; this checks only the path rule below, not a signature (see Console). stick wipe <path>removes a file.
Writing is only allowed inside \EOS\ and never directly to the committed kernels KX64.ELF/KAA64.ELF (only commit replaces those); \EFI\ is never touched, so the stick always keeps booting.
How do I diagnose a PC that hangs while booting?
Put \EOS\FW\BOOTDIAG.TXT on the stick (an empty file is fine). The boot loader then draws a column of coloured blocks per step, can try other ways of leaving the firmware (ebs=), pause before the jump (pause=) and reboot after N seconds as a sign of life (reboot=). Take photos of the screen. See docs/BOOT-DIAGNOSTICS.md.
How do I always get the console instead of the boot and login screen?
Put console in \EOS\FW\SCREEN.TXT. Then there is no boot screen and no login screen (see Console).
Details
Boot loader steps
From boot/src/main.rs:
- Read
\EOS\FW\BOOTDIAG.TXTfirst (diagnostic mode). - Create the UEFI boot entry for a freshly installed internal disk if the marker
\EOS\FW\UEFIBOOT.TXTis there (by default as the very first step). - Query the framebuffer (GOP); change the display mode only if the current one is unusable or a really larger one exists (up to 1920x1200).
- Find the ACPI RSDP and device tree pointers.
TRY.TXT: remove it, and if a trial kernel exists, boot it once.- Load every file in
\EOS\FW\(no subdirectories) into memory; a missing directory is fine. Limits: 64 files, 32 MiB per file, 256 MiB in total (see Files from\EOS\FW\). - Copy the SMBIOS table (the device model, for DriverEnricher).
- Load the kernel ELF (trial → committed → backup).
- Read the I key from the keyboard buffer.
- Get the memory map, ExitBootServices, and jump to the kernel with a
BootInfo(flags, kernel name, boot partition GUID, files, framebuffer).
The boot entry after an installation
The installer writes \EOS\FW\UEFIBOOT.TXT with the partition GUID on the new ESP. On every boot the boot loader checks internal disks (SATA or NVMe in the device path, never USB) for that file. If the GUID matches, it reuses or creates a Boot#### entry for \EFI\BOOT\BOOTX64.EFI on that partition, puts it first in BootOrder, reads BootOrder back and only then deletes the marker. If anything fails, the marker stays and the next boot tries again.
Boot flags passed to the kernel
| Flag | Value | Meaning |
|---|---|---|
BOOT_TRIAL | 1 | the trial kernel was started (TRY.TXT) |
BOOT_FALLBACK | 2 | the backup KX64OLD.ELF was started |
BOOT_ENTRY_CREATED | 4 | the UEFI boot entry was created |
BOOT_ENTRY_FAILED | 8 | creating the boot entry failed |
BOOT_DIAG | 16 | BOOTDIAG.TXT was present |
BOOT_INSTALL | 32 | the I key was held: start at the installer |
BOOT_ONE_CORE | 16384 | the S key was held: one core this boot (docs/SMP.md, "Rescue") |
BOOT_FILES_EXT | 64 | the complete file list (up to 64) is passed next to the inline 16 |
BOOT_FILES_TRUNCATED | 128 | the boot loader skipped files from \EOS\FW\ |
Files from \EOS\FW\
The boot loader passes at most 64 files of at most 32 MiB each and 256 MiB in total (libs/bootinfo: MAX_FILES, MAX_FILE_SIZE, MAX_FILES_TOTAL); until 27-10-2026 it was 16 files of 16 MiB, and files beyond that dropped out silently. Now a skipped file (too many, too large, total full, unreadable, or a name that is not 8.3 ASCII) gets a line [EUZOS-boot] SKIPPED firmware file <name> ... on the boot loader's screen, and the kernel prints WARNING : the bootloader skipped N file(s) from \EOS\FW\. Config files that are missing from the list (SSHD, AUTHKEYS, HOSTKEY, PCKEY, LANG, NETWORK, FIREWALL, WORKPLC) are then read from the boot volume instead (settings_file::boot_file_or_volume).
Old and new mixed (the BootInfo layout is append-only; the version stays 6 and the extension is announced with the flag BOOT_FILES_EXT):
| Boot loader | Kernel | Result |
|---|---|---|
| new | new | up to 64 files; skipped files reported |
| old (16 files) | new | the 16 the old boot loader passed; if its list is full the kernel warns and reads missing config files from the boot volume |
| new | old | the old kernel sees the first 16 files (the rest stays in memory unused), as before |
| old | old | unchanged |
Choosing the right stick
With several sticks plugged in, the kernel opens the partition whose GPT GUID the boot loader reported. An internal disk is only ever used as boot volume via that GUID; the driver's lock then allows writes only within that partition, never the GPT or the rest of the disk.
Reference
Console commands
| Command | Arguments | What it does |
|---|---|---|
stick | – | USB storage devices, boot volume, how it was chosen, sizes of KX64.ELF, KX64TRY.ELF, TRY.TXT |
stick hash | <path> | size and SHA-256 of a file on the boot volume |
stick wipe | <path> | delete a file (only inside \EOS\, never the committed kernels); hidden aliases stick delete and legacy stick wis |
try | – | write \EOS\TRY.TXT (needs \EOS\KX64TRY.ELF) and reboot into the trial kernel once |
commit | – | make the running trial kernel the committed kernel; old one kept as KX64OLD.ELF |
fetch | <url> <path> | fetch over HTTPS, check <url>.sig (Ed25519) and the version, then write to the boot volume |
fetch manifest | <url> [verify] | show a release's signed MANIFEST.TXT; verify also fetches and checks every file, without writing (hidden aliases check, from an older help text, and legacy controleer) |
reboot | – | reboot (emergency: hold Ctrl+Alt+Esc for 3 s); legacy alias herstart |
put (SSH only) | <path> (data on stdin) | write a file to the boot volume (same path rule: only \EOS\, not the committed kernels; no signature check) |
Legacy alias: haal = fetch.
Functions and modules
| Function / module | Role |
|---|---|
boot/src/main.rs::efi_main | boot loader entry: the steps above |
boot/src/main.rs::try_once | remove TRY.TXT and decide on the trial boot |
boot/src/main.rs::install_key | look for I/i in the firmware keyboard buffer |
boot/src/main.rs::load_firmware_dir | load all files of \EOS\FW\ |
boot/src/boot_entry.rs::create | UEFI Boot#### entry and BootOrder for an installed internal disk |
boot/src/priority.rs | from the internal disk: start an EUZOS stick on USB first |
euzos_bootinfo::bootdiag::parse | parse BOOTDIAG.TXT |
kernel::boot_volume::with_volume | open the boot volume (by partition GUID) |
kernel::boot_volume::writable | the write rule (only \EOS\, not the committed kernels) |
kernel::boot_volume::prepare_try | try |
kernel::boot_volume::commit | commit |
kernel::boot_volume::command | stick |
kernel::boot_screen | the boot screen (Esc toggles the boot text) |
kernel::setup_choice::must_choose | does the choice screen come? |
kernel::setup_choice::immediately | was I held (BOOT_INSTALL)? |
kernel::setup_choice::show | show the choice screen (or straight to the disk step) |
euzos_ui::installation | screen logic of the choice screen and the installer (COUNTDOWN_S = 10) |
kernel::fetch::command | fetch |
kernel::watchdog | stuck-lock watchdog; a trial kernel writes HANG.TXT and reboots |
Config files
All in \EOS\FW\ on the boot volume unless noted.
| File | Key | Values | Meaning |
|---|---|---|---|
INSTALL.TXT | choice (legacy keuze) | no (legacy nee) | no choice screen on this stick |
INSTALL.TXT | automatic (legacy automatisch) | yes (legacy ja) | installation stick: start the graphical installer by itself (no choice screen) |
INSTALL.TXT | manifest | https://…/MANIFEST.TXT | release address for the installer |
BOOT.TXT (internal disk; legacy name OPSTART.TXT, still read) | stick | no (legacy nee) | do not give an EUZOS stick priority over the internal disk |
BOOTDIAG.TXT | ebs | 0–7 | how to leave the firmware (0 default, 1 plain, 2 Linux style, 3 minimal, 4 minimal + CLI, 5 no SetMode, 6 LoaderData, 7 no boot entry) |
BOOTDIAG.TXT | reboot | seconds (max 600) | reboot after N s as a sign of life |
BOOTDIAG.TXT | pause (legacy pauze) | ms (max 10000) | wait before the jump to the kernel |
SCREEN.TXT | console | – | no boot screen and no login screen |
SIGNPUB.TXT | – | public key | Ed25519 key for fetch, manifests and app packages |
FETCH.TXT (legacy name HAAL.TXT, still read) | – | lines NAME VERSION | highest accepted signature version per file (anti-rollback) |
UEFIBOOT.TXT | – | partition GUID | marker: create the UEFI boot entry (written by the installer) |
\EOS\TRY.TXT | – | 1 | marker: boot the trial kernel once (written by try) |
\EOS\HANG.TXT | – | text | report of a trial kernel that hung |
Since 27-10-2026 EUZOS writes English config file names, keys, values and confirmation words (for example
WIPE-…,environment=inPROFILE.TXT); the old Dutch names (marked legacy here) are still read and accepted (docs/ENGLISH.md).
Files on the boot volume
| Path | What |
|---|---|
\EFI\BOOT\BOOTX64.EFI / BOOTAA64.EFI | the boot loader |
\EOS\KX64.ELF / KAA64.ELF | committed kernel |
\EOS\KX64TRY.ELF / KAA64TRY.ELF | trial kernel |
\EOS\KX64OLD.ELF / KAA64OLD.ELF | backup made by commit |
\EOS\MANIFEST.TXT, \EOS\MANIFEST.SIG | signed release manifest (path, size, SHA-256 per file) |
\EOS\BIN\<NAME>.ELF | programs (run <name>) |
\EOS\FW\ | firmware and settings, loaded by the boot loader |
Protocol messages and formats
- Signature file
<name>.sig(72 bytes): 8-byte version (Unix time of signing) + Ed25519 signature over the file name, the version and the content (euzos_crypto::ed25519::download_message). - Fetch retries: after a network error up to three attempts per file (2 s, then 5 s pause), each with its own TLS connection; never after a refusal (signature, SHA-256, size, version, 404).
- Boot loader log: lines starting with
[EUZOS-boot]on the screen and the serial port.
EUZOS