Page 1 of 1

Accessing SMBus registers

Posted: Fri Jun 20, 2025 8:43 am
by avcado
i'm not sure if this is the right place, but none of the other "categories" seem to fit my question.

I recently got nerd sniped, and was curious on how firmware loads SMM, so I decided to write some firmware that's only purpose is to load SMM into memory and enable SMI#. I decided to target the ICH9/Q35 chipset, and booted up the spec and just read through it. I came up with this "strategy":
  1. Enable SMBus by setting HST_EN and SMB_SMI_EN bits in the SMBus PCI register, which seems to be 0x8000fb40.
  2. Set INTREN in the HST_CNT register. (which enables SMI#)
However the specification states that this register is at offset SMBASE + 0x02 -- since the default SMBASE is 0x30000 this would be 0x30002. Additionally, the specification states this register is in Bus 0, Device 31, Function 3, at that offset, which would be 0x8003fb02, however this seems like it's not a PCI address:

Code: Select all

(qemu) x/1i $eax
0xffffffff8003fbff: Cannot read memory
I was thinking that it's somehow a typo, seeing as on page 758 it says "SMB_BASE" while on 760, it states "Register offset: SMBASE + 02h". Intel's errata document doesn't state anything about this. My question is: how do I access HST_CNT?

I read:
The following SMBus registers can be accessed through I/O BAR or Memory BAR registers in PCI configuration space. The offsets are the same for both I/O and Memory Mapped I/O registers.
Which only slightly confused me more. Thanks in advance! :)

Re: Accessing SMBus registers

Posted: Fri Jun 20, 2025 8:46 pm
by nullplan
The HOSTC register is in PCI configuration space. So you access them with the PCI access method. I think it is better to just discover the SMBus controller on the PCI and then do stuff with it than to hardcode some addresses. The second register HST_CNT is in the device's MMIO and Port I/O range. This means the register is available in both, and which one you access depends on which one you like more. The memory base address is given in SMBBAR0 and SMBBAR1 (it is a 64-bit address), and the I/O port base address is given in SMB_BASE. Typically, firmware has already initialized these by the time you get to read them, so don't change them, only read them.

Re: Accessing SMBus registers

Posted: Fri Jun 20, 2025 9:44 pm
by Octocontrabass
avcado wrote: Fri Jun 20, 2025 8:43 amI was thinking that it's somehow a typo, seeing as on page 758 it says "SMB_BASE" while on 760, it states "Register offset: SMBASE + 02h".
Yeah, it's a typo. Any time you see "SMBASE" in that document, it should be "SMB_BASE". (Intel's chipset documentation is rather sloppy.)

Re: Accessing SMBus registers

Posted: Sat Jun 21, 2025 8:56 am
by avcado
nullplan wrote: Fri Jun 20, 2025 8:46 pm The second register HST_CNT is in the device's MMIO and Port I/O range. This means the register is available in both, and which one you access depends on which one you like more. The memory base address is given in SMBBAR0 and SMBBAR1 (it is a 64-bit address), and the I/O port base address is given in SMB_BASE. Typically, firmware has already initialized these by the time you get to read them, so don't change them, only read them.
Just to be sure I understand what you're saying, since the offset of HST_CNT is SMB_BASE+02h, wouldn't that just be

Code: Select all

mov esi, [smbbase]     ;; Retrieved from SMB_Base register in PCI
add esi, 2
mov dx, si
in eax, edx

or al, (1<<0)		;; Set INTREN bit
out dx, eax		;; Write back
Unless I'm completely misunderstanding what you said.

Re: Accessing SMBus registers

Posted: Sat Jun 21, 2025 10:14 am
by nullplan
Yes, that seems correct. At least if I'm reading the datasheet right.