Forest OS

A free and open source operating system, written from scratch. A Bluethefox project, hosted by Enclica.

← Back to Wiki

Install Guide (BIOS)

BIOS (CSM / Legacy) native install of Forest OS to an internal disk from a bootable USB stick, via the forinstall entire-disk flow. For UEFI ESP install see Install Guide (UEFI); for building the media itself see ISO Creation; for VM installs see Install on a VM.

Sources of truth: foreboots/bios/config.h (sector map), userspace/forinstall/installer.h:19-31 (mirrored constants), userspace/forinstall/install.c:359-559 (install_write_foreb_to_disk), BIOS Boot (stage behavior).

Warning: entire-disk install erases the target disk. dd to the wrong of= destroys data. Triple-check every device with lsblk / fdisk -l before writing. When in doubt unplug every disk except stick + target.

Contents

  1. Requirements
  2. Firmware setup — CSM/Legacy + AHCI
  3. Boot the USB stick (F12)
  4. ForeB menu — boot the default entry
  5. forinstall — entire-disk flow
  6. ForeB sectors written
  7. dd seek table (manual equivalent)
  8. Verify before reboot (still in live session)
  9. Remove USB, boot internal
  10. Smoke test (first boot from disk)
  11. Issues and fixes

Requirements

  • Bootable Forest OS USB stick (forebo.iso hybrid or forebo.img raw, written with dd, Rufus DD mode — ISO mode breaks the sector layout).
  • Target PC: x86 / x86_64 with BIOS firmware, or UEFI firmware with CSM / Legacy boot available.
  • Internal disk ≥ 512 MiB (2 GiB+ recommended). All data on it is erased.
  • Built image verified first (xxd 55aa check on the stick, make -C foreboots check).

1. Firmware setup — CSM/Legacy + AHCI

Do once in firmware setup (usually Del / F2 / F10 at power-on):

  1. Enable CSM / Legacy boot. Look under Boot → Boot Mode → Legacy, CSM → Enabled, Boot Priority → Legacy First. Pure-UEFI mode will ignore the MBR and never load ForeB stage1. On old BIOS-only boards there is nothing to enable — the MBR path is automatic.
  2. Set SATA to AHCI (not RAID / Optane / RST / IDE) if the option exists. AHCI is the tested path; proprietary RAID modes hide the disk from the kernel (fdisk -l from live mode shows no internal disk).
  3. Disable Fast Boot / Fast Startup if the USB stick is not detected — it skips USB enumeration.
  4. Secure Boot is irrelevant on the BIOS path (no BOOTX64.EFI involved), but leave it off if you dual-test UEFI later.
  5. Save & exit. Keep the internal disk attached.

2. Boot the USB stick (F12)

  1. Insert the Forest OS USB stick into a USB 2.0 port (rear ports enumerate best on old BIOS; avoid hubs / front-panel ports on first try).
  2. Power on and open the one-time boot menu: F12 (most boards), F8 / F9 / Esc on others. Do not change the permanent boot order yet.
  3. Select the USB stick entry (plain USB: <model> / HDD: <model> — on a UEFI board with CSM you may see both UEFI: <stick> and USB: <stick>; pick the non-UEFI one for this guide).
  4. If the stick never appears: try another port, disable Fast Boot, rewrite in DD mode, re-verify the MBR signature on another machine:
    sudo dd if=/dev/sdX bs=512 count=1 2>/dev/null | xxd -s 510 -l 2
    # expect: 55aa

The ForeB boot menu appears (graphical forest theme, or VGA-text fallback on limited VBE hardware). BIOS entries (config.h:ENTRY_*):

#EntryWhat it does
0Forest OS (default)Normal boot, best VBE mode. Pick this for install.
1Forest OS (no framebuffer)Text mode (nofb) — use on blank screen
2Forest OS (safe mode)Conservative drivers (safe)
3RebootCold reset
  • Navigate with Up/Down, Enter to boot, Esc resets the countdown.
  • Default FOREB_DEFAULT_ENTRY 0, FOREB_DEFAULT_TIMEOUT 5 — let it auto-boot or press Enter on Forest OS.
  • The kernel loads from the stick and drops to the live session (shell on TTY). Confirm display + keyboard work before installing.

Identify source vs target now, from the live session:

fdisk -l
blkid
lsblk -d -o NAME,SIZE,MODEL,TRAN

Sizes tell them apart (e.g. 16 GB stick vs 500 GB HDD). Note which is the USB stick (sdX, source) and which is the internal disk (sdY, target).

4. forinstall — entire-disk flow

Run from the live session as root:

forinstall

