1*2e192b24SSimon Glass /* 2*2e192b24SSimon Glass * Copyright (c) 2015 Google, Inc 3*2e192b24SSimon Glass * 4*2e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 5*2e192b24SSimon Glass */ 6*2e192b24SSimon Glass 7*2e192b24SSimon Glass #include <common.h> 8*2e192b24SSimon Glass #include <command.h> 9*2e192b24SSimon Glass #include <environment.h> 10*2e192b24SSimon Glass #include <tpm.h> 11*2e192b24SSimon Glass 12*2e192b24SSimon Glass /* Prints error and returns on failure */ 13*2e192b24SSimon Glass #define TPM_CHECK(tpm_command) do { \ 14*2e192b24SSimon Glass uint32_t result; \ 15*2e192b24SSimon Glass \ 16*2e192b24SSimon Glass result = (tpm_command); \ 17*2e192b24SSimon Glass if (result != TPM_SUCCESS) { \ 18*2e192b24SSimon Glass printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \ 19*2e192b24SSimon Glass __LINE__, result); \ 20*2e192b24SSimon Glass return result; \ 21*2e192b24SSimon Glass } \ 22*2e192b24SSimon Glass } while (0) 23*2e192b24SSimon Glass 24*2e192b24SSimon Glass #define INDEX0 0xda70 25*2e192b24SSimon Glass #define INDEX1 0xda71 26*2e192b24SSimon Glass #define INDEX2 0xda72 27*2e192b24SSimon Glass #define INDEX3 0xda73 28*2e192b24SSimon Glass #define INDEX_INITIALISED 0xda80 29*2e192b24SSimon Glass #define PHYS_PRESENCE 4 30*2e192b24SSimon Glass #define PRESENCE 8 31*2e192b24SSimon Glass 32*2e192b24SSimon Glass static uint32_t TlclStartupIfNeeded(void) 33*2e192b24SSimon Glass { 34*2e192b24SSimon Glass uint32_t result = tpm_startup(TPM_ST_CLEAR); 35*2e192b24SSimon Glass 36*2e192b24SSimon Glass return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result; 37*2e192b24SSimon Glass } 38*2e192b24SSimon Glass 39*2e192b24SSimon Glass static int test_timer(void) 40*2e192b24SSimon Glass { 41*2e192b24SSimon Glass printf("get_timer(0) = %lu\n", get_timer(0)); 42*2e192b24SSimon Glass return 0; 43*2e192b24SSimon Glass } 44*2e192b24SSimon Glass 45*2e192b24SSimon Glass static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated, 46*2e192b24SSimon Glass uint8_t *nvlocked) 47*2e192b24SSimon Glass { 48*2e192b24SSimon Glass struct tpm_permanent_flags pflags; 49*2e192b24SSimon Glass uint32_t result; 50*2e192b24SSimon Glass 51*2e192b24SSimon Glass result = tpm_get_permanent_flags(&pflags); 52*2e192b24SSimon Glass if (result) 53*2e192b24SSimon Glass return result; 54*2e192b24SSimon Glass if (disable) 55*2e192b24SSimon Glass *disable = pflags.disable; 56*2e192b24SSimon Glass if (deactivated) 57*2e192b24SSimon Glass *deactivated = pflags.deactivated; 58*2e192b24SSimon Glass if (nvlocked) 59*2e192b24SSimon Glass *nvlocked = pflags.nv_locked; 60*2e192b24SSimon Glass debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", 61*2e192b24SSimon Glass pflags.disable, pflags.deactivated, pflags.nv_locked); 62*2e192b24SSimon Glass 63*2e192b24SSimon Glass return 0; 64*2e192b24SSimon Glass } 65*2e192b24SSimon Glass 66*2e192b24SSimon Glass static uint32_t tpm_set_global_lock(void) 67*2e192b24SSimon Glass { 68*2e192b24SSimon Glass uint32_t x; 69*2e192b24SSimon Glass 70*2e192b24SSimon Glass debug("TPM: Set global lock\n"); 71*2e192b24SSimon Glass return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0); 72*2e192b24SSimon Glass } 73*2e192b24SSimon Glass 74*2e192b24SSimon Glass static uint32_t tpm_nv_write_value_lock(uint32_t index) 75*2e192b24SSimon Glass { 76*2e192b24SSimon Glass debug("TPM: Write lock 0x%x\n", index); 77*2e192b24SSimon Glass 78*2e192b24SSimon Glass return tpm_nv_write_value(index, NULL, 0); 79*2e192b24SSimon Glass } 80*2e192b24SSimon Glass 81*2e192b24SSimon Glass static uint32_t tpm_nv_set_locked(void) 82*2e192b24SSimon Glass { 83*2e192b24SSimon Glass debug("TPM: Set NV locked\n"); 84*2e192b24SSimon Glass 85*2e192b24SSimon Glass return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); 86*2e192b24SSimon Glass } 87*2e192b24SSimon Glass 88*2e192b24SSimon Glass static int tpm_is_owned(void) 89*2e192b24SSimon Glass { 90*2e192b24SSimon Glass uint8_t response[TPM_PUBEK_SIZE]; 91*2e192b24SSimon Glass uint32_t result; 92*2e192b24SSimon Glass 93*2e192b24SSimon Glass result = tpm_read_pubek(response, sizeof(response)); 94*2e192b24SSimon Glass 95*2e192b24SSimon Glass return result != TPM_SUCCESS; 96*2e192b24SSimon Glass } 97*2e192b24SSimon Glass 98*2e192b24SSimon Glass static int test_early_extend(void) 99*2e192b24SSimon Glass { 100*2e192b24SSimon Glass uint8_t value_in[20]; 101*2e192b24SSimon Glass uint8_t value_out[20]; 102*2e192b24SSimon Glass 103*2e192b24SSimon Glass printf("Testing earlyextend ..."); 104*2e192b24SSimon Glass tpm_init(); 105*2e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); 106*2e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 107*2e192b24SSimon Glass TPM_CHECK(tpm_extend(1, value_in, value_out)); 108*2e192b24SSimon Glass printf("done\n"); 109*2e192b24SSimon Glass return 0; 110*2e192b24SSimon Glass } 111*2e192b24SSimon Glass 112*2e192b24SSimon Glass static int test_early_nvram(void) 113*2e192b24SSimon Glass { 114*2e192b24SSimon Glass uint32_t x; 115*2e192b24SSimon Glass 116*2e192b24SSimon Glass printf("Testing earlynvram ..."); 117*2e192b24SSimon Glass tpm_init(); 118*2e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); 119*2e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 120*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 121*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 122*2e192b24SSimon Glass printf("done\n"); 123*2e192b24SSimon Glass return 0; 124*2e192b24SSimon Glass } 125*2e192b24SSimon Glass 126*2e192b24SSimon Glass static int test_early_nvram2(void) 127*2e192b24SSimon Glass { 128*2e192b24SSimon Glass uint32_t x; 129*2e192b24SSimon Glass 130*2e192b24SSimon Glass printf("Testing earlynvram2 ..."); 131*2e192b24SSimon Glass tpm_init(); 132*2e192b24SSimon Glass TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); 133*2e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 134*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 135*2e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x))); 136*2e192b24SSimon Glass printf("done\n"); 137*2e192b24SSimon Glass return 0; 138*2e192b24SSimon Glass } 139*2e192b24SSimon Glass 140*2e192b24SSimon Glass static int test_enable(void) 141*2e192b24SSimon Glass { 142*2e192b24SSimon Glass uint8_t disable = 0, deactivated = 0; 143*2e192b24SSimon Glass 144*2e192b24SSimon Glass printf("Testing enable ...\n"); 145*2e192b24SSimon Glass tpm_init(); 146*2e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 147*2e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 148*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 149*2e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 150*2e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); 151*2e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 152*2e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 153*2e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 154*2e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); 155*2e192b24SSimon Glass if (disable == 1 || deactivated == 1) 156*2e192b24SSimon Glass printf("\tfailed to enable or activate\n"); 157*2e192b24SSimon Glass printf("\tdone\n"); 158*2e192b24SSimon Glass return 0; 159*2e192b24SSimon Glass } 160*2e192b24SSimon Glass 161*2e192b24SSimon Glass #define reboot() do { \ 162*2e192b24SSimon Glass printf("\trebooting...\n"); \ 163*2e192b24SSimon Glass reset_cpu(0); \ 164*2e192b24SSimon Glass } while (0) 165*2e192b24SSimon Glass 166*2e192b24SSimon Glass static int test_fast_enable(void) 167*2e192b24SSimon Glass { 168*2e192b24SSimon Glass uint8_t disable = 0, deactivated = 0; 169*2e192b24SSimon Glass int i; 170*2e192b24SSimon Glass 171*2e192b24SSimon Glass printf("Testing fastenable ...\n"); 172*2e192b24SSimon Glass tpm_init(); 173*2e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 174*2e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 175*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 176*2e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 177*2e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); 178*2e192b24SSimon Glass for (i = 0; i < 2; i++) { 179*2e192b24SSimon Glass TPM_CHECK(tpm_force_clear()); 180*2e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 181*2e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, 182*2e192b24SSimon Glass deactivated); 183*2e192b24SSimon Glass assert(disable == 1 && deactivated == 1); 184*2e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 185*2e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 186*2e192b24SSimon Glass TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); 187*2e192b24SSimon Glass printf("\tdisable is %d, deactivated is %d\n", disable, 188*2e192b24SSimon Glass deactivated); 189*2e192b24SSimon Glass assert(disable == 0 && deactivated == 0); 190*2e192b24SSimon Glass } 191*2e192b24SSimon Glass printf("\tdone\n"); 192*2e192b24SSimon Glass return 0; 193*2e192b24SSimon Glass } 194*2e192b24SSimon Glass 195*2e192b24SSimon Glass static int test_global_lock(void) 196*2e192b24SSimon Glass { 197*2e192b24SSimon Glass uint32_t zero = 0; 198*2e192b24SSimon Glass uint32_t result; 199*2e192b24SSimon Glass uint32_t x; 200*2e192b24SSimon Glass 201*2e192b24SSimon Glass printf("Testing globallock ...\n"); 202*2e192b24SSimon Glass tpm_init(); 203*2e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 204*2e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 205*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 206*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 207*2e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 208*2e192b24SSimon Glass sizeof(uint32_t))); 209*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 210*2e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 211*2e192b24SSimon Glass sizeof(uint32_t))); 212*2e192b24SSimon Glass TPM_CHECK(tpm_set_global_lock()); 213*2e192b24SSimon Glass /* Verifies that write to index0 fails */ 214*2e192b24SSimon Glass x = 1; 215*2e192b24SSimon Glass result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)); 216*2e192b24SSimon Glass assert(result == TPM_AREA_LOCKED); 217*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 218*2e192b24SSimon Glass assert(x == 0); 219*2e192b24SSimon Glass /* Verifies that write to index1 is still possible */ 220*2e192b24SSimon Glass x = 2; 221*2e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x))); 222*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 223*2e192b24SSimon Glass assert(x == 2); 224*2e192b24SSimon Glass /* Turns off PP */ 225*2e192b24SSimon Glass tpm_tsc_physical_presence(PHYS_PRESENCE); 226*2e192b24SSimon Glass /* Verifies that write to index1 fails */ 227*2e192b24SSimon Glass x = 3; 228*2e192b24SSimon Glass result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)); 229*2e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE); 230*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 231*2e192b24SSimon Glass assert(x == 2); 232*2e192b24SSimon Glass printf("\tdone\n"); 233*2e192b24SSimon Glass return 0; 234*2e192b24SSimon Glass } 235*2e192b24SSimon Glass 236*2e192b24SSimon Glass static int test_lock(void) 237*2e192b24SSimon Glass { 238*2e192b24SSimon Glass printf("Testing lock ...\n"); 239*2e192b24SSimon Glass tpm_init(); 240*2e192b24SSimon Glass tpm_startup(TPM_ST_CLEAR); 241*2e192b24SSimon Glass tpm_self_test_full(); 242*2e192b24SSimon Glass tpm_tsc_physical_presence(PRESENCE); 243*2e192b24SSimon Glass tpm_nv_write_value_lock(INDEX0); 244*2e192b24SSimon Glass printf("\tLocked 0x%x\n", INDEX0); 245*2e192b24SSimon Glass printf("\tdone\n"); 246*2e192b24SSimon Glass return 0; 247*2e192b24SSimon Glass } 248*2e192b24SSimon Glass 249*2e192b24SSimon Glass static void initialise_spaces(void) 250*2e192b24SSimon Glass { 251*2e192b24SSimon Glass uint32_t zero = 0; 252*2e192b24SSimon Glass uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; 253*2e192b24SSimon Glass 254*2e192b24SSimon Glass printf("\tInitialising spaces\n"); 255*2e192b24SSimon Glass tpm_nv_set_locked(); /* useful only the first time */ 256*2e192b24SSimon Glass tpm_nv_define_space(INDEX0, perm, 4); 257*2e192b24SSimon Glass tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4); 258*2e192b24SSimon Glass tpm_nv_define_space(INDEX1, perm, 4); 259*2e192b24SSimon Glass tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4); 260*2e192b24SSimon Glass tpm_nv_define_space(INDEX2, perm, 4); 261*2e192b24SSimon Glass tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4); 262*2e192b24SSimon Glass tpm_nv_define_space(INDEX3, perm, 4); 263*2e192b24SSimon Glass tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4); 264*2e192b24SSimon Glass perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | 265*2e192b24SSimon Glass TPM_NV_PER_PPWRITE; 266*2e192b24SSimon Glass tpm_nv_define_space(INDEX_INITIALISED, perm, 1); 267*2e192b24SSimon Glass } 268*2e192b24SSimon Glass 269*2e192b24SSimon Glass static int test_readonly(void) 270*2e192b24SSimon Glass { 271*2e192b24SSimon Glass uint8_t c; 272*2e192b24SSimon Glass uint32_t index_0, index_1, index_2, index_3; 273*2e192b24SSimon Glass int read0, read1, read2, read3; 274*2e192b24SSimon Glass 275*2e192b24SSimon Glass printf("Testing readonly ...\n"); 276*2e192b24SSimon Glass tpm_init(); 277*2e192b24SSimon Glass tpm_startup(TPM_ST_CLEAR); 278*2e192b24SSimon Glass tpm_self_test_full(); 279*2e192b24SSimon Glass tpm_tsc_physical_presence(PRESENCE); 280*2e192b24SSimon Glass /* 281*2e192b24SSimon Glass * Checks if initialisation has completed by trying to read-lock a 282*2e192b24SSimon Glass * space that's created at the end of initialisation 283*2e192b24SSimon Glass */ 284*2e192b24SSimon Glass if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) { 285*2e192b24SSimon Glass /* The initialisation did not complete */ 286*2e192b24SSimon Glass initialise_spaces(); 287*2e192b24SSimon Glass } 288*2e192b24SSimon Glass 289*2e192b24SSimon Glass /* Checks if spaces are OK or messed up */ 290*2e192b24SSimon Glass read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)); 291*2e192b24SSimon Glass read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1)); 292*2e192b24SSimon Glass read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2)); 293*2e192b24SSimon Glass read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3)); 294*2e192b24SSimon Glass if (read0 || read1 || read2 || read3) { 295*2e192b24SSimon Glass printf("Invalid contents\n"); 296*2e192b24SSimon Glass return 0; 297*2e192b24SSimon Glass } 298*2e192b24SSimon Glass 299*2e192b24SSimon Glass /* 300*2e192b24SSimon Glass * Writes space, and locks it. Then attempts to write again. 301*2e192b24SSimon Glass * I really wish I could use the imperative. 302*2e192b24SSimon Glass */ 303*2e192b24SSimon Glass index_0 += 1; 304*2e192b24SSimon Glass if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) != 305*2e192b24SSimon Glass TPM_SUCCESS)) { 306*2e192b24SSimon Glass error("\tcould not write index 0\n"); 307*2e192b24SSimon Glass } 308*2e192b24SSimon Glass tpm_nv_write_value_lock(INDEX0); 309*2e192b24SSimon Glass if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) == 310*2e192b24SSimon Glass TPM_SUCCESS) 311*2e192b24SSimon Glass error("\tindex 0 is not locked\n"); 312*2e192b24SSimon Glass 313*2e192b24SSimon Glass printf("\tdone\n"); 314*2e192b24SSimon Glass return 0; 315*2e192b24SSimon Glass } 316*2e192b24SSimon Glass 317*2e192b24SSimon Glass static int test_redefine_unowned(void) 318*2e192b24SSimon Glass { 319*2e192b24SSimon Glass uint32_t perm; 320*2e192b24SSimon Glass uint32_t result; 321*2e192b24SSimon Glass uint32_t x; 322*2e192b24SSimon Glass 323*2e192b24SSimon Glass printf("Testing redefine_unowned ..."); 324*2e192b24SSimon Glass tpm_init(); 325*2e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 326*2e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 327*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 328*2e192b24SSimon Glass assert(!tpm_is_owned()); 329*2e192b24SSimon Glass 330*2e192b24SSimon Glass /* Ensures spaces exist. */ 331*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); 332*2e192b24SSimon Glass TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); 333*2e192b24SSimon Glass 334*2e192b24SSimon Glass /* Redefines spaces a couple of times. */ 335*2e192b24SSimon Glass perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK; 336*2e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t))); 337*2e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t))); 338*2e192b24SSimon Glass perm = TPM_NV_PER_PPWRITE; 339*2e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); 340*2e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); 341*2e192b24SSimon Glass 342*2e192b24SSimon Glass /* Sets the global lock */ 343*2e192b24SSimon Glass tpm_set_global_lock(); 344*2e192b24SSimon Glass 345*2e192b24SSimon Glass /* Verifies that index0 cannot be redefined */ 346*2e192b24SSimon Glass result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); 347*2e192b24SSimon Glass assert(result == TPM_AREA_LOCKED); 348*2e192b24SSimon Glass 349*2e192b24SSimon Glass /* Checks that index1 can */ 350*2e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); 351*2e192b24SSimon Glass TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); 352*2e192b24SSimon Glass 353*2e192b24SSimon Glass /* Turns off PP */ 354*2e192b24SSimon Glass tpm_tsc_physical_presence(PHYS_PRESENCE); 355*2e192b24SSimon Glass 356*2e192b24SSimon Glass /* Verifies that neither index0 nor index1 can be redefined */ 357*2e192b24SSimon Glass result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); 358*2e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE); 359*2e192b24SSimon Glass result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)); 360*2e192b24SSimon Glass assert(result == TPM_BAD_PRESENCE); 361*2e192b24SSimon Glass 362*2e192b24SSimon Glass printf("done\n"); 363*2e192b24SSimon Glass return 0; 364*2e192b24SSimon Glass } 365*2e192b24SSimon Glass 366*2e192b24SSimon Glass #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK) 367*2e192b24SSimon Glass #define PERMPP TPM_NV_PER_PPWRITE 368*2e192b24SSimon Glass 369*2e192b24SSimon Glass static int test_space_perm(void) 370*2e192b24SSimon Glass { 371*2e192b24SSimon Glass uint32_t perm; 372*2e192b24SSimon Glass 373*2e192b24SSimon Glass printf("Testing spaceperm ..."); 374*2e192b24SSimon Glass tpm_init(); 375*2e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 376*2e192b24SSimon Glass TPM_CHECK(tpm_continue_self_test()); 377*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 378*2e192b24SSimon Glass TPM_CHECK(tpm_get_permissions(INDEX0, &perm)); 379*2e192b24SSimon Glass assert((perm & PERMPPGL) == PERMPPGL); 380*2e192b24SSimon Glass TPM_CHECK(tpm_get_permissions(INDEX1, &perm)); 381*2e192b24SSimon Glass assert((perm & PERMPP) == PERMPP); 382*2e192b24SSimon Glass printf("done\n"); 383*2e192b24SSimon Glass return 0; 384*2e192b24SSimon Glass } 385*2e192b24SSimon Glass 386*2e192b24SSimon Glass static int test_startup(void) 387*2e192b24SSimon Glass { 388*2e192b24SSimon Glass uint32_t result; 389*2e192b24SSimon Glass printf("Testing startup ...\n"); 390*2e192b24SSimon Glass 391*2e192b24SSimon Glass tpm_init(); 392*2e192b24SSimon Glass result = tpm_startup(TPM_ST_CLEAR); 393*2e192b24SSimon Glass if (result != 0 && result != TPM_INVALID_POSTINIT) 394*2e192b24SSimon Glass printf("\ttpm startup failed with 0x%x\n", result); 395*2e192b24SSimon Glass result = tpm_get_flags(NULL, NULL, NULL); 396*2e192b24SSimon Glass if (result != 0) 397*2e192b24SSimon Glass printf("\ttpm getflags failed with 0x%x\n", result); 398*2e192b24SSimon Glass printf("\texecuting SelfTestFull\n"); 399*2e192b24SSimon Glass tpm_self_test_full(); 400*2e192b24SSimon Glass result = tpm_get_flags(NULL, NULL, NULL); 401*2e192b24SSimon Glass if (result != 0) 402*2e192b24SSimon Glass printf("\ttpm getflags failed with 0x%x\n", result); 403*2e192b24SSimon Glass printf("\tdone\n"); 404*2e192b24SSimon Glass return 0; 405*2e192b24SSimon Glass } 406*2e192b24SSimon Glass 407*2e192b24SSimon Glass /* 408*2e192b24SSimon Glass * Runs [op] and ensures it returns success and doesn't run longer than 409*2e192b24SSimon Glass * [time_limit] in milliseconds. 410*2e192b24SSimon Glass */ 411*2e192b24SSimon Glass #define TTPM_CHECK(op, time_limit) do { \ 412*2e192b24SSimon Glass ulong start, time; \ 413*2e192b24SSimon Glass uint32_t __result; \ 414*2e192b24SSimon Glass \ 415*2e192b24SSimon Glass start = get_timer(0); \ 416*2e192b24SSimon Glass __result = op; \ 417*2e192b24SSimon Glass if (__result != TPM_SUCCESS) { \ 418*2e192b24SSimon Glass printf("\t" #op ": error 0x%x\n", __result); \ 419*2e192b24SSimon Glass return -1; \ 420*2e192b24SSimon Glass } \ 421*2e192b24SSimon Glass time = get_timer(start); \ 422*2e192b24SSimon Glass printf("\t" #op ": %lu ms\n", time); \ 423*2e192b24SSimon Glass if (time > (ulong)time_limit) { \ 424*2e192b24SSimon Glass printf("\t" #op " exceeded " #time_limit " ms\n"); \ 425*2e192b24SSimon Glass } \ 426*2e192b24SSimon Glass } while (0) 427*2e192b24SSimon Glass 428*2e192b24SSimon Glass 429*2e192b24SSimon Glass static int test_timing(void) 430*2e192b24SSimon Glass { 431*2e192b24SSimon Glass uint32_t x; 432*2e192b24SSimon Glass uint8_t in[20], out[20]; 433*2e192b24SSimon Glass 434*2e192b24SSimon Glass printf("Testing timing ..."); 435*2e192b24SSimon Glass tpm_init(); 436*2e192b24SSimon Glass TTPM_CHECK(TlclStartupIfNeeded(), 50); 437*2e192b24SSimon Glass TTPM_CHECK(tpm_continue_self_test(), 100); 438*2e192b24SSimon Glass TTPM_CHECK(tpm_self_test_full(), 1000); 439*2e192b24SSimon Glass TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100); 440*2e192b24SSimon Glass TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); 441*2e192b24SSimon Glass TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); 442*2e192b24SSimon Glass TTPM_CHECK(tpm_extend(0, in, out), 200); 443*2e192b24SSimon Glass TTPM_CHECK(tpm_set_global_lock(), 50); 444*2e192b24SSimon Glass TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100); 445*2e192b24SSimon Glass printf("done\n"); 446*2e192b24SSimon Glass return 0; 447*2e192b24SSimon Glass } 448*2e192b24SSimon Glass 449*2e192b24SSimon Glass #define TPM_MAX_NV_WRITES_NOOWNER 64 450*2e192b24SSimon Glass 451*2e192b24SSimon Glass static int test_write_limit(void) 452*2e192b24SSimon Glass { 453*2e192b24SSimon Glass printf("Testing writelimit ...\n"); 454*2e192b24SSimon Glass int i; 455*2e192b24SSimon Glass uint32_t result; 456*2e192b24SSimon Glass 457*2e192b24SSimon Glass tpm_init(); 458*2e192b24SSimon Glass TPM_CHECK(TlclStartupIfNeeded()); 459*2e192b24SSimon Glass TPM_CHECK(tpm_self_test_full()); 460*2e192b24SSimon Glass TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); 461*2e192b24SSimon Glass TPM_CHECK(tpm_force_clear()); 462*2e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 463*2e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 464*2e192b24SSimon Glass 465*2e192b24SSimon Glass for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) { 466*2e192b24SSimon Glass printf("\twriting %d\n", i); 467*2e192b24SSimon Glass result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)); 468*2e192b24SSimon Glass switch (result) { 469*2e192b24SSimon Glass case TPM_SUCCESS: 470*2e192b24SSimon Glass break; 471*2e192b24SSimon Glass case TPM_MAXNVWRITES: 472*2e192b24SSimon Glass assert(i >= TPM_MAX_NV_WRITES_NOOWNER); 473*2e192b24SSimon Glass default: 474*2e192b24SSimon Glass error("\tunexpected error code %d (0x%x)\n", 475*2e192b24SSimon Glass result, result); 476*2e192b24SSimon Glass } 477*2e192b24SSimon Glass } 478*2e192b24SSimon Glass 479*2e192b24SSimon Glass /* Reset write count */ 480*2e192b24SSimon Glass TPM_CHECK(tpm_force_clear()); 481*2e192b24SSimon Glass TPM_CHECK(tpm_physical_enable()); 482*2e192b24SSimon Glass TPM_CHECK(tpm_physical_set_deactivated(0)); 483*2e192b24SSimon Glass 484*2e192b24SSimon Glass /* Try writing again. */ 485*2e192b24SSimon Glass TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i))); 486*2e192b24SSimon Glass printf("\tdone\n"); 487*2e192b24SSimon Glass return 0; 488*2e192b24SSimon Glass } 489*2e192b24SSimon Glass 490*2e192b24SSimon Glass #define VOIDTEST(XFUNC) \ 491*2e192b24SSimon Glass int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \ 492*2e192b24SSimon Glass char * const argv[]) \ 493*2e192b24SSimon Glass { \ 494*2e192b24SSimon Glass return test_##XFUNC(); \ 495*2e192b24SSimon Glass } 496*2e192b24SSimon Glass 497*2e192b24SSimon Glass #define VOIDENT(XNAME) \ 498*2e192b24SSimon Glass U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""), 499*2e192b24SSimon Glass 500*2e192b24SSimon Glass VOIDTEST(early_extend) 501*2e192b24SSimon Glass VOIDTEST(early_nvram) 502*2e192b24SSimon Glass VOIDTEST(early_nvram2) 503*2e192b24SSimon Glass VOIDTEST(enable) 504*2e192b24SSimon Glass VOIDTEST(fast_enable) 505*2e192b24SSimon Glass VOIDTEST(global_lock) 506*2e192b24SSimon Glass VOIDTEST(lock) 507*2e192b24SSimon Glass VOIDTEST(readonly) 508*2e192b24SSimon Glass VOIDTEST(redefine_unowned) 509*2e192b24SSimon Glass VOIDTEST(space_perm) 510*2e192b24SSimon Glass VOIDTEST(startup) 511*2e192b24SSimon Glass VOIDTEST(timing) 512*2e192b24SSimon Glass VOIDTEST(write_limit) 513*2e192b24SSimon Glass VOIDTEST(timer) 514*2e192b24SSimon Glass 515*2e192b24SSimon Glass static cmd_tbl_t cmd_cros_tpm_sub[] = { 516*2e192b24SSimon Glass VOIDENT(early_extend) 517*2e192b24SSimon Glass VOIDENT(early_nvram) 518*2e192b24SSimon Glass VOIDENT(early_nvram2) 519*2e192b24SSimon Glass VOIDENT(enable) 520*2e192b24SSimon Glass VOIDENT(fast_enable) 521*2e192b24SSimon Glass VOIDENT(global_lock) 522*2e192b24SSimon Glass VOIDENT(lock) 523*2e192b24SSimon Glass VOIDENT(readonly) 524*2e192b24SSimon Glass VOIDENT(redefine_unowned) 525*2e192b24SSimon Glass VOIDENT(space_perm) 526*2e192b24SSimon Glass VOIDENT(startup) 527*2e192b24SSimon Glass VOIDENT(timing) 528*2e192b24SSimon Glass VOIDENT(write_limit) 529*2e192b24SSimon Glass VOIDENT(timer) 530*2e192b24SSimon Glass }; 531*2e192b24SSimon Glass 532*2e192b24SSimon Glass static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 533*2e192b24SSimon Glass { 534*2e192b24SSimon Glass cmd_tbl_t *c; 535*2e192b24SSimon Glass 536*2e192b24SSimon Glass printf("argc = %d, argv = ", argc); 537*2e192b24SSimon Glass do { 538*2e192b24SSimon Glass int i = 0; 539*2e192b24SSimon Glass 540*2e192b24SSimon Glass for (i = 0; i < argc; i++) 541*2e192b24SSimon Glass printf(" %s", argv[i]); 542*2e192b24SSimon Glass printf("\n------\n"); 543*2e192b24SSimon Glass } while (0); 544*2e192b24SSimon Glass argc--; 545*2e192b24SSimon Glass argv++; 546*2e192b24SSimon Glass c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub, 547*2e192b24SSimon Glass ARRAY_SIZE(cmd_cros_tpm_sub)); 548*2e192b24SSimon Glass return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp); 549*2e192b24SSimon Glass } 550*2e192b24SSimon Glass 551*2e192b24SSimon Glass U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests", 552*2e192b24SSimon Glass "\n\tearly_extend\n" 553*2e192b24SSimon Glass "\tearly_nvram\n" 554*2e192b24SSimon Glass "\tearly_nvram2\n" 555*2e192b24SSimon Glass "\tenable\n" 556*2e192b24SSimon Glass "\tfast_enable\n" 557*2e192b24SSimon Glass "\tglobal_lock\n" 558*2e192b24SSimon Glass "\tlock\n" 559*2e192b24SSimon Glass "\treadonly\n" 560*2e192b24SSimon Glass "\tredefine_unowned\n" 561*2e192b24SSimon Glass "\tspace_perm\n" 562*2e192b24SSimon Glass "\tstartup\n" 563*2e192b24SSimon Glass "\ttiming\n" 564*2e192b24SSimon Glass "\twrite_limit\n"); 565