Files
Deshab-OS/docs/RE/Bug记录.txt
T
2026-07-31 13:53:49 +08:00

289 lines
26 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Deshab Bug 记录
> 所有测试与开发过程中发现的 bug 统一登记于此。每个 bug 按 BUG-YYYYMMDD-NNN 编号。
> 测试用例文档位于 RE/test-cases/。
>
> 2026-07-29 文档治理:此前 8 条遗留纯文本 bug 已按模板补全(编号 001–008,
> 日期为桌面测试期的近似日期);同时补登 B5/B6 及 BSS NOBITS、go_up 条目。
## 严重程度定义
- P0 阻断: 影响主链路启动或核心功能完全不可用(必须立即修复)
- P1 严重: 功能可降级但关键路径受损(本轮内修复)
- P2 一般: 非关键路径异常或体验问题(下一里程碑前修复)
- P3 提示: 日志/小问题,不影响功能(记录备查)
## Bug 条目格式
```
### BUG-YYYYMMDD-NNN [P级] [模块] 简述
- 现象:
- 复现步骤:
- 串口/日志证据:
- 根因分析:
- 修复方案:
- 状态: [OPEN/FIXING/FIXED/CLOSED]
- 修复提交: <commit hash 或 "待提交">
- 验证: <验证方法与结果>
```
---
## Bug 列表
<!-- 在此追加 bug 条目,最新放在顶部 -->
### BUG-20260729-021 [P2] [DSK/kernel_api] 硬偏移读取 kernel_api.block 脆弱性
- 现象: DSK 通过 `*(u64*)(api + 0xA8)` 硬偏移读取 `dkm_kernel_api.block`,若结构体在 `block` 字段前插入新字段,DSK 将读取到错误指针 → 解引用 → 立即崩溃,无日志。
- 复现步骤: 修改 dkm.h 中 `dkm_kernel_api` 在 `block` 字段前增加任意字段 → 编译 DSK(不重新编译)→ 启动。
- 串口/日志证据: 安全审查Agent报告(bd89e1b9),4.1节。
- 根因分析: DSK 独立编译不含 `dkm_kernel_api` 结构体定义,无法在编译期校验偏移一致性;注释虽警告"新增字段只允许追加在末尾",但无编译期保障。
- 修复方案: ① DSK 端 include `dkm_kernel_api` 结构体定义并用字段名访问;② 或添加 `_Static_assert(offsetof(..., block) == 0xA8, ...)` 编译期校验。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/dsk/main.c + CODE/shell/main.c)
- 验证: DSK/shell 均添加 dsk_kernel_api_mirror/shell_kernel_api_mirror 镜像结构体 + _Static_assert 编译期校验 + 字段名访问,不再使用硬偏移。
### BUG-20260729-020 [P1] [UTSM/IDT] IOAPIC 中断路由可能绕过 PIC mask
- 现象: 实机通过 IOAPIC 路由中断时,`dsk_load_and_jump()` 中的 PIC mask 不影响 IOAPIC redirection entry,中断可能绕过 PIC mask 直接到达 CPU。
- 复现步骤: 在使用 IOAPIC 的实机上启动 → UTSM mask PIC → DSK 运行期间 IOAPIC 路由的 IRQ 到达 → IDT halt stub 触发(修复 BUG-013 后)→ 安全停机而非崩溃。
- 串口/日志证据: 系统日志Agent报告(aa2d3f5a),崩溃点B分析。
- 根因分析: `dsk_load_and_jump()` 仅操作 8259 PIC 的 IMR 寄存器,未处理 IOAPIC 的 24 个 redirection entry。实机(尤其是多核平台)中断路由通常经 IOAPIC 而非 PIC。
- 修复方案: ① 在 `dsk_load_and_jump()` 中 mask IOAPIC 全部 24 个 redirection entry(设 mask 位);② 或在 LAPIC 中设置 TPR=0xFF 屏蔽所有中断。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/UTSM/kernel/dsk_loader.c dsk_load_and_jump)
- 验证: 采用方案②:通过 IA32_APIC_BASE MSR 读取 LAPIC 基地址 + HHDM 偏移,写入 TPR=0xFF 屏蔽所有可屏蔽中断优先级。仅在 LAPIC 全局启用时(bit 11)执行。
### BUG-20260729-019 [P1] [UTSM+DSK/FAT32] FAT 表缓冲区在实机大容量磁盘上溢出
- 现象: FAT32 FAT 表缓冲区 `g_dsk_fat32_disk[131072]`(128KB/256扇区)在实机大容量磁盘上不足。2GB 以上分区的 FAT 表超过 128KB,FAT 链遍历在缓冲区边界处中断,文件读取截断或失败。
- 复现步骤: 在 ≥2GB FAT32 分区上启动 → UTSM 从 SATA 盘读取 deshab.elf → FAT 条目偏移超过 128KB → `fat_ent + 4 > sizeof(g_dsk_fat32_disk)` → 循环中断 → 文件未找到或数据截断。
- 串口/日志证据: 安全审查Agent报告(bd89e1b9),2.1节;计算表:2GB分区/32KB簇=256KB FAT(溢出),32GB分区/4KB簇=32MB FAT(严重溢出)。
- 根因分析: FAT 读取策略为"一次性预读 256 扇区",在 QEMU 4MB 测试镜像上够用,但实机磁盘分区远大于此。当文件起始簇在缓冲区内但后续簇不在时,ELF 数据不完整 → 加载后必然崩溃。
- 修复方案: 实现"按需 FAT 扇区读取":仅读取包含目标条目的单个 FAT 扇区(512字节),而非预读整个 FAT 表。需新增 `fat32_get_next_cluster()` 函数。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/UTSM/kernel/dsk_loader.c + CODE/dsk/main.c + CODE/shell/main.c)
- 验证: 三端均实现 fat32_get_next_cluster() 按需 FAT 扇区读取:条目在缓冲区内直接读取,超出则按需读单扇区(512B)。写入路径保留缓冲区内修改+回写逻辑不变。
### BUG-20260729-018 [P1] [DSK/loader] g_fdata 仅 1MB,与 UTSM 端 2MB 不一致
- 现象: DSK 端文件数据缓冲区 `g_fdata[1048576]` 仅 1MB,而 UTSM 端 `g_dsk_fat32_filedata[2097152]` 为 2MB。当前 desktop.elf 约 150KB 暂时够用,但增长后将突破 1MB 限制。
- 复现步骤: desktop.elf 增长至 >1MB → `fat32_read_root_file` 因 `found_size > sizeof(g_fdata)` 返回 -6 → desktop 无法加载。
- 串口/日志证据: 安全审查Agent报告(bd89e1b9),2.2节。
- 根因分析: UTSM 和 DSK 两端缓冲区大小定义不一致,DSK 端未与 UTSM 对齐。
- 修复方案: `g_fdata[1048576]` → `g_fdata[2097152]`,与 UTSM 端对齐。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/dsk/main.c L66)
- 验证: 编译通过,镜像生成成功。
### BUG-20260729-017 [P1] [UTSM/dsk_loader] FAT32 加载器 11 个返回点无日志
- 现象: `dsk_load_from_block_fat32()` 有 11 个 `return -1` 出口但无任何日志输出。实机 SATA 盘 FAT32 结构与 QEMU 不同时,函数静默失败回退 Limine boot module,用户无法从日志得知失败原因。
- 复现步骤: 实机启动 → FAT32 解析任意步骤失败 → 串口无相关日志 → 回退 Limine 或 halt。
- 串口/日志证据: 系统日志Agent报告(aa2d3f5a),缺口1分析。
- 根因分析: 函数编写时为早期最小实现,未添加错误路径日志。
- 修复方案: 在全部 11 个 `return -1` 前添加 `log_error` + 诊断 `log_hex64`,输出失败条件和关键参数值。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/UTSM/kernel/dsk_loader.c L182-317)
- 验证: 编译通过,日志覆盖完整。
### BUG-20260729-016 [P0] [DSK/loader] kernel_api / framebuffer 解引用无 NULL 验证
- 现象: DSK `dsk_spinner_and_check()` 直接解引用 `ctx->dkm_kernel_api` 和 `ctx->framebuffer_address`,无 NULL 检查。若 `api` 为 0 → `*(u64*)(0 + 0xA8)` 解引用地址 0xA8 → 页错误 → 三重故障重启。framebuffer 为 NULL 同理。
- 复现步骤: boot_context 传递错误(kernel_api=0 或 fb=0)→ DSK entry → 立即页错误。
- 串口/日志证据: 系统日志Agent报告(aa2d3f5a),缺口3/4分析。
- 根因分析: 早期实现假设 boot_context 始终有效,未添加防御性检查。
- 修复方案: ① `kernel_api` NULL 检查 + 诊断日志;② `framebuffer_address` NULL 检查;③ 输出 `block_api` / `block_read` / `block_write` 函数指针地址便于调试。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/dsk/main.c L866-878)
- 验证: 编译通过。
### BUG-20260729-015 [P0] [DKM/ahci] AHCI 写入超时使用固定循环 + PxCMD.W 违规写入
- 现象: `ahci_write_blocks_internal()` 使用 `for(i=0;i<5000000;i++)` 固定循环超时。实机 CPU 频率差异导致超时时间不可预测(快 CPU 可能过早超时,慢 CPU 可能等待过久)。同时代码写入 `PxCMD.W` 位(AHCI 规范中为只读位),违反 AHCI 1.3 规范。
- 复现步骤: 实机启动 → DSK 通过 AHCI 写入 FAT32 → 固定循环超时不足 → 写入超时失败 → FAT32 写操作失败 → 系统异常。
- 串口/日志证据: 驱动开发Agent报告;原代码 L356-358(PxCMD.W 写入)、L363-371(固定循环)。
- 根因分析: ① 写入路径复制了早期读取路径的固定循环模式,未跟随读取路径升级为 TSC deadline;② `AHCI_CMD_W` (bit 6) 在 AHCI 规范中为只读,硬件根据命令头 `flags.W` 自动设置。
- 修复方案: ① 写入超时替换为 TSC 5 秒 deadline(与读取路径一致);② 移除所有 PxCMD.W 读/写操作。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/DKM/ahci/ahci.c L355-371)
- 验证: 编译通过;QEMU 读取路径已验证 TSC 超时有效。
### BUG-20260729-014 [P0] [DSK/loader] dsk_load_elf 完全忽略 size 参数 + PIE 重定位无边界检查
- 现象: DSK 端 `dsk_load_elf()` 显式 `(void)size` 忽略文件大小参数,程序头、PT_LOAD 段、PT_DYNAMIC 段的读取均无边界检查。PIE 重定位中 `rela_off - min_vaddr` 和 `rel->offset - min_vaddr` 可能无符号整数下溢(若 < min_vaddr),导致从 `image` 基址偏移到巨大地址 → 随机内存写入 → 三重故障重启。UTSM 端有完整的 `range_ok` 检查,DSK 端完全缺失。
- 复现步骤: 加载损坏/恶意的 ELF → `rela_off < min_vaddr` → `rela_off - min_vaddr` 下溢为 ~0xFFFFFFFFFFFFFFFF → 读取/写入随机内存 → 崩溃。
- 串口/日志证据: 安全审查Agent报告(bd89e1b9),1.1/1.2/3.1节。
- 根因分析: DSK ELF 加载器为简化实现,省略了 UTSM 端已实现的安全检查。两端 ELF 加载逻辑不一致(UTSM 有 `range_ok`,DSK 忽略 `size`)。
- 修复方案: ① 移除 `(void)size`,添加 `size < sizeof(elf64_ehdr)` 检查;② 程序头范围验证 `phoff + phnum*phentsize <= size`;③ PT_LOAD `offset + filesz <= size` 检查;④ PT_DYNAMIC vaddr 范围检查;⑤ PIE `rela_off >= min_vaddr && rela_off < min_vaddr + isize` 边界检查;⑥ `rel->offset >= min_vaddr && rel->offset < min_vaddr + isize` 边界检查;⑦ entry 范围验证。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/dsk/main.c L721-824)
- 验证: 编译通过;边界检查逻辑与 UTSM 端 `dsk_load_elf_image` 一致。
### BUG-20260729-013 [P0] [UTSM/dsk_loader] UTSM→DSK 跳转前 cli 缺失 + IDT 未重置导致实机三重故障
- 现象: 实机从 UTSM 加载 DSK 后崩溃重启。`dsk_load_and_jump()` 中 PIC mask 操作前未执行 `cli`,两条 `outb`(mask PIC2 和 PIC1)之间存在中断竞争窗口。实机在此窗口内可能触发 spurious IRQ7/15 或 IOAPIC 中断 → 跳转到 UTSM 过期 IDT handler → 若 handler 内调用的内存被 DSK 覆盖 → 双重异常 → 三重故障 → 重启。同时,跳转后 IDT 仍指向 UTSM 的 ISR stub,DSK 运行期间任何 CPU 异常(PF/GP)会执行 UTSM 的 `idt_handler`(含 log_error + for(;;)cli;hlt),若发生双重异常则重启。
- 复现步骤: 实机启动 → UTSM 完成 DKM 加载 → `dsk_load_and_jump()` → PIC mask 两步操作之间中断到达 → 三重故障重启。或在 DSK 运行期间发生 CPU 异常 → UTSM handler → 可能双重异常 → 重启。
- 串口/日志证据: 系统日志Agent报告(aa2d3f5a),崩溃点A/B分析;安全审查Agent报告确认。QEMU 不复现(无 spurious IRQ、无 SMI/NMI)。
- 根因分析: ① `outb(0xA1,0xFF)` 和 `outb(0x21,0xFF)` 之间 IF=1,PIC2 IRQ 可通过 cascade 到 PIC1 触发中断;② IDT 未重置,DSK 阶段异常仍路由到 UTSM handler,handler 依赖的代码/数据可能已被覆盖。
- 修复方案: ① PIC mask 前添加 `__asm__ volatile("cli")` 消除中断窗口;② 新增 `idt_halt_all()` 函数将全部 256 个 IDT 条目替换为安全 halt stub(`cli; hlt` 循环),防止 DSK 运行期间过期 handler 被触发;③ DSK entry 前输出 context 关键字段诊断日志(magic/api/fb)。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/UTSM/kernel/dsk_loader.c L613-650, CODE/UTSM/arch/x86_64/idt.c L440-460, CODE/UTSM/include/utsm/idt.h L8-11)
- 验证: 编译通过;QEMU 启动正常;实机验证待用户执行。
### BUG-20260729-012 [P3] [tools/fileman] go_up 缺少前向声明导致编译错误
- 现象: fileman 编译失败,`open_selected()` 调用 `go_up()` 时函数尚未定义(隐式声明/未定义引用)。
- 复现步骤: 编译 `CODE/tools/fileman/`。
- 串口/日志证据: 编译器报错(implicit declaration of function 'go_up')。
- 根因分析: C 文件内函数定义顺序——`open_selected`(L259)在 `go_up`(L298)之前,缺少前向声明。
- 修复方案: `CODE/tools/fileman/main.c` L258 添加 `static void go_up(void); /* 前向声明:open_selected 调用 go_up */`。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——main.c L258 前向声明存在,编译通过。
### BUG-20260729-011 [P1] [build/linker] 全项目 linker.ld 未将 .bss 分离为 NOBITS 段导致 ELF 膨胀
- 现象: 多个用户态 ELF 体积异常膨胀:shell 773KB、cmd 499KB、fileman ~470KB,远超代码实际大小;fileman 因超出桌面宿主加载缓冲区而崩溃(见 BUG-20260728-009)。
- 复现步骤: 构建 shell/cmd/fileman 等 .elf,观察文件体积;反查 program header 的 filesz/memsz。
- 串口/日志证据: 无运行期日志;构建产物体积异常即为证据。
- 根因分析: linker.ld 将 `.bss` 与 `.data` 合并且未分离为独立 NOBITS 段,零初始化 BSS 数据(f32_disk/f32_data 等大缓冲)被计入 ELF 文件体积。
- 修复方案: 全项目 linker.ld 将 `.bss` 分离为独立段置于 `.dynamic` 之后(仍归 `:data` PT_LOAD,phdr filesz<memsz,NOBITS 不占文件空间)。修复后 shell 773KB→92KB、cmd 499KB→92KB、fileman ~470KB→46KB。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——`CODE/tools/fileman/linker.ld` L23–28 含分离注释与独立 .bss 段;shell/cmd 等 linker.ld 同构。
### BUG-20260729-010 [P1] [firstInit] FirstInit 设置向导按键崩溃(策划 B6)
- 现象: FirstInit 账户设置卡片中按键导致崩溃。原记录:"fb_text -O2 optimization issue"。
- 复现步骤: firstInit.txt=0 → 首次启动 → 进入 FirstInit 账户设置卡片 → 按任意键。
- 串口/日志证据: 调试会话 `debug-firstinit-key-crash.md`(状态 OPEN)记录 H1–H5 假设:① -O2 下 clang 生成 memset/memcpy 隐式调用或对齐 SSE 指令(freestanding 环境出错);② fb_text/fb_char 路径数组越界(g_ascii 95 项索引边界 / 18px 中文字模尺寸);③ 栈溢出(DSK 直接 call 入口共享同一栈,-O2 内联帧膨胀);④ 扫描码状态机(shift/release)越界写;⑤ linker.ld BSS NOBITS 分离后 rela 覆盖遗漏(指针数组未重定位)。已确认:所有模块 -O2 编译、无 -fno-strict-aliasing;DSK loader 已 memset 整个 image(BSS 安全)。
- 根因分析: 未定,待 QEMU 复现(monitor sendkey + 串口捕获异常向量/RIP)后 addr2line 定位。M1 里程碑确认 QEMU 未复现。
- 修复方案: 添加防御性边界检查:scan_to_ascii 调用前 sc>=58 提前跳过(防止越界);已确认 -fno-builtin 编译标志存在。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/firstInit/main.c read_field 防御性边界检查)
- 验证: M1 里程碑 QEMU 验证未复现;已添加 sc>=58 防御性跳过;-fno-builtin 已存在于编译标志。
### BUG-20260728-009 [P1] [desktop/fileman] fileman.elf 启动触发 QEMU exit(策划 B5)
- 现象: 桌面中打开 Files 应用(外部 .elf 全屏宿主)时 QEMU 进程直接退出,文件管理器不可用。
- 复现步骤: 构建含 fileman.elf 的镜像 → 启动至 desktop → 打开 fileman → QEMU exit。
- 串口/日志证据: fileman 启动后串口输出中断(当时未留存完整日志,退出码待补录)。
- 根因分析: fileman 的 linker.ld 未将 .bss 分离为 NOBITS 段(见 BUG-20260729-011),ELF 膨胀至 ~470KB,超出 desktop `dt_load_elf` 的 `g_elf_image` 256KB 静态缓冲区,加载越界/校验失败。
- 修复方案: ① 全项目 linker.ld .bss 分离 NOBITS(fileman ~470KB→46KB);② desktop `g_elf_image` 由 256KB 扩至 1MB(`CODE/desktop/main.c` L1802)。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——linker.ld NOBITS 分离 + g_elf_image=1048576 已确认;fileman 现可打开/浏览/关闭(QEMU 实机回归建议补做)。
### BUG-20260728-008 [P2] [desktop/fileman] Files 缺少 ".." 返回上级目录
- 现象: Files 进入子目录后没有 ".." 条目,用户无法返回上一级文件夹。
- 复现步骤: desktop 打开 Files → 进入任意子目录 → 列表中无返回入口(仅键盘 Backspace)。
- 串口/日志证据: 无(UI 行为问题)。
- 根因分析: `load_current_dir()` 未在非根目录时合成 ".." 伪条目。
- 修复方案: `CODE/tools/fileman/main.c` `load_current_dir()` 在 path_depth>0 时于列表开头插入 ".." 条目(clus=0 特殊标记),`open_selected()` 特判调用 `go_up()`;同时补充 `go_up()` 前向声明(见 BUG-20260729-012)。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——main.c L67–82 插入 ".." 条目、L264–267 特判、L298–303 go_up 实现均存在。
### BUG-20260728-007 [P2] [desktop/fileman] Files 未显示文件夹条目(直接显示文件夹下文件)
- 现象: Files 列表中不显示文件夹条目,直接展开了文件夹下的文件,目录层级丢失。
- 复现步骤: desktop 打开 Files → 根目录列表中看不到 SYSTEM 等目录条目。
- 串口/日志证据: 无(UI 行为问题)。
- 根因分析: 目录列举/过滤逻辑未正确区分 `is_dir` 条目(attr 0x10)。
- 修复方案: 修复后 `fm_entry.is_dir` 正确填充,目录以黄色图标 + "DIR" 类型 + "--" 大小显示,Enter 进入子目录(`CODE/tools/fileman/main.c`)。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——main.c 列表绘制含 is_dir 分支(图标颜色/类型列),`open_selected()` 目录进入逻辑存在。
### BUG-20260728-006 [P2] [desktop/fileman] Files 默认未显示 SYSTEM/user 目录内容
- 现象: 桌面第一页 Files 面板/Files 应用默认显示根目录,而非用户期望的 SYSTEM/user 内容。
- 复现步骤: 启动至 desktop → 打开 Files → 默认路径为根目录。
- 串口/日志证据: 无(UI 行为问题)。
- 根因分析: fileman 启动时 path_depth=0(根目录),未定位到 SYSTEM/user。
- 修复方案: `CODE/tools/fileman/main.c` `find_user_dir()`:启动时先枚举根目录找 SYSTEM,再在其中找 USER,命中则预设路径栈(path_depth=2)后 `load_current_dir()`。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——main.c L306–339 find_user_dir 实现存在,dsk_entry 中调用。
### BUG-20260728-005 [P2] [desktop] DASHBOARD shell 回车后上一条命令文字跑到下一行
- 现象: 桌面第一页(DASHBOARD)的 shell 面板中输入命令回车后,上一条命令的输入文字异常出现在下一行。
- 复现步骤: desktop DASHBOARD → TERM 面板输入任意命令 → 回车 → 观察回显错位。
- 串口/日志证据: 无(UI 行为问题)。
- 根因分析: `redraw_input_line()` 只更新 framebuffer 视觉渲染,不同步终端缓冲区 `term_ch[]`。当 `term_redraw_all()` 从缓冲区重新渲染时,旧输入文字残留在缓冲区导致错位。
- 修复方案: `redraw_input_line()` 中同步更新终端缓冲区 term_ch[]/term_fg[](提示符+输入+空白填充),确保 term_redraw_all() 渲染与视觉一致。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/shell/main.c redraw_input_line)
- 验证: 编译通过;redraw_input_line 现在同步 term_ch/term_fg 缓冲区。
### BUG-20260728-004 [P3] [desktop] Boot 打字机效果速度过慢(期望提速 3 倍)
- 现象: 桌面启动时的打字机 Boot 屏逐字输出节奏过慢,影响开机体验。
- 复现步骤: 启动至 desktop → 观察 Boot 屏打字速度。
- 串口/日志证据: 无(体验问题)。
- 根因分析: 打字机帧间隔常量偏大。
- 修复方案: 缩小打字机每字符间隔(约 3 倍提速)。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: ROADMAP 近期进展已记录"Boot 打字机提速";QEMU 观感验证。
### BUG-20260728-003 [P2] [shell] 开发者模式 shell 回车后文字消失无反应
- 现象: 开发者模式(dev_mode)中 shell 输入命令回车,输入文字消失且无任何响应/输出。
- 复现步骤: firstInit.txt 第二行=1 或 FUCK dev_mode=1 → DSK 加载 shell.elf → 手动输入命令 → 回车。
- 串口/日志证据: 无(当时未留存)。
- 根因分析: 与 BUG-005 同根因:`redraw_input_line()` 不同步终端缓冲区,`term_redraw_all()` 从旧缓冲区渲染覆盖当前输入行,导致视觉上输入文字"消失"。
- 修复方案: BUG-005 修复(redraw_input_line 同步 term_ch/term_fg 缓冲区)同时解决此问题。
- 状态: [FIXED]
- 修复提交: 工作区已修复(CODE/shell/main.c redraw_input_line — 与 BUG-005 同修复)
- 验证: 编译通过;BUG-005 修复确保终端缓冲区与视觉渲染一致。
### BUG-20260728-002 [P3] [desktop] DESKTOP 页冗余显示终端/CMD 图标
- 现象: 第一页(DASHBOARD)已有 TERM-01/TERM-02 终端面板,第三页 DESKTOP 图标网格仍显示终端和 CMD 图标,入口冗余。
- 复现步骤: desktop → 切到 DESKTOP 页 → 可见终端/CMD 图标。
- 串口/日志证据: 无(UI 设计问题)。
- 根因分析: DESKTOP 页快捷方式列表未排除已在 DASHBOARD 常驻的终端类应用。
- 修复方案: 从 DESKTOP 页图标列表移除终端与 CMD 冗余项。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: ROADMAP 近期进展已记录"DESKTOP 页冗余图标移除";代码核查——desktop 图标过滤逻辑已生效(当前 DESKTOP 页无终端/CMD 图标)。
### BUG-20260728-001 [P2] [desktop/fileman] Files 窗口点击关闭按钮(叉)无法关闭
- 现象: Files 应用窗口右上角关闭按钮(叉)点击无反应,无法退出应用。
- 复现步骤: desktop 打开 Files → 点击右上角关闭区域 → 应用未退出。
- 串口/日志证据: 无(UI 行为问题)。
- 根因分析: 鼠标点击处理未命中关闭按钮热区(右上角 w-28..w-4, y 4..24)。
- 修复方案: `CODE/tools/fileman/main.c` 鼠标轮询中检测关闭按钮热区命中后 `da_slog("fileman","close button clicked")` 并 return 退出。
- 状态: [FIXED]
- 修复提交: 待提交(工作区已修复)
- 验证: 代码核查——main.c L372–377 关闭热区判定与退出存在。
---
## 附:遗留条目对照
2026-07-29 结构化前的 8 条纯文本遗留 bug 与新编号对照:
| 遗留原文 | 新编号 | 状态 |
|---------|--------|------|
| 软件Files的窗口点击叉无法关闭 | BUG-20260728-001 | FIXED |
| 第一页已有终端,第四页桌面不用显示终端和CMD | BUG-20260728-002 | FIXED |
| 开发者模式 shell 回车文字消失没有反应 | BUG-20260728-003 | FIXED |
| 启动时打字机效果再快3倍 | BUG-20260728-004 | FIXED |
| 第一页 shell 回车后上一条命令文字跑到下一行 | BUG-20260728-005 | FIXED |
| 第一页 Files 显示的不是 SYSTEM/user 中的文件夹内容 | BUG-20260728-006 | FIXED |
| Files 中没有显示文件夹,直接显示文件夹下的文件 | BUG-20260728-007 | FIXED |
| Files 没有提供 ".." 返回上一级文件夹 | BUG-20260728-008 | FIXED |
### BUG-20260730-P12 [P0] [DSK/Shell] fat32_write_root_file 不遍历 FAT 链,根目录首簇满时报告 "no free dir entry"
- 现象: DSK 里程碑标记和 Shell 测试日志无法写入磁盘,QEMU 串口日志显示 4 次 [DSK] fat32 write: no free dir entry。
- 复现步骤: 使用 SATA FAT32 测试镜像启动(根目录首簇 16 条目全部占用),任何需要创建新文件的写入操作均失败。
- 串口/日志证据: QEMU serial.log 中 4 次 [DSK] fat32 write: no free dir entry。
- 根因分析: at32_write_root_file 只扫描根目录的第一个簇(spc=1 时仅 16 条目),不跟随 FAT 链检查后续簇。SATA 测试镜像根目录 FAT 链为 2→3→EOF,首簇满但第二簇有 10 个空闲条目,代码未到达第二簇。
- 修复方案: 修改 DSK 和 Shell 的 at32_write_root_file,用 while 循环遍历完整 FAT 链搜索空闲条目,记录 ree_clus/ ound_clus,写回时使用活动簇而非硬编码
oot_clus。
- 状态: [FIXED]
- 修复文件: CODE/dsk/main.c (L589-655), CODE/shell/main.c (L437-490)
- 验证: QEMU 测试显示 4 次 [DSK] fat32 write: success,4 个里程碑标记文件成功写入 SATA 镜像。
### BUG-20260730-P13 [P0] [Shell] fat32_write_root_file 不遍历 FAT 链 (同 P12)
- 现象/根因/修复: 与 P12 相同,影响 Shell 模块。
- 状态: [FIXED]
- 修复文件: CODE/shell/main.c (L437-490, L553-606, L682-684)
- 额外修复: 当整条 FAT 链都无空闲条目时,自动扩展根目录(分配新簇并链接到 FAT 链尾部)。
- 验证: 同 P12。
### BUG-20260730-P14 [P0] [DKM/ahci] AHCI 写入 TFD 错误检查误判正常状态为错误
- 现象: QEMU 测试中 AHCI 写入报 write error: TFD ERR,导致 FAT32 写入函数返回错误码。实际写入可能成功但因错误检查提前返回,后续 FLUSH CACHE 被跳过。
- 复现步骤: QEMU q35 + SATA 驱动,任何 AHCI 写入操作。
- 串口/日志证据: [WARN] [ahci] write error: TFD ERR,TFD 值为 0x50(DRDY|DRQ,正常状态)。
- 根因分析: hci.c L376 的错误检查 if (tfd & 0xFF) 检查的是 STS 低字节是否非零。但 STS=0x50 (DRDY=1, DRQ=1) 是 DMA 完成后的正常状态,不是错误。正确的检查应只看 STS bit0 (ERR) 和 ERR 寄存器 (bits15:8)。
- 修复方案: 改为 u8 sts = (u8)(tfd & 0xFF); u8 err_reg = (u8)((tfd >> 8) & 0xFF); if ((sts & 0x01) || err_reg)。
- 状态: [FIXED]
- 修复文件: CODE/DKM/ahci/ahci.c (L372-386)
- 验证: QEMU 测试无 TFD ERR 错误,4 次 FAT32 写入成功,里程碑文件正确写入磁盘。