forinstall is the 23-step wizard (userspace/forinstall/main.c:445-486, v0.1.0). Defaults in [brackets] — Enter accepts. For a BIOS full install choose:

  1. Welcome — banner, any key.
  2. Language — English / Spanish / French / German (en default).
  3. Keyboard — US / UK / German / French / Spanish / Dvorak (US default).
  4. Install typeFull (~2 GB) (Minimal ~500 MB / Custom only for tight disks).
  5. Target disk — pick the internal disk (/dev/sda/dev/sdh probed via lseek size; < 1 MiB skipped). Never pick the USB stick or cd0. Confirm sizes/models on screen match step 3 notes.
  6. Partition schemeEntire disk (guided). This is the supported BIOS path. Manual (60 % root / 10 % swap / rest home) is for advanced use.
  7. Steps 7–9. Manual partitions — skipped on entire-disk flow.
  8. Filesystem — ext2 (no journaling) / ext4 (default). Note: the formatter currently writes a minimal ext2-like fs either way; the choice sets the fstab type string (install.c / disk.c:216-328).
  9. Hostname — default forest (e.g. forest-node-01).
  10. Timezone — 10 named zones + custom UTC offset.
  11. Steps 13–16. Network — DHCP (default) / Static (+ IP / gateway / DNS; DNS defaults to 8.8.8.8).
  12. Sound — PC-speaker test tune (C4/E4/G4/C5 + 880 Hz confirm, Y/N; N still continues).
  13. Steps 18–20. Users — primary user (default user), user password × 2 (default password), root password × 2 (default toor). Stored as $fsh<hash>$ in /etc/shadow + /etc/passwd + /etc/group; /home/<user> created 0755.
  14. Confirm — destructive-write gate (YES required). Cancelling here makes zero changes. Last chance to check sdX vs sdY.
  15. Install — runs install_perform() 8 sub-steps:
    1. Fresh MBR partition table (guided: one bootable 0x83 Linux partition).
    2. ForeB bootloader + kernel + initrd to raw sectors (§5).
    3. Format root partition.
    4. Mount at /mnt/forest.
    5. Create tree (/bin /sbin /etc /dev /proc /sys /tmp /usr… /var… /home /root /boot …).
    6. Copy kernel + initrd + core binaries.
    7. Write configs (hostname, os-release, hosts, resolv.conf, inittab, rcS, fstab, shadow/passwd/group, boot/forebo/forebo.cfg).
    8. Ensure /boot/forebo on target. Then sync() + umount.
  16. Reboot — success screen. Do not reboot yet — verify first (§7).

Final MBR note: install_write_foreb_to_disk() clears MBR bytes 446–509, installs one bootable 0x83 partition starting at FOREB_PARTITION_START 63, sets 0x55AA. The final table starts at sector 63 (overwrites the LBA-1 table from sub-step 1).

Full step table and file map: Installer.

5. ForeB sectors written

All sectors 512 B (FOREB_SECTOR_SIZE). Mirrors foreboots/bios/config.h:35-77 / installer.h:19-31:

SectorsSizeContentMagic / note
0512 BStage 1 (MBR: boot code 0–439, part table 446–509, 0xAA55)bytes 510–511 = 55 AA
1–2222 × 512 B = 11264 BStage 2 (real-mode GUI / BIOS / menu)word at sector 1 offset 2 = 0xFEB1 (b1fe LE)
23–3816 × 512 B = 8192 BStage 3 (PM / long-mode trampoline, ELF parse)
39–53Gap (reserved)untouched
54+variable, zero-padded last sectorKernel ELF image (FOREB_KERNEL_SECTOR 54 / KERNEL_START_SECTOR)starts 7F 45 4C 46 (.ELF)
past kernel, 16-sector alignedvariableOptional initrd (BIOS_INITRD_SECTOR)((54 + ksectors + 15) / 16) * 16; skipped with note if absent

Stage1 loads stage2 to 0x8000, checks 0xFEB1 at 0x8002, then stage2 streams the kernel ELF to its PT_LOAD targets and stage3 does the Multiboot1 handoff. See BIOS Boot for the full pipeline.

6. dd seek table (manual equivalent)

What forinstall step 2/8 does via disk_write_raw(), expressed as dd. /dev/sdY = internal disk. stage*.bin / kernel / initrd come from the live image (/boot/forebo/, /cdrom/boot/forebo/, or forebo.img blob).

# sdY = INTERNAL disk (verified with fdisk -l). count/seek in 512-B sectors.
# Stage 1 -> sector 0 (includes partition table + 55AA):
dd if=stage1.bin  of=/dev/sdY bs=512 seek=0  count=1   conv=notrunc

# Stage 2 -> sectors 1-22:
dd if=stage2.bin  of=/dev/sdY bs=512 seek=1  count=22  conv=notrunc

# Stage 3 -> sectors 23-38:
dd if=stage3.bin  of=/dev/sdY bs=512 seek=23 count=16  conv=notrunc

# Kernel ELF -> sector 54+ (pad last sector with zeros):
dd if=kernel.elf  of=/dev/sdY bs=512 seek=54 conv=notrunc,sync

