[SeaBIOS] [PATCH 2/3] Support for TPM Physical Presence Interface
Igor Mammedov
imammedo at redhat.com
Fri May 15 17:23:50 CEST 2015
On Fri, 8 May 2015 13:45:47 -0400
Stefan Berger <stefanb at linux.vnet.ibm.com> wrote:
> This patch implements the specification found here:
>
> http://www.trustedcomputinggroup.org/resources/tcg_physical_presence_interface_specification
>
> It adds the necessary BIOS code so that for example an administrator can send
> messages from the OS to the BIOS for the BIOS to change the state of the TPM
> upon reboot. With the help of this interface, an administrator does not have
> to manually interact with the BIOS.
>
> As an example, on Linux the root use can send an opcode to the BIOS through the
> TPM's sysfs entries following the opcodes listed in table 2 of the above
> specs. To for example disable and deactivate the TPM, the root user would
> send opcode '7' to the BIOS:
>
> #> cd /sys/devices/pnp0/00:0?/ppi
>
> #> echo 7 > request
>
> #> reboot
>
> To exchange data between the OS and SeaBIOS, we use the TIS's vendor
> specific extensions in locations 0xf90-fff where RAM locations reside
> that are not reset during a machine reboot. This memory is initialized
> and two locations receive a 32 bit value 'TCG_MAGIC' that the ACPI code
> and SeaBIOS are looking for to accept the memory. If after a reboot the
Why do you need to look for TCG_MAGIC?
buffer is at the fixed known address so BIOS could just use it, in addition
it will save 8 bytes of precious low memory.
Also I'd pass buffer address via fwcfg file instead of hardcoding it
in QEMU and SeaBIOS.
> signature is found by SeaBIOS, the opcode (sent from the OS) is looked
> at and acted upon.
>
> The implementation requires an ACPI _DSM method to be implemented for the
> TPM's SSDT. The code in the _DSM will write the administrator's opcode
> into the TIS's RAM locations. The _DSM method is invoked when the root
> user interacts with the entries shown in the above ppi sysfs directory.
> The patch implementing the _DSM will be posted independently.
>
> This patch supports opcodes 1-11, 14, 21, and 22.
>
> Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
> ---
> src/hw/tpm_drivers.h | 1 +
> src/post.c | 3 +
> src/tcgbios.c | 570 +++++++++++++++++++++++++++++++++++++++++++++++++++
> src/tcgbios.h | 47 +++++
> 4 files changed, 621 insertions(+)
>
> diff --git a/src/hw/tpm_drivers.h b/src/hw/tpm_drivers.h
> index 34bb12d..83e4a62 100644
> --- a/src/hw/tpm_drivers.h
> +++ b/src/hw/tpm_drivers.h
> @@ -53,6 +53,7 @@ extern struct tpm_driver tpm_drivers[];
> #define TIS_REG_DATA_FIFO 0x24
> #define TIS_REG_DID_VID 0xf00
> #define TIS_REG_RID 0xf04
> +#define TIS_REG_RAM 0xfa0
>
> #define TIS_STS_VALID (1 << 7) /* 0x80 */
> #define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
> diff --git a/src/post.c b/src/post.c
> index e273c18..4c944c8 100644
> --- a/src/post.c
> +++ b/src/post.c
> @@ -219,6 +219,7 @@ maininit(void)
>
> // Setup platform devices.
> platform_hardware_setup();
> + tpm_ppi_init();
>
> // Start hardware initialization (if threads allowed during optionroms)
> if (threads_during_optionroms())
> @@ -240,6 +241,8 @@ maininit(void)
> // Run option roms
> optionrom_setup();
>
> + // Process user-requested TPM state change
> + tpm_ppi_process();
> // Allow user to modify overall boot order.
> interactive_bootmenu();
> wait_threads();
> diff --git a/src/tcgbios.c b/src/tcgbios.c
> index 3f31231..610ed12 100644
> --- a/src/tcgbios.c
> +++ b/src/tcgbios.c
> @@ -24,6 +24,8 @@
> #include "bregs.h" // struct bregs
> #include "sha1.h" // sha1
> #include "std/smbios.h"
> +#include "malloc.h" // malloc_*
> +#include "fw/paravirt.h" // runningOnQEMU
>
>
> static const u8 Startup_ST_CLEAR[2] = { 0x00, TPM_ST_CLEAR };
> @@ -42,6 +44,11 @@ static const u8 GetCapability_Permanent_Flags[12] = {
> 0x00, 0x00, 0x01, 0x08
> };
>
> +static const u8 GetCapability_STClear_Flags[12] = {
> + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04,
> + 0x00, 0x00, 0x01, 0x09
> +};
> +
> static const u8 GetCapability_OwnerAuth[12] = {
> 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
> 0x00, 0x00, 0x01, 0x11
> @@ -89,6 +96,10 @@ static tpm_state_t tpm_state = {
> .tpm_driver_to_use = TPM_INVALID_DRIVER,
> };
>
> +typedef struct {
> + u8 op;
> +} tpm_bios_cfg_t;
> +
>
> /********************************************************
> Extensions for TCG-enabled BIOS
> @@ -1438,6 +1449,521 @@ tpm_ipl(enum ipltype bootcd, const u8 *addr, u32 length)
> return rc;
> }
>
> +static u32
> +read_stclear_flags(char *buf, int buf_len)
> +{
> + u32 rc;
> + u32 returnCode;
> + struct tpm_res_getcap_stclear_flags stcf;
> +
> + memset(buf, 0x0, buf_len);
> +
> + rc = build_and_send_cmd(0, TPM_ORD_GetCapability,
> + GetCapability_STClear_Flags,
> + sizeof(GetCapability_STClear_Flags),
> + (u8 *)&stcf,
> + sizeof(struct tpm_res_getcap_stclear_flags),
> + &returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability() "
> + "= 0x%08x\n", returnCode);
> +
> + if (rc || returnCode)
> + goto err_exit;
> +
> + memcpy(buf, &stcf.stclear_flags, buf_len);
> +
> + 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;
> +}
> +
> +
> +static u32
> +assert_physical_presence(int verbose)
> +{
> + u32 rc = 0;
> + u32 returnCode;
> + struct tpm_stclear_flags stcf;
> +
> + rc = read_stclear_flags((char *)&stcf, sizeof(stcf));
> + if (rc) {
> + dprintf(DEBUG_tcg,
> + "Error reading STClear flags: 0x%08x\n", rc);
> + return rc;
> + }
> +
> + if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE])
> + /* physical presence already asserted */
> + return 0;
> +
> + rc = build_and_send_cmd(0, TPM_ORD_PhysicalPresence,
> + PhysicalPresence_CMD_ENABLE,
> + sizeof(PhysicalPresence_CMD_ENABLE),
> + NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg,
> + "Return code from TSC_PhysicalPresence(CMD_ENABLE) = 0x%08x\n",
> + returnCode);
> +
> + if (rc || returnCode) {
> + if (verbose)
> + printf("Error: Could not enable physical presence.\n\n");
> + goto err_exit;
> + }
> +
> + rc = build_and_send_cmd(0, TPM_ORD_PhysicalPresence,
> + PhysicalPresence_PRESENT,
> + sizeof(PhysicalPresence_PRESENT),
> + NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg,
> + "Return code from TSC_PhysicalPresence(PRESENT) = 0x%08x\n",
> + returnCode);
> +
> + if (rc || returnCode) {
> + if (verbose)
> + printf("Error: Could not set presence flag.\n\n");
> + 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;
> +}
> +
> +
> +static u32
> +read_permanent_flags(char *buf, int buf_len)
> +{
> + u32 rc;
> + u32 returnCode;
> + struct tpm_res_getcap_perm_flags pf;
> +
> + memset(buf, 0x0, buf_len);
> +
> + rc = build_and_send_cmd(0, TPM_ORD_GetCapability,
> + GetCapability_Permanent_Flags,
> + sizeof(GetCapability_Permanent_Flags),
> + (u8 *)&pf,
> + sizeof(struct tpm_res_getcap_perm_flags),
> + &returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability() "
> + "= 0x%08x\n", returnCode);
> +
> + if (rc || returnCode)
> + goto err_exit;
> +
> + memcpy(buf, &pf.perm_flags, buf_len);
> +
> + 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;
> +}
> +
> +
> +static u32
> +read_has_owner(u8 *has_owner)
> +{
> + u32 rc;
> + u32 returnCode;
> + struct tpm_res_getcap_ownerauth oauth;
> +
> + rc = build_and_send_cmd(0, TPM_ORD_GetCapability,
> + GetCapability_OwnerAuth,
> + sizeof(GetCapability_OwnerAuth),
> + (u8 *)&oauth,
> + sizeof(struct tpm_res_getcap_ownerauth),
> + &returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability() "
> + "= 0x%08x\n", returnCode);
> +
> + if (rc || returnCode)
> + goto err_exit;
> +
> + *has_owner = oauth.flag;
> +
> + 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;
> +}
> +
> +
> +static u32
> +disable_tpm(int disable, u32 *returnCode, int verbose)
> +{
> + u32 rc;
> + struct tpm_permanent_flags pf;
> +
> + rc = read_permanent_flags((char *)&pf, sizeof(pf));
> + if (rc)
> + return rc;
> +
> + if (!!pf.flags[PERM_FLAG_IDX_DISABLE] == !!disable) {
> + if (verbose)
> + printf("TPM is already %s.\n,",
> + disable ? "disabled" : "enabled");
> + return 0;
> + }
> +
> + rc = assert_physical_presence(verbose);
> + if (rc) {
> + dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
> + return rc;
> + }
> +
> + rc = build_and_send_cmd(0, disable ? TPM_ORD_PhysicalDisable
> + : TPM_ORD_PhysicalEnable,
> + NULL, 0, NULL, 10, returnCode,
> + TPM_DURATION_TYPE_SHORT);
> + dprintf(DEBUG_tcg, "Return code from TPM_Physical%sable = 0x%08x\n",
> + disable ? "Dis" : "En", *returnCode);
> +
> + if (rc || *returnCode)
> + goto err_exit;
> +
> +
> + return 0;
> +
> +err_exit:
> + dprintf(DEBUG_tcg, "TCGBIOS: %sabling the TPM failed.\n",
> + disable ? "Dis" : "En");
> + dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
> +
> + tpm_state.tpm_working = 0;
> + if (rc)
> + return rc;
> + return TCG_TCG_COMMAND_ERROR;
> +}
> +
> +
> +static u32
> +deactivate_tpm(int deactivate, int allow_reset, u32 *returnCode, int verbose)
> +{
> + u32 rc;
> + struct tpm_permanent_flags pf;
> +
> + rc = read_permanent_flags((char *)&pf, sizeof(pf));
> + if (rc)
> + return rc;
> +
> + if (!!pf.flags[PERM_FLAG_IDX_DEACTIVATED] == !!deactivate) {
> + if (verbose)
> + printf("TPM is already %s.\n",
> + deactivate ? "deactivated" : "activated");
> + return 0;
> + }
> +
> + if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
> + if (verbose)
> + printf("TPM must first be enabled.\n");
> + return 0;
> + }
> +
> + rc = assert_physical_presence(verbose);
> + if (rc) {
> + dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
> + return rc;
> + }
> +
> + rc = build_and_send_cmd(0, TPM_ORD_PhysicalSetDeactivated,
> + deactivate ? CommandFlag_TRUE
> + : CommandFlag_FALSE,
> + deactivate ? sizeof(CommandFlag_TRUE)
> + : sizeof(CommandFlag_FALSE),
> + NULL, 10, returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg,
> + "Return code from PhysicalSetDeactivated(%d) = 0x%08x\n",
> + deactivate ? 1 : 0, *returnCode);
> +
> + if (rc || *returnCode)
> + goto err_exit;
> +
> + if (!deactivate && allow_reset) {
> + if (verbose) {
> + printf("Requiring a reboot to activate the TPM.\n");
> +
> + msleep(2000);
> + }
> + extern void reset_vector(void) __noreturn;
> + reset_vector();
> + }
> +
> + 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;
> +}
> +
> +
> +static u32
> +enable_activate(int allow_reset, u32 *returnCode, int verbose)
> +{
> + u32 rc;
> +
> + rc = disable_tpm(0, returnCode, verbose);
> + if (rc)
> + return rc;
> +
> + rc = deactivate_tpm(0, allow_reset, returnCode, verbose);
> +
> + return rc;
> +}
> +
> +
> +static u32
> +force_clear(int enable_activate_before, int enable_activate_after,
> + u32 *returnCode, int verbose)
> +{
> + u32 rc;
> + u8 has_owner;
> +
> + rc = read_has_owner(&has_owner);
> + if (rc)
> + return rc;
> + if (!has_owner) {
> + if (verbose)
> + printf("TPM does not have an owner.\n");
> + return 0;
> + }
> +
> + if (enable_activate_before) {
> + rc = enable_activate(0, returnCode, verbose);
> + if (rc) {
> + dprintf(DEBUG_tcg,
> + "TCGBIOS: Enabling/activating the TPM failed.\n");
> + return rc;
> + }
> + }
> +
> + rc = assert_physical_presence(verbose);
> + if (rc) {
> + dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
> + return rc;
> + }
> +
> + rc = build_and_send_cmd(0, TPM_ORD_ForceClear,
> + NULL, 0, NULL, 10, returnCode,
> + TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg, "Return code from TPM_ForceClear() = 0x%08x\n",
> + *returnCode);
> +
> + if (rc || *returnCode)
> + goto err_exit;
> +
> + if (!enable_activate_after) {
> + if (verbose)
> + printf("Owner successfully cleared.\n"
> + "You will need to enable/activate the TPM again.\n\n");
> + return 0;
> + }
> +
> + enable_activate(1, returnCode, verbose);
> +
> + 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;
> +}
> +
> +
> +static u32
> +set_owner_install(int allow, u32 *returnCode, int verbose)
> +{
> + u32 rc;
> + u8 has_owner;
> + struct tpm_permanent_flags pf;
> +
> + rc = read_has_owner(&has_owner);
> + if (rc)
> + return rc;
> + if (has_owner) {
> + if (verbose)
> + printf("Must first remove owner.\n");
> + return 0;
> + }
> +
> + rc = read_permanent_flags((char *)&pf, sizeof(pf));
> + if (rc)
> + return rc;
> +
> + if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
> + if (verbose)
> + printf("TPM must first be enable.\n");
> + return 0;
> + }
> +
> + rc = assert_physical_presence(verbose);
> + if (rc) {
> + dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
> + return rc;
> + }
> +
> + rc = build_and_send_cmd(0, TPM_ORD_SetOwnerInstall,
> + (allow) ? CommandFlag_TRUE :
> + CommandFlag_FALSE,
> + sizeof(CommandFlag_TRUE),
> + NULL, 10, returnCode, TPM_DURATION_TYPE_SHORT);
> +
> + dprintf(DEBUG_tcg, "Return code from TPM_SetOwnerInstall() = 0x%08x\n",
> + *returnCode);
> +
> + if (rc || *returnCode)
> + goto err_exit;
> +
> + if (verbose)
> + printf("Installation of owner %s.\n", allow ? "enabled" : "disabled");
> +
> + 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;
> +}
> +
> +
> +static u32
> +tpm_process_cfg(const tpm_bios_cfg_t *cfg, int verbose,
> + u32 *returnCode, u8 *next_step)
> +{
> + u32 rc = 0;
> +
> + switch (cfg->op) {
> + case 0: /* no-op */
> + break;
> +
> + case 1:
> + rc = disable_tpm(0, returnCode, verbose);
> + break;
> +
> + case 2:
> + rc = disable_tpm(1, returnCode, verbose);
> + break;
> +
> + case 3:
> + rc = deactivate_tpm(0, 1, returnCode, verbose);
> + break;
> +
> + case 4:
> + rc = deactivate_tpm(1, 1, returnCode, verbose);
> + break;
> +
> + case 5:
> + rc = force_clear(1, 0, returnCode, verbose);
> + break;
> +
> + case 6:
> + rc = enable_activate(1, returnCode, verbose);
> + break;
> +
> + case 7:
> + rc = deactivate_tpm(1, 1, returnCode, verbose);
> + if (!rc)
> + rc = disable_tpm(1, returnCode, verbose);
> + break;
> +
> + case 8:
> + rc = set_owner_install(1, returnCode, verbose);
> + break;
> +
> + case 9:
> + rc = set_owner_install(0, returnCode, verbose);
> + break;
> +
> + case 10:
> + *next_step = 8;
> + rc = enable_activate(1, returnCode, verbose);
> + /* no reboot happened */
> + if (!rc)
> + rc = set_owner_install(1, returnCode, verbose);
> + break;
> +
> + case 11:
> + rc = set_owner_install(0, returnCode, verbose);
> + if (!rc)
> + rc = deactivate_tpm(1, 0, returnCode, verbose);
> + if (!rc)
> + rc = disable_tpm(1, returnCode, verbose);
> + break;
> +
> + case 14:
> + rc = force_clear(0, 0, returnCode, verbose);
> + if (!rc)
> + rc = enable_activate(1, returnCode, verbose);
> + break;
> +
> + case 21:
> + *next_step = 5;
> + rc = enable_activate(1, returnCode, verbose);
> + /* no reboot happened */
> + if (!rc)
> + rc = force_clear(0, 0, returnCode, verbose);
> + break;
> +
> + case 22:
> + *next_step = 14;
> + rc = enable_activate(1, returnCode, verbose);
> + /* no reboot happened */
> + if (!rc)
> + rc = force_clear(0, 0, returnCode, verbose);
> + *next_step = 0;
> + if (!rc)
> + rc = enable_activate(1, returnCode, verbose);
> + break;
> +
> + default:
> + break;
> + }
> +
> + if (rc)
> + printf("Op %d: An error occurred: 0x%x\n", cfg->op, rc);
> +
> + /* no reboot, no next step */
> + *next_step = 0;
> +
> + return rc;
> +}
>
> u32
> tpm_add_bootdevice_ipl(u32 bootcd, u32 bootdrv,
> @@ -1484,3 +2010,47 @@ err_exit:
> return rc;
> return TCG_TCG_COMMAND_ERROR;
> }
> +
> +void
> +tpm_ppi_init(void)
> +{
> + if (runningOnQEMU()) {
> + struct tpm_ppi *tp = (void *)(TPM_TIS_BASE_ADDRESS + TIS_REG_RAM);
> +
> + if (tp->sign1 != TCG_MAGIC || tp->sign2 != TCG_MAGIC) {
> + memset(tp, 0x0, sizeof(*tp));
> + tp->sign1 = TCG_MAGIC;
> + tp->sign2 = TCG_MAGIC;
> + /* set number of bytes that ACPI can read/write */
> + tp->size = sizeof(tp->opcode) + sizeof(tp->failure) +
> + sizeof(tp->recent_opcode) + sizeof(tp->response);
> + }
> + }
> +}
> +
> +void
> +tpm_ppi_process(void)
> +{
> + tpm_bios_cfg_t cfg;
> +
> + if (runningOnQEMU()) {
> + struct tpm_ppi *tp = (void *)(TPM_TIS_BASE_ADDRESS + TIS_REG_RAM);
> +
> + if (tp->sign1 == TCG_MAGIC && tp->sign2 == TCG_MAGIC) {
> + cfg.op = tp->opcode;
> + dprintf(DEBUG_tcg, "TCGBIOS: PPI opcode found: 0x%08x\n", tp->opcode);
> + if (!cfg.op) {
> + /* intermediate step after a reboot? */
> + cfg.op = tp->next_step;
> + } else {
> + /* last full opcode */
> + tp->recent_opcode = cfg.op;
> + }
> + if (cfg.op) {
> + printf("Processing TPM PPI opcode %d\n", cfg.op);
> + tp->failure = (tpm_process_cfg(&cfg, 0, &tp->response,
> + &tp->next_step) != 0);
> + }
> + }
> + }
> +}
> diff --git a/src/tcgbios.h b/src/tcgbios.h
> index 7cf4364..9811827 100644
> --- a/src/tcgbios.h
> +++ b/src/tcgbios.h
> @@ -328,6 +328,36 @@ struct tpm_res_getcap_perm_flags {
> } PACKED;
>
>
> +struct tpm_req_getcap_stclear_flags {
> + TPM_REQ_HEADER
> + u32 capArea;
> + u32 subCapSize;
> + u32 subCap;
> +} PACKED;
> +
> +
> +struct tpm_stclear_flags {
> + u16 tag;
> + u8 flags[5];
> +} PACKED;
> +
> +
> +enum stclearFlagsIndex {
> + STCLEAR_FLAG_IDX_DEACTIVATED = 0,
> + STCLEAR_FLAG_IDX_DISABLE_FORCE_CLEAR,
> + STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE,
> + STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE_LOCK,
> + STCLEAR_FLAG_IDX_GLOBAL_LOCK,
> +};
> +
> +
> +struct tpm_res_getcap_stclear_flags {
> + TPM_RSP_HEADER
> + u32 size;
> + struct tpm_stclear_flags stclear_flags;
> +} PACKED;
> +
> +
> struct tpm_res_getcap_ownerauth {
> TPM_RSP_HEADER
> u32 size;
> @@ -378,6 +408,23 @@ enum ipltype {
> IPL_EL_TORITO_2
> };
>
> +/*
> + * physical presence interface
> + */
> +
> +struct tpm_ppi {
> + u32 sign1;
> + u16 size; // number of subsequent bytes for ACPI to access
> + u8 opcode; // set by ACPI
> + u8 failure; // set by BIOS (0 = success)
> + u8 recent_opcode; // set by BIOS
> + u32 response; // set by BIOS
> + u8 next_step; // BIOS only
> + u32 sign2;
> +} PACKED;
> +
> +void tpm_ppi_init(void);
> +void tpm_ppi_process(void);
>
> struct bregs;
> void tpm_interrupt_handler32(struct bregs *regs);
More information about the SeaBIOS
mailing list