1 /* Support for generating ACPI TPM tables
3 * Copyright (C) 2018 IBM, Corp.
4 * Copyright (C) 2018 Red Hat Inc
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "qapi/error.h"
21 #include "hw/acpi/tpm.h"
23 void tpm_build_ppi_acpi(TPMIf
*tpm
, Aml
*dev
)
25 Aml
*method
, *field
, *ifctx
, *ifctx2
, *ifctx3
, *func_mask
,
26 *not_implemented
, *pak
, *tpm2
, *tpm3
, *pprm
, *pprq
, *zero
, *one
;
28 if (!object_property_get_bool(OBJECT(tpm
), "ppi", &error_abort
)) {
34 func_mask
= aml_int(TPM_PPI_FUNC_MASK
);
35 not_implemented
= aml_int(TPM_PPI_FUNC_NOT_IMPLEMENTED
);
38 * TPP2 is for the registers that ACPI code used to pass
39 * the PPI code and parameter (PPRQ, PPRM) to the firmware.
42 aml_operation_region("TPP2", AML_SYSTEM_MEMORY
,
43 aml_int(TPM_PPI_ADDR_BASE
+ 0x100),
45 field
= aml_field("TPP2", AML_ANY_ACC
, AML_NOLOCK
, AML_PRESERVE
);
46 aml_append(field
, aml_named_field("PPIN", 8));
47 aml_append(field
, aml_named_field("PPIP", 32));
48 aml_append(field
, aml_named_field("PPRP", 32));
49 aml_append(field
, aml_named_field("PPRQ", 32));
50 aml_append(field
, aml_named_field("PPRM", 32));
51 aml_append(field
, aml_named_field("LPPR", 32));
52 aml_append(dev
, field
);
53 pprq
= aml_name("PPRQ");
54 pprm
= aml_name("PPRM");
58 "TPP3", AML_SYSTEM_MEMORY
,
59 aml_int(TPM_PPI_ADDR_BASE
+
60 0x15a /* movv, docs/specs/tpm.rst */),
62 field
= aml_field("TPP3", AML_BYTE_ACC
, AML_NOLOCK
, AML_PRESERVE
);
63 aml_append(field
, aml_named_field("MOVV", 8));
64 aml_append(dev
, field
);
67 * DerefOf in Windows is broken with SYSTEM_MEMORY. Use a dynamic
68 * operation region inside of a method for getting FUNC[op].
70 method
= aml_method("TPFN", 1, AML_SERIALIZED
);
73 ifctx
= aml_if(aml_lgreater_equal(op
, aml_int(0x100)));
75 aml_append(ifctx
, aml_return(zero
));
77 aml_append(method
, ifctx
);
80 aml_operation_region("TPP1", AML_SYSTEM_MEMORY
,
81 aml_add(aml_int(TPM_PPI_ADDR_BASE
), op
, NULL
), 0x1));
82 field
= aml_field("TPP1", AML_BYTE_ACC
, AML_NOLOCK
, AML_PRESERVE
);
83 aml_append(field
, aml_named_field("TPPF", 8));
84 aml_append(method
, field
);
85 aml_append(method
, aml_return(aml_name("TPPF")));
87 aml_append(dev
, method
);
90 * Use global TPM2 & TPM3 variables to workaround Windows ACPI bug
91 * when returning packages.
94 aml_append(pak
, zero
);
95 aml_append(pak
, zero
);
96 aml_append(dev
, aml_name_decl("TPM2", pak
));
97 tpm2
= aml_name("TPM2");
100 aml_append(pak
, zero
);
101 aml_append(pak
, zero
);
102 aml_append(pak
, zero
);
103 aml_append(dev
, aml_name_decl("TPM3", pak
));
104 tpm3
= aml_name("TPM3");
106 method
= aml_method("_DSM", 4, AML_SERIALIZED
);
108 uint8_t zerobyte
[1] = { 0 };
109 Aml
*function
, *arguments
, *rev
, *op
, *op_arg
, *op_flags
, *uuid
;
113 function
= aml_arg(2);
114 arguments
= aml_arg(3);
116 op_flags
= aml_local(1);
118 /* Physical Presence Interface */
121 aml_touuid("3DDDFAA6-361B-4EB4-A424-8D10089D1653")));
123 /* standard DSM query function */
124 ifctx2
= aml_if(aml_equal(function
, zero
));
126 uint8_t byte_list
[2] = { 0xff, 0x01 }; /* functions 1-8 */
129 aml_return(aml_buffer(sizeof(byte_list
),
132 aml_append(ifctx
, ifctx2
);
135 * PPI 1.0: 2.1.1 Get Physical Presence Interface Version
137 * Arg 2 (Integer): Function Index = 1
138 * Arg 3 (Package): Arguments = Empty Package
139 * Returns: Type: String
141 ifctx2
= aml_if(aml_equal(function
, one
));
143 aml_append(ifctx2
, aml_return(aml_string("1.3")));
145 aml_append(ifctx
, ifctx2
);
148 * PPI 1.0: 2.1.3 Submit TPM Operation Request to Pre-OS Environment
150 * Arg 2 (Integer): Function Index = 2
151 * Arg 3 (Package): Arguments = Package: Type: Integer
152 * Operation Value of the Request
153 * Returns: Type: Integer
155 * 1: Operation Value of the Request Not Supported
158 ifctx2
= aml_if(aml_equal(function
, aml_int(2)));
162 aml_store(aml_derefof(aml_index(arguments
,
165 /* get opcode flags */
167 aml_store(aml_call1("TPFN", op
), op_flags
));
169 /* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
172 aml_and(op_flags
, func_mask
, NULL
),
175 /* 1: Operation Value of the Request Not Supported */
176 aml_append(ifctx3
, aml_return(one
));
178 aml_append(ifctx2
, ifctx3
);
180 aml_append(ifctx2
, aml_store(op
, pprq
));
181 aml_append(ifctx2
, aml_store(zero
, pprm
));
183 aml_append(ifctx2
, aml_return(zero
));
185 aml_append(ifctx
, ifctx2
);
188 * PPI 1.0: 2.1.4 Get Pending TPM Operation Requested By the OS
190 * Arg 2 (Integer): Function Index = 3
191 * Arg 3 (Package): Arguments = Empty Package
192 * Returns: Type: Package of Integers
193 * Integer 1: Function Return code
196 * Integer 2: Pending operation requested by the OS
198 * >0: Operation Value of the Pending Request
199 * Integer 3: Optional argument to pending operation
200 * requested by the OS
202 * >0: Argument Value of the Pending Request
204 ifctx2
= aml_if(aml_equal(function
, aml_int(3)));
207 * Revision ID of 1, no integer parameter beyond
208 * parameter two are expected
210 ifctx3
= aml_if(aml_equal(rev
, one
));
214 aml_store(pprq
, aml_index(tpm2
, one
)));
215 aml_append(ifctx3
, aml_return(tpm2
));
217 aml_append(ifctx2
, ifctx3
);
220 * A return value of {0, 23, 1} indicates that
221 * operation 23 with argument 1 is pending.
223 ifctx3
= aml_if(aml_equal(rev
, aml_int(2)));
227 aml_store(pprq
, aml_index(tpm3
, one
)));
230 aml_store(pprm
, aml_index(tpm3
, aml_int(2))));
231 aml_append(ifctx3
, aml_return(tpm3
));
233 aml_append(ifctx2
, ifctx3
);
235 aml_append(ifctx
, ifctx2
);
238 * PPI 1.0: 2.1.5 Get Platform-Specific Action to Transition to
241 * Arg 2 (Integer): Function Index = 4
242 * Arg 3 (Package): Arguments = Empty Package
243 * Returns: Type: Integer
247 * 3: OS Vendor-specific
249 ifctx2
= aml_if(aml_equal(function
, aml_int(4)));
252 aml_append(ifctx2
, aml_return(aml_int(2)));
254 aml_append(ifctx
, ifctx2
);
257 * PPI 1.0: 2.1.6 Return TPM Operation Response to OS Environment
259 * Arg 2 (Integer): Function Index = 5
260 * Arg 3 (Package): Arguments = Empty Package
261 * Returns: Type: Package of Integer
262 * Integer 1: Function Return code
265 * Integer 2: Most recent operation request
267 * >0: Operation Value of the most recent request
268 * Integer 3: Response to the most recent operation request
270 * 0x00000001..0x00000FFF: Corresponding TPM
272 * 0xFFFFFFF0: User Abort or timeout of dialog
273 * 0xFFFFFFF1: firmware Failure
275 ifctx2
= aml_if(aml_equal(function
, aml_int(5)));
279 aml_store(aml_name("LPPR"),
280 aml_index(tpm3
, one
)));
283 aml_store(aml_name("PPRP"),
284 aml_index(tpm3
, aml_int(2))));
285 aml_append(ifctx2
, aml_return(tpm3
));
287 aml_append(ifctx
, ifctx2
);
290 * PPI 1.0: 2.1.7 Submit preferred user language
292 * Arg 2 (Integer): Function Index = 6
293 * Arg 3 (Package): Arguments = String Package
294 * Preferred language code
295 * Returns: Type: Integer
296 * Function Return Code
299 ifctx2
= aml_if(aml_equal(function
, aml_int(6)));
301 /* 3 = not implemented */
302 aml_append(ifctx2
, aml_return(aml_int(3)));
304 aml_append(ifctx
, ifctx2
);
307 * PPI 1.1: 2.1.7 Submit TPM Operation Request to
308 * Pre-OS Environment 2
310 * Arg 2 (Integer): Function Index = 7
311 * Arg 3 (Package): Arguments = Package: Type: Integer
312 * Integer 1: Operation Value of the Request
313 * Integer 2: Argument for Operation (optional)
314 * Returns: Type: Integer
318 * 3: Operation blocked by current firmware settings
320 ifctx2
= aml_if(aml_equal(function
, aml_int(7)));
323 aml_append(ifctx2
, aml_store(aml_derefof(aml_index(arguments
,
327 /* get opcode flags */
328 aml_append(ifctx2
, aml_store(aml_call1("TPFN", op
),
330 /* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
333 aml_and(op_flags
, func_mask
, NULL
),
336 /* 1: not implemented */
337 aml_append(ifctx3
, aml_return(one
));
339 aml_append(ifctx2
, ifctx3
);
341 /* if func[opcode] & TPM_PPI_FUNC_BLOCKED */
344 aml_and(op_flags
, func_mask
, NULL
),
345 aml_int(TPM_PPI_FUNC_BLOCKED
)));
347 /* 3: blocked by firmware */
348 aml_append(ifctx3
, aml_return(aml_int(3)));
350 aml_append(ifctx2
, ifctx3
);
352 /* revision to integer */
353 ifctx3
= aml_if(aml_equal(rev
, one
));
357 aml_append(ifctx3
, aml_store(op
, pprq
));
358 /* no argument, PPRM = 0 */
359 aml_append(ifctx3
, aml_store(zero
, pprm
));
361 aml_append(ifctx2
, ifctx3
);
363 ifctx3
= aml_if(aml_equal(rev
, aml_int(2)));
367 op_arg
= aml_derefof(aml_index(arguments
, one
));
368 aml_append(ifctx3
, aml_store(op
, pprq
));
370 aml_append(ifctx3
, aml_store(op_arg
, pprm
));
372 aml_append(ifctx2
, ifctx3
);
374 aml_append(ifctx2
, aml_return(zero
));
376 aml_append(ifctx
, ifctx2
);
379 * PPI 1.1: 2.1.8 Get User Confirmation Status for Operation
381 * Arg 2 (Integer): Function Index = 8
382 * Arg 3 (Package): Arguments = Package: Type: Integer
383 * Operation Value that may need user confirmation
384 * Returns: Type: Integer
387 * 2: Blocked for OS by firmware configuration
388 * 3: Allowed and physically present user required
389 * 4: Allowed and physically present user not required
391 ifctx2
= aml_if(aml_equal(function
, aml_int(8)));
395 aml_store(aml_derefof(aml_index(arguments
,
399 /* get opcode flags */
400 aml_append(ifctx2
, aml_store(aml_call1("TPFN", op
),
402 /* return confirmation status code */
405 aml_and(op_flags
, func_mask
, NULL
)));
407 aml_append(ifctx
, ifctx2
);
409 aml_append(ifctx
, aml_return(aml_buffer(1, zerobyte
)));
411 aml_append(method
, ifctx
);
414 * "TCG Platform Reset Attack Mitigation Specification 1.00",
415 * Chapter 6 "ACPI _DSM Function"
419 aml_touuid("376054ED-CC13-4675-901C-4756D7F2D45D")));
421 /* standard DSM query function */
422 ifctx2
= aml_if(aml_equal(function
, zero
));
424 uint8_t byte_list
[1] = { 0x03 }; /* functions 1-2 supported */
427 aml_return(aml_buffer(sizeof(byte_list
),
430 aml_append(ifctx
, ifctx2
);
433 * TCG Platform Reset Attack Mitigation Specification 1.0 Ch.6
435 * Arg 2 (Integer): Function Index = 1
436 * Arg 3 (Package): Arguments = Package: Type: Integer
437 * Operation Value of the Request
438 * Returns: Type: Integer
442 ifctx2
= aml_if(aml_equal(function
, one
));
445 aml_store(aml_derefof(aml_index(arguments
, zero
)),
448 aml_append(ifctx2
, aml_store(op
, aml_name("MOVV")));
451 aml_append(ifctx2
, aml_return(zero
));
454 aml_append(ifctx
, ifctx2
);
456 aml_append(method
, ifctx
);
458 aml_append(dev
, method
);