Skip to content

Commit

Permalink
Add ACPI tables for TPM
Browse files Browse the repository at this point in the history
Add an SSDT ACPI table for the TPM device.
Add a TCPA table for BIOS logging area when a TPM is being used.

The latter follows this spec here:

http://www.trustedcomputinggroup.org/files/static_page_files/DCD4188E-1A4B-B294-D050A155FB6F7385/TCG_ACPIGeneralSpecification_PublicReview.pdf

This patch has Michael Tsirkin's patches folded in.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
stefanberger authored and mstsirkin committed Aug 24, 2014
1 parent 927766c commit 711b20b
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 8 deletions.
3 changes: 2 additions & 1 deletion hw/i386/Makefile.objs
Expand Up @@ -10,7 +10,8 @@ obj-y += bios-linker-loader.o
hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex
hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex \
hw/i386/ssdt-tpm.hex

iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
Expand Down
45 changes: 45 additions & 0 deletions hw/i386/acpi-build.c
Expand Up @@ -40,6 +40,8 @@
#include "hw/loader.h"
#include "hw/isa/isa.h"
#include "hw/acpi/memory_hotplug.h"
#include "sysemu/tpm.h"
#include "hw/acpi/tpm.h"

/* Supported chipsets: */
#include "hw/acpi/piix4.h"
Expand Down Expand Up @@ -88,6 +90,7 @@ typedef struct AcpiPmInfo {

typedef struct AcpiMiscInfo {
bool has_hpet;
bool has_tpm;
DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
const unsigned char *dsdt_code;
unsigned dsdt_size;
Expand Down Expand Up @@ -210,6 +213,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
static void acpi_get_misc_info(AcpiMiscInfo *info)
{
info->has_hpet = hpet_find();
info->has_tpm = tpm_find();
info->pvpanic_port = pvpanic_port();
}

Expand Down Expand Up @@ -698,6 +702,7 @@ static inline char acpi_get_hex(uint32_t val)

#include "hw/i386/ssdt-misc.hex"
#include "hw/i386/ssdt-pcihp.hex"
#include "hw/i386/ssdt-tpm.hex"

static void
build_append_notify_method(GArray *device, const char *name,
Expand Down Expand Up @@ -1201,6 +1206,39 @@ build_hpet(GArray *table_data, GArray *linker)
(void *)hpet, "HPET", sizeof(*hpet), 1);
}

static void
build_tpm_tcpa(GArray *table_data, GArray *linker)
{
Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
/* the log area will come right after the TCPA table */
uint64_t log_area_start_address = acpi_data_len(table_data);

tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
tcpa->log_area_start_address = cpu_to_le64(log_area_start_address);

/* log area start address to be filled by Guest linker */
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_FILE,
table_data, &tcpa->log_area_start_address,
sizeof(tcpa->log_area_start_address));

build_header(linker, table_data,
(void *)tcpa, "TCPA", sizeof(*tcpa), 2);

/* now only get the log area and with that modify table_data */
acpi_data_push(table_data, TPM_LOG_AREA_MINIMUM_SIZE);
}

static void
build_tpm_ssdt(GArray *table_data, GArray *linker)
{
void *tpm_ptr;

tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm_aml));
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
}

typedef enum {
MEM_AFFINITY_NOFLAGS = 0,
MEM_AFFINITY_ENABLED = (1 << 0),
Expand Down Expand Up @@ -1531,6 +1569,13 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables->table_data);
build_hpet(tables->table_data, tables->linker);
}
if (misc.has_tpm) {
acpi_add_table(table_offsets, tables->table_data);
build_tpm_tcpa(tables->table_data, tables->linker);

acpi_add_table(table_offsets, tables->table_data);
build_tpm_ssdt(tables->table_data, tables->linker);
}
if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables->table_data);
build_srat(tables->table_data, tables->linker, &cpu, guest_info);
Expand Down
11 changes: 11 additions & 0 deletions hw/i386/acpi-defs.h
Expand Up @@ -314,4 +314,15 @@ struct AcpiTableMcfg {
} QEMU_PACKED;
typedef struct AcpiTableMcfg AcpiTableMcfg;

/*
* TCPA Description Table
*/
struct Acpi20Tcpa {
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint16_t platform_class;
uint32_t log_area_minimum_length;
uint64_t log_area_start_address;
} QEMU_PACKED;
typedef struct Acpi20Tcpa Acpi20Tcpa;

#endif
43 changes: 43 additions & 0 deletions hw/i386/ssdt-tpm.dsl
@@ -0,0 +1,43 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw/acpi/tpm.h"

ACPI_EXTRACT_ALL_CODE ssdt_tpm_aml

DefinitionBlock (
"ssdt-tpm.aml", // Output Filename
"SSDT", // Signature
0x01, // SSDT Compliance Revision
"BXPC", // OEMID
"BXSSDT", // TABLE ID
0x1 // OEM Revision
)
{
Scope(\_SB) {
/* TPM with emulated TPM TIS interface */
Device (TPM) {
Name (_HID, EisaID ("PNP0C31"))
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
// older Linux tpm_tis drivers do not work with IRQ
//IRQNoFlags () {TPM_TIS_IRQ}
})
Method (_STA, 0, NotSerialized) {
Return (0x0F)
}
}
}
}
8 changes: 1 addition & 7 deletions hw/tpm/tpm_tis.h
Expand Up @@ -18,23 +18,17 @@
#define TPM_TPM_TIS_H

#include "hw/isa/isa.h"
#include "hw/acpi/tpm.h"
#include "qemu-common.h"

#define TPM_TIS_ADDR_BASE 0xFED40000

#define TPM_TIS_NUM_LOCALITIES 5 /* per spec */
#define TPM_TIS_LOCALITY_SHIFT 12
#define TPM_TIS_NO_LOCALITY 0xff

#define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES)

#define TPM_TIS_IRQ 5

#define TPM_TIS_BUFFER_MAX 4096

#define TYPE_TPM_TIS "tpm-tis"


typedef enum {
TPM_TIS_STATE_IDLE = 0,
TPM_TIS_STATE_READY,
Expand Down
29 changes: 29 additions & 0 deletions include/hw/acpi/tpm.h
@@ -0,0 +1,29 @@
/*
* tpm.h - TPM ACPI definitions
*
* Copyright (C) 2014 IBM Corporation
*
* Authors:
* Stefan Berger <stefanb@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
* Implementation of the TIS interface according to specs found at
* http://www.trustedcomputinggroup.org
*
*/
#ifndef HW_ACPI_TPM_H
#define HW_ACPI_TPM_H

#define TPM_TIS_ADDR_BASE 0xFED40000
#define TPM_TIS_ADDR_SIZE 0x5000

#define TPM_TIS_IRQ 5

#define TPM_LOG_AREA_MINIMUM_SIZE (64 * 1024)

#define TPM_TCPA_ACPI_CLASS_CLIENT 0
#define TPM_TCPA_ACPI_CLASS_SERVER 1

#endif /* HW_ACPI_TPM_H */
7 changes: 7 additions & 0 deletions include/sysemu/tpm.h
Expand Up @@ -20,4 +20,11 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
int tpm_init(void);
void tpm_cleanup(void);

#define TYPE_TPM_TIS "tpm-tis"

static inline bool tpm_find(void)
{
return object_resolve_path_type("", TYPE_TPM_TIS, NULL);
}

#endif /* QEMU_TPM_H */

0 comments on commit 711b20b

Please sign in to comment.