# Initrd -> next 16-sector boundary past kernel end:
#   ksectors = ceil(kernel_size / 512)
#   initrd_sector = ((54 + ksectors + 15) / 16) * 16
#   e.g. kernel 1 MiB -> ksectors=2048 -> initrd_sector=((54+2048+15)/16)*16=2112
dd if=initrd.tar  of=/dev/sdY bs=512 seek=<initrd_sector> conv=notrunc,sync

sync

One-pass shortcut (whole blob, first ~16 MiB covers stages + kernel + initrd) — equivalent when source is the known-good USB stick (sdX):

# sdX = USB stick (source), sdY = INTERNAL disk (target). Swapping wipes the installer.
dd if=/dev/sdX of=/dev/sdY bs=1M count=16
sync

You do not need the manual table when forinstall succeeds — it is for rescue, verification math, and understanding failures.

7. Verify before reboot (still in live session)

Run against the internal disk (sdY). All four must pass:

DEV=/dev/sdY   # e.g. /dev/sda — the INTERNAL disk

# 1. MBR signature 55 AA at bytes 510-511 of sector 0:
dd if=$DEV bs=512 count=1 2>/dev/null | xxd -s 510 -l 2
# expect: 55aa

# 2. Stage2 magic 0xFEB1 (b1fe little-endian) at sector 1, offset 2:
dd if=$DEV bs=512 skip=1 count=1 2>/dev/null | xxd -s 2 -l 2
# expect: b1fe

# 3. Kernel ELF magic 7F 45 4C 46 at sector 54:
dd if=$DEV bs=512 skip=54 count=1 2>/dev/null | xxd -l 4
# expect: 7f45 4c46  (".ELF")

# 4. Partition table sane:
fdisk -l $DEV
# expect: one bootable (*) Linux (0x83) partition starting at sector 63, no errors
blkid $DEV

If any check fails do not reboot into it — re-run forinstall step 22 (or re-dd the exact ranges from §6), sync, verify again. Cross-check sizes with make -C foreboots check (stage1 exactly 512 B, stage2/3 ≤ 8192 B each).

8. Remove USB, boot internal

  1. sync, then shut down: shutdown -h now (or reboot -p).
  2. Wait for power-off, physically remove the USB stick.
  3. Power on. Enter the boot menu (F12) if needed and select the internal disk; optionally set it first in Boot Priority for subsequent boots.
  4. ForeB should appear from the internal disk and auto-boot entry 0 in ~5 s. If the machine drops to firmware or prints a stage error (s2!, ERR:Invalid kernel entry point), power off and re-verify §7 from the USB live session — do not reinstall blindly.

9. Smoke test (first boot from disk)

Log in as the user created in §4 (or root), then:

uname -a
df -hT            # root mounted, space free (base wants ~100-200 MiB free)
ls /bin | head
cat /etc/hostname /etc/os-release
fdisk -l /dev/sda
ip addr            # NIC appears only if driver built in (see below)

Expected: kernel banners on screen/serial, framebuffer TUI/GUI on display, shell prompt on TTY, root fs mounted per fstab, hostname as set.

Post-install essentials:

ip link set e1000 up                  # name varies by driver
ip addr add 10.0.2.15/24 dev e1000
ip route add default via 10.0.2.2 dev e1000
ping -c 4 10.0.2.2
pac list                              # needs route to /etc/pacservers
hostname forest-node-01

Snapshot / image the disk now, before experimenting.

10. Issues and fixes

SymptomCauseFix
USB stick not in F12 menuPort / Fast Boot / ISO-mode writeUSB 2.0 rear port, disable Fast Boot, rewrite in DD mode, re-verify 55aa per §2
Drops to firmware, no ForeB from internal diskCSM off / wrong boot deviceEnable CSM/Legacy, pick internal disk in F12, re-verify §7 55aa + b1fe
s2! flash / ERR:Invalid kernel entry point / boot loopCorrupt or misaligned stagesRecheck §7 (all three xxd + fdisk -l), re-dd exact §6 ranges, sync, full catalog: BIOS Boot §12
Internal disk missing in live fdisk -lRAID/Optane/IDE mode or NVMe w/o driverSet SATA to AHCI; on NVMe-only boards record lspci -n if still missing
No network (ip addr empty)NIC driver not built inRebuild with ENABLE_NETWORKING + your NIC driver, reinstall; not a cable problem
Blank screen after ForeB menuVBE mode unsupportedReboot, pick entry 1 (nofb, VGA text) or entry 2 (safe)
Wiped the USB stick instead of the diskif= / of= swappedPrevention only: fdisk -l + lsblk sizes before every write; unplug extra disks

Still stuck? See Troubleshooting, Development Troubleshooting (serial -serial stdio, make check, GDB stub), FAQ.

See Also

← Back to Wiki