VirtualBox - 找不到可启动介质

4
有很多类似标题的问题在stackoverflow上。我阅读了所有这些问题,但没有一个能解决我的问题。这就是为什么我提出这个问题的原因。
我正在用汇编和C语言创建操作系统。我发现我必须将C代码编译为二进制格式,提取文本部分并保存为文件,然后将其转换为ISO,然后将其挂载到虚拟软盘的光学驱动器中,最后在VirtualBox中加载我的操作系统。所以这是很多工作,我想避免。我不想每次都将我的二进制文件转换为ISO。
因此,我决定将我的操作系统的二进制机器代码放入虚拟硬盘(VDI文件)中,然后将其设置为启动顺序的顶部,并加载它,而不是从虚拟光盘驱动器ISO中加载。
我正在研究VDI的工作原理,发现它通常是动态分配的,只存储数据的开头。因此,VDI的开头表示标头,其余部分是存储在虚拟驱动器上的实际数据。所以,我发现数据从某个地址开始(在我的情况下,它是从VDI文件的开头0x00200000开始)。
然后,我基本上使用模式55 AA填充从该地址到VDI文件末尾。所以,我认为现在它意味着磁盘是可引导的(因为在第一个扇区的末尾仍然有签名55 AA)。
我启动虚拟机,它显示:
“未找到可引导介质!系统已停止。”
有没有办法解决这个问题?为什么我的虚拟磁盘仍然无法引导?
编辑
这是实际的VDI文件:1.vdi

错误提示说介质不可引导,而不是不能挂载。你做了什么使你的介质可引导? - Lightness Races in Orbit
@BoundaryImposition。修正了拼写错误。 - patak daca
@BoundaryImposition。“你是怎样使你的媒介设备可启动的?” - 我用模式“55 AA”填充了整个虚拟驱动器。 - patak daca
@Olaf。感谢您的编辑。 - patak daca
1
@MichaelPetch:我认为你是对的 - 这种期望来自对“可引导”的含义的误解,或者至少是一种假设,认为接下来会显示不同的错误消息。 - Lightness Races in Orbit
显示剩余2条评论
1个回答

7
您没有提供一个最小的完整可验证的示例,展示引导加载程序以及如何将其放入VDI中。但至少需要在主引导记录的最后两个字节中放置0xAA55。以下示例创建了一个简单的引导加载程序;创建了一个2MiB的原始映像;将引导加载程序放置在原始映像中;并将原始映像转换为VDI。

boot.asm:

BITS 16
ORG 0x7C00

    xor ax, ax
    mov ds, ax
    mov ss, ax       ; Stack below bootloader
    mov sp, 0x7c00

    mov ax, 0xb800   ; Video segment b800
    mov es, ax

    ; Print Hello with white on light magenta
    mov word [es:0x0], 0x57 << 8 | 'H'
    mov word [es:0x2], 0x57 << 8 | 'e'
    mov word [es:0x4], 0x57 << 8 | 'l'
    mov word [es:0x6], 0x57 << 8 | 'l'
    mov word [es:0x8], 0x57 << 8 | 'o'

    ; End with infinite loop
    cli
endloop:
    hlt
    jmp endloop

; Fill out to 510 bytes and add boot signature
times 510 - ($ - $$) db 0
dw 0xAA55            ; add boot signature at the end of bootloader

然后我使用以下命令来创建引导加载程序文件boot.bin

nasm -f bin boot.asm -o boot.bin

创建一个2MiB的磁盘映像文件1.raw:
dd if=/dev/zero of=1.raw bs=1024 count=2048

将 bootloader boot.bin 放置在文件 1.raw 的开头,而不截断文件的其余部分:

dd if=boot.bin of=1.raw conv=notrunc

1.raw创建名为1.vdi的VDI映像:

rm -f 1.vdi
VBoxManage convertfromraw 1.raw 1.vdi --format VDI

当在VirtualBox中添加到虚拟机时,显示器上会出现以下内容:

enter image description here


您的VDI文件

在您提供的图像文件1.vdi中,当我执行hexdump时,我注意到了以下内容:

00200000  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
*
002004c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
*
00300000
这个输出让我认为您在文件中颠倒了引导标志的字节顺序。它应该是0x55后跟0xaa。以WORD形式存储的0xaa55具有反转的字节。
有效的启动介质可能不仅仅是正确获取启动标志。一些BIOS可能会在前几个字节中搜索通常在引导加载程序中找到的某些指令。未能找到这样的指令(例如,JMPXORCLIMOV)可能导致它认为它不是有效的启动介质。
测试0xAA55是否足够本身可以使用hexedit,并修改您的1.vdi文件如下:
00200000  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
00200010  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
*
002001f0  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 55 aa <-- Corrected signature
                                                               at 1fe & 1ff
00200200  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
*
002004c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
*
00300000

仅仅进行这个改变是不起作用的。然后我使用了hexedit,并将一个CLI操作码(0xFA)放置在扇区的第一个字节。结果文件现在看起来像:

           v-- CLI instruction
00200000  fa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
00200010  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
*
002001f0  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 55 aa
00200200  aa 55 aa 55 aa 55 aa 55  aa 55 aa 55 aa 55 aa 55
*
002004c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
*
00300000

我已经将fa作为引导加载程序的第一个字节。现在当我使用您的镜像时,错误信息未找到可启动介质!系统已停止。不再出现。这表明VirtualBox正在寻找的不仅仅是引导标识,而且正在执行某种健全性检查以确定引导加载程序的开头是否具有可执行指令。这在BIOS中并不罕见。有些可能会进行此类检查,有些则不会。目前我还没有查看VirtualBox源代码以确定它执行哪些准确的检查来进行判断。


1
你是否有时候感觉自己总是在写同样的答案呢? :-) - Cody Gray
1
@CodyGray:每个答案都有相似之处,没错。在这种情况下,我不知道是否存在一个处理Virtual Box和VDI格式的现有答案,所以就想着发表一篇回答哈哈。 - Michael Petch
说真的,考虑到这个编程任务有多受欢迎,你可能想要将这个答案迁移到文档中,并永久链接到它。只要他们一直在强制我们使用文档,我们就应该想办法让它有价值。或者,也许创建一个关于如何开始创建引导程序的规范问答会很有价值,再加上你在另一个答案中提供的故障排除技巧,然后我们可以将问题关闭为重复。你的答案中有很多很好的入门材料,但很难找到。 - Cody Gray
@CodyGray 我们中的一些人已经提出了关于bootloader的文档。我同意你的看法;-) - Michael Petch
1
@CodyGray:一个规范的问答(为什么不只是给这个打标签呢?)比试图把有用性塞进文档中要有更大的价值。 - Lightness Races in Orbit
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接