[SeaBIOS] Long delay: WARNING - Timeout at wait_reg8:81!
Stefan Berger
stefanb at linux.vnet.ibm.com
Tue Mar 13 12:31:10 CET 2018
On 03/12/2018 06:11 PM, Kevin O'Connor wrote:
> On Mon, Mar 12, 2018 at 01:38:52PM -0400, Stephen Douthit wrote:
>> I've got a board modded so I can jumper the TPM in and out.
>>
>> What I found in the no-TPM case was that both tis_probe() and
>> crb_probe() incorrectly return 1 for device present if all Fs are read.
>>
>> For tis_probe() that was because rc wasn't updated to 0 if didvid was
>> 0xffffffff. For crb_probe() the last three return statements are
static u32 tis_probe(void)
{
if (!CONFIG_TCGBIOS)
return 0;
/* Wait for the interface to report it's ready */
u32 rc = tis_wait_access(0, TIS_DEFAULT_TIMEOUT_A,
TIS_ACCESS_TPM_REG_VALID_STS,
TIS_ACCESS_TPM_REG_VALID_STS);
if (rc)
return 0;
u32 didvid = readl(TIS_REG(0, TIS_REG_DID_VID));
if ((didvid != 0) && (didvid != 0xffffffff))
rc = 1;
/* TPM 2 has an interface register */
u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID));
if ((ifaceid & 0xf) != 0xf) {
if ((ifaceid & 0xf) == 1) {
/* CRB is active; no TIS */
return 0;
}
if ((ifaceid & (1 << 13)) == 0) {
/* TIS cannot be selected */
return 0;
}
/* write of 0 to bits 17-18 selects TIS */
writel(TIS_REG(0, TIS_REG_IFACE_ID), 0);
/* since we only support TIS, we lock it */
writel(TIS_REG(0, TIS_REG_IFACE_ID), (1 << 19));
}
return rc;
}
When tis_probe() returns '1', it means the interface was detected.
If all registers return 0xffffffff in the no-TPM case we should return a
'0' from tis_probe since rc was set to 0 from tis_wait_access() and we
will not get into the ifaceid test case. If they return 0 then we
shouldn't get past the tis_wait_access() because the expected pattern
would not show up. I think tis_probe() is correct.
static u32 crb_probe(void)
{
if (!CONFIG_TCGBIOS)
return 0;
u32 ifaceid = readl(CRB_REG(0, CRB_REG_INTF_ID));
if ((ifaceid & 0xf) != 0xf) {
if ((ifaceid & 0xf) == 1) {
/* CRB is active */
return 1;
}
if ((ifaceid & (1 << 14)) == 0) {
/* CRB cannot be selected */
return 0;
}
/* write of 1 to bits 17-18 selects CRB */
writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 17));
/* lock it */
writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 19));
}
/* no support for 64 bit addressing yet */
if (readl(CRB_REG(0, CRB_REG_CTRL_CMD_HADDR)))
return 1;
u64 addr = readq(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR));
if (addr > 0xffffffff)
return 1;
return 0;
}
if ifaceid returns ~0 we may return when reading CRB_REG_CTRL_CMD_HADDR.
So probably we should test for ifaceid = ~0 after it is read and return 0.
>> inverted from what they should be, and the first 64bit address check
>> returned the wrong value. Fixing both probe functions got rid of the
>> timeout for me when the TPM was disconnected.
I see a problem with the crb_probe function but not the tis_probe.
>>
>> It looks like there's a bit in the ACCESS register called Seize that
>> must always read '0' for the version 1.2/1.3 interfaces. I'd like to
>> check that instead of didvid in tis_probe to handle the aborted read all
>> 0s/Fs case.
Why would there be a 'aborted read all'? I think the didvid registers
should not return either 0 or ~0 for there to be a valid device. Why
would that not be a good first test to see whether anything is there?
>>
>> I'd like to add a poll for tpmRegValidSts to crb_probe() similar to
>> what's in tis_probe() to avoid potential races on real hardware.
That may be something necessary on real hardware, though in case nothing
is there we all need to wait... I am not sure whether the checking for
these bits has impact on the didvid registers. ValidSts presumably means
that the STS register has valid bits. I don't have real hardware anymore
-- my Acer died a while ago, so I cannot tell but its hardware didn't
need the wait.
>> There's a Seize bit in TPM_LOC_CTRL_x which always reads 0 that we could
>> use as a sanity check against the no device all Fs case.
>>
>> Let me know if that sounds like a better way to catch the no device
>> case, or if there's is some other check that would be better.
> Thanks for looking at this. It is common on x86 for invalid memory
> accesses to return 0xff. I don't know enough about the TPM hardware
> to make a judgement call on the best way to test for presence. I'd
> like to hear what Stefan's thoughts are on this.
>
> -Kevin
>
More information about the SeaBIOS
mailing list