【问题标题】:Phoenix BIOS skips MBR code, what is the ACTUAL BIOS standard?Phoenix BIOS 跳过 MBR 代码,ACTUAL BIOS 标准是什么?
【发布时间】:2019-05-18 08:48:12
【问题描述】:

我想学习汇编程序以使用超最少的裸代码让任何 x86 兼容机器运行,以便在开机时在屏幕上显示硬编码文本。 我关心与 x86/IBM 机器的完全兼容性。

我按照关于简单引导代码的教程进行操作,但惨遭失败,无法通过笔记本电脑上的 USB 物理运行它们。就像我的笔记本甚至没有触及 MBR 代码一样。 我花了两个星期阅读大量文章,但结果一无所获。我学到了很多关于 BIOS 参数块、分区条目、this old Phoenix BIOS specification 和 UEFI 的知识。

我的笔记本电脑可以通过可启动的 FreeDOS USB 正确启动。 这是带有 MBR 的 FreeDOS USB 的第一个扇区: Nice and full of real useful codey-code

我尝试从带有 UEFI 的台式计算机启动它,它工作正常。 我尝试从带有 Phoenix BIOS 的笔记本电脑启动它,它工作正常。

然后我擦除了所有启动指令: Nice and full of NOTHING but one partition entry

我尝试使用 UEFI 从同一台台式计算机启动它,但它按预期失败。 我尝试从带有 Phoenix BIOS 的笔记本电脑启动它,它工作正常。我发誓。

我想知道为什么有一个 BIOS 可以自行处理并跳过 MBR 指令,如果有更多类似的,我在哪里可以找到有关它们的文档,以便我可以使我的启动代码与所有 BIOS 完全兼容.

我笔记本的BIOS版本是1.08,EC版本是1.07。 我不想更新它。如果 FreeDOS 可以正常启动,那么我希望我的引导代码也可以正常启动。

【问题讨论】:

  • 我假设您正在使用硬盘驱动器仿真 (HDD) 而不是软盘仿真 (FDD) 启动此 USB。
  • 使用 HDD USB 仿真时,一些 BIOS 实际上会从第一个扇区 (MBR) 读取分区表,找到一个活动条目,然后自动加载卷 (VBR) 的第一个扇区并开始运行它MBR 中的代码。对于 Freedos,分区的第一个扇区很可能是运行的实际代码。这只是一个疯狂的猜测。
  • BIOS 的工作方式因制造商而异,不幸的是,情况可能有些随意。增加通过 USB HDD 引导并在 MBR 中运行代码的一种技术是实际创建一个分区表,其中活动分区指向 MBR 本身,而不是卷引导记录 (VBR)。
  • 嗨@MichaelPetch,你猜对了。该 BIOS 只能模拟 USB 硬盘,它是不可配置的。我还猜测 VBR 会直接执行,并考虑通过跳转到 MBR 来修复它,以最大限度地提高 BIOS 之间的兼容性。但是现在我想知道是否存在包含所有已知 BIOS 引导行为的书或文章中的列表,这样我可以确保我的代码不会在我插入的下一台机器上崩溃。FreeDOS 开发人员是如何知道这些行为的存在做出这样的解决方法吗?或者您认为这只是巧合,因为它是首先加载 VBR 的标准程序?
  • 不,这并没有很好地记录在一个地方,而是基于互联网上传播的信息。 osdev.org 在他们的 Wiki 页面和论坛上有一些信息,但又不是全部合并在一个地方。这就是为什么很多人使用像 GRUB 这样的引导加载程序来处理所有这些问题的原因。

标签: x86 usb phoenix bios mbr


【解决方案1】:

此答案基于经验和有根据的猜测。如果没有实际的硬件,测试是相当困难的。我假设 OP 正在将他的引导扇区写入 MBR 而不是 VBR。


多年来创建的 BIOS 既愚蠢又聪明(恕我直言,有些太聪明了)。有些人试图根据是否存在 BIOS 参数块和/或带有可引导分区的分区表来区分可能是软盘驱动器或硬盘驱动器的介质。不幸的是,这不是标准化的,许多 BIOS 制造商只针对 Windows 分区的磁盘测试他们的代码。

一些认为他们看到有效分区表的 BIOS 将假定 HDD 仿真并尝试从活动分区加载卷引导记录 (VBR),而不是在 MBR 上执行代码。我怀疑这是机器上的情况,尽管将代码归零并保留了分区表,但它似乎仍然可以启动。执行的代码可能直接来自 VBR。

如果使用充当硬盘驱动器(而不是软盘)的设备,您可以使用分区表创建 MBR,其中唯一的活动分区从驱动器的开头开始(CHS=0,0,1 或 LBA=0 );被标记为可启动;并且具有非零分区类型。如果您遇到机器意图直接加载 VBR,则此方法会欺骗它以将 MBR 作为 VBR 加载。

