33#include <types.h>
44#include <acpi/acpigen.h>
55#include <acpi/acpi_device.h>
6+ #include <cpu/x86/smm.h>
67#include <cbmem.h>
78#include <console/console.h>
89#include <security/tpm/tss.h>
10+ #include <smm_call.h>
911
1012#include "tpm_ppi.h"
1113
@@ -153,7 +155,14 @@ static void tpm_ppi_func2_cb(void *arg)
153155 acpigen_write_store_op_to_namestr (ZERO_OP , "^OARG" );
154156 acpigen_write_store_op_to_namestr (ZERO_OP , "^USER" );
155157
156- acpigen_write_return_integer (PPI2_RET_SUCCESS );
158+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
159+ acpigen_write_store_op_to_namestr (ARG2_OP , "^PPIP" );
160+ acpigen_write_store_namestr_to_namestr ( "^PPIN" , "^SMI" );
161+ acpigen_write_return_namestr ("^FRET" );
162+ } else {
163+ acpigen_write_return_integer (PPI2_RET_SUCCESS );
164+ }
165+
157166 acpigen_pop_len ();
158167
159168 acpigen_write_return_integer (PPI2_RET_GENERAL_FAILURE );
@@ -289,6 +298,11 @@ static void tpm_ppi_func5_cb(void *arg)
289298 acpigen_emit_byte (LOCAL1_OP );
290299 set_package_element_op ("^TPM3" , 0 , LOCAL1_OP );
291300
301+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
302+ acpigen_write_store_op_to_namestr (ARG2_OP , "^PPIP" );
303+ acpigen_write_store_namestr_to_namestr ( "^PPIN" , "^SMI" );
304+ }
305+
292306 /* ^TPM3 [1] = ^LCMD */
293307 set_package_element_name ("^TPM3" , 1 , "^LCMD" );
294308
@@ -345,12 +359,13 @@ static void tpm_ppi_func7_cb(void *arg)
345359 acpigen_emit_byte (LOCAL1_OP );
346360 acpigen_write_if_lequal_op_int (LOCAL1_OP , 3 );
347361
348- /* Enforce use of Revision 1 that doesn't take an optional argument. */
349-
350- /* Local0 = One */
351- acpigen_write_store ();
352- acpigen_emit_byte (ONE_OP );
353- acpigen_emit_byte (LOCAL0_OP );
362+ if (!CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
363+ /* Enforce use of Revision 1 that doesn't take an optional argument. */
364+ /* Local0 = One */
365+ acpigen_write_store ();
366+ acpigen_emit_byte (ONE_OP );
367+ acpigen_emit_byte (LOCAL0_OP );
368+ }
354369
355370 acpigen_pop_len ();
356371
@@ -365,7 +380,14 @@ static void tpm_ppi_func7_cb(void *arg)
365380 /* ^OARG = Zero */
366381 acpigen_write_store_op_to_namestr (ZERO_OP , "^OARG" );
367382
368- acpigen_write_return_byte (PPI7_RET_SUCCESS );
383+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
384+ acpigen_write_store_op_to_namestr (ARG2_OP , "^PPIP" );
385+ acpigen_write_store_namestr_to_namestr ( "^PPIN" , "^SMI" );
386+ acpigen_write_return_namestr ("^FRET" );
387+ } else {
388+ acpigen_write_return_byte (PPI7_RET_SUCCESS );
389+ }
390+
369391 acpigen_pop_len ();
370392
371393 /* Revision 2 */
@@ -379,7 +401,14 @@ static void tpm_ppi_func7_cb(void *arg)
379401 acpigen_emit_byte (LOCAL3_OP );
380402 acpigen_emit_namestring ("^OARG" );
381403
382- acpigen_write_return_byte (PPI7_RET_SUCCESS );
404+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
405+ acpigen_write_store_op_to_namestr (ARG2_OP , "^PPIP" );
406+ acpigen_write_store_namestr_to_namestr ( "^PPIN" , "^SMI" );
407+ acpigen_write_return_namestr ("^FRET" );
408+ } else {
409+ acpigen_write_return_byte (PPI7_RET_SUCCESS );
410+ }
411+
383412 acpigen_pop_len ();
384413
385414 acpigen_write_return_byte (PPI7_RET_GENERAL_FAILURE );
@@ -430,9 +459,9 @@ static void tpm_ppi_func8_cb(void *arg)
430459 */
431460 static const u32 tpm1_funcs [] = {
432461 TPM_NOOP ,
433- TPM_SET_NOPPICLEAR_TRUE ,
434- TPM_SET_NOPPIMAINTAINANCE_TRUE ,
435- TPM_SET_NOPPIPROVISION_TRUE ,
462+ TPM_SET_NOPPIPROVISION_FALSE ,
463+ TPM_SET_NOPPICLEAR_FALSE ,
464+ TPM_SET_NOPPIMAINTAINANCE_FALSE ,
436465 };
437466 for (size_t i = 0 ; i < ARRAY_SIZE (tpm1_funcs ); i ++ ) {
438467 acpigen_write_if_lequal_op_int (LOCAL2_OP , tpm1_funcs [i ]);
@@ -460,7 +489,15 @@ static void tpm_ppi_func8_cb(void *arg)
460489 acpigen_pop_len (); /* Pop : If */
461490 }
462491 }
463- acpigen_write_return_integer (PPI8_RET_ALLOWED_WITH_PP );
492+
493+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
494+ acpigen_write_store_op_to_namestr (ARG2_OP , "^PPIP" );
495+ acpigen_write_store_op_to_namestr (LOCAL2_OP , "^UCRQ" );
496+ acpigen_write_store_namestr_to_namestr ( "^PPIN" , "^SMI" );
497+ acpigen_write_return_namestr ("^FRET" );
498+ } else {
499+ acpigen_write_return_integer (PPI8_RET_ALLOWED_WITH_PP );
500+ }
464501
465502 acpigen_pop_len ();
466503
@@ -501,13 +538,18 @@ void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
501538
502539 static const struct fieldlist list [] = {
503540 FIELDLIST_OFFSET (0x100 ),// FIXME: Add support for func
504- FIELDLIST_NAMESTR ("PPIN" , 8 ),// Not used
505- FIELDLIST_NAMESTR ("PPIP" , 32 ),// Not used
541+ FIELDLIST_NAMESTR ("PPIN" , 8 ), // SMI interrupt to use
542+ FIELDLIST_NAMESTR ("PPIP" , 32 ),// ACPI function index to pass to SMM code
506543 FIELDLIST_NAMESTR ("RESU" , 32 ),// Result of the last operation (TPM error code)
507544 FIELDLIST_NAMESTR ("CMDR" , 32 ),// The command requested by OS. 0 for NOP
508545 FIELDLIST_NAMESTR ("OARG" , 32 ),// The command optional argument requested by OS
509546 FIELDLIST_NAMESTR ("LCMD" , 32 ),// The last command requested by OS.
510- FIELDLIST_NAMESTR ("FRET" , 32 ),// Not used
547+ FIELDLIST_NAMESTR ("FRET" , 32 ),// Result code from SMM function
548+ FIELDLIST_NAMESTR ("MCIN" , 8 ), // SMI interrupt for Memory Clear Interface
549+ FIELDLIST_NAMESTR ("MCIP" , 32 ),// Used for save the Mor parameter
550+ FIELDLIST_NAMESTR ("MORD" , 32 ),// Memory Overwrite Request Data
551+ FIELDLIST_NAMESTR ("MRET" , 32 ),// Memory Overwrite function return code
552+ FIELDLIST_NAMESTR ("UCRQ" , 32 ),// Physical Presence request operation to Get User Confirmation Status
511553 };
512554 static const u8 tpm1_funcs [] = {
513555 TPM_NOOP ,
@@ -577,7 +619,8 @@ void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
577619
578620 /* Clear unsupported fields */
579621 ppib -> next_step = 0 ;
580- ppib -> ppin = 1 ; // Not used by ACPI. Read by EDK-2, must be 1.
622+ /* Read by EDK-2, must be non-zero. */
623+ ppib -> ppin = CONFIG (TPM_PPI_UEFIVAR_BACKED ) ? APM_CNT_TPM_PPI : 1 ;
581624 ppib -> ppip = 0 ;
582625 ppib -> fret = 0 ;
583626
@@ -612,6 +655,19 @@ void tpm_ppi_acpi_fill_ssdt(const struct device *dev)
612655 acpigen_write_field (opreg .name , list , ARRAY_SIZE (list ),
613656 FIELD_ANYACC | FIELD_NOLOCK | FIELD_PRESERVE );
614657
658+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED )) {
659+ const struct opregion smi_opreg = OPREGION ("TSMI" , SYSTEMIO ,
660+ pm_acpi_smi_cmd_port (),
661+ sizeof (uint16_t ));
662+ const struct fieldlist smi_port [] = {
663+ FIELDLIST_NAMESTR ("SMI" , 16 ),
664+ };
665+
666+ acpigen_write_opregion (& smi_opreg );
667+ acpigen_write_field (smi_opreg .name , smi_port , ARRAY_SIZE (smi_port ),
668+ FIELD_WORDACC | FIELD_NOLOCK | FIELD_PRESERVE );
669+ }
670+
615671 acpigen_write_name ("TPM2" );
616672 acpigen_write_package (2 );
617673 acpigen_write_dword (0 );
@@ -732,8 +788,11 @@ void lb_tpm_ppi(struct lb_header *header)
732788 void * ppib ;
733789
734790 ppib = cbmem_find (CBMEM_ID_TPM_PPI );
735- if (!ppib )
791+ if (!ppib ) {
792+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED ))
793+ call_smm (APM_CNT_TPM_PPI , 0 , NULL );
736794 return ;
795+ }
737796
738797 family = tlcl_get_family ();
739798 if (family == TPM_UNKNOWN ) {
@@ -749,4 +808,7 @@ void lb_tpm_ppi(struct lb_header *header)
749808 LB_TPM_VERSION_TPM_VERSION_2 ;
750809
751810 tpm_ppi -> ppi_version = BCD (1 , 3 );
811+
812+ if (CONFIG (TPM_PPI_UEFIVAR_BACKED ))
813+ call_smm (APM_CNT_TPM_PPI , 0 , (void * )ppib );
752814}
0 commit comments