stackoverflow 上有很多类似标题的问题。我阅读了所有这些,但没有一个能回答我的问题。这就是我打开这个问题的原因。
我正在用汇编器和 C 创建一个操作系统。我发现我必须将 C 代码编译为二进制格式,提取文本部分并将其保存为文件,然后将其转换为 ISO,然后将其安装到磁盘的虚拟光驱中,然后在 VirtualBox 中加载我的操作系统。所以,这是我想避免的很多工作。我不想每次都将我的二进制文件转换为 ISO。
因此,我决定将我的操作系统的二进制机器码放到虚拟硬盘驱动器(VDI
文件)中,然后将其设置为引导顺序的顶部并加载它,而不是从虚拟光驱ISO
加载它。 .
我正在研究如何VDI
工作,我发现它通常是动态分配的,并且只存储数据的开头。所以,开始VDI
代表一个标题,其余的是存储在虚拟驱动器上的实际数据。所以,我发现数据从某个地址开始(在我的例子中是 0x00200000
从 VDI
文件的开头)。
然后,我基本上是从那个地址填到VDI
结尾的带图案的文件 55 AA
.所以,我想现在这意味着磁盘是可启动的(因为在第一个扇区的末尾仍然是签名 55 AA
)。
我启动了虚拟机,它说:
No bootable medium found! System halted
有没有办法解决这个问题?为什么我的虚拟磁盘仍然无法启动?
编辑
这是实际
VDI
文件:1.vdi
最佳答案
您没有提供显示引导加载程序以及如何将其放入 VDI 的最小完整可验证示例。但至少您需要将 0xAA55 放在主引导记录的最后 2 个字节中。下面的示例创建了一个简单的引导加载程序;创建一个 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
放置引导加载程序
boot.bin
在文件开头 1.raw
不截断文件的其余部分:dd if=boot.bin of=1.raw conv=notrunc
创建一个名为
1.vdi
的 VDI 镜像来自 1.raw
:rm -f 1.vdi
VBoxManage convertfromraw 1.raw 1.vdi --format VDI
当添加到 VirtualBox 下的虚拟机时,我会在显示屏上看到:
您的 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。 0xaa55 作为 WORD 存储,字节颠倒。
有效的引导介质可能不仅仅是让引导签名正确。某些 BIOS 可能会在通常在引导加载程序中找到的前几个字节中搜索某些指令。找不到此类指令(示例通常包括 JMP、XOR、CLI、MOV 之类的内容)可能会导致它认为它不是有效的引导介质。
一种测试末尾的 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
作为引导加载程序的第一个字节。现在,当我使用您的图像时,会出现错误 No bootable medium found!系统停止不再出现。这表明 VirtualBox 正在寻找的不仅仅是引导签名,而是在进行某种完整性检查以确定引导加载程序的开始是否是可执行指令。这对于 BIOS 来说并不少见。有些人可能会做这样的检查,有些人可能不会。目前我还没有查看 VirtualBox 源代码来确定它为做出决定而执行的确切检查。
关于x86 - VirtualBox - 找不到可启动媒体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43566542/