应该在您的 USB 上作为硬盘介质在您似乎正在测试的机器上启动的示例代码如下所示:

bits 16
org 0x7c00

boot_start:
    xor ax, ax                  ; DS=0 since we use ORG 0x7c00. 0x0000<<4+0x7c00=0x7c00
    mov ds, ax
    mov es, ax

    ; If you will be reading data into memory outside of 0x7c00 to 0x7dff
    ; then you want to set the stack SS:SP - uncomment these lines
    ; mov ss, ax                ; Stack at 0x0000:0x7c00
    ; mov sp, 0x7c00            ;     Just below bootloader

    cld                         ; Forward movement of string instructions
                                ;     (MOVSB, SCASB, etc)

    mov si, HelloWorldMsg       ; Print hello world
    call print_string

end_loop:                       ; Loop forever to terminate
    hlt
    jmp end_loop

; Function: print_string
;           Display a string to the console on display page 0
;
; Inputs:   SI = Offset of address to print
; Clobbers: AX, BX, SI

print_string:
    mov ah, 0x0e                ; BIOS tty Print
    xor bx, bx                  ; Set display page to 0 (BL)
    jmp .getch
.repeat:
    int 0x10                    ; print character
.getch:
    lodsb                       ; Get character from string
    test al,al                  ; Have we reached end of string?
    jnz .repeat                 ;     if not process next character
.end:
    ret

HelloWorldMsg:   db "Hello, world!", 0x0d, 0x0a, 0

times 446-($-$$) db 0   ; Pad with 0s up until first partition entry
part1_entry:
db 0x80                 ; 0x80 = Active boot partition, 0x00=inactive
db 0x00, 0x01, 0x00     ; CHS of first absolute sector (MBR) of hard drive
                        ;     Head=0, Sector=1, Cylinder=0
db 0x0c                 ; Partition type (has to be non-zero)
                        ;     0x0c = Win 95 FAT32 (LBA)
db 0x00, 0x01, 0x00     ; CHS of last absolute sector (MBR) of hard drive
                        ;     Head=0, Sector=1, Cylinder=0
                        ;     We are effectively saying Size of partition is 1 sector
dd 0x0                  ; LBA of first absolute sector (0=MBR)
dd 0x1                  ; Number of sectors in partition. We set it to 1 but if you
                        ;     wish you could set it to the number of sectors on the disk

times 510-($-$$) db 0   ; Pad remainder of boot sector up to boot signature. This zeroes
                        ;     partition entries 2,3,4 effectively making them inactive

dw 0xAA55               ; The standard PC boot signature after partition table

您可以使用以下方法构建 MBR:

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

如果成功放置在媒体上,则应打印此代码:

你好,世界!

【讨论】:

  • 你好,Michael,我想让你知道我必须通过将汇编代码写入 VBR 来运行它。但这并不是那么简单。事实上,它不是那么简单的原因与您上面的代码仍然无法在我的笔记本上运行的原因相同。原因是:我的 BIOS 不仅检查有效的分区表,它还加载第一个活动分区的第一个扇区并检查分区的 VALID FS HEADER(确实太聪明了>:C)。只有这样,它才会设计自己在 VBR(这是我编写程序的地方)上运行引导代码 Src:link
  • 如果您有兴趣:我的程序必须加载到内存地址 0x7C5A(如果我没记错的话),这意味着我必须先写“org 0x7C5A”。然后我必须在我的usb VBR上的FS头之后复制编译的二进制文件,就是这样。让它运行 boiii :D
  • @AntonioDelasCarreras 听起来您的 BIOS 还需要一个 BIOS 参数块和一个分区表(如果有人尝试使用自引用方法)。这是一个真正的可能性,但我想通过消除过程尝试一些事情来改进答案。你能从这里下载这两个文件吗:capp-sysware.com/misc/osdev/test1。然后与nasm -f bin boot.asm -o boot.bin 组装并尝试将其写入驱动器的MBR?谢谢
  • 不要担心答案中的代码。我的问题与其说是“我想要解决我的具体问题”。但是“我想知道在哪里可以找到有关完整 BIOS 行为范围的文档”。当您回答“这不是标准化的,许多 BIOS 制造商仅针对 Windows 分区的磁盘测试他们的代码”时,您已经给了我想要的答案。 (加上您对我的问题的一个问题:“这在一个地方没有得到很好的记录,并且基于互联网上传播的信息”)
  • @AntonioDelasCarreras :我明白,我只是想知道我自己的记录会发生什么。
猜你喜欢
  • 2011-10-30
  • 2016-06-07
  • 2014-10-29
  • 2018-08-06
  • 1970-01-01
  • 2021-08-08
  • 2021-05-21
  • 2012-03-24
  • 2011-03-17
相关资源
最近更新 更多