[SeaBIOS] Saving a few bytes across a reboot

Stefan Berger stefanb at linux.vnet.ibm.com
Thu Jan 11 18:16:03 CET 2018

On 01/11/2018 11:44 AM, Laszlo Ersek wrote:
> (I'm not trying to further argue for the idea below, just to clarify it:)
> On 01/11/18 15:29, Stefan Berger wrote:
>> On 01/11/2018 09:02 AM, Laszlo Ersek wrote:
>>> On 01/11/18 13:40, Igor Mammedov wrote:
>>>> On Wed, 10 Jan 2018 17:45:52 +0100
>>>> Laszlo Ersek <lersek at redhat.com> wrote:
>>>>> (My understanding is that the guest has to populate the CRB, and then
>>>>> kick the hypervisor, so at least the register used for kicking must be
>>>>> in MMIO (or IO) space. And firmware cannot allocate MMIO or IO space
>>>>> (for platform devices). Thus, the register block must reside at a
>>>>> QEMU-determined GPA. Once we do that, why bother about RAM allocation?)
>>>> MMIO doesn't have to be fixed nor exist at all, we could use
>>>> linker write to file operation in FW for switching from guest
>>>> to QEMU. That's obviously intrusive work for FW and QEMU
>>>> compared to hardcodded address in both QEMU and FW but as
>>>> benefit changes to QEMU and FW don't have to be tightly coupled
>>>> and layout could be changed whenever need arises.
>>> Marc-André wrote, "The [CRB] region is registered at the same address as
>>> TIS (it's not entirely clear from the spec it is supposed to be there,
>>> but my laptop tpm use the same)."
>>> And, the spec declares the register block at the fixed range
>>> FED4_0000h-FED4_4FFFh.
>>> How about this:
>>> (1) stick with the TPM specs and implement the TIS and/or CRB interfaces,
>>> (2) *except* make the base address of the register block a compat
>>> property for the QEMU device,
>>> (3) generate data tables (TPM2) and AML tables (SSDT/_DSM) that expose
>>> the device to the guest OS as ACPI or ACPI+CRB (i.e., "fTPM"), *not* TIS
>>> and/or CRB
>> Why? Linux doesn't use this type of interface. Actually, for the TIS the
>> base address has been hard coded as well.
> The idea would be to hide the actual address from the OS. Let the OS go
> through the ACPI methods only, and keep the ACPI constants in sync with
> the device model.
>>> (4) in the generated ACPI payload, adhere to the compat property (i.e.,
>>> generate the base address values from the compat prop),
>>> (5) expose the base address stand-alone in a new fw_cfg file as well.
>>> Benefits as I see it:
>>> - register block can move around from one QEMU release to next,
>> Why would we need that?
> It's not a requirement that I'm presenting -- I took the requirement as
> a given and attempted to satisfy it.
>> fed4_0000 is presumably reserved for TPM device
>> interfaces and shouldn't clash with anything in the future. With the PPI
>> memory at ffff_0000 - ffff_00ffI am not so sure. Here we could use the
>> proposed QEMU ACPI table and a hard-coded address, ffff_0000 at the
>> beginning. Would that not solve it? Why not?
>>> - migration remains functional (ACPI comes from source host, but it
>>>     matches the device model on the target host, due to the compat prop),
>>> - firmware remains dumb about TPM activations (OS calls ACPI calls
>>>     virtual hardware),
>> Linux doesn't use the ACPI interface from what I can tell.
>> What are 'TPM activations'?
> I coined this expression for "interacting with the TPM device". I used
> this expression because the TPM ACPI spec uses the expression
> "activation methods" for describing the various ways to interact with
> the device (TIS, CRB, ACPI, ACPI+CRB are four methods that we've been
> discussing).
> So above I meant that the firmware does not participate in OS->TPM requests.
>> We have a TIS interface for example that
>> SeaBIOS uses to initialize the TPM1.2 / TPM2.
>>> - the ACPI-to-hardware interface is dictated by an industry spec, so we
>> Do you have a pointer to this spec?
> I simply meant that a TIS client would have to be written in AML
> (generated by QEMU). To the OS the device would be available via ACPI or

But for that we would need an official spec. I haven't seen a spec that 
describes it. Maybe EDK2 has such a driver, but this may be one written 
without a public spec.

> ACPI+CRB activation, but to the ACPI implementation itself, it would
> look like a TIS or CRB device, with a moveable base address. This way
> the OS would be separated from the base address (because the OS would
> have to go through ACPI), and the firmware could reuse existent TIS
> drivers with hopefully minimal customization (base address taken from
> fw_cfg).

The OS could be separated by telling where the base address is via an 
ACPI table. TPM 2 does that but the other specs for TIS say it's at fed4 
0000. The CRB may be more flexible, but


See page 34, also table 6, etc


Page 34, also table 7, etc

Also of interest is Table 10. Table 13 shows that the Interface 
Identifier Register indicates whether TIS and / or CRB are implemented 
and either one can be selected per writing to bits 18:17.

> So, by the above industry spec, I simply meant the TIS interface.
> Anyway, based on your description, there's a disconnect between the
> Linux guest and the base address movability requirement:
> - we have four activation methods: TIS+Cancel, CRB, ACPI, ACPI+CRB
> - of this, Linux only supports the first two (TIS+Cancel, CRB), IIUC
> - in addition, Linux hard-codes the MMIO base address for both
>    TIS+Cancel and CRB (at the spec-given address)

Actually it only hard codes it when one forces the device driver in. 
Otherwise it retrieves it (probably) via ACPI by calling 
platform_get_resource(), which probably passes back what ACPI defines 
via Memory32Fixed().

We set the address via a constant when building the ACPI.

> - Windows cannot consume TIS+Cancel directly (according to research done
>    by Marc-André, if I understand correctly), but it supports CRB, ACPI,

I believe that's true for recent versions of it. Many years ago, when I 
was working on Xen, TIS was detected by Windows.

I am not sure where the ACPI for this is spec'ed.

> - so the intersection is "CRB with hard-coded MMIO base address".

I can only point to the standard for the address. If QEMU has an API 
where we can first try to allocate fed4 0000 and if that fails ask for 
another address, then we can use that. But does driver initialization 
work that way that we can first let all other devices register their 
MMIO requirements and then the TPM device ask whether fed4 0000 is 
available and then falls back to using a random address?


> Thanks
> Laszlo
>>>     don't have to invent and document a paravirtual interface. If it ever
>>>     becomes necessary for the firmware to directly access the TPM
>>>     hardware (for example, to replay physical presence commands queued by
>>>     the OS), fw can rely on the same industry spec, only the base address
>>>     has to be updated -- which is available stand-alone from the named
>>>     fw_cfg file.
>>> Thanks
>>> Laszlo

More information about the SeaBIOS mailing list