mb/google/brya: Create rull variant
[coreboot2.git] / src / drivers / tpm / ppi.c
blob68923eaedaf9706f8ce335bbd8726e0642093a94
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <types.h>
4 #include <acpi/acpigen.h>
5 #include <acpi/acpi_device.h>
6 #include <cbmem.h>
7 #include <console/console.h>
8 #include <security/tpm/tss.h>
10 #include "tpm_ppi.h"
12 #define BCD(x, y) (((x) << 4) | ((y) << 0))
14 static void set_package_element_op(const char *package_name, unsigned int element,
15 uint8_t src_op)
17 acpigen_write_store();
18 acpigen_emit_byte(src_op);
19 acpigen_emit_byte(INDEX_OP);
20 acpigen_emit_namestring(package_name);
21 acpigen_write_integer(element);
22 acpigen_emit_byte(ZERO_OP); /* Ignore Index() Destination */
25 static void set_package_element_name(const char *package_name, unsigned int element,
26 const char *src)
28 acpigen_write_store();
29 acpigen_emit_namestring(src);
30 acpigen_emit_byte(INDEX_OP);
31 acpigen_emit_namestring(package_name);
32 acpigen_write_integer(element);
33 acpigen_emit_byte(ZERO_OP); /* Ignore Index() Destination */
36 /* PPI function is passed in src_op. Converted to Local2. Clobbers Local1 and Local2 */
37 static void verify_supported_ppi(uint8_t src_op)
39 enum tpm_family family = tlcl_get_family();
42 * Old OSes incorrectly pass a Buffer instead of a Package.
43 * See TCG Physical Presence Interface Specification Chapter 8.1.2 for details.
46 /* If (ObjectType(Arg3) == Package) */
47 acpigen_write_store();
48 acpigen_emit_byte(OBJ_TYPE_OP);
49 acpigen_emit_byte(src_op);
50 acpigen_emit_byte(LOCAL1_OP);
51 acpigen_write_if_lequal_op_int(LOCAL1_OP, 4);
52 acpigen_get_package_op_element(src_op, 0, LOCAL2_OP);
53 acpigen_pop_len();
55 /* If (ObjectType(Arg3) == Buffer) */
56 acpigen_write_store();
57 acpigen_emit_byte(OBJ_TYPE_OP);
58 acpigen_emit_byte(src_op);
59 acpigen_emit_byte(LOCAL1_OP);
60 acpigen_write_if_lequal_op_int(LOCAL1_OP, 3);
61 acpigen_write_to_integer(src_op, LOCAL2_OP);
62 acpigen_pop_len();
64 /* Check if it's a valid PPI function */
65 acpigen_write_store();
66 acpigen_emit_namestring("^FSUP");
67 acpigen_emit_byte(LOCAL2_OP);
68 acpigen_emit_byte(family == TPM_1 ? ONE_OP : ZERO_OP);
69 acpigen_emit_byte(LOCAL1_OP);
70 acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
73 * Note: Must fake success for 1-4, 6-13, 15-16, 19-20
74 * see "Trusted Execution Environment ACPI Profile"
76 * Even if not available, the TPM 1.2 PPI must be advertised as
77 * supported. Tests showed that Windows relies on it, even when
78 * a TPM2.0 is present!
79 * The functions aren't actually used when a TPM2.0 is present...
80 * Without this the Windows TPM 2.0 stack refuses to work.
84 * Check if we have TPM1.2 but a TPM2 PPI function was called
85 * or if we have TPM2.0 but a TPM1.2 PPI function was called.
87 acpigen_write_store();
88 acpigen_emit_namestring("^FSUP");
89 acpigen_emit_byte(LOCAL2_OP);
90 acpigen_emit_byte(family == TPM_1 ? ZERO_OP : ONE_OP);
91 acpigen_emit_byte(LOCAL1_OP);
93 acpigen_write_if_lequal_op_int(LOCAL1_OP, 1);
94 acpigen_write_return_integer(PPI2_RET_SUCCESS); /* As per TPM spec */
95 acpigen_pop_len();
96 acpigen_write_return_integer(PPI2_RET_NOT_SUPPORTED);
98 acpigen_pop_len();
101 /* TPM PPI functions */
103 static void tpm_ppi_func0_cb(void *arg)
105 /* Functions 1-8. */
106 u8 buf[] = {0xff, 0x01};
107 acpigen_write_return_byte_buffer(buf, 2);
111 * PPI 1.0: 2.1.1 Get Physical Presence Interface Version
113 * Arg2 (Integer): Function Index = 1
114 * Arg3 (Package): Arguments = Empty Package
116 * Returns: Type: String
118 static void tpm_ppi_func1_cb(void *arg)
120 if (tlcl_get_family() == TPM_2)
121 /* Interface version: 1.3 */
122 acpigen_write_return_string("1.3");
123 else
124 /* Interface version: 1.2 */
125 acpigen_write_return_string("1.2");
129 * Submit TPM Operation Request to Pre-OS Environment [Windows optional]
130 * PPI 1.0: 2.1.3 Submit TPM Operation Request to Pre-OS Environment
132 * Supported Revisions: 1
133 * Arg1 (Integer): Revision
134 * Arg2 (Integer): Function Index = 2
135 * Arg3 (Package): Arguments = Package: Type: Integer
136 * Operation Value of the Request
138 * Returns: Type: Integer
139 * 0: Success
140 * 1: Operation Value of the Request Not Supported
141 * 2: General Failure
143 static void tpm_ppi_func2_cb(void *arg)
145 /* Revision 1 */
146 acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
147 acpigen_write_if_lequal_op_int(LOCAL0_OP, 1);
149 /* Local2 = ConvertAndVerify(Arg3) */
150 verify_supported_ppi(ARG3_OP);
152 acpigen_write_store_op_to_namestr(LOCAL2_OP, "^CMDR");
153 acpigen_write_store_op_to_namestr(ZERO_OP, "^OARG");
154 acpigen_write_store_op_to_namestr(ZERO_OP, "^USER");
156 acpigen_write_return_integer(PPI2_RET_SUCCESS);
157 acpigen_pop_len();
159 acpigen_write_return_integer(PPI2_RET_GENERAL_FAILURE);
163 * PPI 1.0: 2.1.4 Get Pending TPM Operation Requested By the OS
165 * Supported Revisions: 1, 2
166 * Arg1 (Integer): Revision
167 * Arg2 (Integer): Function Index = 3
168 * Arg3 (Package): Empty package
170 * Returns: Type: Package(Integer, Integer, Integer (optional))
171 * Integer 1:
172 * 0: Success
173 * 1: General Failure
174 * Integer 2:
175 * Pending TPM operation requested by OS
176 * Integer 3:
177 * Pending TPM operation argument requested by OS
179 static void tpm_ppi_func3_cb(void *arg)
181 acpigen_write_store();
182 acpigen_write_integer(PPI3_RET_GENERAL_FAILURE);
183 acpigen_emit_byte(LOCAL0_OP);
185 /* ^TPM3 [0] = PPI3_RET_GENERAL_FAILURE */
186 set_package_element_op("^TPM3", 0, LOCAL0_OP);
188 /* ^TPM2 [0] = PPI3_RET_GENERAL_FAILURE */
189 set_package_element_op("^TPM2", 0, LOCAL0_OP);
191 acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
193 /* Revision 1 */
194 acpigen_write_if_lequal_op_int(LOCAL0_OP, 1);
196 /* ^TPM2 [0] = PPI3_RET_SUCCESS */
197 acpigen_write_store();
198 acpigen_write_integer(PPI3_RET_SUCCESS);
199 acpigen_emit_byte(LOCAL1_OP);
200 set_package_element_op("^TPM2", 0, LOCAL1_OP);
202 /* ^TPM2 [1] = ^CMDR */
203 set_package_element_name("^TPM2", 1, "^CMDR");
205 acpigen_emit_byte(RETURN_OP);
206 acpigen_emit_namestring("^TPM2");
207 acpigen_pop_len();
210 * A return value of {0, 23, 1} indicates that operation 23
211 * with argument 1 is pending.
214 /* Revision 2 */
215 acpigen_write_if_lequal_op_int(LOCAL0_OP, 2);
217 /* ^TPM3 [0] = PPI3_RET_SUCCESS */
218 acpigen_write_store();
219 acpigen_write_integer(PPI3_RET_SUCCESS);
220 acpigen_emit_byte(LOCAL1_OP);
221 set_package_element_op("^TPM3", 0, LOCAL1_OP);
223 /* ^TPM3 [1] = ^CMDR */
224 set_package_element_name("^TPM3", 1, "^CMDR");
226 /* ^TPM3 [2] = ^OARG */
227 set_package_element_name("^TPM3", 2, "^OARG");
229 acpigen_emit_byte(RETURN_OP);
230 acpigen_emit_namestring("^TPM3");
231 acpigen_pop_len();
233 acpigen_emit_byte(RETURN_OP);
234 acpigen_emit_namestring("^TPM3");
238 * PPI 1.0: 2.1.5 Get Platform-Specific Action to Transition to Pre-OS Environment
240 * Arg1 (Integer): Revision
241 * Arg2 (Integer): Function Index = 4
242 * Arg3 (Package): Empty package
244 * Returns: Type: Integer
245 * 0: None
246 * 1: Shutdown
247 * 2: Reboot
248 * 3: Vendor specific
250 static void tpm_ppi_func4_cb(void *arg)
252 /* Pre-OS transition method: reboot. */
253 acpigen_write_return_byte(PPI4_RET_REBOOT);
257 * PPI 1.0: 2.1.6 Return TPM Operation Response to OS Environment
259 * Supported Revisions: 1
260 * Arg1 (Integer): Revision
261 * Arg2 (Integer): Function Index = 5
262 * Arg3 (Package): Empty package
264 * Returns: Type: Package(Integer, Integer, Integer)
265 * Integer 1:
266 * 0: Success
267 * 1: General Failure
268 * Integer 2:
269 * Most recent TPM operation requested by OS
270 * Integer 3:
271 * Response to most recent TPM operation requested by OS
273 static void tpm_ppi_func5_cb(void *arg)
275 /* ^TPM3 [0] = PPI5_RET_GENERAL_FAILURE */
276 acpigen_write_store();
277 acpigen_write_integer(PPI5_RET_GENERAL_FAILURE);
278 acpigen_emit_byte(LOCAL1_OP);
279 set_package_element_op("^TPM3", 0, LOCAL1_OP);
281 acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
283 /* Revision 1 */
284 acpigen_write_if_lequal_op_int(LOCAL0_OP, 1);
286 /* ^TPM3 [0] = PPI5_RET_SUCCESS */
287 acpigen_write_store();
288 acpigen_write_integer(PPI5_RET_SUCCESS);
289 acpigen_emit_byte(LOCAL1_OP);
290 set_package_element_op("^TPM3", 0, LOCAL1_OP);
292 /* ^TPM3 [1] = ^LCMD */
293 set_package_element_name("^TPM3", 1, "^LCMD");
295 /* ^TPM3 [2] = ^RESU */
296 set_package_element_name("^TPM3", 2, "^RESU");
298 acpigen_pop_len();
300 acpigen_emit_byte(RETURN_OP);
301 acpigen_emit_namestring("^TPM3");
305 * PPI 1.2: 2.1.6 Submit preferred user language [Windows optional]
307 * Arg1 (Integer): Revision
308 * Arg2 (Integer): Function Index = 5
309 * Arg3 (Package): Empty package
311 static void tpm_ppi_func6_cb(void *arg)
314 * Set preferred user language: deprecated and must return 3 aka
315 * "not implemented".
317 acpigen_write_return_byte(PPI6_RET_NOT_IMPLEMENTED);
321 * PPI 1.2: 2.1.7 Submit TPM Operation Request to Pre-OS Environment 2
323 * Supported Revisions: 1, 2
324 * Arg1 (Integer): Revision
325 * Arg2 (Integer): Function Index = 7
326 * Arg3 (Package): Integer
328 * Returns: Type: Integer
329 * 0: Success
330 * 1: Not implemented
331 * 2: General Failure
332 * 3: Blocked by current BIOS settings
334 static void tpm_ppi_func7_cb(void *arg)
336 acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
338 /* Local2 = ConvertAndVerify(Arg3) */
339 verify_supported_ppi(ARG3_OP);
341 /* If (ObjectType(Arg3) == Buffer) */
342 acpigen_write_store();
343 acpigen_emit_byte(OBJ_TYPE_OP);
344 acpigen_emit_byte(ARG3_OP);
345 acpigen_emit_byte(LOCAL1_OP);
346 acpigen_write_if_lequal_op_int(LOCAL1_OP, 3);
348 /* Enforce use of Revision 1 that doesn't take an optional argument. */
350 /* Local0 = One */
351 acpigen_write_store();
352 acpigen_emit_byte(ONE_OP);
353 acpigen_emit_byte(LOCAL0_OP);
355 acpigen_pop_len();
357 // FIXME: Only advertise supported functions
359 /* Revision 1 */
360 acpigen_write_if_lequal_op_int(LOCAL0_OP, 1);
362 /* ^CMDR = Local2 */
363 acpigen_write_store_op_to_namestr(LOCAL2_OP, "^CMDR");
365 /* ^OARG = Zero */
366 acpigen_write_store_op_to_namestr(ZERO_OP, "^OARG");
368 acpigen_write_return_byte(PPI7_RET_SUCCESS);
369 acpigen_pop_len();
371 /* Revision 2 */
372 acpigen_write_if_lequal_op_int(LOCAL0_OP, 2);
373 /* ^CMDR = Local2 */
374 acpigen_write_store_op_to_namestr(LOCAL2_OP, "^CMDR");
376 /* ^OARG = Arg3 [1] */
377 acpigen_get_package_op_element(ARG3_OP, 1, LOCAL3_OP);
378 acpigen_write_store();
379 acpigen_emit_byte(LOCAL3_OP);
380 acpigen_emit_namestring("^OARG");
382 acpigen_write_return_byte(PPI7_RET_SUCCESS);
383 acpigen_pop_len();
385 acpigen_write_return_byte(PPI7_RET_GENERAL_FAILURE);
389 * PPI 1.2: 2.1.8 Get User Confirmation Status for Operation
391 * Returns if a command is supported and allowed by firmware
392 * Supported Revisions: 1
393 * Arg1 (Integer): Revision
394 * Arg2 (Integer): Function Index = 7
395 * Arg3 (Package): Integer
397 * Returns: Type: Integer
398 * 0: Not implemented
399 * 1: BIOS only
400 * 2: Blocked for OS by BIOS settings
401 * 3: Allowed and physical present user required
402 * 4: Allowed and physical present user not required
404 static void tpm_ppi_func8_cb(void *arg)
406 enum tpm_family family = tlcl_get_family();
408 acpigen_write_to_integer(ARG1_OP, LOCAL0_OP);
410 /* Revision 1 */
411 acpigen_write_if_lequal_op_int(LOCAL0_OP, 1);
412 acpigen_get_package_op_element(ARG3_OP, 0, LOCAL2_OP);
414 /* Check if it's a valid PPI function */
415 acpigen_write_store();
416 acpigen_emit_namestring("^FSUP");
417 acpigen_emit_byte(LOCAL2_OP);
418 acpigen_emit_byte(family == TPM_1 ? ONE_OP : ZERO_OP);
419 acpigen_emit_byte(LOCAL1_OP);
420 acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
421 acpigen_write_return_byte(0); /* Not implemented */
422 acpigen_pop_len();
424 // FIXME: Only advertise supported functions
426 if (family == TPM_1) {
428 * Some functions do not require PP depending on configuration.
429 * Those aren't listed here, so the 'required PP' is always set for those.
431 static const u32 tpm1_funcs[] = {
432 TPM_NOOP,
433 TPM_SET_NOPPICLEAR_TRUE,
434 TPM_SET_NOPPIMAINTAINANCE_TRUE,
435 TPM_SET_NOPPIPROVISION_TRUE,
437 for (size_t i = 0; i < ARRAY_SIZE(tpm1_funcs); i++) {
438 acpigen_write_if_lequal_op_int(LOCAL2_OP, tpm1_funcs[i]);
439 acpigen_write_return_integer(PPI8_RET_ALLOWED);
440 acpigen_pop_len(); /* Pop : If */
442 } else if (family == TPM_2) {
444 * Some functions do not require PP depending on configuration.
445 * Those aren't listed here, so the 'required PP' is always set for those.
447 static const u32 tpm2_funcs[] = {
448 TPM2_NOOP,
449 TPM2_SET_PP_REQUIRED_FOR_CLEAR_TRUE,
450 TPM2_SET_PP_REQUIRED_FOR_CHANGE_PCRS_TRUE,
451 TPM2_SET_PP_REQUIRED_FOR_TURN_ON_TRUE,
452 TPM2_SET_PP_REQUIRED_FOR_CHANGE_EPS_TRUE,
453 TPM2_SET_PP_REQUIRED_FOR_TURN_OFF_TRUE,
454 TPM2_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_TRUE,
455 TPM2_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_TRUE,
457 for (size_t i = 0; i < ARRAY_SIZE(tpm2_funcs); i++) {
458 acpigen_write_if_lequal_op_int(LOCAL2_OP, tpm2_funcs[i]);
459 acpigen_write_return_integer(PPI8_RET_ALLOWED);
460 acpigen_pop_len(); /* Pop : If */
463 acpigen_write_return_integer(PPI8_RET_ALLOWED_WITH_PP);
465 acpigen_pop_len();
467 acpigen_write_return_integer(PPI8_RET_NOT_IMPLEMENTED);
470 static void (*tpm_ppi_callbacks[])(void *) = {
471 tpm_ppi_func0_cb,
472 tpm_ppi_func1_cb,
473 tpm_ppi_func2_cb,
474 tpm_ppi_func3_cb,
475 tpm_ppi_func4_cb,
476 tpm_ppi_func5_cb,
477 tpm_ppi_func6_cb,
478 tpm_ppi_func7_cb,
479 tpm_ppi_func8_cb,
482 static void tpm_mci_func0_cb(void *arg)
484 /* Function 1. */
485 acpigen_write_return_singleton_buffer(0x3);
487 static void tpm_mci_func1_cb(void *arg)
489 /* Just return success. */
490 acpigen_write_return_byte(0);
493 static void (*tpm_mci_callbacks[])(void *) = {
494 tpm_mci_func0_cb,
495 tpm_mci_func1_cb,
498 void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
500 struct cb_tpm_ppi_payload_handshake *ppib;
502 static const struct fieldlist list[] = {
503 FIELDLIST_OFFSET(0x100),// FIXME: Add support for func
504 FIELDLIST_NAMESTR("PPIN", 8),// Not used
505 FIELDLIST_NAMESTR("PPIP", 32),// Not used
506 FIELDLIST_NAMESTR("RESU", 32),// Result of the last operation (TPM error code)
507 FIELDLIST_NAMESTR("CMDR", 32),// The command requested by OS. 0 for NOP
508 FIELDLIST_NAMESTR("OARG", 32),// The command optional argument requested by OS
509 FIELDLIST_NAMESTR("LCMD", 32),// The last command requested by OS.
510 FIELDLIST_NAMESTR("FRET", 32),// Not used
512 static const u8 tpm1_funcs[] = {
513 TPM_NOOP,
514 TPM_ENABLE,
515 TPM_DISABLE,
516 TPM_ACTIVATE,
517 TPM_DEACTIVATE,
518 TPM_CLEAR,
519 TPM_ENABLE_ACTIVATE,
520 TPM_DEACTIVATE_DISABLE,
521 TPM_SETOWNERINSTALL_TRUE,
522 TPM_SETOWNERINSTALL_FALSE,
523 TPM_ENABLE_ACTIVATE_SETOWNERINSTALL_TRUE,
524 TPM_SETOWNERINSTALL_FALSE_DEACTIVATE_DISABLE,
525 TPM_CLEAR_ENABLE_ACTIVATE,
526 TPM_SET_NOPPIPROVISION_FALSE,
527 TPM_SET_NOPPIPROVISION_TRUE,
528 TPM_ENABLE_ACTIVE_CLEAR,
529 TPM_ENABLE_ACTIVE_CLEAR_ENABLE_ACTIVE,
531 static const u8 tpm2_funcs[] = {
532 TPM2_NOOP,
533 TPM2_ENABLE,
534 TPM2_DISABLE,
535 TPM2_CLEAR,
536 TPM2_CLEAR_ENABLE_ACTIVE,
537 TPM2_SET_PP_REQUIRED_FOR_CLEAR_TRUE,
538 TPM2_SET_PP_REQUIRED_FOR_CLEAR_FALSE,
539 TPM2_ENABLE_CLEAR,
540 TPM2_ENABLE_CLEAR2,
541 TPM2_SET_PCR_BANKS,
542 TPM2_CHANGE_EPS,
543 TPM2_SET_PP_REQUIRED_FOR_CHANGE_PCRS_FALSE,
544 TPM2_SET_PP_REQUIRED_FOR_CHANGE_PCRS_TRUE,
545 TPM2_SET_PP_REQUIRED_FOR_TURN_ON_FALSE,
546 TPM2_SET_PP_REQUIRED_FOR_TURN_ON_TRUE,
547 TPM2_SET_PP_REQUIRED_FOR_TURN_OFF_FALSE,
548 TPM2_SET_PP_REQUIRED_FOR_TURN_OFF_TRUE,
549 TPM2_SET_PP_REQUIRED_FOR_CHANGE_EPS_FALSE,
550 TPM2_SET_PP_REQUIRED_FOR_CHANGE_EPS_TRUE,
551 TPM2_LOG_ALL_DIGEST,
552 TPM2_DISABLE_ENDORSMENT_ENABLE_STORAGE_HISTORY,
553 TPM2_ENABLE_BLOCK_SID,
554 TPM2_DISABLE_BLOCK_SID,
555 TPM2_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_TRUE,
556 TPM2_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FALSE,
557 TPM2_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_TRUE,
558 TPM2_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FALSE,
562 * On hot reset/ACPI S3 the contents are preserved.
564 ppib = (void *)cbmem_add(CBMEM_ID_TPM_PPI, sizeof(*ppib));
565 if (!ppib) {
566 printk(BIOS_ERR, "PPI: Failed to add CBMEM\n");
567 return;
569 printk(BIOS_DEBUG, "PPI: Pending OS request: 0x%x (0x%x)\n", ppib->pprq, ppib->pprm);
570 printk(BIOS_DEBUG, "PPI: OS response: CMD 0x%x = 0x%x\n", ppib->lppr, ppib->pprp);
572 enum tpm_family family = tlcl_get_family();
573 if (family == TPM_UNKNOWN) {
574 printk(BIOS_WARNING, "PPI: %s: aborting, because no TPM detected\n", __func__);
575 return;
578 /* Clear unsupported fields */
579 ppib->next_step = 0;
580 ppib->ppin = 1; // Not used by ACPI. Read by EDK-2, must be 1.
581 ppib->ppip = 0;
582 ppib->fret = 0;
583 ppib->next_step = 0;
585 bool found = false;
586 /* Fill in defaults, the TPM command executor may overwrite this list */
587 memset(ppib->func, 0, sizeof(ppib->func));
588 if (family == TPM_1) {
589 for (size_t i = 0; i < ARRAY_SIZE(tpm1_funcs); i++) {
590 ppib->func[tpm1_funcs[i]] = 1;
591 if (ppib->pprq == tpm1_funcs[i])
592 found = true;
594 } else {
595 for (size_t i = 0; i < ARRAY_SIZE(tpm2_funcs); i++) {
596 ppib->func[tpm2_funcs[i]] = 1;
597 if (ppib->pprq == tpm2_funcs[i])
598 found = true;
601 if (!found) {
602 // Set sane defaults
603 ppib->pprq = 0;
604 ppib->pprm = 0;
605 ppib->pprp = 0;
608 /* Physical Presence OpRegion */
609 struct opregion opreg = OPREGION("PPOP", SYSTEMMEMORY, (uintptr_t)ppib,
610 sizeof(*ppib));
612 acpigen_write_opregion(&opreg);
613 acpigen_write_field(opreg.name, list, ARRAY_SIZE(list),
614 FIELD_ANYACC | FIELD_NOLOCK | FIELD_PRESERVE);
616 acpigen_write_name("TPM2");
617 acpigen_write_package(2);
618 acpigen_write_dword(0);
619 acpigen_write_dword(0);
620 acpigen_pop_len(); /* Package */
622 acpigen_write_name("TPM3");
623 acpigen_write_package(3);
624 acpigen_write_dword(0);
625 acpigen_write_dword(0);
626 acpigen_write_dword(0);
627 acpigen_pop_len(); /* Package */
630 * Returns One if the firmware implements this function.
632 * Arg0: Integer PPI function
634 acpigen_write_method_serialized("FUNC", 1);
636 acpigen_write_to_integer(ARG0_OP, LOCAL0_OP);
637 acpigen_write_if();
638 acpigen_emit_byte(LGREATER_OP);
639 acpigen_emit_byte(LOCAL0_OP);
640 acpigen_write_integer(VENDOR_SPECIFIC_OFFSET);
641 acpigen_write_return_integer(0);
642 acpigen_pop_len(); /* If */
644 /* TPPF = CreateField("PPOP", Local0) */
645 acpigen_emit_byte(CREATE_BYTE_OP);
646 acpigen_emit_namestring("PPOP");
647 acpigen_emit_byte(LOCAL0_OP);
648 acpigen_emit_namestring("TPPF");
650 /* Local0 = ToInteger("TPPF") */
651 acpigen_emit_byte(TO_INTEGER_OP);
652 acpigen_emit_namestring("TPPF");
653 acpigen_emit_byte(LOCAL0_OP);
655 acpigen_write_return_op(LOCAL0_OP);
656 acpigen_pop_len(); /* Method */
659 * Returns One if the PPI spec supports this functions.
660 * That doesn't necessarily mean that the firmware implements it, or the
661 * TPM can execute the function.
663 * Arg0: Integer PPI function
664 * Arg1: Integer TPMversion (0: TPM2, 1: TPM1.2)
666 acpigen_write_method("FSUP", 2);
668 acpigen_write_to_integer(ARG0_OP, LOCAL0_OP);
669 acpigen_write_to_integer(ARG1_OP, LOCAL1_OP);
670 acpigen_write_if();
671 acpigen_emit_byte(LGREATER_OP);
672 acpigen_emit_byte(LOCAL0_OP);
673 acpigen_write_integer(VENDOR_SPECIFIC_OFFSET);
674 acpigen_write_return_integer(0);
675 acpigen_pop_len(); /* If */
677 acpigen_write_if_lequal_op_int(LOCAL1_OP, 1);
678 for (size_t i = 0; i < ARRAY_SIZE(tpm1_funcs); i++) {
679 acpigen_write_if_lequal_op_int(LOCAL0_OP, tpm1_funcs[i]);
680 acpigen_write_return_integer(1);
681 acpigen_pop_len(); /* Pop : If */
683 acpigen_pop_len(); /* If */
685 acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
687 for (size_t i = 0; i < ARRAY_SIZE(tpm2_funcs); i++) {
688 acpigen_write_if_lequal_op_int(LOCAL0_OP, tpm2_funcs[i]);
689 acpigen_write_return_integer(1);
690 acpigen_pop_len(); /* Pop : If */
692 acpigen_pop_len(); /* If */
694 acpigen_write_return_integer(0);
695 acpigen_pop_len(); /* Method */
698 * _DSM method
700 struct dsm_uuid ids[] = {
701 /* Physical presence interface.
702 * This is used to submit commands like "Clear TPM" to
703 * be run at next reboot provided that user confirms
704 * them.
706 DSM_UUID(TPM_PPI_UUID, &tpm_ppi_callbacks[0],
707 ARRAY_SIZE(tpm_ppi_callbacks), NULL),
708 /* Memory clearing on boot: just a dummy. */
709 DSM_UUID(TPM_MCI_UUID, &tpm_mci_callbacks[0],
710 ARRAY_SIZE(tpm_mci_callbacks), NULL),
713 acpigen_write_dsm_uuid_arr(ids, ARRAY_SIZE(ids));
716 void lb_tpm_ppi(struct lb_header *header)
718 struct lb_tpm_physical_presence *tpm_ppi;
719 enum tpm_family family;
720 void *ppib;
722 ppib = cbmem_find(CBMEM_ID_TPM_PPI);
723 if (!ppib)
724 return;
726 family = tlcl_get_family();
727 if (family == TPM_UNKNOWN) {
728 printk(BIOS_WARNING, "PPI: %s: aborting, because no TPM detected\n", __func__);
729 return;
732 tpm_ppi = (struct lb_tpm_physical_presence *)lb_new_record(header);
733 tpm_ppi->tag = LB_TAG_TPM_PPI_HANDOFF;
734 tpm_ppi->size = sizeof(*tpm_ppi);
735 tpm_ppi->ppi_address = (uintptr_t)ppib;
736 tpm_ppi->tpm_version = family == TPM_1 ? LB_TPM_VERSION_TPM_VERSION_1_2 :
737 LB_TPM_VERSION_TPM_VERSION_2;
739 tpm_ppi->ppi_version = BCD(1, 3);