12e192b24SSimon Glass /* 22e192b24SSimon Glass * Copyright (c) 2015 Google, Inc 32e192b24SSimon Glass * 42e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 52e192b24SSimon Glass */ 62e192b24SSimon Glass 72e192b24SSimon Glass #include <common.h> 82e192b24SSimon Glass #include <command.h> 92e192b24SSimon Glass #include <environment.h> 102e192b24SSimon Glass #include <tpm.h> 112e192b24SSimon Glass 122e192b24SSimon Glass /* Prints error and returns on failure */ 132e192b24SSimon Glass #define TPM_CHECK(tpm_command) do { \ 142e192b24SSimon Glass uint32_t result; \ 152e192b24SSimon Glass \ 162e192b24SSimon Glass result = (tpm_command); \ 172e192b24SSimon Glass if (result != TPM_SUCCESS) { \ 182e192b24SSimon Glass printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \ 192e192b24SSimon Glass __LINE__, result); \ 202e192b24SSimon Glass return result; \ 212e192b24SSimon Glass } \ 222e192b24SSimon Glass } while (0) 232e192b24SSimon Glass 242e192b24SSimon Glass #define INDEX0 0xda70 252e192b24SSimon Glass #define INDEX1 0xda71 262e192b24SSimon Glass #define INDEX2 0xda72 272e192b24SSimon Glass #define INDEX3 0xda73 282e192b24SSimon Glass #define INDEX_INITIALISED 0xda80 292e192b24SSimon Glass #define PHYS_PRESENCE 4 302e192b24SSimon Glass #define PRESENCE 8 312e192b24SSimon Glass 322e192b24SSimon Glass static uint32_t TlclStartupIfNeeded(void) 332e192b24SSimon Glass { 342e192b24SSimon Glass uint32_t result = tpm_startup(TPM_ST_CLEAR); 352e192b24SSimon Glass 362e192b24SSimon Glass return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result; 372e192b24SSimon Glass } 382e192b24SSimon Glass 392e192b24SSimon Glass static int test_timer(void) 402e192b24SSimon Glass { 412e192b24SSimon Glass printf("get_timer(0) = %lu\n", get_timer(0)); 422e192b24SSimon Glass return 0; 432e192b24SSimon Glass } 442e192b24SSimon Glass 452e192b24SSimon Glass static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated, 462e192b24SSimon Glass uint8_t *nvlocked) 472e192b24SSimon Glass { 482e192b24SSimon Glass struct tpm_permanent_flags pflags; 492e192b24SSimon Glass uint32_t result; 502e192b24SSimon Glass 512e192b24SSimon Glass result = tpm_get_permanent_flags(&pflags); 522e192b24SSimon Glass if (result) 532e192b24SSimon Glass return result; 542e192b24SSimon Glass if (disable) 552e192b24SSimon Glass *disable = pflags.disable; 562e192b24SSimon Glass if (deactivated) 572e192b24SSimon Glass *deactivated = pflags.deactivated; 582e192b24SSimon Glass if (nvlocked) 592e192b24SSimon Glass *nvlocked = pflags.nv_locked; 602e192b24SSimon Glass debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", 612e192b24SSimon Glass pflags.disable, pflags.deactivated, pflags.nv_locked); 622e192b24SSimon Glass 632e192b24SSimon Glass return 0; 642e192b24SSimon Glass } 652e192b24SSimon Glass 662e192b24SSimon Glass static uint32_t tpm_set_global_lock(void) 672e192b24SSimon Glass { 682e192b24SSimon Glass uint32_t x; 692e192b24SSimon Glass 702e192b24SSimon Glass debug("TPM: Set global lock\n"); 712e192b24SSimon Glass return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0); 722e192b24SSimon Glass } 732e192b24SSimon Glass 742e192b24SSimon Glass static uint32_t tpm_nv_write_value_lock(uint32_t index) 752e192b24SSimon Glass { 762e192b24SSimon Glass debug("TPM: Write lock 0x%x\n", index); 772e192b24SSimon Glass 782e192b24SSimon Glass return tpm_nv_write_value(index, NULL, 0); 792e192b24SSimon Glass } 802e192b24SSimon Glass 812e192b24SSimon Glass static uint32_t tpm_nv_set_locked(void) 822e192b24SSimon Glass { 832e192b24SSimon Glass debug("TPM: Set NV locked\n"); 842e192b24SSimon Glass 852e192b24SSimon Glass return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); 862e192b24SSimon Glass } 872e192b24SSimon Glass 882e192b24SSimon Glass static int tpm_is_owned(void) 892e192b24SSimon Glass { 902e192b24SSimon Glass uint8_t response[TPM_PUBEK_SIZE]; 912e192b24SSimon Glass uint32_t result; 922e192b24SSimon Glass 932e192b24SSimon Glass result = tpm_read_pubek(response, sizeof(response)); 942e192b24SSimon Glass 952e192b24SSimon Glass return result != TPM_SUCCESS; 962e192b24SSimon Glass } 972e192b24SSimon Glass 982e192b24SSimon Glass static int test_early_extend(void) 992e192b24SSimon Glass { 1002e192b24SSimon Glass uint8_t value_in[20]; 1012e192b24SSimon Glass uint8_t value_out[20]; 1022e192b24SSimon Glass 1032e192b24SSimon Glass printf("Testing earlyextend ..."); 1042e192b24SSimon Glass tpm_init(); 1052e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); 1062e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 1072e192b24SSimon Glass TPM_CHECK(tpm_extend(1, value_in, value_out)); 1082e192b24SSimon Glass printf("done\n"); 1092e192b24SSimon Glass return 0; 1102e192b24SSimon Glass } 1112e192b24SSimon Glass 1122e192b24SSimon Glass static int test_early_nvram(void) 1132e192b24SSimon Glass { 1142e192b24SSimon Glass uint32_t x; 1152e192b24SSimon Glass 1162e192b24SSimon Glass printf("Testing earlynvram ..."); 1172e192b24SSimon Glass tpm_init(); 1182e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); 1192e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 1202e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 1212e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 1222e192b24SSimon Glass printf("done\n"); 1232e192b24SSimon Glass return 0; 1242e192b24SSimon Glass } 1252e192b24SSimon Glass 1262e192b24SSimon Glass static int test_early_nvram2(void) 1272e192b24SSimon Glass { 1282e192b24SSimon Glass uint32_t x; 1292e192b24SSimon Glass 1302e192b24SSimon Glass printf("Testing earlynvram2 ..."); 1312e192b24SSimon Glass tpm_init(); 1322e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); 1332e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 1342e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 1352e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x))); 1362e192b24SSimon Glass printf("done\n"); 1372e192b24SSimon Glass return 0; 1382e192b24SSimon Glass } 1392e192b24SSimon Glass 1402e192b24SSimon Glass static int test_enable(void) 1412e192b24SSimon Glass { 1422e192b24SSimon Glass uint8_t disable = 0, deactivated = 0; 1432e192b24SSimon Glass 1442e192b24SSimon Glass printf("Testing enable ...\n"); 1452e192b24SSimon Glass tpm_init(); 1462e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 1472e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 1482e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 1492e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 1502e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); 1512e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 1522e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 1532e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 1542e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); 1552e192b24SSimon Glass if (disable == 1 || deactivated == 1) 1562e192b24SSimon Glass printf("\tfailed to enable or activate\n"); 1572e192b24SSimon Glass printf("\tdone\n"); 1582e192b24SSimon Glass return 0; 1592e192b24SSimon Glass } 1602e192b24SSimon Glass 1612e192b24SSimon Glass #define reboot() do { \ 1622e192b24SSimon Glass printf("\trebooting...\n"); \ 1632e192b24SSimon Glass reset_cpu(0); \ 1642e192b24SSimon Glass } while (0) 1652e192b24SSimon Glass 1662e192b24SSimon Glass static int test_fast_enable(void) 1672e192b24SSimon Glass { 1682e192b24SSimon Glass uint8_t disable = 0, deactivated = 0; 1692e192b24SSimon Glass int i; 1702e192b24SSimon Glass 1712e192b24SSimon Glass printf("Testing fastenable ...\n"); 1722e192b24SSimon Glass tpm_init(); 1732e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 1742e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 1752e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 1762e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 1772e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); 1782e192b24SSimon Glass for (i = 0; i < 2; i++) { 1792e192b24SSimon Glass TPM_CHECK(tpm_force_clear()); 1802e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 1812e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, 1822e192b24SSimon Glass deactivated); 1832e192b24SSimon Glass assert(disable == 1 && deactivated == 1); 1842e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 1852e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 1862e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 1872e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, 1882e192b24SSimon Glass deactivated); 1892e192b24SSimon Glass assert(disable == 0 && deactivated == 0); 1902e192b24SSimon Glass } 1912e192b24SSimon Glass printf("\tdone\n"); 1922e192b24SSimon Glass return 0; 1932e192b24SSimon Glass } 1942e192b24SSimon Glass 1952e192b24SSimon Glass static int test_global_lock(void) 1962e192b24SSimon Glass { 1972e192b24SSimon Glass uint32_t zero = 0; 1982e192b24SSimon Glass uint32_t result; 1992e192b24SSimon Glass uint32_t x; 2002e192b24SSimon Glass 2012e192b24SSimon Glass printf("Testing globallock ...\n"); 2022e192b24SSimon Glass tpm_init(); 2032e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 2042e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 2052e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 2062e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 2072e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 2082e192b24SSimon Glass sizeof(uint32_t))); 2092e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 2102e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 2112e192b24SSimon Glass sizeof(uint32_t))); 2122e192b24SSimon Glass TPM_CHECK(tpm_set_global_lock()); 2132e192b24SSimon Glass /* Verifies that write to index0 fails */ 2142e192b24SSimon Glass x = 1; 2152e192b24SSimon Glass result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)); 2162e192b24SSimon Glass assert(result == TPM_AREA_LOCKED); 2172e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 2182e192b24SSimon Glass assert(x == 0); 2192e192b24SSimon Glass /* Verifies that write to index1 is still possible */ 2202e192b24SSimon Glass x = 2; 2212e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x))); 2222e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 2232e192b24SSimon Glass assert(x == 2); 2242e192b24SSimon Glass /* Turns off PP */ 2252e192b24SSimon Glass tpm_tsc_physical_presence(PHYS_PRESENCE); 2262e192b24SSimon Glass /* Verifies that write to index1 fails */ 2272e192b24SSimon Glass x = 3; 2282e192b24SSimon Glass result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)); 2292e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE); 2302e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 2312e192b24SSimon Glass assert(x == 2); 2322e192b24SSimon Glass printf("\tdone\n"); 2332e192b24SSimon Glass return 0; 2342e192b24SSimon Glass } 2352e192b24SSimon Glass 2362e192b24SSimon Glass static int test_lock(void) 2372e192b24SSimon Glass { 2382e192b24SSimon Glass printf("Testing lock ...\n"); 2392e192b24SSimon Glass tpm_init(); 2402e192b24SSimon Glass tpm_startup(TPM_ST_CLEAR); 2412e192b24SSimon Glass tpm_self_test_full(); 2422e192b24SSimon Glass tpm_tsc_physical_presence(PRESENCE); 2432e192b24SSimon Glass tpm_nv_write_value_lock(INDEX0); 2442e192b24SSimon Glass printf("\tLocked 0x%x\n", INDEX0); 2452e192b24SSimon Glass printf("\tdone\n"); 2462e192b24SSimon Glass return 0; 2472e192b24SSimon Glass } 2482e192b24SSimon Glass 2492e192b24SSimon Glass static void initialise_spaces(void) 2502e192b24SSimon Glass { 2512e192b24SSimon Glass uint32_t zero = 0; 2522e192b24SSimon Glass uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; 2532e192b24SSimon Glass 2542e192b24SSimon Glass printf("\tInitialising spaces\n"); 2552e192b24SSimon Glass tpm_nv_set_locked(); /* useful only the first time */ 2562e192b24SSimon Glass tpm_nv_define_space(INDEX0, perm, 4); 2572e192b24SSimon Glass tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4); 2582e192b24SSimon Glass tpm_nv_define_space(INDEX1, perm, 4); 2592e192b24SSimon Glass tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4); 2602e192b24SSimon Glass tpm_nv_define_space(INDEX2, perm, 4); 2612e192b24SSimon Glass tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4); 2622e192b24SSimon Glass tpm_nv_define_space(INDEX3, perm, 4); 2632e192b24SSimon Glass tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4); 2642e192b24SSimon Glass perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | 2652e192b24SSimon Glass TPM_NV_PER_PPWRITE; 2662e192b24SSimon Glass tpm_nv_define_space(INDEX_INITIALISED, perm, 1); 2672e192b24SSimon Glass } 2682e192b24SSimon Glass 2692e192b24SSimon Glass static int test_readonly(void) 2702e192b24SSimon Glass { 2712e192b24SSimon Glass uint8_t c; 2722e192b24SSimon Glass uint32_t index_0, index_1, index_2, index_3; 2732e192b24SSimon Glass int read0, read1, read2, read3; 2742e192b24SSimon Glass 2752e192b24SSimon Glass printf("Testing readonly ...\n"); 2762e192b24SSimon Glass tpm_init(); 2772e192b24SSimon Glass tpm_startup(TPM_ST_CLEAR); 2782e192b24SSimon Glass tpm_self_test_full(); 2792e192b24SSimon Glass tpm_tsc_physical_presence(PRESENCE); 2802e192b24SSimon Glass /* 2812e192b24SSimon Glass * Checks if initialisation has completed by trying to read-lock a 2822e192b24SSimon Glass * space that's created at the end of initialisation 2832e192b24SSimon Glass */ 2842e192b24SSimon Glass if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) { 2852e192b24SSimon Glass /* The initialisation did not complete */ 2862e192b24SSimon Glass initialise_spaces(); 2872e192b24SSimon Glass } 2882e192b24SSimon Glass 2892e192b24SSimon Glass /* Checks if spaces are OK or messed up */ 2902e192b24SSimon Glass read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)); 2912e192b24SSimon Glass read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1)); 2922e192b24SSimon Glass read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2)); 2932e192b24SSimon Glass read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3)); 2942e192b24SSimon Glass if (read0 || read1 || read2 || read3) { 2952e192b24SSimon Glass printf("Invalid contents\n"); 2962e192b24SSimon Glass return 0; 2972e192b24SSimon Glass } 2982e192b24SSimon Glass 2992e192b24SSimon Glass /* 3002e192b24SSimon Glass * Writes space, and locks it. Then attempts to write again. 3012e192b24SSimon Glass * I really wish I could use the imperative. 3022e192b24SSimon Glass */ 3032e192b24SSimon Glass index_0 += 1; 3042e192b24SSimon Glass if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) != 3052e192b24SSimon Glass TPM_SUCCESS)) { 3062e192b24SSimon Glass error("\tcould not write index 0\n"); 3072e192b24SSimon Glass } 3082e192b24SSimon Glass tpm_nv_write_value_lock(INDEX0); 3092e192b24SSimon Glass if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) == 3102e192b24SSimon Glass TPM_SUCCESS) 3112e192b24SSimon Glass error("\tindex 0 is not locked\n"); 3122e192b24SSimon Glass 3132e192b24SSimon Glass printf("\tdone\n"); 3142e192b24SSimon Glass return 0; 3152e192b24SSimon Glass } 3162e192b24SSimon Glass 3172e192b24SSimon Glass static int test_redefine_unowned(void) 3182e192b24SSimon Glass { 3192e192b24SSimon Glass uint32_t perm; 3202e192b24SSimon Glass uint32_t result; 3212e192b24SSimon Glass uint32_t x; 3222e192b24SSimon Glass 3232e192b24SSimon Glass printf("Testing redefine_unowned ..."); 3242e192b24SSimon Glass tpm_init(); 3252e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 3262e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 3272e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 3282e192b24SSimon Glass assert(!tpm_is_owned()); 3292e192b24SSimon Glass 3302e192b24SSimon Glass /* Ensures spaces exist. */ 3312e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 3322e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 3332e192b24SSimon Glass 3342e192b24SSimon Glass /* Redefines spaces a couple of times. */ 3352e192b24SSimon Glass perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK; 3362e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t))); 3372e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t))); 3382e192b24SSimon Glass perm = TPM_NV_PER_PPWRITE; 3392e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); 3402e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); 3412e192b24SSimon Glass 3422e192b24SSimon Glass /* Sets the global lock */ 3432e192b24SSimon Glass tpm_set_global_lock(); 3442e192b24SSimon Glass 3452e192b24SSimon Glass /* Verifies that index0 cannot be redefined */ 3462e192b24SSimon Glass result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); 3472e192b24SSimon Glass assert(result == TPM_AREA_LOCKED); 3482e192b24SSimon Glass 3492e192b24SSimon Glass /* Checks that index1 can */ 3502e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); 3512e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); 3522e192b24SSimon Glass 3532e192b24SSimon Glass /* Turns off PP */ 3542e192b24SSimon Glass tpm_tsc_physical_presence(PHYS_PRESENCE); 3552e192b24SSimon Glass 3562e192b24SSimon Glass /* Verifies that neither index0 nor index1 can be redefined */ 3572e192b24SSimon Glass result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); 3582e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE); 3592e192b24SSimon Glass result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)); 3602e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE); 3612e192b24SSimon Glass 3622e192b24SSimon Glass printf("done\n"); 3632e192b24SSimon Glass return 0; 3642e192b24SSimon Glass } 3652e192b24SSimon Glass 3662e192b24SSimon Glass #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK) 3672e192b24SSimon Glass #define PERMPP TPM_NV_PER_PPWRITE 3682e192b24SSimon Glass 3692e192b24SSimon Glass static int test_space_perm(void) 3702e192b24SSimon Glass { 3712e192b24SSimon Glass uint32_t perm; 3722e192b24SSimon Glass 3732e192b24SSimon Glass printf("Testing spaceperm ..."); 3742e192b24SSimon Glass tpm_init(); 3752e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 3762e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 3772e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 3782e192b24SSimon Glass TPM_CHECK(tpm_get_permissions(INDEX0, &perm)); 3792e192b24SSimon Glass assert((perm & PERMPPGL) == PERMPPGL); 3802e192b24SSimon Glass TPM_CHECK(tpm_get_permissions(INDEX1, &perm)); 3812e192b24SSimon Glass assert((perm & PERMPP) == PERMPP); 3822e192b24SSimon Glass printf("done\n"); 3832e192b24SSimon Glass return 0; 3842e192b24SSimon Glass } 3852e192b24SSimon Glass 3862e192b24SSimon Glass static int test_startup(void) 3872e192b24SSimon Glass { 3882e192b24SSimon Glass uint32_t result; 3892e192b24SSimon Glass printf("Testing startup ...\n"); 3902e192b24SSimon Glass 3912e192b24SSimon Glass tpm_init(); 3922e192b24SSimon Glass result = tpm_startup(TPM_ST_CLEAR); 3932e192b24SSimon Glass if (result != 0 && result != TPM_INVALID_POSTINIT) 3942e192b24SSimon Glass printf("\ttpm startup failed with 0x%x\n", result); 3952e192b24SSimon Glass result = tpm_get_flags(NULL, NULL, NULL); 3962e192b24SSimon Glass if (result != 0) 3972e192b24SSimon Glass printf("\ttpm getflags failed with 0x%x\n", result); 3982e192b24SSimon Glass printf("\texecuting SelfTestFull\n"); 3992e192b24SSimon Glass tpm_self_test_full(); 4002e192b24SSimon Glass result = tpm_get_flags(NULL, NULL, NULL); 4012e192b24SSimon Glass if (result != 0) 4022e192b24SSimon Glass printf("\ttpm getflags failed with 0x%x\n", result); 4032e192b24SSimon Glass printf("\tdone\n"); 4042e192b24SSimon Glass return 0; 4052e192b24SSimon Glass } 4062e192b24SSimon Glass 4072e192b24SSimon Glass /* 4082e192b24SSimon Glass * Runs [op] and ensures it returns success and doesn't run longer than 4092e192b24SSimon Glass * [time_limit] in milliseconds. 4102e192b24SSimon Glass */ 4112e192b24SSimon Glass #define TTPM_CHECK(op, time_limit) do { \ 4122e192b24SSimon Glass ulong start, time; \ 4132e192b24SSimon Glass uint32_t __result; \ 4142e192b24SSimon Glass \ 4152e192b24SSimon Glass start = get_timer(0); \ 4162e192b24SSimon Glass __result = op; \ 4172e192b24SSimon Glass if (__result != TPM_SUCCESS) { \ 4182e192b24SSimon Glass printf("\t" #op ": error 0x%x\n", __result); \ 4192e192b24SSimon Glass return -1; \ 4202e192b24SSimon Glass } \ 4212e192b24SSimon Glass time = get_timer(start); \ 4222e192b24SSimon Glass printf("\t" #op ": %lu ms\n", time); \ 4232e192b24SSimon Glass if (time > (ulong)time_limit) { \ 4242e192b24SSimon Glass printf("\t" #op " exceeded " #time_limit " ms\n"); \ 4252e192b24SSimon Glass } \ 4262e192b24SSimon Glass } while (0) 4272e192b24SSimon Glass 4282e192b24SSimon Glass 4292e192b24SSimon Glass static int test_timing(void) 4302e192b24SSimon Glass { 4312e192b24SSimon Glass uint32_t x; 4322e192b24SSimon Glass uint8_t in[20], out[20]; 4332e192b24SSimon Glass 4342e192b24SSimon Glass printf("Testing timing ..."); 4352e192b24SSimon Glass tpm_init(); 4362e192b24SSimon Glass TTPM_CHECK(TlclStartupIfNeeded(), 50); 4372e192b24SSimon Glass TTPM_CHECK(tpm_continue_self_test(), 100); 4382e192b24SSimon Glass TTPM_CHECK(tpm_self_test_full(), 1000); 4392e192b24SSimon Glass TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100); 4402e192b24SSimon Glass TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); 4412e192b24SSimon Glass TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); 4422e192b24SSimon Glass TTPM_CHECK(tpm_extend(0, in, out), 200); 4432e192b24SSimon Glass TTPM_CHECK(tpm_set_global_lock(), 50); 4442e192b24SSimon Glass TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100); 4452e192b24SSimon Glass printf("done\n"); 4462e192b24SSimon Glass return 0; 4472e192b24SSimon Glass } 4482e192b24SSimon Glass 4492e192b24SSimon Glass #define TPM_MAX_NV_WRITES_NOOWNER 64 4502e192b24SSimon Glass 4512e192b24SSimon Glass static int test_write_limit(void) 4522e192b24SSimon Glass { 4532e192b24SSimon Glass printf("Testing writelimit ...\n"); 4542e192b24SSimon Glass int i; 4552e192b24SSimon Glass uint32_t result; 4562e192b24SSimon Glass 4572e192b24SSimon Glass tpm_init(); 4582e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 4592e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 4602e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 4612e192b24SSimon Glass TPM_CHECK(tpm_force_clear()); 4622e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 4632e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 4642e192b24SSimon Glass 4652e192b24SSimon Glass for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) { 4662e192b24SSimon Glass printf("\twriting %d\n", i); 4672e192b24SSimon Glass result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)); 4682e192b24SSimon Glass switch (result) { 4692e192b24SSimon Glass case TPM_SUCCESS: 4702e192b24SSimon Glass break; 4712e192b24SSimon Glass case TPM_MAXNVWRITES: 4722e192b24SSimon Glass assert(i >= TPM_MAX_NV_WRITES_NOOWNER); 4732e192b24SSimon Glass default: 4742e192b24SSimon Glass error("\tunexpected error code %d (0x%x)\n", 4752e192b24SSimon Glass result, result); 4762e192b24SSimon Glass } 4772e192b24SSimon Glass } 4782e192b24SSimon Glass 4792e192b24SSimon Glass /* Reset write count */ 4802e192b24SSimon Glass TPM_CHECK(tpm_force_clear()); 4812e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 4822e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 4832e192b24SSimon Glass 4842e192b24SSimon Glass /* Try writing again. */ 4852e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i))); 4862e192b24SSimon Glass printf("\tdone\n"); 4872e192b24SSimon Glass return 0; 4882e192b24SSimon Glass } 4892e192b24SSimon Glass 4902e192b24SSimon Glass #define VOIDTEST(XFUNC) \ 4912e192b24SSimon Glass int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \ 4922e192b24SSimon Glass char * const argv[]) \ 4932e192b24SSimon Glass { \ 4942e192b24SSimon Glass return test_##XFUNC(); \ 4952e192b24SSimon Glass } 4962e192b24SSimon Glass 4972e192b24SSimon Glass #define VOIDENT(XNAME) \ 4982e192b24SSimon Glass U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""), 4992e192b24SSimon Glass 5002e192b24SSimon Glass VOIDTEST(early_extend) 5012e192b24SSimon Glass VOIDTEST(early_nvram) 5022e192b24SSimon Glass VOIDTEST(early_nvram2) 5032e192b24SSimon Glass VOIDTEST(enable) 5042e192b24SSimon Glass VOIDTEST(fast_enable) 5052e192b24SSimon Glass VOIDTEST(global_lock) 5062e192b24SSimon Glass VOIDTEST(lock) 5072e192b24SSimon Glass VOIDTEST(readonly) 5082e192b24SSimon Glass VOIDTEST(redefine_unowned) 5092e192b24SSimon Glass VOIDTEST(space_perm) 5102e192b24SSimon Glass VOIDTEST(startup) 5112e192b24SSimon Glass VOIDTEST(timing) 5122e192b24SSimon Glass VOIDTEST(write_limit) 5132e192b24SSimon Glass VOIDTEST(timer) 5142e192b24SSimon Glass 5152e192b24SSimon Glass static cmd_tbl_t cmd_cros_tpm_sub[] = { 5162e192b24SSimon Glass VOIDENT(early_extend) 5172e192b24SSimon Glass VOIDENT(early_nvram) 5182e192b24SSimon Glass VOIDENT(early_nvram2) 5192e192b24SSimon Glass VOIDENT(enable) 5202e192b24SSimon Glass VOIDENT(fast_enable) 5212e192b24SSimon Glass VOIDENT(global_lock) 5222e192b24SSimon Glass VOIDENT(lock) 5232e192b24SSimon Glass VOIDENT(readonly) 5242e192b24SSimon Glass VOIDENT(redefine_unowned) 5252e192b24SSimon Glass VOIDENT(space_perm) 5262e192b24SSimon Glass VOIDENT(startup) 5272e192b24SSimon Glass VOIDENT(timing) 5282e192b24SSimon Glass VOIDENT(write_limit) 5292e192b24SSimon Glass VOIDENT(timer) 5302e192b24SSimon Glass }; 5312e192b24SSimon Glass 5322e192b24SSimon Glass static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 5332e192b24SSimon Glass { 5342e192b24SSimon Glass cmd_tbl_t *c; 535*0427b9c5SStefan Brüns int i; 5362e192b24SSimon Glass 5372e192b24SSimon Glass printf("argc = %d, argv = ", argc); 5382e192b24SSimon Glass 5392e192b24SSimon Glass for (i = 0; i < argc; i++) 5402e192b24SSimon Glass printf(" %s", argv[i]); 541*0427b9c5SStefan Brüns 5422e192b24SSimon Glass printf("\n------\n"); 543*0427b9c5SStefan Brüns 5442e192b24SSimon Glass argc--; 5452e192b24SSimon Glass argv++; 5462e192b24SSimon Glass c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub, 5472e192b24SSimon Glass ARRAY_SIZE(cmd_cros_tpm_sub)); 5482e192b24SSimon Glass return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp); 5492e192b24SSimon Glass } 5502e192b24SSimon Glass 5512e192b24SSimon Glass U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests", 5522e192b24SSimon Glass "\n\tearly_extend\n" 5532e192b24SSimon Glass "\tearly_nvram\n" 5542e192b24SSimon Glass "\tearly_nvram2\n" 5552e192b24SSimon Glass "\tenable\n" 5562e192b24SSimon Glass "\tfast_enable\n" 5572e192b24SSimon Glass "\tglobal_lock\n" 5582e192b24SSimon Glass "\tlock\n" 5592e192b24SSimon Glass "\treadonly\n" 5602e192b24SSimon Glass "\tredefine_unowned\n" 5612e192b24SSimon Glass "\tspace_perm\n" 5622e192b24SSimon Glass "\tstartup\n" 5632e192b24SSimon Glass "\ttiming\n" 5642e192b24SSimon Glass "\twrite_limit\n"); 565