mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 03:44:53 +00:00 
			
		
		
		
	 773c1f1e94
			
		
	
	
		773c1f1e94
		
	
	
	
	
		
			
			Commit 6e8a3ff6ed ("docs/specs/tpm: reST-ify TPM documentation")
converted docs/specs/tpm.txt to docs/specs/tpm.rst.
We still have several references to the old file, so let's fix them
with the following command:
  sed -i s/tpm.txt/tpm.rst/ $(git grep -l docs/specs/tpm.txt)
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20210517151702.109066-5-sgarzare@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
		
	
			
		
			
				
	
	
		
			460 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			460 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Support for generating ACPI TPM tables
 | |
|  *
 | |
|  * Copyright (C) 2018 IBM, Corp.
 | |
|  * Copyright (C) 2018 Red Hat Inc
 | |
|  *
 | |
|  * 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 "qemu/osdep.h"
 | |
| #include "qapi/error.h"
 | |
| #include "hw/acpi/tpm.h"
 | |
| 
 | |
| void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev)
 | |
| {
 | |
|     Aml *method, *field, *ifctx, *ifctx2, *ifctx3, *func_mask,
 | |
|         *not_implemented, *pak, *tpm2, *tpm3, *pprm, *pprq, *zero, *one;
 | |
| 
 | |
|     if (!object_property_get_bool(OBJECT(tpm), "ppi", &error_abort)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     zero = aml_int(0);
 | |
|     one = aml_int(1);
 | |
|     func_mask = aml_int(TPM_PPI_FUNC_MASK);
 | |
|     not_implemented = aml_int(TPM_PPI_FUNC_NOT_IMPLEMENTED);
 | |
| 
 | |
|     /*
 | |
|      * TPP2 is for the registers that ACPI code used to pass
 | |
|      * the PPI code and parameter (PPRQ, PPRM) to the firmware.
 | |
|      */
 | |
|     aml_append(dev,
 | |
|                aml_operation_region("TPP2", AML_SYSTEM_MEMORY,
 | |
|                                     aml_int(TPM_PPI_ADDR_BASE + 0x100),
 | |
|                                     0x5A));
 | |
|     field = aml_field("TPP2", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
 | |
|     aml_append(field, aml_named_field("PPIN", 8));
 | |
|     aml_append(field, aml_named_field("PPIP", 32));
 | |
|     aml_append(field, aml_named_field("PPRP", 32));
 | |
|     aml_append(field, aml_named_field("PPRQ", 32));
 | |
|     aml_append(field, aml_named_field("PPRM", 32));
 | |
|     aml_append(field, aml_named_field("LPPR", 32));
 | |
|     aml_append(dev, field);
 | |
|     pprq = aml_name("PPRQ");
 | |
|     pprm = aml_name("PPRM");
 | |
| 
 | |
|     aml_append(dev,
 | |
|                aml_operation_region(
 | |
|                    "TPP3", AML_SYSTEM_MEMORY,
 | |
|                    aml_int(TPM_PPI_ADDR_BASE +
 | |
|                            0x15a /* movv, docs/specs/tpm.rst */),
 | |
|                            0x1));
 | |
|     field = aml_field("TPP3", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
 | |
|     aml_append(field, aml_named_field("MOVV", 8));
 | |
|     aml_append(dev, field);
 | |
| 
 | |
|     /*
 | |
|      * DerefOf in Windows is broken with SYSTEM_MEMORY.  Use a dynamic
 | |
|      * operation region inside of a method for getting FUNC[op].
 | |
|      */
 | |
|     method = aml_method("TPFN", 1, AML_SERIALIZED);
 | |
|     {
 | |
|         Aml *op = aml_arg(0);
 | |
|         ifctx = aml_if(aml_lgreater_equal(op, aml_int(0x100)));
 | |
|         {
 | |
|             aml_append(ifctx, aml_return(zero));
 | |
|         }
 | |
|         aml_append(method, ifctx);
 | |
| 
 | |
|         aml_append(method,
 | |
|             aml_operation_region("TPP1", AML_SYSTEM_MEMORY,
 | |
|                 aml_add(aml_int(TPM_PPI_ADDR_BASE), op, NULL), 0x1));
 | |
|         field = aml_field("TPP1", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
 | |
|         aml_append(field, aml_named_field("TPPF", 8));
 | |
|         aml_append(method, field);
 | |
|         aml_append(method, aml_return(aml_name("TPPF")));
 | |
|     }
 | |
|     aml_append(dev, method);
 | |
| 
 | |
|     /*
 | |
|      * Use global TPM2 & TPM3 variables to workaround Windows ACPI bug
 | |
|      * when returning packages.
 | |
|      */
 | |
|     pak = aml_package(2);
 | |
|     aml_append(pak, zero);
 | |
|     aml_append(pak, zero);
 | |
|     aml_append(dev, aml_name_decl("TPM2", pak));
 | |
|     tpm2 = aml_name("TPM2");
 | |
| 
 | |
|     pak = aml_package(3);
 | |
|     aml_append(pak, zero);
 | |
|     aml_append(pak, zero);
 | |
|     aml_append(pak, zero);
 | |
|     aml_append(dev, aml_name_decl("TPM3", pak));
 | |
|     tpm3 = aml_name("TPM3");
 | |
| 
 | |
|     method = aml_method("_DSM", 4, AML_SERIALIZED);
 | |
|     {
 | |
|         uint8_t zerobyte[1] = { 0 };
 | |
|         Aml *function, *arguments, *rev, *op, *op_arg, *op_flags, *uuid;
 | |
| 
 | |
|         uuid = aml_arg(0);
 | |
|         rev = aml_arg(1);
 | |
|         function = aml_arg(2);
 | |
|         arguments = aml_arg(3);
 | |
|         op = aml_local(0);
 | |
|         op_flags = aml_local(1);
 | |
| 
 | |
|         /* Physical Presence Interface */
 | |
|         ifctx = aml_if(
 | |
|             aml_equal(uuid,
 | |
|                       aml_touuid("3DDDFAA6-361B-4EB4-A424-8D10089D1653")));
 | |
|         {
 | |
|             /* standard DSM query function */
 | |
|             ifctx2 = aml_if(aml_equal(function, zero));
 | |
|             {
 | |
|                 uint8_t byte_list[2] = { 0xff, 0x01 }; /* functions 1-8 */
 | |
| 
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_return(aml_buffer(sizeof(byte_list),
 | |
|                                                  byte_list)));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.0: 2.1.1 Get Physical Presence Interface Version
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 1
 | |
|              * Arg 3 (Package): Arguments = Empty Package
 | |
|              * Returns: Type: String
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, one));
 | |
|             {
 | |
|                 aml_append(ifctx2, aml_return(aml_string("1.3")));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.0: 2.1.3 Submit TPM Operation Request to Pre-OS Environment
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 2
 | |
|              * Arg 3 (Package): Arguments = Package: Type: Integer
 | |
|              *                              Operation Value of the Request
 | |
|              * Returns: Type: Integer
 | |
|              *          0: Success
 | |
|              *          1: Operation Value of the Request Not Supported
 | |
|              *          2: General Failure
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(2)));
 | |
|             {
 | |
|                 /* get opcode */
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_store(aml_derefof(aml_index(arguments,
 | |
|                                                            zero)), op));
 | |
| 
 | |
|                 /* get opcode flags */
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_store(aml_call1("TPFN", op), op_flags));
 | |
| 
 | |
|                 /* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
 | |
|                 ifctx3 = aml_if(
 | |
|                     aml_equal(
 | |
|                         aml_and(op_flags, func_mask, NULL),
 | |
|                         not_implemented));
 | |
|                 {
 | |
|                     /* 1: Operation Value of the Request Not Supported */
 | |
|                     aml_append(ifctx3, aml_return(one));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
| 
 | |
|                 aml_append(ifctx2, aml_store(op, pprq));
 | |
|                 aml_append(ifctx2, aml_store(zero, pprm));
 | |
|                 /* 0: success */
 | |
|                 aml_append(ifctx2, aml_return(zero));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.0: 2.1.4 Get Pending TPM Operation Requested By the OS
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 3
 | |
|              * Arg 3 (Package): Arguments = Empty Package
 | |
|              * Returns: Type: Package of Integers
 | |
|              *          Integer 1: Function Return code
 | |
|              *                     0: Success
 | |
|              *                     1: General Failure
 | |
|              *          Integer 2: Pending operation requested by the OS
 | |
|              *                     0: None
 | |
|              *                    >0: Operation Value of the Pending Request
 | |
|              *          Integer 3: Optional argument to pending operation
 | |
|              *                     requested by the OS
 | |
|              *                     0: None
 | |
|              *                    >0: Argument Value of the Pending Request
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(3)));
 | |
|             {
 | |
|                 /*
 | |
|                  * Revision ID of 1, no integer parameter beyond
 | |
|                  * parameter two are expected
 | |
|                  */
 | |
|                 ifctx3 = aml_if(aml_equal(rev, one));
 | |
|                 {
 | |
|                     /* TPM2[1] = PPRQ */
 | |
|                     aml_append(ifctx3,
 | |
|                                aml_store(pprq, aml_index(tpm2, one)));
 | |
|                     aml_append(ifctx3, aml_return(tpm2));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
| 
 | |
|                 /*
 | |
|                  * A return value of {0, 23, 1} indicates that
 | |
|                  * operation 23 with argument 1 is pending.
 | |
|                  */
 | |
|                 ifctx3 = aml_if(aml_equal(rev, aml_int(2)));
 | |
|                 {
 | |
|                     /* TPM3[1] = PPRQ */
 | |
|                     aml_append(ifctx3,
 | |
|                                aml_store(pprq, aml_index(tpm3, one)));
 | |
|                     /* TPM3[2] = PPRM */
 | |
|                     aml_append(ifctx3,
 | |
|                                aml_store(pprm, aml_index(tpm3, aml_int(2))));
 | |
|                     aml_append(ifctx3, aml_return(tpm3));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.0: 2.1.5 Get Platform-Specific Action to Transition to
 | |
|              *     Pre-OS Environment
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 4
 | |
|              * Arg 3 (Package): Arguments = Empty Package
 | |
|              * Returns: Type: Integer
 | |
|              *          0: None
 | |
|              *          1: Shutdown
 | |
|              *          2: Reboot
 | |
|              *          3: OS Vendor-specific
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(4)));
 | |
|             {
 | |
|                 /* reboot */
 | |
|                 aml_append(ifctx2, aml_return(aml_int(2)));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.0: 2.1.6 Return TPM Operation Response to OS Environment
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 5
 | |
|              * Arg 3 (Package): Arguments = Empty Package
 | |
|              * Returns: Type: Package of Integer
 | |
|              *          Integer 1: Function Return code
 | |
|              *                     0: Success
 | |
|              *                     1: General Failure
 | |
|              *          Integer 2: Most recent operation request
 | |
|              *                     0: None
 | |
|              *                    >0: Operation Value of the most recent request
 | |
|              *          Integer 3: Response to the most recent operation request
 | |
|              *                     0: Success
 | |
|              *                     0x00000001..0x00000FFF: Corresponding TPM
 | |
|              *                                             error code
 | |
|              *                     0xFFFFFFF0: User Abort or timeout of dialog
 | |
|              *                     0xFFFFFFF1: firmware Failure
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(5)));
 | |
|             {
 | |
|                 /* TPM3[1] = LPPR */
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_store(aml_name("LPPR"),
 | |
|                                      aml_index(tpm3, one)));
 | |
|                 /* TPM3[2] = PPRP */
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_store(aml_name("PPRP"),
 | |
|                                      aml_index(tpm3, aml_int(2))));
 | |
