1

好的,这就是我的意思:

假设您想编写自己的可引导代码。

此外,您的代码将非常简单。

事实上,它非常简单,只包含一条指令。

您的可引导代码将向外围设备上的寄存器或 RAM 位置写入字节或字或双字或任何内容,而不是主 RAM 或 CPU 寄存器。

您如何找出 BIOS / UEFI 分配给该外围存储器位置的地址?

这是一个更具体的例子:

我的可引导代码的第一条也是唯一一条指令会将数字 11H 写入位于声卡上的寄存器中。

如果 BIOS / UEFI 初始化代码正常工作,则声卡寄存器应该映射到 CPU 的内存空间和/或 IO 空间。

我需要找到那个地址来完成那个写入。

我如何找到它?

这是真正的操作系统在某些时候必须做的事情。

当您在 Windows 中打开控制面板/设备管理器时,您会看到此处列出的外围设备的所有内存范围。

在某些时候,Windows 必须查询 BIOS /UEFI 才能找到此数据。

再次,这是如何完成的?

编辑:

这是我编写这个可引导汇编程序的尝试:

    BITS    16
    ORG     100h
start:
    ;I want to write a byte into a register on the sound card or NIC or 
    ;whatever. So, I'm using a move instruction to accomplish that where X 
    ;is the register's memory mapped or IO mapped address.
    mov X,11h
times 510 - ($ - $$)  db 0
dw 0xaa55

我为 X 输入什么数字?如何找到该外设寄存器的地址?

4

1 回答 1

2

If you want to do this with one instruction, you can just get the address for the device from the Windows device manager. But if you want to do it the "proper" way, you need to scan the PCI bus to find the device you want to program, and then read the Base Address Registers (BARs) of the device to find its MMIO ranges. This is what Windows does; it doesn't query the BIOS.

To find the device that you want to access, scan the PCI bus looking for the device. Devices are addressed on the PCI bus by their "BDF" (short for Bus/ Device/ Function). Devices are identified by a Vendor ID and a Device ID assigned by the vendor.

Read offset 0 and 2 of each BDF to get the Vendor ID and Device ID. When you have found the device you want to program, read the correct 32-bit BAR value at an offset between 10h and 24h. You need to know which BAR contains the register you want to program, which is specific to the device you are using.

This article describes how to access PCI config space and has sample code in C showing how to scan the PCI bus. http://wiki.osdev.org/PCI

于 2017-08-28T05:47:19.680 回答