xref: /openbmc/qemu/hw/acpi/tpm.c (revision 8c345b3e6a736d4985b2bca6f7f24b985900de63)
1ac6dd31eSStefan Berger /* Support for generating ACPI TPM tables
2ac6dd31eSStefan Berger  *
3ac6dd31eSStefan Berger  * Copyright (C) 2018 IBM, Corp.
4ac6dd31eSStefan Berger  * Copyright (C) 2018 Red Hat Inc
5ac6dd31eSStefan Berger  *
6ac6dd31eSStefan Berger  * This program is free software; you can redistribute it and/or modify
7ac6dd31eSStefan Berger  * it under the terms of the GNU General Public License as published by
8ac6dd31eSStefan Berger  * the Free Software Foundation; either version 2 of the License, or
9ac6dd31eSStefan Berger  * (at your option) any later version.
10ac6dd31eSStefan Berger 
11ac6dd31eSStefan Berger  * This program is distributed in the hope that it will be useful,
12ac6dd31eSStefan Berger  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ac6dd31eSStefan Berger  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14ac6dd31eSStefan Berger  * GNU General Public License for more details.
15ac6dd31eSStefan Berger 
16ac6dd31eSStefan Berger  * You should have received a copy of the GNU General Public License along
17ac6dd31eSStefan Berger  * with this program; if not, see <http://www.gnu.org/licenses/>.
18ac6dd31eSStefan Berger  */
19ac6dd31eSStefan Berger #include "qemu/osdep.h"
20ac6dd31eSStefan Berger #include "qapi/error.h"
21ac6dd31eSStefan Berger #include "hw/acpi/tpm.h"
22ac6dd31eSStefan Berger 
tpm_build_ppi_acpi(TPMIf * tpm,Aml * dev)23ac6dd31eSStefan Berger void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev)
24ac6dd31eSStefan Berger {
25ac6dd31eSStefan Berger     Aml *method, *field, *ifctx, *ifctx2, *ifctx3, *func_mask,
26ac6dd31eSStefan Berger         *not_implemented, *pak, *tpm2, *tpm3, *pprm, *pprq, *zero, *one;
27ac6dd31eSStefan Berger 
28ac6dd31eSStefan Berger     if (!object_property_get_bool(OBJECT(tpm), "ppi", &error_abort)) {
29ac6dd31eSStefan Berger         return;
30ac6dd31eSStefan Berger     }
31ac6dd31eSStefan Berger 
32ac6dd31eSStefan Berger     zero = aml_int(0);
33ac6dd31eSStefan Berger     one = aml_int(1);
34ac6dd31eSStefan Berger     func_mask = aml_int(TPM_PPI_FUNC_MASK);
35ac6dd31eSStefan Berger     not_implemented = aml_int(TPM_PPI_FUNC_NOT_IMPLEMENTED);
36ac6dd31eSStefan Berger 
37ac6dd31eSStefan Berger     /*
38ac6dd31eSStefan Berger      * TPP2 is for the registers that ACPI code used to pass
39ac6dd31eSStefan Berger      * the PPI code and parameter (PPRQ, PPRM) to the firmware.
40ac6dd31eSStefan Berger      */
41ac6dd31eSStefan Berger     aml_append(dev,
42ac6dd31eSStefan Berger                aml_operation_region("TPP2", AML_SYSTEM_MEMORY,
43ac6dd31eSStefan Berger                                     aml_int(TPM_PPI_ADDR_BASE + 0x100),
44ac6dd31eSStefan Berger                                     0x5A));
45ac6dd31eSStefan Berger     field = aml_field("TPP2", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
46ac6dd31eSStefan Berger     aml_append(field, aml_named_field("PPIN", 8));
47ac6dd31eSStefan Berger     aml_append(field, aml_named_field("PPIP", 32));
48ac6dd31eSStefan Berger     aml_append(field, aml_named_field("PPRP", 32));
49ac6dd31eSStefan Berger     aml_append(field, aml_named_field("PPRQ", 32));
50ac6dd31eSStefan Berger     aml_append(field, aml_named_field("PPRM", 32));
51ac6dd31eSStefan Berger     aml_append(field, aml_named_field("LPPR", 32));
52ac6dd31eSStefan Berger     aml_append(dev, field);
53ac6dd31eSStefan Berger     pprq = aml_name("PPRQ");
54ac6dd31eSStefan Berger     pprm = aml_name("PPRM");
55ac6dd31eSStefan Berger 
56ec86c0f6SMarc-André Lureau     aml_append(dev,
57ec86c0f6SMarc-André Lureau                aml_operation_region(
58ec86c0f6SMarc-André Lureau                    "TPP3", AML_SYSTEM_MEMORY,
59ec86c0f6SMarc-André Lureau                    aml_int(TPM_PPI_ADDR_BASE +
60*773c1f1eSStefano Garzarella                            0x15a /* movv, docs/specs/tpm.rst */),
61ec86c0f6SMarc-André Lureau                            0x1));
62ec86c0f6SMarc-André Lureau     field = aml_field("TPP3", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
63ec86c0f6SMarc-André Lureau     aml_append(field, aml_named_field("MOVV", 8));
64ec86c0f6SMarc-André Lureau     aml_append(dev, field);
65ec86c0f6SMarc-André Lureau 
66ac6dd31eSStefan Berger     /*
67ac6dd31eSStefan Berger      * DerefOf in Windows is broken with SYSTEM_MEMORY.  Use a dynamic
68ac6dd31eSStefan Berger      * operation region inside of a method for getting FUNC[op].
69ac6dd31eSStefan Berger      */
70ac6dd31eSStefan Berger     method = aml_method("TPFN", 1, AML_SERIALIZED);
71ac6dd31eSStefan Berger     {
72ac6dd31eSStefan Berger         Aml *op = aml_arg(0);
73ac6dd31eSStefan Berger         ifctx = aml_if(aml_lgreater_equal(op, aml_int(0x100)));
74ac6dd31eSStefan Berger         {
75ac6dd31eSStefan Berger             aml_append(ifctx, aml_return(zero));
76ac6dd31eSStefan Berger         }
77ac6dd31eSStefan Berger         aml_append(method, ifctx);
78ac6dd31eSStefan Berger 
79ac6dd31eSStefan Berger         aml_append(method,
80ac6dd31eSStefan Berger             aml_operation_region("TPP1", AML_SYSTEM_MEMORY,
81ac6dd31eSStefan Berger                 aml_add(aml_int(TPM_PPI_ADDR_BASE), op, NULL), 0x1));
82ac6dd31eSStefan Berger         field = aml_field("TPP1", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
83ac6dd31eSStefan Berger         aml_append(field, aml_named_field("TPPF", 8));
84ac6dd31eSStefan Berger         aml_append(method, field);
85ac6dd31eSStefan Berger         aml_append(method, aml_return(aml_name("TPPF")));
86ac6dd31eSStefan Berger     }
87ac6dd31eSStefan Berger     aml_append(dev, method);
88ac6dd31eSStefan Berger 
89ac6dd31eSStefan Berger     /*
90ac6dd31eSStefan Berger      * Use global TPM2 & TPM3 variables to workaround Windows ACPI bug
91ac6dd31eSStefan Berger      * when returning packages.
92ac6dd31eSStefan Berger      */
93ac6dd31eSStefan Berger     pak = aml_package(2);
94ac6dd31eSStefan Berger     aml_append(pak, zero);
95ac6dd31eSStefan Berger     aml_append(pak, zero);
96ac6dd31eSStefan Berger     aml_append(dev, aml_name_decl("TPM2", pak));
97ac6dd31eSStefan Berger     tpm2 = aml_name("TPM2");
98ac6dd31eSStefan Berger 
99ac6dd31eSStefan Berger     pak = aml_package(3);
100ac6dd31eSStefan Berger     aml_append(pak, zero);
101ac6dd31eSStefan Berger     aml_append(pak, zero);
102ac6dd31eSStefan Berger     aml_append(pak, zero);
103ac6dd31eSStefan Berger     aml_append(dev, aml_name_decl("TPM3", pak));
104ac6dd31eSStefan Berger     tpm3 = aml_name("TPM3");
105ac6dd31eSStefan Berger 
106ac6dd31eSStefan Berger     method = aml_method("_DSM", 4, AML_SERIALIZED);
107ac6dd31eSStefan Berger     {
108ac6dd31eSStefan Berger         uint8_t zerobyte[1] = { 0 };
109ac6dd31eSStefan Berger         Aml *function, *arguments, *rev, *op, *op_arg, *op_flags, *uuid;
110ac6dd31eSStefan Berger 
111ac6dd31eSStefan Berger         uuid = aml_arg(0);
112ac6dd31eSStefan Berger         rev = aml_arg(1);
113ac6dd31eSStefan Berger         function = aml_arg(2);
114ac6dd31eSStefan Berger         arguments = aml_arg(3);
115ac6dd31eSStefan Berger         op = aml_local(0);
116ac6dd31eSStefan Berger         op_flags = aml_local(1);
117ac6dd31eSStefan Berger 
118ac6dd31eSStefan Berger         /* Physical Presence Interface */
119ac6dd31eSStefan Berger         ifctx = aml_if(
120ac6dd31eSStefan Berger             aml_equal(uuid,
121ac6dd31eSStefan Berger                       aml_touuid("3DDDFAA6-361B-4EB4-A424-8D10089D1653")));
122ac6dd31eSStefan Berger         {
123ac6dd31eSStefan Berger             /* standard DSM query function */
124ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, zero));
125ac6dd31eSStefan Berger             {
126ac6dd31eSStefan Berger                 uint8_t byte_list[2] = { 0xff, 0x01 }; /* functions 1-8 */
127ac6dd31eSStefan Berger 
128ac6dd31eSStefan Berger                 aml_append(ifctx2,
129ac6dd31eSStefan Berger                            aml_return(aml_buffer(sizeof(byte_list),
130ac6dd31eSStefan Berger                                                  byte_list)));
131ac6dd31eSStefan Berger             }
132ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
133ac6dd31eSStefan Berger 
134ac6dd31eSStefan Berger             /*
135ac6dd31eSStefan Berger              * PPI 1.0: 2.1.1 Get Physical Presence Interface Version
136ac6dd31eSStefan Berger              *
137ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 1
138ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Empty Package
139ac6dd31eSStefan Berger              * Returns: Type: String
140ac6dd31eSStefan Berger              */
141ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, one));
142ac6dd31eSStefan Berger             {
143ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_return(aml_string("1.3")));
144ac6dd31eSStefan Berger             }
145ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
146ac6dd31eSStefan Berger 
147ac6dd31eSStefan Berger             /*
148ac6dd31eSStefan Berger              * PPI 1.0: 2.1.3 Submit TPM Operation Request to Pre-OS Environment
149ac6dd31eSStefan Berger              *
150ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 2
151ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Package: Type: Integer
152ac6dd31eSStefan Berger              *                              Operation Value of the Request
153ac6dd31eSStefan Berger              * Returns: Type: Integer
154ac6dd31eSStefan Berger              *          0: Success
155ac6dd31eSStefan Berger              *          1: Operation Value of the Request Not Supported
156ac6dd31eSStefan Berger              *          2: General Failure
157ac6dd31eSStefan Berger              */
158ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(2)));
159ac6dd31eSStefan Berger             {
160ac6dd31eSStefan Berger                 /* get opcode */
161ac6dd31eSStefan Berger                 aml_append(ifctx2,
162ac6dd31eSStefan Berger                            aml_store(aml_derefof(aml_index(arguments,
163ac6dd31eSStefan Berger                                                            zero)), op));
164ac6dd31eSStefan Berger 
165ac6dd31eSStefan Berger                 /* get opcode flags */
166ac6dd31eSStefan Berger                 aml_append(ifctx2,
167ac6dd31eSStefan Berger                            aml_store(aml_call1("TPFN", op), op_flags));
168ac6dd31eSStefan Berger 
169ac6dd31eSStefan Berger                 /* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
170ac6dd31eSStefan Berger                 ifctx3 = aml_if(
171ac6dd31eSStefan Berger                     aml_equal(
172ac6dd31eSStefan Berger                         aml_and(op_flags, func_mask, NULL),
173ac6dd31eSStefan Berger                         not_implemented));
174ac6dd31eSStefan Berger                 {
175ac6dd31eSStefan Berger                     /* 1: Operation Value of the Request Not Supported */
176ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_return(one));
177ac6dd31eSStefan Berger                 }
178ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
179ac6dd31eSStefan Berger 
180ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_store(op, pprq));
181ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_store(zero, pprm));
182ac6dd31eSStefan Berger                 /* 0: success */
183ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_return(zero));
184ac6dd31eSStefan Berger             }
185ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
186ac6dd31eSStefan Berger 
187ac6dd31eSStefan Berger             /*
188ac6dd31eSStefan Berger              * PPI 1.0: 2.1.4 Get Pending TPM Operation Requested By the OS
189ac6dd31eSStefan Berger              *
190ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 3
191ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Empty Package
192ac6dd31eSStefan Berger              * Returns: Type: Package of Integers
193ac6dd31eSStefan Berger              *          Integer 1: Function Return code
194ac6dd31eSStefan Berger              *                     0: Success
195ac6dd31eSStefan Berger              *                     1: General Failure
196ac6dd31eSStefan Berger              *          Integer 2: Pending operation requested by the OS
197ac6dd31eSStefan Berger              *                     0: None
198ac6dd31eSStefan Berger              *                    >0: Operation Value of the Pending Request
199ac6dd31eSStefan Berger              *          Integer 3: Optional argument to pending operation
200ac6dd31eSStefan Berger              *                     requested by the OS
201ac6dd31eSStefan Berger              *                     0: None
202ac6dd31eSStefan Berger              *                    >0: Argument Value of the Pending Request
203ac6dd31eSStefan Berger              */
204ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(3)));
205ac6dd31eSStefan Berger             {
206ac6dd31eSStefan Berger                 /*
207ac6dd31eSStefan Berger                  * Revision ID of 1, no integer parameter beyond
208ac6dd31eSStefan Berger                  * parameter two are expected
209ac6dd31eSStefan Berger                  */
210ac6dd31eSStefan Berger                 ifctx3 = aml_if(aml_equal(rev, one));
211ac6dd31eSStefan Berger                 {
212ac6dd31eSStefan Berger                     /* TPM2[1] = PPRQ */
213ac6dd31eSStefan Berger                     aml_append(ifctx3,
214ac6dd31eSStefan Berger                                aml_store(pprq, aml_index(tpm2, one)));
215ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_return(tpm2));
216ac6dd31eSStefan Berger                 }
217ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
218ac6dd31eSStefan Berger 
219ac6dd31eSStefan Berger                 /*
220ac6dd31eSStefan Berger                  * A return value of {0, 23, 1} indicates that
221ac6dd31eSStefan Berger                  * operation 23 with argument 1 is pending.
222ac6dd31eSStefan Berger                  */
223ac6dd31eSStefan Berger                 ifctx3 = aml_if(aml_equal(rev, aml_int(2)));
224ac6dd31eSStefan Berger                 {
225ac6dd31eSStefan Berger                     /* TPM3[1] = PPRQ */
226ac6dd31eSStefan Berger                     aml_append(ifctx3,
227ac6dd31eSStefan Berger                                aml_store(pprq, aml_index(tpm3, one)));
228ac6dd31eSStefan Berger                     /* TPM3[2] = PPRM */
229ac6dd31eSStefan Berger                     aml_append(ifctx3,
230ac6dd31eSStefan Berger                                aml_store(pprm, aml_index(tpm3, aml_int(2))));
231ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_return(tpm3));
232ac6dd31eSStefan Berger                 }
233ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
234ac6dd31eSStefan Berger             }
235ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
236ac6dd31eSStefan Berger 
237ac6dd31eSStefan Berger             /*
238ac6dd31eSStefan Berger              * PPI 1.0: 2.1.5 Get Platform-Specific Action to Transition to
239ac6dd31eSStefan Berger              *     Pre-OS Environment
240ac6dd31eSStefan Berger              *
241ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 4
242ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Empty Package
243ac6dd31eSStefan Berger              * Returns: Type: Integer
244ac6dd31eSStefan Berger              *          0: None
245ac6dd31eSStefan Berger              *          1: Shutdown
246ac6dd31eSStefan Berger              *          2: Reboot
247ac6dd31eSStefan Berger              *          3: OS Vendor-specific
248ac6dd31eSStefan Berger              */
249ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(4)));
250ac6dd31eSStefan Berger             {
251ac6dd31eSStefan Berger                 /* reboot */
252ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_return(aml_int(2)));
253ac6dd31eSStefan Berger             }
254ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
255ac6dd31eSStefan Berger 
256ac6dd31eSStefan Berger             /*
257ac6dd31eSStefan Berger              * PPI 1.0: 2.1.6 Return TPM Operation Response to OS Environment
258ac6dd31eSStefan Berger              *
259ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 5
260ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Empty Package
261ac6dd31eSStefan Berger              * Returns: Type: Package of Integer
262ac6dd31eSStefan Berger              *          Integer 1: Function Return code
263ac6dd31eSStefan Berger              *                     0: Success
264ac6dd31eSStefan Berger              *                     1: General Failure
265ac6dd31eSStefan Berger              *          Integer 2: Most recent operation request
266ac6dd31eSStefan Berger              *                     0: None
267ac6dd31eSStefan Berger              *                    >0: Operation Value of the most recent request
268ac6dd31eSStefan Berger              *          Integer 3: Response to the most recent operation request
269ac6dd31eSStefan Berger              *                     0: Success
270ac6dd31eSStefan Berger              *                     0x00000001..0x00000FFF: Corresponding TPM
271ac6dd31eSStefan Berger              *                                             error code
272ac6dd31eSStefan Berger              *                     0xFFFFFFF0: User Abort or timeout of dialog
273ac6dd31eSStefan Berger              *                     0xFFFFFFF1: firmware Failure
274ac6dd31eSStefan Berger              */
275ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(5)));
276ac6dd31eSStefan Berger             {
277ac6dd31eSStefan Berger                 /* TPM3[1] = LPPR */
278ac6dd31eSStefan Berger                 aml_append(ifctx2,
279ac6dd31eSStefan Berger                            aml_store(aml_name("LPPR"),
280ac6dd31eSStefan Berger                                      aml_index(tpm3, one)));
281ac6dd31eSStefan Berger                 /* TPM3[2] = PPRP */
282ac6dd31eSStefan Berger                 aml_append(ifctx2,
283ac6dd31eSStefan Berger                            aml_store(aml_name("PPRP"),
284ac6dd31eSStefan Berger                                      aml_index(tpm3, aml_int(2))));
285ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_return(tpm3));
286ac6dd31eSStefan Berger             }
287ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
288ac6dd31eSStefan Berger 
289ac6dd31eSStefan Berger             /*
290ac6dd31eSStefan Berger              * PPI 1.0: 2.1.7 Submit preferred user language
291ac6dd31eSStefan Berger              *
292ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 6
293ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = String Package
294ac6dd31eSStefan Berger              *                  Preferred language code
295ac6dd31eSStefan Berger              * Returns: Type: Integer
296ac6dd31eSStefan Berger              * Function Return Code
297ac6dd31eSStefan Berger              *          3: Not implemented
298ac6dd31eSStefan Berger              */
299ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(6)));
300ac6dd31eSStefan Berger             {
301ac6dd31eSStefan Berger                 /* 3 = not implemented */
302ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_return(aml_int(3)));
303ac6dd31eSStefan Berger             }
304ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
305ac6dd31eSStefan Berger 
306ac6dd31eSStefan Berger             /*
307ac6dd31eSStefan Berger              * PPI 1.1: 2.1.7 Submit TPM Operation Request to
308ac6dd31eSStefan Berger              *     Pre-OS Environment 2
309ac6dd31eSStefan Berger              *
310ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 7
311ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Package: Type: Integer
312ac6dd31eSStefan Berger              *                  Integer 1: Operation Value of the Request
313ac6dd31eSStefan Berger              *                  Integer 2: Argument for Operation (optional)
314ac6dd31eSStefan Berger              * Returns: Type: Integer
315ac6dd31eSStefan Berger              *          0: Success
316ac6dd31eSStefan Berger              *          1: Not Implemented
317ac6dd31eSStefan Berger              *          2: General Failure
318ac6dd31eSStefan Berger              *          3: Operation blocked by current firmware settings
319ac6dd31eSStefan Berger              */
320ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(7)));
321ac6dd31eSStefan Berger             {
322ac6dd31eSStefan Berger                 /* get opcode */
323ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_store(aml_derefof(aml_index(arguments,
324ac6dd31eSStefan Berger                                                                    zero)),
325ac6dd31eSStefan Berger                                              op));
326ac6dd31eSStefan Berger 
327ac6dd31eSStefan Berger                 /* get opcode flags */
328ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_store(aml_call1("TPFN", op),
329ac6dd31eSStefan Berger                                              op_flags));
330ac6dd31eSStefan Berger                 /* if func[opcode] & TPM_PPI_FUNC_NOT_IMPLEMENTED */
331ac6dd31eSStefan Berger                 ifctx3 = aml_if(
332ac6dd31eSStefan Berger                     aml_equal(
333ac6dd31eSStefan Berger                         aml_and(op_flags, func_mask, NULL),
334ac6dd31eSStefan Berger                         not_implemented));
335ac6dd31eSStefan Berger                 {
336ac6dd31eSStefan Berger                     /* 1: not implemented */
337ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_return(one));
338ac6dd31eSStefan Berger                 }
339ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
340ac6dd31eSStefan Berger 
341ac6dd31eSStefan Berger                 /* if func[opcode] & TPM_PPI_FUNC_BLOCKED */
342ac6dd31eSStefan Berger                 ifctx3 = aml_if(
343ac6dd31eSStefan Berger                     aml_equal(
344ac6dd31eSStefan Berger                         aml_and(op_flags, func_mask, NULL),
345ac6dd31eSStefan Berger                         aml_int(TPM_PPI_FUNC_BLOCKED)));
346ac6dd31eSStefan Berger                 {
347ac6dd31eSStefan Berger                     /* 3: blocked by firmware */
348ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_return(aml_int(3)));
349ac6dd31eSStefan Berger                 }
350ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
351ac6dd31eSStefan Berger 
352ac6dd31eSStefan Berger                 /* revision to integer */
353ac6dd31eSStefan Berger                 ifctx3 = aml_if(aml_equal(rev, one));
354ac6dd31eSStefan Berger                 {
355ac6dd31eSStefan Berger                     /* revision 1 */
356ac6dd31eSStefan Berger                     /* PPRQ = op */
357ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_store(op, pprq));
358ac6dd31eSStefan Berger                     /* no argument, PPRM = 0 */
359ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_store(zero, pprm));
360ac6dd31eSStefan Berger                 }
361ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
362ac6dd31eSStefan Berger 
363ac6dd31eSStefan Berger                 ifctx3 = aml_if(aml_equal(rev, aml_int(2)));
364ac6dd31eSStefan Berger                 {
365ac6dd31eSStefan Berger                     /* revision 2 */
366ac6dd31eSStefan Berger                     /* PPRQ = op */
367ac6dd31eSStefan Berger                     op_arg = aml_derefof(aml_index(arguments, one));
368ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_store(op, pprq));
369ac6dd31eSStefan Berger                     /* PPRM = arg3[1] */
370ac6dd31eSStefan Berger                     aml_append(ifctx3, aml_store(op_arg, pprm));
371ac6dd31eSStefan Berger                 }
372ac6dd31eSStefan Berger                 aml_append(ifctx2, ifctx3);
373ac6dd31eSStefan Berger                 /* 0: success */
374ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_return(zero));
375ac6dd31eSStefan Berger             }
376ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
377ac6dd31eSStefan Berger 
378ac6dd31eSStefan Berger             /*
379ac6dd31eSStefan Berger              * PPI 1.1: 2.1.8 Get User Confirmation Status for Operation
380ac6dd31eSStefan Berger              *
381ac6dd31eSStefan Berger              * Arg 2 (Integer): Function Index = 8
382ac6dd31eSStefan Berger              * Arg 3 (Package): Arguments = Package: Type: Integer
383ac6dd31eSStefan Berger              *                  Operation Value that may need user confirmation
384ac6dd31eSStefan Berger              * Returns: Type: Integer
385ac6dd31eSStefan Berger              *          0: Not implemented
386ac6dd31eSStefan Berger              *          1: Firmware only
387ac6dd31eSStefan Berger              *          2: Blocked for OS by firmware configuration
388ac6dd31eSStefan Berger              *          3: Allowed and physically present user required
389ac6dd31eSStefan Berger              *          4: Allowed and physically present user not required
390ac6dd31eSStefan Berger              */
391ac6dd31eSStefan Berger             ifctx2 = aml_if(aml_equal(function, aml_int(8)));
392ac6dd31eSStefan Berger             {
393ac6dd31eSStefan Berger                 /* get opcode */
394ac6dd31eSStefan Berger                 aml_append(ifctx2,
395ac6dd31eSStefan Berger                            aml_store(aml_derefof(aml_index(arguments,
396ac6dd31eSStefan Berger                                                            zero)),
397ac6dd31eSStefan Berger                                      op));
398ac6dd31eSStefan Berger 
399ac6dd31eSStefan Berger                 /* get opcode flags */
400ac6dd31eSStefan Berger                 aml_append(ifctx2, aml_store(aml_call1("TPFN", op),
401ac6dd31eSStefan Berger                                              op_flags));
402ac6dd31eSStefan Berger                 /* return confirmation status code */
403ac6dd31eSStefan Berger                 aml_append(ifctx2,
404ac6dd31eSStefan Berger                            aml_return(
405ac6dd31eSStefan Berger                                aml_and(op_flags, func_mask, NULL)));
406ac6dd31eSStefan Berger             }
407ac6dd31eSStefan Berger             aml_append(ifctx, ifctx2);
408ac6dd31eSStefan Berger 
409ac6dd31eSStefan Berger             aml_append(ifctx, aml_return(aml_buffer(1, zerobyte)));
410ac6dd31eSStefan Berger         }
411ac6dd31eSStefan Berger         aml_append(method, ifctx);
412ec86c0f6SMarc-André Lureau 
413ec86c0f6SMarc-André Lureau         /*
414ec86c0f6SMarc-André Lureau          * "TCG Platform Reset Attack Mitigation Specification 1.00",
415ec86c0f6SMarc-André Lureau          * Chapter 6 "ACPI _DSM Function"
416ec86c0f6SMarc-André Lureau          */
417ec86c0f6SMarc-André Lureau         ifctx = aml_if(
418ec86c0f6SMarc-André Lureau             aml_equal(uuid,
419ec86c0f6SMarc-André Lureau                       aml_touuid("376054ED-CC13-4675-901C-4756D7F2D45D")));
420ec86c0f6SMarc-André Lureau         {
421ec86c0f6SMarc-André Lureau             /* standard DSM query function */
422ec86c0f6SMarc-André Lureau             ifctx2 = aml_if(aml_equal(function, zero));
423ec86c0f6SMarc-André Lureau             {
424ec86c0f6SMarc-André Lureau                 uint8_t byte_list[1] = { 0x03 }; /* functions 1-2 supported */
425ec86c0f6SMarc-André Lureau 
426ec86c0f6SMarc-André Lureau                 aml_append(ifctx2,
427ec86c0f6SMarc-André Lureau                            aml_return(aml_buffer(sizeof(byte_list),
428ec86c0f6SMarc-André Lureau                                                  byte_list)));
429ec86c0f6SMarc-André Lureau             }
430ec86c0f6SMarc-André Lureau             aml_append(ifctx, ifctx2);
431ec86c0f6SMarc-André Lureau 
432ec86c0f6SMarc-André Lureau             /*
433ec86c0f6SMarc-André Lureau              * TCG Platform Reset Attack Mitigation Specification 1.0 Ch.6
434ec86c0f6SMarc-André Lureau              *
435ec86c0f6SMarc-André Lureau              * Arg 2 (Integer): Function Index = 1
436ec86c0f6SMarc-André Lureau              * Arg 3 (Package): Arguments = Package: Type: Integer
437ec86c0f6SMarc-André Lureau              *                  Operation Value of the Request
438ec86c0f6SMarc-André Lureau              * Returns: Type: Integer
439ec86c0f6SMarc-André Lureau              *          0: Success
440ec86c0f6SMarc-André Lureau              *          1: General Failure
441ec86c0f6SMarc-André Lureau              */
442ec86c0f6SMarc-André Lureau             ifctx2 = aml_if(aml_equal(function, one));
443ec86c0f6SMarc-André Lureau             {
444ec86c0f6SMarc-André Lureau                 aml_append(ifctx2,
445ec86c0f6SMarc-André Lureau                            aml_store(aml_derefof(aml_index(arguments, zero)),
446ec86c0f6SMarc-André Lureau                                      op));
447ec86c0f6SMarc-André Lureau                 {
448ec86c0f6SMarc-André Lureau                     aml_append(ifctx2, aml_store(op, aml_name("MOVV")));
449ec86c0f6SMarc-André Lureau 
450ec86c0f6SMarc-André Lureau                     /* 0: success */
451ec86c0f6SMarc-André Lureau                     aml_append(ifctx2, aml_return(zero));
452ec86c0f6SMarc-André Lureau                 }
453ec86c0f6SMarc-André Lureau             }
454ec86c0f6SMarc-André Lureau             aml_append(ifctx, ifctx2);
455ec86c0f6SMarc-André Lureau         }
456ec86c0f6SMarc-André Lureau         aml_append(method, ifctx);
457ac6dd31eSStefan Berger     }
458ac6dd31eSStefan Berger     aml_append(dev, method);
459ac6dd31eSStefan Berger }
460