cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
     23void 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}