[SeaBIOS] [PATCH v9 2/6] Implementation of the TCG BIOS extensions
Stefan Berger
stefanb at linux.vnet.ibm.com
Sun Mar 22 14:55:47 CET 2015
On 03/20/2015 09:15 PM, Kevin O'Connor wrote:
> On Fri, Mar 20, 2015 at 02:00:37PM -0400, Stefan Berger wrote:
>> From: Stefan Berger <stefann at linux.vnet.ibm.com>
>>
>> This patch implements the main part of the TCG BIOS extensions. It provides
>> the following functionality:
>>
>> - initialization of the TCPA ACPI table used for logging of measurements
>> - initialization of the TPM by sending a sequence of commands to it
>> - proper setup of the TPM before the BIOS hands over control to the bootloader
>> - support for S3 resume; BIOS sends TPM_Startup(ST_STATE) to TPM
>> - enable configuration of SeaBIOS to be built with TCGBIOS extensions
>> All TCG BIOS extensions are activated with CONFIG_TCGBIOS.
> [...]
>> --- a/src/Kconfig
>> +++ b/src/Kconfig
>> @@ -421,6 +421,13 @@ menu "BIOS interfaces"
>> modified by programs. However, some old DOS high memory
>> managers may require the UMB region to be read-only.
>>
>> + config TCGBIOS
>> + select S3_RESUME
>> + bool "TPM support and TCG BIOS extensions"
>> + default y
>> + help
>> + Provide TPM support along with TCG BIOS extensions
> I don't think TCGBIOS should select S3_RESUME. If resume processing
> is an absolute requirement then I think it should use "depends on".
Ok.
>
> [...]
>> --- a/src/boot.c
>> +++ b/src/boot.c
>> @@ -19,6 +19,7 @@
>> #include "std/disk.h" // struct mbr_s
>> #include "string.h" // memset
>> #include "util.h" // irqtimer_calc
>> +#include "tcgbios.h" // tpm_*
>>
>>
>> /****************************************************************
>> @@ -475,6 +476,7 @@ interactive_bootmenu(void)
>>
>> printf("Select boot device:\n\n");
>> wait_threads();
>> + tpm_leave_bios();
> Is this call really supposed to be in the boot menu? The call wont
> get invoked if the boot menu isn't selected.
Right. I moved it into post.c maininit() after the wait_threads() call
there.
>
>> --- a/src/post.c
>> +++ b/src/post.c
>> @@ -28,6 +28,7 @@
>> #include "output.h" // dprintf
>> #include "string.h" // memset
>> #include "util.h" // kbd_init
>> +#include "tcgbios.h" // tpm_*
>>
>>
>> /****************************************************************
>> @@ -220,6 +221,10 @@ maininit(void)
>> if (threads_during_optionroms())
>> device_hardware_setup();
>>
>> + // Initialize tpm (after acpi tables were written)
>> + tpm_acpi_init();
>> + tpm_startup();
> I think this should be just one call - such as "tpm_setup()", which in
> turn calls tpm_xyz().
>
> Also, functions with "_init" and "_setup" suffixes have specific
> meaning in the bootstrap ordering sequence. So tpm shouldn't export
> functions with these suffixes unless they are invoked during the given
> sequence.
I move the tpm_acpi_init() call into tpm_startup().
>
> [...]
>> +u32
>> +tpm_startup(void)
>> +{
>> + u32 rc;
>> + u32 returnCode;
>> +
>> + if (!CONFIG_TCGBIOS)
>> + return 0;
>> +
>> + if (!has_working_tpm())
>> + return TCG_GENERAL_ERROR;
>> +
>> + dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n");
>> + rc = build_and_send_cmd(TPM_ORD_Startup,
>> + Startup_ST_CLEAR, sizeof(Startup_ST_CLEAR),
>> + NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
>> +
>> + dprintf(DEBUG_tcg, "Return code from TPM_Startup = 0x%08x\n",
>> + returnCode);
>> +
>> +#if CONFIG_COREBOOT
>> + /* with other firmware on the system the TPM may already have been
>> + * initialized
>> + */
>> + if (returnCode == TPM_INVALID_POSTINIT)
>> + returnCode = 0;
>> +#endif
> That '#if' should be turned into an 'if (...)'.
>
> [...]
Done
>> +u32
>> +tpm_s3_resume(void)
>> +{
>> + u32 rc;
>> + u32 returnCode;
>> +
>> + if (!CONFIG_TCGBIOS)
>> + return 0;
>> +
>> + if (!has_working_tpm())
>> + return TCG_GENERAL_ERROR;
>> +
>> + timer_setup();
> Why is the timer reinitialized here? There may be implications in
> touching that hardware during an S3 resume.
I am initializing the time because of the TPM driver's usage of
msleep(). Your comment reminds me of a comment years ago from Keir
Fraser from Xen. There, we ended up using I think a DRAM refresh timer
bit that was emulated by QEMU and flipped every few ns.
>
>> +
>> + dprintf(DEBUG_tcg, "TCGBIOS: Resuming with TPM_Startup(ST_STATE)\n");
>> +
>> + rc = build_and_send_cmd(TPM_ORD_Startup,
>> + Startup_ST_STATE, sizeof(Startup_ST_STATE),
>> + NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
>> +
>> + dprintf(DEBUG_tcg, "TCGBIOS: ReturnCode from TPM_Startup = 0x%08x\n",
>> + returnCode);
>> +
>> + if (rc || returnCode)
>> + goto err_exit;
>> +
>> + return 0;
>> +
>> +err_exit:
>> + dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
>> +
>> + tpm_state.tpm_working = 0;
>> + if (rc)
>> + return rc;
>> + return TCG_TCG_COMMAND_ERROR;
>> +}
>> diff --git a/src/tcgbios.h b/src/tcgbios.h
>> new file mode 100644
>> index 0000000..7be89f8
>> --- /dev/null
>> +++ b/src/tcgbios.h
>> @@ -0,0 +1,388 @@
>> +#ifndef TCGBIOS_H
>> +#define TCGBIOS_H
>> +
>> +#include "types.h"
>> +#include "bregs.h" /* struct bregs */
> Why is "bregs.h" needed in the header - can it be included in the
> individual C files that need it?
This #include needs to only appear in the 3rd patch when the interrupt
handler prototype appears. I move it there now.
Stefan
More information about the SeaBIOS
mailing list