# Build & run your own programs on JefeOS

The published `jefeos-<ver>.iso` is a **kernel-only** boot image. Booted on its
own it gives you the shell, the GUI, the network stack, and a couple of
kernel-embedded ring-3 self-tests — a good demo, but nowhere to store files and
no way to run *your* code. To actually run programs you need two things:

1. a **writable NTFS disk** attached to the VM, and
2. a **program** on it that JefeOS can load.

This guide covers both. If you just want to try the bundled programs first,
grab `jefeos-examples.vhd` (ships next to the ISO), skip to
[Attach a disk](#1-attach-a-disk), and `exec /programs/hello`.

---

## 0. What runs with *no* disk at all

Boot the ISO by itself and these work immediately — worth trying before you
build anything:

```
help            # full command list (80+)
version         # kernel build + version
gui             # windowed GUI; then:  theme list  /  theme set win95
elftest         # runs a kernel-EMBEDDED ELF in ring 3 (proves the loader)
sigtest         # raises + catches a signal in that embedded ELF
cryptotest      # self-tests the crypto suite (SHA/ChaCha/Ed25519/X25519…)
ping 1.1.1.1    # the TCP/IP stack (also: dns, ntp, curl, ssh)
```

`elftest`/`sigtest` prove the userspace path works with zero storage because
those ELFs are compiled *into* the kernel image. Everything below is about
running programs that are **not** baked in.

---

## 1. Attach a disk

JefeOS's NTFS driver mounts the **first IDE drive (IDE 0:0)** as its root
filesystem. In every hypervisor that means "the primary/first hard disk."

### QEMU

```sh
qemu-system-x86_64 -cdrom jefeos-1.1.2.iso \
  -drive file=jefeos-examples.vhd,format=raw,if=ide -m 512
```

That attaches the disk as the primary IDE master, which is exactly what JefeOS
mounts as root. (The short form `-hda jefeos-examples.vhd` also works — a fixed
VHD's MBR is at offset 0 so QEMU reads it as raw — but modern QEMU prints a
format-probe warning; the explicit `format=raw` above silences it.) Any
raw/`.img` or VHD works. To make a blank one:

```sh
qemu-img create -f raw mydisk.img 48M
# then format it NTFS from a Linux host (ntfs-3g):  mkfs.ntfs -F mydisk.img
```

### Hyper-V (Generation 1)

- **New → Virtual Machine → Generation 1.**
- Attach the ISO to the **DVD drive**.
- Attach an **NTFS-formatted VHD** to **IDE Controller 0, Location 0** (the
  primary master). This is the disk JefeOS mounts as root.
- Boot. (`jefeos-examples.vhd` is already NTFS-formatted and seeded.)
- For networking (`ping`, `ssh`, `curl`, `ntp`), replace the default
  **synthetic** network adapter with a **Legacy Network Adapter** — JefeOS's
  NIC drivers don't bind the synthetic one on Gen 1. This is **not** needed
  just to `exec` the bundled programs; they run fine with no network.

### VirtualBox

- Create a VM, attach the ISO as an optical drive.
- Attach the VHD to the **IDE** controller as the **primary master**
  (VirtualBox reads `.vhd` natively; or convert with `VBoxManage clonemedium`).

> The bundled `jefeos-examples.vhd` is a small fixed VHD with `/programs/*`
> already on it. Unzip it first (`jefeos-examples.vhd.zip`).

---

## 2. The easy path — a Linux binary via `exec_linux`

JefeOS has a **WSL1-style Linux ABI layer**: statically-linked Linux x86_64
binaries run unmodified through the `SYSCALL` instruction. You only need
`musl-gcc` on any Linux box — no JefeOS source, no special toolchain.

```c
// hello.c
#include <stdio.h>
int main(int argc, char **argv) {
    printf("hello from a Linux binary on JefeOS! argc=%d\n", argc);
    return 0;
}
```

```sh
musl-gcc -static -O2 -o hello hello.c      # on any Linux host (apk add musl-dev, etc.)
file hello                                  # ELF 64-bit … statically linked
```

Put `hello` on the disk (see [§4](#4-getting-your-binary-onto-the-disk)), then
on JefeOS:

```
exec_linux /programs/hello one two three
```

Unimplemented syscalls log to the serial console with their number, so if a
binary needs something JefeOS doesn't have yet, you'll see exactly what.
(`glibc`-dynamic binaries partially work via the Tier-3 dynamic linker, but
**musl `-static` is the reliable target**.)

---

## 3. The native path — INT 0x80 (reference)

If you have the JefeOS source tree, you can build against its own libc
(`libjefec.a`) and use the **native** syscall interface. Native programs use
`INT 0x80`, distinct from the Linux-ABI `SYSCALL` path in §2.

**Calling convention** (`userspace/libc/src/syscall.S`):

| Register | Meaning |
|----------|---------|
| `RAX` | syscall number |
| `RDI, RSI, RDX, R10, R8, R9` | args 1–6 |
| `RAX` (return) | result; **negative = `-errno`** |

**Common syscall numbers** (`userspace/libc/include/jefeos_syscall.h`):

| # | Name | # | Name |
|---|------|---|------|
| 0 | `exit` | 10 | `open` |
| 1 | `write` | 11 | `close` |
| 2 | `read` | 12 | `lseek` |
| 3 | `sleep` | 13/14 | `stat`/`fstat` |
| 4 | `getpid` | 17 | `getdents` |
| 5 | `yield` | 30/31/32 | `fork`/`execve`/`waitpid` |
| 6 | `time` | 40–51 | BSD sockets (`socket`…`shutdown`) |

A freestanding "hello" with no libc at all:

```c
// native_hello.c  — build with: x86_64-elf-gcc -ffreestanding -nostdlib -static
static long sys_write(long fd, const void *buf, long n) {
    long ret;
    __asm__ volatile("int $0x80"
        : "=a"(ret) : "a"(1 /*SYS_WRITE*/), "D"(fd), "S"(buf), "d"(n) : "memory");
    return ret;
}
static void sys_exit(long code) {
    __asm__ volatile("int $0x80" :: "a"(0 /*SYS_EXIT*/), "D"(code));
    __builtin_unreachable();
}
void _start(void) {
    const char msg[] = "hello from a native JefeOS ELF\n";
    sys_write(1, msg, sizeof(msg) - 1);
    sys_exit(0);
}
```

For the full ABI (all ~140 native calls, argument shapes, and the crt0
argc/argv/envp plumbing) read `userspace/libc/include/jefeos_syscall.h` and
`userspace/libc/src/`. Every program under `userspace/programs/` is a worked
example; `userspace/programs/hello/` is the canonical starting point. Run
`userspace/programs/build-all.sh` to build them all.

---

## 4. Getting your binary onto the disk

JefeOS's NTFS writer can create and grow files on-VM, but the simplest way to
stage a fresh binary is host-side:

- **Mount the VHD on your host** (Linux: `ntfs-3g`; Windows: attach the VHD),
  copy the ELF into `\programs\`, unmount, boot.
- Or, once JefeOS is up on the network, use its **SFTP/SCP** client/server
  (`ssh adduser <name> <pass>` on JefeOS first) — good for small files.

Then run it: `exec /programs/yourprog` (native) or
`exec_linux /programs/yourprog` (Linux binary).

---

## Troubleshooting

| Symptom | Fix |
|---------|-----|
| `exec: file not found` | The disk isn't mounted as IDE 0:0, or the path is wrong. `ls /programs` to confirm what JefeOS sees. |
| Nothing under `/` | Disk isn't the **primary master**. Re-attach to IDE controller 0, location 0 (Hyper-V) / `-hda` (QEMU). |
| Linux binary exits oddly | Check the serial console for `unimplemented syscall N` lines. Rebuild `-static` if it was dynamic. |
| Writes fail on large files | Grow past the initial allocation is supported, but stage big binaries host-side to be safe. |

---

*Part of the JefeOS 1.1.2 download bundle. The OS source is private; this
covers everything you need to build for and run on the public ISO.*
