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.
Linux 6.6 LTS for UTSM Dual-Kernel Architecture
Overview
This directory contains the Linux 6.6 LTS configuration and build scripts for the UTSM + Linux dual-kernel architecture. Linux runs as a VMX non-root guest under the UTSM hypervisor (VMX root).
Prerequisites
- WSL (Windows Subsystem for Linux) with Ubuntu 22.04+ installed
wsl --install -d Ubuntu-22.04 - Build dependencies (inside WSL):
sudo apt update sudo apt install -y build-essential bc flex bison libelf-dev libssl-dev cpio gzip git - ~3GB free disk space
Building Linux
1. From WSL
# Navigate to the project from your repo root in WSL
cd CODE/linux
# Make the build script executable
chmod +x build.sh
# Run the build (clones Linux 6.6 LTS, configures, builds)
./build.sh
The build will:
- Clone Linux 6.6 LTS source to
CODE/linux/src/ - Apply UTSM patches from
CODE/linux/patches/(if any) - Configure with
configs/utsm_x86_64_defconfig - Build
bzImage - Copy to
SYSTEM/boot/linux-bzImage - Build initramfs if
CODE/linux/initramfs/exists
2. Enable in Limine
After building, uncomment the Linux module entries in SYSTEM/limine/limine.conf:
module_path: boot():/boot/linux-bzImage
module_cmdline: linux:bzImage
module_path: boot():/boot/linux-initrd.img
module_cmdline: linux:initrd
3. Rebuild the disk image
cd d:\Code\Deshab
.\build.bat
4. Test with QEMU
Note: VMX requires hardware virtualization support. QEMU's TCG (software emulation) does NOT support VMX instructions. To test the VMX path:
- Real hardware: Boot on an Intel machine with VT-x enabled in BIOS
- QEMU with WHPX:
qemu-system-x86_64 -accel whpx -cpu max(may not expose nested VMX to the guest) - QEMU with KVM (Linux host only):
qemu-system-x86_64 -enable-kvm -cpu host
Without VMX, UTSM gracefully falls back to the normal DSK boot flow.
Configuration Details
The utsm_x86_64_defconfig enables:
- 64-bit kernel with SMP support
- Serial console (8250/16550 at 0x3F8, 115200 baud)
- virtio: console, block, net, fs (for UTSM host backends)
- ext4, FAT, tmpfs, proc, sysfs filesystems
- No module loading (all drivers built-in for Phase 1)
- No EFI stub (UTSM uses custom VMX boot protocol)
- Debug info and printk timestamps
File Structure
CODE/linux/
├── configs/
│ └── utsm_x86_64_defconfig # Kernel configuration
├── patches/ # UTSM-specific kernel patches
│ ├── utsm-hcall.patch # /dev/utsm hypercall driver (Phase 1.3)
│ ├── utsm-ipc.patch # Shared memory IPC driver (Phase 1.3)
│ └── utsm-virtio.patch # virtio enhancements (Phase 1.4+)
├── initramfs/ # Minimal initramfs contents (optional)
├── build.sh # Build script (run in WSL/Linux)
└── README.md # This file
Boot Flow
Limine (UEFI)
→ utsm.elf (VMX root)
→ vmm_init() + vmm_self_test()
→ linux_loader_init() (parse bzImage, set up boot_params, EPT)
→ linux_launch() (VMCS config + vmlaunch)
→ Linux 6.6 startup_64 (VMX non-root)
→ Serial console output
→ virtio-console ↔ UTSM
→ virtio-fs mount /utsm
→ User space (init/shell)
Guest Networking (virtio-net)
UTSM vmm 侧模拟一块 virtio-net 网卡(virtio-mmio 模型,GPA 0xF4001000,
guest ISA IRQ6),数据路径桥接到 host 真实网卡(e1000/virtio-net DKM 驱动,
经 kernel_api.net 的 tx/rx_poll 收发帧)。guest 内核 cmdline 已自动注入:
virtio_mmio.device=4K@0xF4001000:6
utsm_x86_64_defconfig 已启用 CONFIG_VIRTIO_NET=y(内置,非模块),
内核启动后应出现 eth0(virtio-mmio 无 PCI 拓扑,网卡名固定为 eth0):
# 确认网卡已识别(dmesg 应能看到 virtio_net probe 日志)
ip link show
# 拉起接口
ip link set eth0 up
# 方式一:DHCP(QEMU user-net/slirp 环境,网关 10.0.2.2,DNS 10.0.2.3)
dhcpcd eth0
# 或:dhclient eth0
# 方式二:静态地址(无 DHCP 服务器时)
ip addr add 10.0.2.15/24 dev eth0
ip route add default via 10.0.2.2
echo "nameserver 10.0.2.3" > /etc/resolv.conf
# 验证连通性
ping -c3 10.0.2.2 # QEMU slirp 网关(永远在线,适合冒烟测试)
ping -c3 10.0.2.3 # slirp 内建 DNS
pacman -Sy # 联网同步包数据库
注意事项:
- MAC 共用:guest virtio-net 的 MAC 与 host e1000 相同(UTSM 桥接模型,
config 空间直接回填 host 网卡 MAC)。QEMU user-net 下 slirp 按 MAC 分配
10.0.2.15;若 host Deshab 原生网络栈同时用该网卡联网,两者会抢同一 DHCP 租约,实测时请只让一侧做 DHCP(或 host 完全不用网络)。 - MTU:后端按标准 1500 MTU 转发,不支持 GSO/TSO(feature 未协商, guest 自动走软件分片/checksum 路径)。
- 无中断收包:RX 走 UTSM 周期轮询(VMX preemption timer,~1kHz)
填充 guest RX ring 并注入 IRQ6;大流量下串口统计日志每 512 帧打印一行
[VNET] stat ...(rx_filled / rx_drop_nobuf / tx_sent / tx_drop), 可用于判断包在哪一段丢失。 - 若
ip link看不到 eth0:检查 dmesg 中virtio_mmioprobe 是否成功, 以及 host 串口日志是否有[VNET] bound to UTSM net device 0(host 侧 e1000/virtio-net DKM 驱动需先注册 netdev)。