# 启动 U 盘文件、设置与外部 C# 程序 2026-10-16 用户选择将文件和设置也保存到启动 U 盘。Console / Desktop 仍是两个独立系统,每张镜像只包含其中一个;专用 U 盘交付 Desktop。黑底 Logo、XFESystem 字样和就绪后交接动画保留。 ## 使用 启动 U 盘成功挂载后,`X:` 的工作文件和设置持久保存。编辑器保存、终端文件命令和 Settings 外观设置使用同一个存储接口,每次成功修改都提交到 U 盘。`help` 会显示 `Storage: persistent workspace`;如果没有可用且唯一匹配的启动 USB 存储,明确显示 RAM 回退,会话文件不会保留。临时目录和 `X:\System\Diagnostics` 始终为临时数据。 在启动 U 盘 FAT32 卷的 `UserFiles` 文件夹放入外部文件或符合现有 ConsoleIL 范围的标准 .NET 程序;系统内对应 `X:\UsbFiles`。这是只读导入目录,可复制到工作区后编辑。例如: ```text ls X:\UsbFiles run X:\UsbFiles\UsbHello.dll cp X:\UsbFiles\UsbHello.dll X:\Users\Default\Documents\MyApp.dll run X:\Users\Default\Documents\MyApp.dll ``` 随镜像提供的 `UsbHello.dll` 是单独编译的普通 .NET PE,位于 FAT 文件夹,未嵌入内核。它输出 `XFE_USB_EXTERNAL_APP_OK`。原有 `X:\Programs\ManagedHello\ManagedHello.dll` 继续保留。仍使用受限 ConsoleIL 指令和 API,不等于任意 .NET 程序、WinForms/WPF、P/Invoke、NuGet 依赖图或完整 CLR 动态加载已经兼容。 单个导入文件读取上限 4 MiB。工作区沿用现有配额:最多 1024 项、单文本文件 256 Ki 字符、文本合计 4 Mi 字符、单二进制文件 4 MiB、二进制合计 8 MiB。64 MiB 容器并不等于 64 MiB 可用文件空间。 ## 实现与恢复 单系统镜像扩大至 256 MiB,以容纳当前 Desktop 内核和预分配的 64 MiB `Workspace.bin`。现阶段只支持 xHCI 上 USB Mass Storage BOT、SCSI transparent、LUN 0、512 字节扇区和 READ CAPACITY(10) 范围;不支持 UAS-only、NVMe/SATA 或其他盘的通用挂载。 内核复用 Limine 已有 executable-file 响应中的启动磁盘/分区 GUID,回读实际 USB GPT 与 CRC 后匹配。多个相同身份设备会拒绝可写挂载。FAT32 读取器检查镜像 FAT、链边界、循环、长文件名和连续工作区分配。原生写入只允许工作区描述扇区后的两个数据区;不修改 FAT、目录、启动器或内核。 原生 USB worker 独占传输环和 DMA,托管侧通过 64 KiB mailbox 复制数据,GC 管理的缓冲区不会交给控制器 DMA。写入先更新非活动数据区并执行 SCSI SYNCHRONIZE CACHE,再提交带代数和 CRC 的整扇区头并再次同步。重启选取最新完整数据区;新提交中断或校验失败时回退到上一份。两份都损坏会拒绝自动覆盖。内存缓存只在提交成功后报告保存成功,提交失败会恢复此前缓存。 这验证了协议和故障注入下的恢复逻辑,实体 USB 桥接器是否正确执行同步、真实掉电和拔盘行为仍需实测,不能保证任意硬件掉电零损失。运行系统时不可由另一个系统同时修改这个 FAT 卷。 更新脚本 `IndependentCSharpUsb256` 会在改写前备份已有完整工作区,写入新系统后恢复到新分配位置,并将恢复内容计入完整回读哈希和真实盘尾 GPT 校验。发现额外的 FAT 根目录用户文件、额外导入文件、被替换的 `UsbHello.dll` 或损坏的工作区分配时,自动更新会停止,原数据保留,需先迁移后重试。旧版本产物和备份不覆盖。 启动包 `Start.ps1` 使用按版本保存的独立虚拟 USB 工作盘,重复打开同一包会保留工作文件。每次核对工作区之外的全部字节,原始发行镜像与验收记录保留不变;不允许通过 snapshot 模式假称持久化。 ## 验证入口 ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File Tools/TestCSharp.ps1 python Tools/IndependentKernel/TestBoot.py --console --virtual-cpus 8 --timeout 180 python Tools/IndependentKernel/TestBoot.py --desktop --browser --documents --bing --virtual-cpus 8 --timeout 360 python Tools/IndependentKernel/TestUsbStorage.py powershell -NoProfile -ExecutionPolicy Bypass -File scripts/physical-media-usb-tests.ps1 -Image <发行镜像> -SavedUsbImage <验收后的私有USB镜像> ``` 完整应用验收自动附带独立的两次 USB 冷启动:i8042 关闭,实际 xHCI USB 启动盘、USB HID 输入,创建/重命名文件、写设置、读取 FAT 程序、复制程序,退出 QEMU 后使用同一可写盘重新启动,再读取文件、设置和执行复制后的程序集。Desktop 另验证 Settings 深色主题重启保留。校验实际 framebuffer、终端输出、磁盘变化范围及原镜像不变。主应用完整工作流仍单独验证显式 RAM 回退,避免把其结果当作 USB 持久化证据。 实际回执和交付状态见 [本版摘要](validation-results/UsbPersistentWorkspace20261016.json)。只声明 QEMU 验证过的范围;实际执行仍为 BSP 1、CPU 软件绘制,实体启动/输入、实体存储持久化、GPU/CUDA、SMP 和长期稳定性未验收,`FullReleaseQualified=false`。 协议参考:[USB-IF Bulk-Only Transport](https://www.usb.org/sites/default/files/usbmassbulk_10.pdf)、[Limine 官方协议头](https://github.com/Limine-Bootloader/limine-protocol/blob/trunk/include/limine.h)。自研范围及依赖声明见 [THIRD_PARTY.md](../THIRD_PARTY.md)。