qemu

Форк
0
/
tpm.c 
459 строк · 17.6 Кб
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
}
460

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.