使用自定义引导程序创建可引导的ISO映像

12

我正在尝试将我用汇编语言写的引导程序转换为一个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=1)。

接下来我键入以下命令:

mkdosfs -C floppy.img 1440 

我遇到了如下错误:mkdosfs: unable to create floppy.img。我该如何解决遇到的问题?是否有其他更简单的方法可以将我的引导程序.bin文件转换为ISO镜像?

2个回答

34

看起来你从这个StackOverflow答案中找到了创建可引导ISO映像的示例。不幸的是,你选择了一个在许多方面都是不正确的已接受答案。假装你从未见过那个答案。

在大多数Linux发行版中,都存在一个名为genisoimagemkisofs的程序。如今它们实际上是同一程序。无论你拥有哪一个,都可以在下面的示例中进行替换。我的示例将假设ISO创建实用程序被称为genisoimage


在你的问题中,你有一个名为boot.asm的引导加载程序代码文件。你可以使用以下方法将其正确汇编为引导扇区二进制映像:

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

9
关于CD的启动,有一个规范(“El Torito”)描述了启动CD的工作原理;其中前16个(2048字节)扇区未使用,有一个“引导目录”,固件使用它来决定应该使用哪个启动加载程序(因此您可以拥有单个CD,可以引导非常不同的系统 - 例如PC BIOS、UEFI、PowerPC等),然后是启动加载程序本身。
对于仅涉及“PC BIOS”的情况,有3种可能性:
  • 模拟软盘(使用存储在CD上的“软盘映像”)
  • 模拟硬盘(使用存储在CD上的“硬盘映像”)
  • 无模拟
前两个选项大多只用于兼容性目的(像MS-DOS这样不支持从CD引导的古老操作系统)并且存在性能问题(例如,为了模拟加载一个512字节的虚拟扇区,固件必须加载实际的2048字节扇区并抛弃多余的1536字节)。过去15年设计/编写的任何操作系统都应该使用“无模拟”。
对于“无模拟”:
  • 固件将加载整个启动加载程序(最多约512 KiB),而不仅仅是一个扇区。
  • CD上的扇区为2048字节(而不是512字节);应通过“int 0x13扩展”(而不是旧的/有限的“CHS磁盘函数”)加载。
  • 无需BIOS参数块(应将其视为软盘的强制要求)。
  • 无需分区表(应将其视为硬盘的强制要求,包括GPT)。
  • 您可能希望支持ISO9660作为文件系统(以查找内核和/或启动程序需要加载的其他文件),而不是FAT。
此外,请注意(一般而言),对于“PC BIOS”,您可能需要5个不同的引导加载程序(一个用于软盘、一个用于“MBR分区”硬盘、一个用于“GPT分区”硬盘、一个用于CD和一个用于网络引导)。这些情况都足够不同(并且其中3种情况的“仅一个512字节初始扇区”限制足够严格),以使“所有设备都由一个引导加载程序支持”成为灾难。
要实际生成ISO,可以使用现有工具(例如mkisofs),也可以编写自己的工具(ISO9660和“El Torito”都相对容易理解,编写自己的工具来生成ISO可以在不到2天的时间内完成,这对于操作系统开发项目来说只是一点小事)。

我是你的一位点赞者。虽然你的问题在技术上并没有回答如何实现特定的问题,但它确实包含了有关ISO镜像的有用信息。 - Michael Petch

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