Add ACPI tables for TPM
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>
This commit is contained in:
		
							parent
							
								
									927766c7d3
								
							
						
					
					
						commit
						711b20b479
					
				| @ -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 ;) | ||||
|  | ||||
| @ -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" | ||||
| @ -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; | ||||
| @ -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(); | ||||
| } | ||||
| 
 | ||||
| @ -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, | ||||
| @ -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), | ||||
| @ -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); | ||||
|  | ||||
| @ -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
									
								
								hw/i386/ssdt-tpm.dsl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								hw/i386/ssdt-tpm.dsl
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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, | ||||
|  | ||||
							
								
								
									
										29
									
								
								include/hw/acpi/tpm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								include/hw/acpi/tpm.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 */ | ||||
| @ -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 */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Stefan Berger
						Stefan Berger