|                 aml_append(ifctx2, aml_return(tpm3));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.0: 2.1.7 Submit preferred user language
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 6
 | |
|              * Arg 3 (Package): Arguments = String Package
 | |
|              *                  Preferred language code
 | |
|              * Returns: Type: Integer
 | |
|              * Function Return Code
 | |
|              *          3: Not implemented
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(6)));
 | |
|             {
 | |
|                 /* 3 = not implemented */
 | |
|                 aml_append(ifctx2, aml_return(aml_int(3)));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.1: 2.1.7 Submit TPM Operation Request to
 | |
|              *     Pre-OS Environment 2
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 7
 | |
|              * Arg 3 (Package): Arguments = Package: Type: Integer
 | |
|              *                  Integer 1: Operation Value of the Request
 | |
|              *                  Integer 2: Argument for Operation (optional)
 | |
|              * Returns: Type: Integer
 | |
|              *          0: Success
 | |
|              *          1: Not Implemented
 | |
|              *          2: General Failure
 | |
|              *          3: Operation blocked by current firmware settings
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(7)));
 | |
|             {
 | |
|                 /* get opcode */
 | |
|                 aml_append(ifctx2, aml_store(aml_derefof(aml_index(arguments,
 | |
|                                                                    zero)),
 | |
|                                              op));
 | |
| 
 | |
|                 /* get opcode flags */
 | |
|                 aml_append(ifctx2, aml_store(aml_call1("TPFN", op),
 | |
|                                              op_flags));
 | |
|                 /* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
 | |
|                 ifctx3 = aml_if(
 | |
|                     aml_equal(
 | |
|                         aml_and(op_flags, func_mask, NULL),
 | |
|                         not_implemented));
 | |
|                 {
 | |
|                     /* 1: not implemented */
 | |
|                     aml_append(ifctx3, aml_return(one));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
| 
 | |
|                 /* if func[opcode] & TPM_PPI_FUNC_BLOCKED */
 | |
|                 ifctx3 = aml_if(
 | |
|                     aml_equal(
 | |
|                         aml_and(op_flags, func_mask, NULL),
 | |
|                         aml_int(TPM_PPI_FUNC_BLOCKED)));
 | |
|                 {
 | |
|                     /* 3: blocked by firmware */
 | |
|                     aml_append(ifctx3, aml_return(aml_int(3)));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
| 
 | |
|                 /* revision to integer */
 | |
|                 ifctx3 = aml_if(aml_equal(rev, one));
 | |
|                 {
 | |
|                     /* revision 1 */
 | |
|                     /* PPRQ = op */
 | |
|                     aml_append(ifctx3, aml_store(op, pprq));
 | |
|                     /* no argument, PPRM = 0 */
 | |
|                     aml_append(ifctx3, aml_store(zero, pprm));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
| 
 | |
|                 ifctx3 = aml_if(aml_equal(rev, aml_int(2)));
 | |
|                 {
 | |
|                     /* revision 2 */
 | |
|                     /* PPRQ = op */
 | |
|                     op_arg = aml_derefof(aml_index(arguments, one));
 | |
|                     aml_append(ifctx3, aml_store(op, pprq));
 | |
|                     /* PPRM = arg3[1] */
 | |
|                     aml_append(ifctx3, aml_store(op_arg, pprm));
 | |
|                 }
 | |
|                 aml_append(ifctx2, ifctx3);
 | |
|                 /* 0: success */
 | |
|                 aml_append(ifctx2, aml_return(zero));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * PPI 1.1: 2.1.8 Get User Confirmation Status for Operation
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 8
 | |
|              * Arg 3 (Package): Arguments = Package: Type: Integer
 | |
|              *                  Operation Value that may need user confirmation
 | |
|              * Returns: Type: Integer
 | |
|              *          0: Not implemented
 | |
|              *          1: Firmware only
 | |
|              *          2: Blocked for OS by firmware configuration
 | |
|              *          3: Allowed and physically present user required
 | |
|              *          4: Allowed and physically present user not required
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, aml_int(8)));
 | |
|             {
 | |
|                 /* get opcode */
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_store(aml_derefof(aml_index(arguments,
 | |
|                                                            zero)),
 | |
|                                      op));
 | |
| 
 | |
|                 /* get opcode flags */
 | |
|                 aml_append(ifctx2, aml_store(aml_call1("TPFN", op),
 | |
|                                              op_flags));
 | |
|                 /* return confirmation status code */
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_return(
 | |
|                                aml_and(op_flags, func_mask, NULL)));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             aml_append(ifctx, aml_return(aml_buffer(1, zerobyte)));
 | |
