我们在基于 MCU 的定制硬件上开发了 USB 复合设备(CDC 和 MSD 类)。该磁盘是一个 RAM 磁盘(24 kb 空间),在通电时,它由 MCU 供应商固件格式化(FAT 12)。不幸的是,该设备被视为可引导磁盘,典型的 BIOS 会尝试引导它。但是,我们知道将不同的 USB 磁盘连接到不同的 PC 会产生不同的结果,这取决于磁盘的 FAT 类型和 BIOS 行为(显然每个 BIOS 在 HDD 之前都有 USB 启动)。我们的目标是拥有一个无法启动的U 盘(FAT12 格式)。
我们尝试了许多解决方案,但没有一个奏效。在我们看来,BIOS 似乎不仅仅是检查有效引导扇区的存在,将第一个扇区复制到地址 0x7C00 并跳转到该地址,从而将控制权交给 x86 ASM 引导代码。事实上,我们已经用 Linux 格式化了一个商业 U 盘,命令如下:
mkdosfs -F 12 /dev/sda1
这个 USB 记忆棒现在有一个 FAT12 卷启动记录,我们还没有发现在尝试从它启动时卡住的 BIOS。
因此,我们将其引导扇区复制到我们的设备中,并且我们希望它可以用作商业 USB 记忆棒。不:BIOS 在尝试引导磁盘时挂起。下面是上面Linux命令生成的引导扇区的反汇编。
;Jump instructions
0x00007c00 eb 3c jmp 0x00007c3e
0x00007c02 90 nop
;VBR segment
0x00007c03 6d
0x00007c04 6b 66 73 2e
0x00007c08 66 61
..............
;Boot code
0x00007c3e 0e push %cs
0x00007c3f 1f pop %ds
0x00007c40 be 5b 7c mov $0x7c5b,%si
0x00007c43 ac lods %ds:(%si),%al
0x00007c44 22 c0 and %al,%al
0x00007c46 74 0b je 0x00007c53
0x00007c48 56 push %si
0x00007c49 b4 0e mov $0xe,%ah
0x00007c4b bb 07 00 mov $0x7,%bx
0x00007c4e cd 10 int $0x10
0x00007c50 5e pop %si
0x00007c51 eb f0 jmp 0x00007c43
0x00007c53 32 e4 xor %ah,%ah
0x00007c55 cd 16 int $0x16
0x00007c57 cd 19 int $0x19
0x00007c59 eb fe jmp 0x00007c59
;String to be displayed followed by zeros
0x00007c5b 54
0x00007c5c 68 69 73
..........
;Boot signature
0x00007dfe 55
0x00007dff aa
显然,上面的代码打印出字符串“This is not a bootable disk. Please insert a bootable floppy and press any key to try again”,然后调用INT16H和INT19H。
例如,为什么我正在写入的 PC 的 BIOS 会打印:“尝试从 USB 磁盘启动”,然后跳转到我的硬盘,而我们设备中写入的相同汇编代码却没有?也就是说,它写“请插入...”?有一个代码可以替代它并且永远不会尝试启动我的自定义 USB 磁盘吗?
另外,在读取第一个扇区之前,BIOS 是否会与 USB 设备进行一些特殊的通信,例如,从设备描述符中获取一些信息,以便了解它是否可以用作启动盘?
谢谢大家。