Four independent blockers sat between "the image boots UTSM" and "the desktop
comes up". Each one wedged the boot on its own; all four are fixed here and the
tree now reaches "[desktop] desktop ready" under QEMU/OVMF
(evidence: .build_tmp/d2.log).
1. FirstInit made networking a hard gate (CODE/firstInit/main.c)
The setup wizard always showed the network page, and on a machine with no
wireless device the only exit was Save - pressing Connect raised NET-E01.
Networking is not a precondition for entering the system, so a wizard that
cannot be completed without it is a plain design defect.
- No wireless device detected -> skip the network page entirely (the
g_no_wireless_device flag already existed but was only logged).
- With a device present, add a Skip button (draw + mouse hit-box + keyboard
Enter), mirroring "I don't have internet" on Windows.
- Connect keeps its zero-fallback NET-E01 panic: the unimplemented path is
still honest, it just no longer holds the user hostage.
2. ESP cluster size left no room in the root directory
(CODE/linux/pack_system_image.sh)
With the cluster size left to mkfs it chose 1 sector, i.e. 16 directory
entries per cluster. The ESP root ends up holding exactly 16 entries
(DESHABBOOT/EFI/LIMINE/BOOT/DRIVER/SYSTEM/USER/NVVARS plus one long-name
entry each), and the root chain is a single cluster - so on first boot the
DSK could never write USER.CONF.
Pin -s 4 (2KiB, 64 entries): it clears the FAT32 65525 lower bound and the
0xFFF5 boundary that -s 8 lands on at this 256MiB size, and leaves 48 free
entries. The alternatives were measured, not guessed (see the comment).
3. DSK could not grow the root directory (CODE/dsk/main.c)
fat32_write_root_file returned -4 "no free dir entry" whenever the scan of
the root chain came up empty. A FAT filesystem is supposed to extend the
directory chain, so allocate a cluster, link it at the current tail, write
the entry there and commit the FAT. Fixing only (2) would have papered over
this: any real disk whose root fills up would still fail the same way.
4. Nothing generated the CJK bitmap font packs (build.ps1)
The desktop loads system/font/simhei_16.dbf and panics DESK-E04 FONT PACK
MISSING without it. The .dbf files are generated from simhei.ttf by
CODE/font/mkfont.py and are gitignored, but no build step ever invoked it -
same class of bug as the previously untracked .drv binaries. Generate
simhei_16.dbf / simhei_24.dbf in build.ps1 (with the existing WSL python3
fallback for Pillow), rebuilding only when the TTF is newer than the pack.
docs/STATUS.md updated to match: FirstInit wizard and the D3 named API export
table move to done, and the FAT32 / ESP cluster size / CJK font pack entries
are added or corrected. D3 was already fully implemented (table, lookup,
selftest with positive and negative cases, TST-E21..E24 instrumentation) -
only the status row was stale.
Verified boot chain (QEMU/OVMF, dev variant):
BdsDxe -> Limine -> UTSM -> DKM 17/17 -> DSK -> FirstInit (network page
skipped) -> USER.CONF written -> login (password accepted) -> desktop:
"[zhfont] dbf loaded (16px ok)" ... "[desktop] desktop ready"
There were three independent reasons a fresh build produced an image that
OVMF would not boot. All three are fixed here; verified by booting the
resulting ISO/deshab-dev.img under QEMU/OVMF through to FirstInit.
1. ESP rejected by OVMF (CODE/linux/pack_system_image.sh)
The vfat formatter was invoked with an explicit -s 8, forcing 4KiB clusters.
On the 256MiB ESP that yields exactly 65535 clusters - the FAT32 0xFFF5
boundary - and OVMF's FatPkg refuses to mount the volume. Symptom: BdsDxe
logs "failed to load ... Not Found", the ESP shows up as BLKn with no FS in
the UEFI Shell, and the firmware falls through to the internal shell.
The sidecar FAT32 image (make_sata_sidecar.sh) mounts fine because it calls
the formatter without -s. Drop -s here too and let the tool pick geometry.
Do NOT add -f 1: OVMF mounts nfat=1 and nfat=2 alike, it was not the cause.
2. Limine dropped into a panic (CODE/linux/pack_system_image.sh)
limine.conf declares the Linux-compat guest modules. build.sh uncomments
them once Linux has been built, but nothing ever comments them back, so the
file says "load boot():/boot/linux-initrd.img" while only linux-bzImage
exists on disk - Limine panics on the missing module and never reaches the
kernel. Filter the guest module_path lines against SYSTEM/boot/ at pack
time and write the result to the ESP. Both the root /limine.conf and
/limine/limine.conf are written, since Limine 10 prefers the latter. The
tracked source file is left untouched.
3. Nine drivers were never compiled (build.ps1)
Commit 055c521 untracked the .drv binaries on the grounds that they are
regenerable, but build.ps1 only ever invoked Build-DkmDriver for 8 of the
17 drivers listed in manifest.json. timer/acpi/pci/ahci/bootfs/vfs/fat32/
devfs/ps2kbd had sources under CODE/DKM/ and no build step, so the image
shipped without them and Limine failed on the first one. Add the missing
compile steps, grouped by load stage. All 17 now match manifest.json.
Also in this commit (environment/tooling hygiene):
- check_env.sh: stop hardcoding /mnt/d/Code/Deshab (the original author's
machine); derive the repo root from the script's own location. It was
reporting a bogus "wsl_mount" failure on every other checkout and sending
people to install packages that were already present. Also check and
advertise the image-packing tools (dosfstools/e2fsprogs/fdisk/rsync), which
were missing from the dependency list even though pack_system_image.sh
hard-requires them.
- build_initrd.sh: same hardcoded-path fix.
- README.md: relative path instead of the stale absolute one.
Verified: ./build.bat -Variant dev under WSL2/Ubuntu, then QEMU/OVMF boots
through BdsDxe -> Limine -> UTSM -> DKM (17/17) -> DSK -> FirstInit, with the
PS/2 mouse initialising cleanly.
stale-check compared LastWriteTime against a stamp file that does not
exist yet on the first build, so Get-Item threw PathNotFound and aborted
the build before make DSK.
- build.ps1: guard the texSrc/texStamp mtime comparison with
Test-Path $TexStamp; $needTex is already $true when the stamp is
absent, so the comparison is only meaningful when both files exist
- .gitignore: ignore IDEA.md local scratch note
Verified: .\build.bat now reaches gen_textures.py and emits
back.rgba / startMenuLogo.rgba / bootlogo.rgba into
SYSTEM/system/deshab64/desktop/textures/.
- desktop boot screen: typewriter effect removed, whole screen drawn in one pass
- login: ohMyLogo (DEAICUP lotus, 288px embedded) intro screen before password card
- strict error policy instrumentation (zero degradation): login LOGIN-E01..E05 (integrity/badctx/noconf/nouser/nohash) and desktop DSK-E01 now full-screen fatal with symbol + halt instead of silent skip
- root-cause fixed: missing .build_tmp/mkfat32.ps1 silently left SATA sidecar stale (login.elf 'not found' degradation) - replaced with CODE/linux/make_sata_sidecar.sh (auto adaptive FAT32 rebuild each build)
- recreated lost CODE/login/patch_login_hash.ps1 (.text SHA256 -> .hashseg)
- dev config now full flow: show_logo=1, wizard+login enabled, dev shell off
- panic screen now draws embedded ohMyLogo.png (384px RGBA, gen_panic_logo.py); background color sampled from image corners so screen bg matches logo bg
- F2: include/utsm/fbcon.h unified framebuffer console (pixel/blend/fill/rgba-image/text with FBCON_HAVE_FONT opt-in); panic.c migrated onto it
- build.ps1 regenerates panic_logo_data.inc when ohMyLogo.png changes
Add the current OS source tree, build scripts, system image layout, and development notes covering DMA page allocation, e1000 bring-up, net API dispatch, and DHCP work in progress.