|         }
 | |
|         aml_append(method, ifctx);
 | |
| 
 | |
|         /*
 | |
|          * "TCG Platform Reset Attack Mitigation Specification 1.00",
 | |
|          * Chapter 6 "ACPI _DSM Function"
 | |
|          */
 | |
|         ifctx = aml_if(
 | |
|             aml_equal(uuid,
 | |
|                       aml_touuid("376054ED-CC13-4675-901C-4756D7F2D45D")));
 | |
|         {
 | |
|             /* standard DSM query function */
 | |
|             ifctx2 = aml_if(aml_equal(function, zero));
 | |
|             {
 | |
|                 uint8_t byte_list[1] = { 0x03 }; /* functions 1-2 supported */
 | |
| 
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_return(aml_buffer(sizeof(byte_list),
 | |
|                                                  byte_list)));
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
| 
 | |
|             /*
 | |
|              * TCG Platform Reset Attack Mitigation Specification 1.0 Ch.6
 | |
|              *
 | |
|              * Arg 2 (Integer): Function Index = 1
 | |
|              * Arg 3 (Package): Arguments = Package: Type: Integer
 | |
|              *                  Operation Value of the Request
 | |
|              * Returns: Type: Integer
 | |
|              *          0: Success
 | |
|              *          1: General Failure
 | |
|              */
 | |
|             ifctx2 = aml_if(aml_equal(function, one));
 | |
|             {
 | |
|                 aml_append(ifctx2,
 | |
|                            aml_store(aml_derefof(aml_index(arguments, zero)),
 | |
|                                      op));
 | |
|                 {
 | |
|                     aml_append(ifctx2, aml_store(op, aml_name("MOVV")));
 | |
| 
 | |
|                     /* 0: success */
 | |
|                     aml_append(ifctx2, aml_return(zero));
 | |
|                 }
 | |
|             }
 | |
|             aml_append(ifctx, ifctx2);
 | |
|         }
 | |
|         aml_append(method, ifctx);
 | |
|     }
 | |
|     aml_append(dev, method);
 | |
| }
 |