qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

tpm.c (18053B)


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