| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  |  * tpm_tis_common.c - QEMU's TPM TIS interface emulator | 
					
						
							|  |  |  |  * device agnostic functions | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2006,2010-2013 IBM Corporation | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Authors: | 
					
						
							|  |  |  |  *  Stefan Berger <stefanb@us.ibm.com> | 
					
						
							|  |  |  |  *  David Safford <safford@us.ibm.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. This implementation currently
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:20 -05:00
										 |  |  |  * supports version 1.3, 21 March 2013 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |  * In the developers menu choose the PC Client section then find the TIS | 
					
						
							|  |  |  |  * specification. | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * TPM TIS for TPM 2 implementation following TCG PC Client Platform | 
					
						
							|  |  |  |  * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-01-26 18:17:30 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:42 +02:00
										 |  |  | #include "hw/irq.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:59 +02:00
										 |  |  | #include "hw/isa/isa.h"
 | 
					
						
							| 
									
										
											  
											
												include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef.  Since then, we've moved to include qemu/osdep.h
everywhere.  Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h.  That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h.  Include qapi/error.h in .c files that need it and don't
get it now.  Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly.  Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h.  Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third.  Unfortunately, the number depending on
qapi-types.h shrinks only a little.  More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
											
										 
											2016-03-14 09:01:28 +01:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 16:35:07 +02:00
										 |  |  | #include "qemu/module.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:59 +02:00
										 |  |  | #include "hw/acpi/tpm.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:13 +01:00
										 |  |  | #include "hw/pci/pci_ids.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:51 +02:00
										 |  |  | #include "hw/qdev-properties.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:45 +02:00
										 |  |  | #include "migration/vmstate.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:13 +01:00
										 |  |  | #include "sysemu/tpm_backend.h"
 | 
					
						
							| 
									
										
										
										
											2020-06-12 10:54:43 +02:00
										 |  |  | #include "sysemu/tpm_util.h"
 | 
					
						
							| 
									
										
										
										
											2019-01-15 02:27:50 +04:00
										 |  |  | #include "tpm_ppi.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  | #include "trace.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | #include "tpm_tis.h"
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 14:49:10 -04:00
										 |  |  | #define DEBUG_TIS 0
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  | /* local prototypes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, | 
					
						
							|  |  |  |                                   unsigned size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | /* utility functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint8_t tpm_tis_locality_from_addr(hwaddr addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Set the given flags in the STS register by clearing the register but | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |  * preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting | 
					
						
							|  |  |  |  * the new flags. | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The SELFTEST_DONE flag is acquired from the backend that determines it by | 
					
						
							|  |  |  |  * peeking into TPM commands. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * A VM suspend/resume will preserve the flag by storing it into the VM | 
					
						
							|  |  |  |  * device state, but the backend will not remember it when QEMU is started | 
					
						
							|  |  |  |  * again. Therefore, we cache the flag here. Once set, it will not be unset | 
					
						
							|  |  |  |  * except by a reset. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |     l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |     l->sts |= flags; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Send a request to the TPM. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-12 10:54:40 +02:00
										 |  |  |     tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |      * rw_offset serves as length indicator for length of data; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |      * it's reset when the response comes back | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->loc[locty].state = TPM_TIS_STATE_EXECUTION; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:55 +02:00
										 |  |  |     s->cmd = (TPMBackendCmd) { | 
					
						
							|  |  |  |         .locty = locty, | 
					
						
							| 
									
										
										
										
											2017-11-09 20:12:39 -05:00
										 |  |  |         .in = s->buffer, | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |         .in_len = s->rw_offset, | 
					
						
							| 
									
										
										
										
											2017-11-09 20:12:39 -05:00
										 |  |  |         .out = s->buffer, | 
					
						
							| 
									
										
										
										
											2017-11-09 19:30:05 -05:00
										 |  |  |         .out_len = s->be_buffer_size, | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:55 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tpm_backend_deliver_request(s->be_driver, &s->cmd); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* raise an interrupt if allowed */ | 
					
						
							|  |  |  | static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!TPM_TIS_IS_VALID_LOCTY(locty)) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     if ((s->loc[locty].inte & TPM_TIS_INT_ENABLED) && | 
					
						
							|  |  |  |         (s->loc[locty].inte & irqmask)) { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |         trace_tpm_tis_raise_irq(irqmask); | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         qemu_irq_raise(s->irq); | 
					
						
							|  |  |  |         s->loc[locty].ints |= irqmask; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint8_t l; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { | 
					
						
							|  |  |  |         if (l == locty) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if ((s->loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     bool change = (s->active_locty != new_active_locty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     bool is_seize; | 
					
						
							|  |  |  |     uint8_t mask; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     if (change && TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) && | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                    s->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (is_seize) { | 
					
						
							|  |  |  |             mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY| | 
					
						
							|  |  |  |                      TPM_TIS_ACCESS_REQUEST_USE); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* reset flags on the old active locality */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         s->loc[s->active_locty].access &= mask; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (is_seize) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             s->loc[s->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->active_locty = new_active_locty; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     trace_tpm_tis_new_active_locality(s->active_locty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) { | 
					
						
							|  |  |  |         /* set flags on the new active locality */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         s->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY; | 
					
						
							|  |  |  |         s->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE | | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                                                TPM_TIS_ACCESS_SEIZE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (change) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         tpm_tis_raise_irq(s, s->active_locty, TPM_TIS_INT_LOCALITY_CHANGED); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* abort -- this function switches the locality */ | 
					
						
							| 
									
										
										
										
											2018-11-20 13:06:19 -05:00
										 |  |  | static void tpm_tis_abort(TPMState *s) | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |     s->rw_offset = 0; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     trace_tpm_tis_abort(s->next_locty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Need to react differently depending on who's aborting now and | 
					
						
							|  |  |  |      * which locality will become active afterwards. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     if (s->aborting_locty == s->next_locty) { | 
					
						
							|  |  |  |         s->loc[s->aborting_locty].state = TPM_TIS_STATE_READY; | 
					
						
							|  |  |  |         tpm_tis_sts_set(&s->loc[s->aborting_locty], | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |                         TPM_TIS_STS_COMMAND_READY); | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         tpm_tis_raise_irq(s, s->aborting_locty, TPM_TIS_INT_COMMAND_READY); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* locality after abort is another one than the current one */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     tpm_tis_new_active_locality(s, s->next_locty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->next_locty = TPM_TIS_NO_LOCALITY; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     /* nobody's aborting a command anymore */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->aborting_locty = TPM_TIS_NO_LOCALITY; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* prepare aborting current command */ | 
					
						
							|  |  |  | static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint8_t busy_locty; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 13:14:51 -05:00
										 |  |  |     assert(TPM_TIS_IS_VALID_LOCTY(newlocty)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->next_locty = newlocty;  /* locality after successful abort */ | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * only abort a command using an interrupt if currently executing | 
					
						
							|  |  |  |      * a command AND if there's a valid connection to the vTPM. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             /*
 | 
					
						
							|  |  |  |              * request the backend to cancel. Some backends may not | 
					
						
							|  |  |  |              * support it | 
					
						
							|  |  |  |              */ | 
					
						
							| 
									
										
										
										
											2013-03-28 07:26:21 -04:00
										 |  |  |             tpm_backend_cancel_cmd(s->be_driver); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 13:06:19 -05:00
										 |  |  |     tpm_tis_abort(s); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:02 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Callback from the TPM to indicate that the response was received. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | void tpm_tis_request_completed(TPMState *s, int ret) | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:55 +02:00
										 |  |  |     uint8_t locty = s->cmd.locty; | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:02 +01:00
										 |  |  |     uint8_t l; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 09:54:39 -05:00
										 |  |  |     assert(TPM_TIS_IS_VALID_LOCTY(locty)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:02 +01:00
										 |  |  |     if (s->cmd.selftest_done) { | 
					
						
							|  |  |  |         for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { | 
					
						
							| 
									
										
										
										
											2018-11-06 10:51:44 +05:30
										 |  |  |             s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE; | 
					
						
							| 
									
										
										
										
											2017-11-06 19:39:02 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 19:33:06 +01:00
										 |  |  |     /* FIXME: report error if ret != 0 */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     tpm_tis_sts_set(&s->loc[locty], | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |                     TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->loc[locty].state = TPM_TIS_STATE_COMPLETION; | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |     s->rw_offset = 0; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 10:54:40 +02:00
										 |  |  |     tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); | 
					
						
							| 
									
										
										
										
											2017-10-11 15:46:14 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { | 
					
						
							| 
									
										
										
										
											2018-11-20 13:06:19 -05:00
										 |  |  |         tpm_tis_abort(s); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tpm_tis_raise_irq(s, locty, | 
					
						
							|  |  |  |                       TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Read a byte of response data | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t ret = TPM_TIS_NO_DATA_BYTE; | 
					
						
							|  |  |  |     uint16_t len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:12:39 -05:00
										 |  |  |         len = MIN(tpm_cmd_get_size(&s->buffer), | 
					
						
							| 
									
										
										
										
											2017-11-09 19:30:05 -05:00
										 |  |  |                   s->be_buffer_size); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |         ret = s->buffer[s->rw_offset++]; | 
					
						
							|  |  |  |         if (s->rw_offset >= len) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             /* got last byte */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |         trace_tpm_tis_data_read(ret, s->rw_offset - 1); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  | #ifdef DEBUG_TIS
 | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:41 +01:00
										 |  |  | static void tpm_tis_dump_state(TPMState *s, hwaddr addr) | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     static const unsigned regs[] = { | 
					
						
							|  |  |  |         TPM_TIS_REG_ACCESS, | 
					
						
							|  |  |  |         TPM_TIS_REG_INT_ENABLE, | 
					
						
							|  |  |  |         TPM_TIS_REG_INT_VECTOR, | 
					
						
							|  |  |  |         TPM_TIS_REG_INT_STATUS, | 
					
						
							|  |  |  |         TPM_TIS_REG_INTF_CAPABILITY, | 
					
						
							|  |  |  |         TPM_TIS_REG_STS, | 
					
						
							|  |  |  |         TPM_TIS_REG_DID_VID, | 
					
						
							|  |  |  |         TPM_TIS_REG_RID, | 
					
						
							|  |  |  |         0xfff}; | 
					
						
							|  |  |  |     int idx; | 
					
						
							|  |  |  |     uint8_t locty = tpm_tis_locality_from_addr(addr); | 
					
						
							|  |  |  |     hwaddr base = addr & ~0xfff; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     printf("tpm_tis: active locality      : %d\n" | 
					
						
							|  |  |  |            "tpm_tis: state of locality %d : %d\n" | 
					
						
							|  |  |  |            "tpm_tis: register dump:\n", | 
					
						
							|  |  |  |            s->active_locty, | 
					
						
							|  |  |  |            locty, s->loc[locty].state); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (idx = 0; regs[idx] != 0xfff; idx++) { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |         printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:41 +01:00
										 |  |  |                (int)tpm_tis_mmio_read(s, base + regs[idx], 4)); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     printf("tpm_tis: r/w offset    : %d\n" | 
					
						
							|  |  |  |            "tpm_tis: result buffer : ", | 
					
						
							|  |  |  |            s->rw_offset); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  |     for (idx = 0; | 
					
						
							| 
									
										
										
										
											2017-11-09 20:12:39 -05:00
										 |  |  |          idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  |          idx++) { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |         printf("%c%02x%s", | 
					
						
							|  |  |  |                s->rw_offset == idx ? '>' : ' ', | 
					
						
							|  |  |  |                s->buffer[idx], | 
					
						
							|  |  |  |                ((idx & 0xf) == 0xf) ? "\ntpm_tis:                 " : ""); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     printf("\n"); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Read a register of the TIS interface | 
					
						
							|  |  |  |  * See specs pages 33-63 for description of the registers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, | 
					
						
							|  |  |  |                                   unsigned size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TPMState *s = opaque; | 
					
						
							|  |  |  |     uint16_t offset = addr & 0xffc; | 
					
						
							|  |  |  |     uint8_t shift = (addr & 0x3) * 8; | 
					
						
							|  |  |  |     uint32_t val = 0xffffffff; | 
					
						
							|  |  |  |     uint8_t locty = tpm_tis_locality_from_addr(addr); | 
					
						
							|  |  |  |     uint32_t avail; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |     uint8_t v; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-28 07:26:21 -04:00
										 |  |  |     if (tpm_backend_had_startup_error(s->be_driver)) { | 
					
						
							| 
									
										
										
										
											2017-11-10 22:33:14 -05:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (offset) { | 
					
						
							|  |  |  |     case TPM_TIS_REG_ACCESS: | 
					
						
							|  |  |  |         /* never show the SEIZE flag even though we use it internally */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         val = s->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         /* the pending flag is always calculated */ | 
					
						
							|  |  |  |         if (tpm_tis_check_request_use_except(s, locty)) { | 
					
						
							|  |  |  |             val |= TPM_TIS_ACCESS_PENDING_REQUEST; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-03-28 07:26:21 -04:00
										 |  |  |         val |= !tpm_backend_get_tpm_established_flag(s->be_driver); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INT_ENABLE: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         val = s->loc[locty].inte; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INT_VECTOR: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         val = s->irq_num; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INT_STATUS: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         val = s->loc[locty].ints; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INTF_CAPABILITY: | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |         switch (s->be_tpm_version) { | 
					
						
							|  |  |  |         case TPM_VERSION_UNSPEC: | 
					
						
							|  |  |  |             val = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case TPM_VERSION_1_2: | 
					
						
							|  |  |  |             val = TPM_TIS_CAPABILITIES_SUPPORTED1_3; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case TPM_VERSION_2_0: | 
					
						
							|  |  |  |             val = TPM_TIS_CAPABILITIES_SUPPORTED2_0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_STS: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->active_locty == locty) { | 
					
						
							|  |  |  |             if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 val = TPM_TIS_BURST_COUNT( | 
					
						
							| 
									
										
										
										
											2017-11-09 20:12:39 -05:00
										 |  |  |                        MIN(tpm_cmd_get_size(&s->buffer), | 
					
						
							| 
									
										
										
										
											2017-11-09 19:30:05 -05:00
										 |  |  |                            s->be_buffer_size) | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                        - s->rw_offset) | s->loc[locty].sts; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                 avail = s->be_buffer_size - s->rw_offset; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 /*
 | 
					
						
							|  |  |  |                  * byte-sized reads should not return 0x00 for 0x100 | 
					
						
							|  |  |  |                  * available bytes. | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |                 if (size == 1 && avail > 0xff) { | 
					
						
							|  |  |  |                     avail = 0xff; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 val = TPM_TIS_BURST_COUNT(avail) | s->loc[locty].sts; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_DATA_FIFO: | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:18 -05:00
										 |  |  |     case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->active_locty == locty) { | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |             if (size > 4 - (addr & 0x3)) { | 
					
						
							|  |  |  |                 /* prevent access beyond FIFO */ | 
					
						
							|  |  |  |                 size = 4 - (addr & 0x3); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             val = 0; | 
					
						
							|  |  |  |             shift = 0; | 
					
						
							|  |  |  |             while (size > 0) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 switch (s->loc[locty].state) { | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |                 case TPM_TIS_STATE_COMPLETION: | 
					
						
							|  |  |  |                     v = tpm_tis_data_read(s, locty); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     v = TPM_TIS_NO_DATA_BYTE; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 val |= (v << shift); | 
					
						
							|  |  |  |                 shift += 8; | 
					
						
							|  |  |  |                 size--; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |             shift = 0; /* no more adjustments */ | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |     case TPM_TIS_REG_INTERFACE_ID: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         val = s->loc[locty].iface_id; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     case TPM_TIS_REG_DID_VID: | 
					
						
							|  |  |  |         val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_RID: | 
					
						
							|  |  |  |         val = TPM_TIS_TPM_RID; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  | #ifdef DEBUG_TIS
 | 
					
						
							|  |  |  |     case TPM_TIS_REG_DEBUG: | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:41 +01:00
										 |  |  |         tpm_tis_dump_state(s, addr); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:51 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (shift) { | 
					
						
							|  |  |  |         val >>= shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     trace_tpm_tis_mmio_read(size, addr, val); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Write a value to a register of the TIS interface | 
					
						
							|  |  |  |  * See specs pages 33-63 for description of the registers | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:42 +02:00
										 |  |  | static void tpm_tis_mmio_write(void *opaque, hwaddr addr, | 
					
						
							|  |  |  |                                uint64_t val, unsigned size) | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     TPMState *s = opaque; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |     uint16_t off = addr & 0xffc; | 
					
						
							|  |  |  |     uint8_t shift = (addr & 0x3) * 8; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     uint8_t locty = tpm_tis_locality_from_addr(addr); | 
					
						
							|  |  |  |     uint8_t active_locty, l; | 
					
						
							|  |  |  |     int c, set_new_locty = 1; | 
					
						
							|  |  |  |     uint16_t len; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |     uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |     trace_tpm_tis_mmio_write(size, addr, val); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:42 +02:00
										 |  |  |     if (locty == 4) { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |         trace_tpm_tis_mmio_write_locty4(); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-28 07:26:21 -04:00
										 |  |  |     if (tpm_backend_had_startup_error(s->be_driver)) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |     val &= mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (shift) { | 
					
						
							|  |  |  |         val <<= shift; | 
					
						
							|  |  |  |         mask <<= shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mask ^= 0xffffffff; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     switch (off) { | 
					
						
							|  |  |  |     case TPM_TIS_REG_ACCESS: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((val & TPM_TIS_ACCESS_SEIZE)) { | 
					
						
							|  |  |  |             val &= ~(TPM_TIS_ACCESS_REQUEST_USE | | 
					
						
							|  |  |  |                      TPM_TIS_ACCESS_ACTIVE_LOCALITY); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         active_locty = s->active_locty; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) { | 
					
						
							|  |  |  |             /* give up locality if currently owned */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             if (s->active_locty == locty) { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |                 trace_tpm_tis_mmio_write_release_locty(locty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 uint8_t newlocty = TPM_TIS_NO_LOCALITY; | 
					
						
							|  |  |  |                 /* anybody wants the locality ? */ | 
					
						
							|  |  |  |                 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                     if ((s->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |                         trace_tpm_tis_mmio_write_locty_req_use(c); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                         newlocty = c; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |                 trace_tpm_tis_mmio_write_next_locty(newlocty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) { | 
					
						
							|  |  |  |                     set_new_locty = 0; | 
					
						
							|  |  |  |                     tpm_tis_prep_abort(s, locty, newlocty); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     active_locty = TPM_TIS_NO_LOCALITY; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 /* not currently the owner; clear a pending request */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 s->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             s->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((val & TPM_TIS_ACCESS_SEIZE)) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * allow seize if a locality is active and the requesting | 
					
						
							|  |  |  |              * locality is higher than the one that's active | 
					
						
							|  |  |  |              * OR | 
					
						
							|  |  |  |              * allow seize for requesting locality if no locality is | 
					
						
							|  |  |  |              * active | 
					
						
							|  |  |  |              */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) && | 
					
						
							|  |  |  |                     locty > s->active_locty) || | 
					
						
							|  |  |  |                     !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { | 
					
						
							| 
									
										
										
										
											2019-03-23 17:26:37 +03:00
										 |  |  |                 bool higher_seize = false; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 /* already a pending SEIZE ? */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 /* check for ongoing seize by a higher locality */ | 
					
						
							|  |  |  |                 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                     if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { | 
					
						
							| 
									
										
										
										
											2019-03-23 17:26:37 +03:00
										 |  |  |                         higher_seize = true; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (higher_seize) { | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 /* cancel any seize by a lower locality */ | 
					
						
							| 
									
										
										
										
											2019-02-15 13:35:17 +00:00
										 |  |  |                 for (l = 0; l < locty; l++) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                     s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 s->loc[locty].access |= TPM_TIS_ACCESS_SEIZE; | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 trace_tpm_tis_mmio_write_locty_seized(locty, s->active_locty); | 
					
						
							|  |  |  |                 trace_tpm_tis_mmio_write_init_abort(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 set_new_locty = 0; | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 tpm_tis_prep_abort(s, s->active_locty, locty); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((val & TPM_TIS_ACCESS_REQUEST_USE)) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             if (s->active_locty != locty) { | 
					
						
							|  |  |  |                 if (TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { | 
					
						
							|  |  |  |                     s->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 } else { | 
					
						
							|  |  |  |                     /* no locality active -> make this one active now */ | 
					
						
							|  |  |  |                     active_locty = locty; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (set_new_locty) { | 
					
						
							|  |  |  |             tpm_tis_new_active_locality(s, active_locty); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INT_ENABLE: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->active_locty != locty) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         s->loc[locty].inte &= mask; | 
					
						
							|  |  |  |         s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |                                         TPM_TIS_INT_POLARITY_MASK | | 
					
						
							|  |  |  |                                         TPM_TIS_INTERRUPTS_SUPPORTED)); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INT_VECTOR: | 
					
						
							|  |  |  |         /* hard wired -- ignore */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_INT_STATUS: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->active_locty != locty) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* clearing of interrupt flags */ | 
					
						
							|  |  |  |         if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { | 
					
						
							|  |  |  |             s->loc[locty].ints &= ~val; | 
					
						
							|  |  |  |             if (s->loc[locty].ints == 0) { | 
					
						
							|  |  |  |                 qemu_irq_lower(s->irq); | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |                 trace_tpm_tis_mmio_write_lowering_irq(); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         s->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_STS: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->active_locty != locty) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |         if (s->be_tpm_version == TPM_VERSION_2_0) { | 
					
						
							|  |  |  |             /* some flags that are only supported for TPM 2 */ | 
					
						
							|  |  |  |             if (val & TPM_TIS_STS_COMMAND_CANCEL) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 if (s->loc[locty].state == TPM_TIS_STATE_EXECUTION) { | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |                     /*
 | 
					
						
							|  |  |  |                      * request the backend to cancel. Some backends may not | 
					
						
							|  |  |  |                      * support it | 
					
						
							|  |  |  |                      */ | 
					
						
							|  |  |  |                     tpm_backend_cancel_cmd(s->be_driver); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) { | 
					
						
							|  |  |  |                 if (locty == 3 || locty == 4) { | 
					
						
							|  |  |  |                     tpm_backend_reset_tpm_established_flag(s->be_driver, locty); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | | 
					
						
							|  |  |  |                 TPM_TIS_STS_RESPONSE_RETRY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (val == TPM_TIS_STS_COMMAND_READY) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             switch (s->loc[locty].state) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             case TPM_TIS_STATE_READY: | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                 s->rw_offset = 0; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case TPM_TIS_STATE_IDLE: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_COMMAND_READY); | 
					
						
							|  |  |  |                 s->loc[locty].state = TPM_TIS_STATE_READY; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case TPM_TIS_STATE_EXECUTION: | 
					
						
							|  |  |  |             case TPM_TIS_STATE_RECEPTION: | 
					
						
							|  |  |  |                 /* abort currently running command */ | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |                 trace_tpm_tis_mmio_write_init_abort(); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 tpm_tis_prep_abort(s, locty, locty); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case TPM_TIS_STATE_COMPLETION: | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                 s->rw_offset = 0; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 /* shortcut to ready state with C/R set */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 s->loc[locty].state = TPM_TIS_STATE_READY; | 
					
						
							|  |  |  |                 if (!(s->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { | 
					
						
							|  |  |  |                     tpm_tis_sts_set(&s->loc[locty], | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |                                     TPM_TIS_STS_COMMAND_READY); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                     tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 s->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (val == TPM_TIS_STS_TPM_GO) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             switch (s->loc[locty].state) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             case TPM_TIS_STATE_RECEPTION: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 if ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                     tpm_tis_tpm_send(s, locty); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 /* ignore */ | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (val == TPM_TIS_STS_RESPONSE_RETRY) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             switch (s->loc[locty].state) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             case TPM_TIS_STATE_COMPLETION: | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                 s->rw_offset = 0; | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 tpm_tis_sts_set(&s->loc[locty], | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |                                 TPM_TIS_STS_VALID| | 
					
						
							|  |  |  |                                 TPM_TIS_STS_DATA_AVAILABLE); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 /* ignore */ | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TPM_TIS_REG_DATA_FIFO: | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:18 -05:00
										 |  |  |     case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |         /* data fifo */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->active_locty != locty) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         if (s->loc[locty].state == TPM_TIS_STATE_IDLE || | 
					
						
							|  |  |  |             s->loc[locty].state == TPM_TIS_STATE_EXECUTION || | 
					
						
							|  |  |  |             s->loc[locty].state == TPM_TIS_STATE_COMPLETION) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             /* drop the byte */ | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2018-03-02 21:30:38 -05:00
										 |  |  |             trace_tpm_tis_mmio_write_data2send(val, size); | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             if (s->loc[locty].state == TPM_TIS_STATE_READY) { | 
					
						
							|  |  |  |                 s->loc[locty].state = TPM_TIS_STATE_RECEPTION; | 
					
						
							|  |  |  |                 tpm_tis_sts_set(&s->loc[locty], | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |                                 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |             val >>= shift; | 
					
						
							|  |  |  |             if (size > 4 - (addr & 0x3)) { | 
					
						
							|  |  |  |                 /* prevent access beyond FIFO */ | 
					
						
							|  |  |  |                 size = 4 - (addr & 0x3); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                 if (s->rw_offset < s->be_buffer_size) { | 
					
						
							|  |  |  |                     s->buffer[s->rw_offset++] = | 
					
						
							| 
									
										
										
										
											2017-11-09 19:30:05 -05:00
										 |  |  |                         (uint8_t)val; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:17 -05:00
										 |  |  |                     val >>= 8; | 
					
						
							|  |  |  |                     size--; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                     tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* check for complete packet */ | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |             if (s->rw_offset > 5 && | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 (s->loc[locty].sts & TPM_TIS_STS_EXPECT)) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 /* we have a packet length - see if we have all of it */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID); | 
					
						
							| 
									
										
										
										
											2017-10-10 00:55:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:12:39 -05:00
										 |  |  |                 len = tpm_cmd_get_size(&s->buffer); | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |                 if (len > s->rw_offset) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                     tpm_tis_sts_set(&s->loc[locty], | 
					
						
							| 
									
										
										
										
											2015-02-23 09:27:19 -05:00
										 |  |  |                                     TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 } else { | 
					
						
							|  |  |  |                     /* packet complete */ | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                     tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-04-15 10:18:55 -04:00
										 |  |  |                 if (need_irq) { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |                     tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |     case TPM_TIS_REG_INTERFACE_ID: | 
					
						
							|  |  |  |         if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) { | 
					
						
							|  |  |  |             for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |                 s->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | const MemoryRegionOps tpm_tis_memory_ops = { | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     .read = tpm_tis_mmio_read, | 
					
						
							|  |  |  |     .write = tpm_tis_mmio_write, | 
					
						
							|  |  |  |     .endianness = DEVICE_LITTLE_ENDIAN, | 
					
						
							|  |  |  |     .valid = { | 
					
						
							|  |  |  |         .min_access_size = 1, | 
					
						
							|  |  |  |         .max_access_size = 4, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:07 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Get the TPMVersion of the backend device being used | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | enum TPMVersion tpm_tis_get_tpm_version(TPMState *s) | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:07 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-10 22:07:35 -05:00
										 |  |  |     if (tpm_backend_had_startup_error(s->be_driver)) { | 
					
						
							|  |  |  |         return TPM_VERSION_UNSPEC; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:07 -04:00
										 |  |  |     return tpm_backend_get_tpm_version(s->be_driver); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This function is called when the machine starts, resets or due to | 
					
						
							|  |  |  |  * S3 resume. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | void tpm_tis_reset(TPMState *s) | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     int c; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |     s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); | 
					
						
							| 
									
										
										
										
											2017-11-09 19:24:02 -05:00
										 |  |  |     s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver), | 
					
						
							|  |  |  |                             TPM_TIS_BUFFER_MAX); | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 02:27:54 +04:00
										 |  |  |     if (s->ppi_enabled) { | 
					
						
							|  |  |  |         tpm_ppi_reset(&s->ppi); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-03-28 07:26:21 -04:00
										 |  |  |     tpm_backend_reset(s->be_driver); | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |     s->active_locty = TPM_TIS_NO_LOCALITY; | 
					
						
							|  |  |  |     s->next_locty = TPM_TIS_NO_LOCALITY; | 
					
						
							|  |  |  |     s->aborting_locty = TPM_TIS_NO_LOCALITY; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         s->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |         switch (s->be_tpm_version) { | 
					
						
							|  |  |  |         case TPM_VERSION_UNSPEC: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case TPM_VERSION_1_2: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2; | 
					
						
							|  |  |  |             s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |             break; | 
					
						
							|  |  |  |         case TPM_VERSION_2_0: | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |             s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0; | 
					
						
							|  |  |  |             s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0; | 
					
						
							| 
									
										
										
										
											2015-05-26 16:51:05 -04:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-10 00:56:00 +02:00
										 |  |  |         s->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; | 
					
						
							|  |  |  |         s->loc[c].ints = 0; | 
					
						
							|  |  |  |         s->loc[c].state = TPM_TIS_STATE_IDLE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 07:45:33 -05:00
										 |  |  |         s->rw_offset = 0; | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 06:29:39 -04:00
										 |  |  |     if (tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size) < 0) { | 
					
						
							|  |  |  |         exit(1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-02-27 12:47:50 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-11 10:36:53 -04:00
										 |  |  | /* persistent state handling */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | int tpm_tis_pre_save(TPMState *s) | 
					
						
							| 
									
										
										
										
											2017-10-11 10:36:53 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     uint8_t locty = s->active_locty; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_tpm_tis_pre_save(locty, s->rw_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (DEBUG_TIS) { | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:41 +01:00
										 |  |  |         tpm_tis_dump_state(s, 0); | 
					
						
							| 
									
										
										
										
											2017-10-11 10:36:53 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Synchronize with backend completion. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     tpm_backend_finish_sync(s->be_driver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 17:51:42 +01:00
										 |  |  | const VMStateDescription vmstate_locty = { | 
					
						
							| 
									
										
										
										
											2017-10-11 10:36:53 -04:00
										 |  |  |     .name = "tpm-tis/locty", | 
					
						
							|  |  |  |     .version_id = 0, | 
					
						
							|  |  |  |     .fields      = (VMStateField[]) { | 
					
						
							|  |  |  |         VMSTATE_UINT32(state, TPMLocality), | 
					
						
							|  |  |  |         VMSTATE_UINT32(inte, TPMLocality), | 
					
						
							|  |  |  |         VMSTATE_UINT32(ints, TPMLocality), | 
					
						
							|  |  |  |         VMSTATE_UINT8(access, TPMLocality), | 
					
						
							|  |  |  |         VMSTATE_UINT32(sts, TPMLocality), | 
					
						
							|  |  |  |         VMSTATE_UINT32(iface_id, TPMLocality), | 
					
						
							|  |  |  |         VMSTATE_END_OF_LIST(), | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 |