使用自定义引导加载程序创建可引导 ISO 映像
Creating a bootable ISO image with custom bootloader
我正在尝试将我用汇编语言编写的引导加载程序转换为 ISO 映像文件。以下是来自 MikeOS 引导加载程序的代码。这是我的引导程序代码:
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'This is my cool new OS!', 0
print_string: ; Routine: output string in SI to screen
mov ah, 0Eh ; int 10h 'print char' function
.repeat:
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
我输入了以下命令:
nasm -f bin -o boot.bin boot.asm
此命令运行良好,并提供 .bin 输出。接下来我输入了以下命令:
dd if=boot.bin of=floppy.img count=1 bs=512
这也很好用,并为我提供了 .img 输出文件。当我键入此命令时:
dd if=boot.bin of=floppy.img skip seek=1 count=1339
我收到以下错误:dd: unrecognized operand ‘skip’
。我在 DD 文档中读到,skip 属性必须分配一个数字。任何想法我应该使用 skip 属性键入什么数字(例如 skip=1)。
接下来我输入以下命令:
mkdosfs -C floppy.img 1440
我收到以下错误:mkdosfs: unable to create floppy.img
。如何解决我遇到的问题?还有另一种更简单的方法可以将我的引导加载程序 .bin 文件转换为 ISO 映像吗?
您似乎找到了从这个 Whosebug Answer 创建可引导 ISO 映像的示例。不幸的是,您选择了一个在很多方面都不正确的公认答案。假装你从来没有看到那个答案。
在大多数 Linux 发行版中,存在名为 genisoimage
或 mkisofs
的程序。现在它们实际上是同一个程序。无论您有什么,都可以在下面的示例中替换。我的示例将假定 ISO 创建实用程序称为 genisoimage
.
在您的问题中,您在名为 boot.asm
的文件中有一些引导加载程序代码。您正确地 assemble 将此设置为引导扇区二进制映像:
nasm -f bin -o boot.bin boot.asm
这将创建 boot.bin
,这是您的引导扇区。下一步是创建软盘映像并将 boot.bin
放在第一个扇区。你可以这样做:
dd if=/dev/zero of=floppy.img bs=1024 count=1440
dd if=boot.bin of=floppy.img seek=0 count=1 conv=notrunc
第一个命令简单地使零填充的磁盘映像等于 1.44MB 软盘的大小(1024*1440 字节)。第二个命令将 boot.bin
放入 floppy.img
的第一个扇区而不截断文件的其余部分。 seek=0
表示查找第一个扇区(512 字节是 DD 的块的默认大小)。 count=1
指定我们只想从 boot.bin
复制 1 个扇区(512 字节)。 conv=notrunc
表示在写入输出文件后,剩余的磁盘映像将保持完整(未被截断)。
如上所示构建磁盘映像后,您可以使用以下命令创建 ISO 映像:
mkdir iso
cp floppy.img iso/
genisoimage -quiet -V 'MYOS' -input-charset iso8859-1 -o myos.iso -b floppy.img \
-hide floppy.img iso/
上面的命令首先创建一个名为 iso
的子目录,其中将包含要放置到最终 CD-ROM 映像中的文件。第二个命令只是将我们的 floppy.img
复制到 iso
目录,因为我们需要它来启动。第三个命令执行繁重的工作并构建 ISO 映像。
-V 'MYOS'
设置卷标(可以随意)
-input-charset iso8859-1
设置正在使用的字符集。不要改变它
-o myos.iso
表示 ISO 图像将输出到文件 myos.iso
-b floppy.img
表示我们的 ISO 将是可引导的,并且正在使用的引导映像是文件 floppy.img
-hide floppy.img
不是必需的,但它隐藏了最终 ISO 目录列表中的引导映像。如果您挂载此 ISO 并在其上执行 ls
以列出文件,floppy.img
将不会出现。
命令末尾的 iso/
是用于构建 ISO 映像的目录。它至少需要包含我们的可引导软盘映像,但您可以将任何其他文件放入 iso/
目录。
生成的ISO镜像myos.iso
可以启动。使用 QEMU 启动这样一个镜像的例子:
qemu-system-i386 -cdrom ./myos.iso
对于光盘;有一个规范 ("El Torito") 描述了 bootable CD 的工作原理;在前 16 个(2048 字节)扇区未使用的地方,固件使用 "boot catalogue" 来决定它应该使用哪个引导加载程序(因此您可以使用一张 CD 来引导非常不同的系统 - 例如 PC BIOS、UEFI、PowerPC 等),然后是引导加载程序本身。
仅 "PC BIOS" 就有 3 种可能性:
- 模拟软盘(使用存储在 CD 上的 "floppy disk image")
- 模拟硬盘(使用 "hard disk image" 存储在 CD 上)
- 没有仿真
前两个选项主要是为了兼容(不支持从 CD 启动的老 OSs,如 MS-DOS);并具有性能影响(例如,要模拟加载一个 512 字节的虚拟扇区,固件必须加载一个真正的 2048 字节的扇区并丢弃多余的 1536 字节)。在过去 15 年以上的任何 OS designed/written 都应该使用 "no emulation".
对于"no emulation":
- 固件会加载整个引导加载程序(最多可达 512 KiB),而不仅仅是一个扇区
- CD 上的扇区是 2048 字节(而不是 512 字节);并且应该通过加载。 "int 0x13 extensions"(而不是您用于软盘的 old/limited "CHS disk functions")
- 不需要 BIOS 参数块(对于软盘应该被认为是必需的)
- 不需要分区table(对于硬盘应该算是强制分区,包括GPT)
- 您可能希望支持 ISO9660 作为文件系统(以查找内核 and/or 引导加载程序需要加载的其他文件)而不是 FAT。
还要注意(通常)对于 "PC BIOS",您可能需要 5 个不同的引导装载程序(一个用于软盘,一个用于 "MBR partitioned" 硬盘,一个用于 "GPT partitioned" 硬盘,一个用于CD,一个用于网络引导)。这些案例完全不同(并且 "one 512-byte initial sector only" 对其中 3 个案例的限制已经足够严格)使 "all devices supported by one boot loader" 想法成为一场灾难。
实际生成ISO;可以使用已有的工具(例如mkisofs),也可以自己写工具(ISO9660和"El Torito"都比较容易理解,自己写工具生成ISO不到2天就搞定,这对于 OS 个开发项目来说就像沧海一粟)。
我正在尝试将我用汇编语言编写的引导加载程序转换为 ISO 映像文件。以下是来自 MikeOS 引导加载程序的代码。这是我的引导程序代码:
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'This is my cool new OS!', 0
print_string: ; Routine: output string in SI to screen
mov ah, 0Eh ; int 10h 'print char' function
.repeat:
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
我输入了以下命令:
nasm -f bin -o boot.bin boot.asm
此命令运行良好,并提供 .bin 输出。接下来我输入了以下命令:
dd if=boot.bin of=floppy.img count=1 bs=512
这也很好用,并为我提供了 .img 输出文件。当我键入此命令时:
dd if=boot.bin of=floppy.img skip seek=1 count=1339
我收到以下错误:dd: unrecognized operand ‘skip’
。我在 DD 文档中读到,skip 属性必须分配一个数字。任何想法我应该使用 skip 属性键入什么数字(例如 skip=1)。
接下来我输入以下命令:
mkdosfs -C floppy.img 1440
我收到以下错误:mkdosfs: unable to create floppy.img
。如何解决我遇到的问题?还有另一种更简单的方法可以将我的引导加载程序 .bin 文件转换为 ISO 映像吗?
您似乎找到了从这个 Whosebug Answer 创建可引导 ISO 映像的示例。不幸的是,您选择了一个在很多方面都不正确的公认答案。假装你从来没有看到那个答案。
在大多数 Linux 发行版中,存在名为 genisoimage
或 mkisofs
的程序。现在它们实际上是同一个程序。无论您有什么,都可以在下面的示例中替换。我的示例将假定 ISO 创建实用程序称为 genisoimage
.
在您的问题中,您在名为 boot.asm
的文件中有一些引导加载程序代码。您正确地 assemble 将此设置为引导扇区二进制映像:
nasm -f bin -o boot.bin boot.asm
这将创建 boot.bin
,这是您的引导扇区。下一步是创建软盘映像并将 boot.bin
放在第一个扇区。你可以这样做:
dd if=/dev/zero of=floppy.img bs=1024 count=1440
dd if=boot.bin of=floppy.img seek=0 count=1 conv=notrunc
第一个命令简单地使零填充的磁盘映像等于 1.44MB 软盘的大小(1024*1440 字节)。第二个命令将 boot.bin
放入 floppy.img
的第一个扇区而不截断文件的其余部分。 seek=0
表示查找第一个扇区(512 字节是 DD 的块的默认大小)。 count=1
指定我们只想从 boot.bin
复制 1 个扇区(512 字节)。 conv=notrunc
表示在写入输出文件后,剩余的磁盘映像将保持完整(未被截断)。
如上所示构建磁盘映像后,您可以使用以下命令创建 ISO 映像:
mkdir iso
cp floppy.img iso/
genisoimage -quiet -V 'MYOS' -input-charset iso8859-1 -o myos.iso -b floppy.img \
-hide floppy.img iso/
上面的命令首先创建一个名为 iso
的子目录,其中将包含要放置到最终 CD-ROM 映像中的文件。第二个命令只是将我们的 floppy.img
复制到 iso
目录,因为我们需要它来启动。第三个命令执行繁重的工作并构建 ISO 映像。
-V 'MYOS'
设置卷标(可以随意)-input-charset iso8859-1
设置正在使用的字符集。不要改变它-o myos.iso
表示 ISO 图像将输出到文件myos.iso
-b floppy.img
表示我们的 ISO 将是可引导的,并且正在使用的引导映像是文件floppy.img
-hide floppy.img
不是必需的,但它隐藏了最终 ISO 目录列表中的引导映像。如果您挂载此 ISO 并在其上执行ls
以列出文件,floppy.img
将不会出现。
命令末尾的 iso/
是用于构建 ISO 映像的目录。它至少需要包含我们的可引导软盘映像,但您可以将任何其他文件放入iso/
目录。
生成的ISO镜像myos.iso
可以启动。使用 QEMU 启动这样一个镜像的例子:
qemu-system-i386 -cdrom ./myos.iso
对于光盘;有一个规范 ("El Torito") 描述了 bootable CD 的工作原理;在前 16 个(2048 字节)扇区未使用的地方,固件使用 "boot catalogue" 来决定它应该使用哪个引导加载程序(因此您可以使用一张 CD 来引导非常不同的系统 - 例如 PC BIOS、UEFI、PowerPC 等),然后是引导加载程序本身。
仅 "PC BIOS" 就有 3 种可能性:
- 模拟软盘(使用存储在 CD 上的 "floppy disk image")
- 模拟硬盘(使用 "hard disk image" 存储在 CD 上)
- 没有仿真
前两个选项主要是为了兼容(不支持从 CD 启动的老 OSs,如 MS-DOS);并具有性能影响(例如,要模拟加载一个 512 字节的虚拟扇区,固件必须加载一个真正的 2048 字节的扇区并丢弃多余的 1536 字节)。在过去 15 年以上的任何 OS designed/written 都应该使用 "no emulation".
对于"no emulation":
- 固件会加载整个引导加载程序(最多可达 512 KiB),而不仅仅是一个扇区
- CD 上的扇区是 2048 字节(而不是 512 字节);并且应该通过加载。 "int 0x13 extensions"(而不是您用于软盘的 old/limited "CHS disk functions")
- 不需要 BIOS 参数块(对于软盘应该被认为是必需的)
- 不需要分区table(对于硬盘应该算是强制分区,包括GPT)
- 您可能希望支持 ISO9660 作为文件系统(以查找内核 and/or 引导加载程序需要加载的其他文件)而不是 FAT。
还要注意(通常)对于 "PC BIOS",您可能需要 5 个不同的引导装载程序(一个用于软盘,一个用于 "MBR partitioned" 硬盘,一个用于 "GPT partitioned" 硬盘,一个用于CD,一个用于网络引导)。这些案例完全不同(并且 "one 512-byte initial sector only" 对其中 3 个案例的限制已经足够严格)使 "all devices supported by one boot loader" 想法成为一场灾难。
实际生成ISO;可以使用已有的工具(例如mkisofs),也可以自己写工具(ISO9660和"El Torito"都比较容易理解,自己写工具生成ISO不到2天就搞定,这对于 OS 个开发项目来说就像沧海一粟)。