# Deshab Linux/EXE 兼容层开发 ## 需求 - Linux 程序兼容层(依赖双内核架构,WSL 互操作模式) - EXE 兼容层直接写在 UTSM 里(PE32+ 64位原生 Ring0 执行 + PE32 32位 x86 解释器) - cmd.exe 编译到 `SYSTEM/system/deshab64` - 桌面命令行1: shell.elf(原生 + `linux` 命令运行 Linux 程序) - 桌面命令行2: cmd.elf(Windows 风格 + PE/EXE 兼容) --- ## PE/EXE 兼容层(UTSM 内置) ### 核心文件 | 文件 | 职责 | |------|------| | `CODE/UTSM/pe/pe_loader.c` / `.h` | PE 解析、映射、重定位(R_X86_64_64/32/32S/PC32)、import 解析 | | `CODE/UTSM/pe/pe_shim.c` / `.h` | Windows API shim(`__attribute__((ms_abi))`,`__builtin_setjmp`/`__builtin_longjmp`)| | `CODE/UTSM/pe/x86emu32.c` / `.h` | x86-32 解释器:支持 push/call/add esp/ret/mov/xor/ModRM 解码/IAT 拦截 | | `CODE/UTSM/pe/pe_service.c` | 统一服务:`pe_service_load`/`pe_service_run`/`pe_service_unload` | ### PE 加载流程 - **PE32+**: 原生 Ring0 执行,MS x64 ABI shim - **PE32**: x86emu32 解释器执行,`preferred_base` 加载(0x00400000),专用大缓冲区含栈和堆 - `pe_image_info` 结构体返回加载信息(entry_point, image_base, image_size, is_pe32_plus) - 通过 `dsk_boot_context.reserved[4]` 暴露给 cmd.elf ### 关键结构 ```c // pe.h - PE 服务接口 struct pe_service { int (*load)(const char *name, u8 **out_data, u64 *out_size, pe_image_info *info); int (*run)(u8 *data, u64 size, pe_image_info *info, int argc, char **argv); void (*unload)(u8 *data, u64 size, pe_image_info *info); }; // pe_loader.h - PE 结构体(DOS/NT/File/Optional32/64/Section/Import Descriptor) #define PE_DOS_MAGIC 0x5A4D #define PE_NT_MAGIC 0x00004550 #define PE32_MAGIC 0x010B #define PE32_PLUS_MAGIC 0x020B ``` --- ## Linux 兼容层(双内核 park-and-resume) ### 架构 ``` shell 输入 `linux ls` → g_lxc_svc->exec("/bin/ls") → 写 IPC 请求 → linux_resume() vmresume 唤醒 Linux guest → daemon fork+exec ls → pipe 捕获 stdout → 发 EXEC_STDOUT/EXIT → HLT park → UTSM 读取响应返回 shell ``` ### 核心文件 | 组件 | 文件 | 说明 | |------|------|------| | park-and-resume | `vmm/linux_resume.c`, `vmm/linux_boot.c`, `vmm/vmexit.c` | Linux guest HLT 时 park(推进 RIP),UTSM 通过 vmresume 唤醒 | | IPC exec 协议 | `CODE/utsm-ipc/ipc_proto.h` | EXEC_REQUEST/STDOUT/STDERR/EXIT/READY 消息类型 + 载荷 | | Linux compat 服务 | `vmm/linux_compat.c`, `include/utsm/linux_compat.h` | exec(): 写 IPC 请求 → linux_resume → 读取响应 | | Boot context | `kernel/dsk_loader.c` | reserved[4]=pe_service, reserved[5]=linux_compat_service | | shell `linux` 命令 | `CODE/shell/main.c` | `linux ls -la` → /bin/ls,支持绝对路径 | | Linux 驱动 ioctl | `CODE/linux/patches/utsm_hcall.c` | RECV_MSG/SEND_MSG/PARK/GET_READY ioctl | | Linux exec daemon | `CODE/linux/initramfs/bin/utsm_exec_daemon.c` | fork+exec+pipe 捕获输出,通过 IPC 回传 | | init 脚本 | `CODE/linux/initramfs/init` | 启动 daemon,daemon 发 EXEC_READY 后 HLT park | ### 关键全局变量 ```c // vmm.c volatile int g_guest_parked; // Linux guest 是否已 park volatile int g_guest_terminated; // self-test guest 是否已终止 // linux_boot.c volatile u64 g_saved_host_rsp; // linux_launch/linux_resume 保存的 host RSP volatile u64 g_saved_return_rip; // linux_launch/linux_resume 保存的返回 RIP ``` ### IPC 消息类型(ipc_proto.h 扩展) ```c #define UTSMB_MSG_EXEC_REQUEST 0x10 // {cmd_path[256], argc, argv[8][128]} #define UTSMB_MSG_EXEC_STDOUT 0x11 // {data[N], len} #define UTSMB_MSG_EXEC_STDERR 0x12 // {data[N], len} #define UTSMB_MSG_EXEC_EXIT 0x13 // {exit_code} #define UTSMB_MSG_EXEC_READY 0x14 // daemon 就绪 ``` --- ## 第一阶段:Linux guest 底层基础设施 ### EPT 动态页映射 - `vmexit.c` handle_ept_violation 区分 RAM(按需分配 HPA)和 MMIO(路由到设备模拟) - 需从 guest 指令解码 MMIO 访问大小和数据 ### virtio-mmio 框架 | 文件 | 说明 | |------|------| | `vmm/virtio_mmio.c` / `.h` | 寄存器分发 + virtqueue 状态机 + 后端路由 | | `vmm/virtio_blk.c` | virtio-blk 后端,桥接 guest 块请求到 UTSM block API | | `vmm/virtio_net.c` | virtio-net 后端占位 | **GPA 布局**: - `0x0A000000-0x0A0001FF`: virtio-mmio #0 (blk, IRQ5) - `0x0A000200-0x0A0003FF`: virtio-mmio #1 (net, IRQ6) **virtqueue 关键 API**: ```c void virtio_queue_get_ptrs(virtio_dev_state *dev, int qidx, u16 *avail_idx, u16 *used_idx, u64 *desc_addr, u64 *avail_addr, u64 *used_addr); ``` ### vmexit dispatch 接线 | Exit Reason | Handler | 说明 | |-------------|---------|------| | EXIT_CPUID | handle_cpuid | host passthrough + 屏蔽 VMX/hypervisor 位 | | EXIT_IO_INSTRUCTION | handle_io | COM1/PIC/PIT 模拟 | | EXIT_INTERRUPT_WINDOW | 新增 | guest 开中断时注入 pending IRQ | | EXIT_VMX_PREEMPTION_TIMER | 新增 | 1ms 周期 exit | | resume 路径 | vmexit_before_resume() | arm timer + 串口 RX 轮询 + PIT tick + IRQ 注入 | **virtio IRQ**:QUEUE_NOTIFY 后 `vmx_guest_queue_irq(0x30+irq)`,blk→0x35,net→0x36 ### initramfs - `build.sh`: busybox 1.35.0 静态下载 + gen_init_cpio 打包 - init: daemon 缺失时 `setsid cttyhack sh` 回退 ttyS0 交互 shell - `/dev/console`, `/dev/ttyS0` 节点 + 12 个 applet symlink ### linux_boot 集成 - `linux_launch()` 调用 `virtio_mmio_init()` + 启用 PIN_VMX_PREEMPTION_TIMER + 初始 arm preemption timer --- ## cmd.elf Windows 风格命令行,支持 PE/EXE 执行。 ### 关键功能 - FAT32 根目录 + `/bin` 子目录 PE 查找(PATH 查找:先根目录,再 /bin) - `pe` 命令:显式运行 PE 程序 - `peinfo` 命令:解析 PE 头显示 DOS/NT/File/Optional Header、节区表、导入表 - 内建命令:help, echo, cls, dir, ver, exit, type, copy, del, ren, cd, color - 通过 `reserved[4]` 获取 pe_service,`reserved[5]` 获取 linux_compat_service ### PE 样本部署 | 文件 | 格式 | 位置 | |------|------|------| | hello64.exe | PE32+ (1536B) | SYSTEM/bin/ | | hello32.exe | PE32 (2048B) | SYSTEM/bin/ | | cmd.exe | PE32+ (1536B) | SYSTEM/bin/ | --- ## 构建验证 全量构建成功,新代码零警告: - utsm.elf, deshab.elf, shell.elf (791KB), cmd.elf (490KB), desktop.elf (140KB) - FAT32 镜像含 CMD ELF ## 待办(需 WSL) Linux 内核需在 WSL 构建(`CODE/linux/build.sh`,约 30 分钟)。构建后取消注释 `SYSTEM/limine/limine.conf` 中 bzImage/initrd module 条目即可启用。Linux 未构建时 `linux` 命令显示"兼容层不可用"。 ### WSL 构建命令 ```bash sudo apt update && sudo apt install -y build-essential bc flex bison libelf-dev libssl-dev cpio cd ~ curl -L -o linux-6.6.tar.xz https://mirrors.tuna.tsinghua.edu.cn/kernel/v6.x/linux-6.6.tar.xz tar xf linux-6.6.tar.xz && cd linux-6.6 # 安装 UTSM 驱动 + 配置 + 编译 cp /mnt/d/Code/Deshab/CODE/linux/configs/utsm_x86_64_defconfig .config make olddefconfig make -j$(nproc) KCFLAGS='-std=gnu17' bzImage # 拷贝产物 + 构建 initramfs mkdir -p /mnt/d/Code/Deshab/SYSTEM/boot cp arch/x86/boot/bzImage /mnt/d/Code/Deshab/SYSTEM/boot/linux-bzImage cd /mnt/d/Code/Deshab/CODE/linux && ./build.sh ``` **注意**:gcc 15 默认 C23,需 `KCFLAGS='-std=gnu17'` 修复与 Linux 6.6 的兼容性。