1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2013 The Chromium OS Authors. 4 */ 5 6 #include <common.h> 7 #include <command.h> 8 #include <dm.h> 9 #include <environment.h> 10 #include <malloc.h> 11 #include <asm/unaligned.h> 12 #include <linux/string.h> 13 #include <tpm-common.h> 14 #include "tpm-user-utils.h" 15 16 static struct udevice *tpm_dev; 17 18 /** 19 * Print a byte string in hexdecimal format, 16-bytes per line. 20 * 21 * @param data byte string to be printed 22 * @param count number of bytes to be printed 23 */ 24 void print_byte_string(u8 *data, size_t count) 25 { 26 int i, print_newline = 0; 27 28 for (i = 0; i < count; i++) { 29 printf(" %02x", data[i]); 30 print_newline = (i % 16 == 15); 31 if (print_newline) 32 putc('\n'); 33 } 34 /* Avoid duplicated newline at the end */ 35 if (!print_newline) 36 putc('\n'); 37 } 38 39 /** 40 * Convert a text string of hexdecimal values into a byte string. 41 * 42 * @param bytes text string of hexdecimal values with no space 43 * between them 44 * @param data output buffer for byte string. The caller has to make 45 * sure it is large enough for storing the output. If 46 * NULL is passed, a large enough buffer will be allocated, 47 * and the caller must free it. 48 * @param count_ptr output variable for the length of byte string 49 * Return: pointer to output buffer 50 */ 51 void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr) 52 { 53 char byte[3]; 54 size_t count, length; 55 int i; 56 57 if (!bytes) 58 return NULL; 59 length = strlen(bytes); 60 count = length / 2; 61 62 if (!data) 63 data = malloc(count); 64 if (!data) 65 return NULL; 66 67 byte[2] = '\0'; 68 for (i = 0; i < length; i += 2) { 69 byte[0] = bytes[i]; 70 byte[1] = bytes[i + 1]; 71 data[i / 2] = (u8)simple_strtoul(byte, NULL, 16); 72 } 73 74 if (count_ptr) 75 *count_ptr = count; 76 77 return data; 78 } 79 80 /** 81 * report_return_code() - Report any error and return failure or success 82 * 83 * @param return_code TPM command return code 84 * Return: value of enum command_ret_t 85 */ 86 int report_return_code(int return_code) 87 { 88 if (return_code) { 89 printf("Error: %d\n", return_code); 90 return CMD_RET_FAILURE; 91 } else { 92 return CMD_RET_SUCCESS; 93 } 94 } 95 96 /** 97 * Return number of values defined by a type string. 98 * 99 * @param type_str type string 100 * Return: number of values of type string 101 */ 102 int type_string_get_num_values(const char *type_str) 103 { 104 return strlen(type_str); 105 } 106 107 /** 108 * Return total size of values defined by a type string. 109 * 110 * @param type_str type string 111 * Return: total size of values of type string, or 0 if type string 112 * contains illegal type character. 113 */ 114 size_t type_string_get_space_size(const char *type_str) 115 { 116 size_t size; 117 118 for (size = 0; *type_str; type_str++) { 119 switch (*type_str) { 120 case 'b': 121 size += 1; 122 break; 123 case 'w': 124 size += 2; 125 break; 126 case 'd': 127 size += 4; 128 break; 129 default: 130 return 0; 131 } 132 } 133 134 return size; 135 } 136 137 /** 138 * Allocate a buffer large enough to hold values defined by a type 139 * string. The caller has to free the buffer. 140 * 141 * @param type_str type string 142 * @param count pointer for storing size of buffer 143 * Return: pointer to buffer or NULL on error 144 */ 145 void *type_string_alloc(const char *type_str, u32 *count) 146 { 147 void *data; 148 size_t size; 149 150 size = type_string_get_space_size(type_str); 151 if (!size) 152 return NULL; 153 data = malloc(size); 154 if (data) 155 *count = size; 156 157 return data; 158 } 159 160 /** 161 * Pack values defined by a type string into a buffer. The buffer must have 162 * large enough space. 163 * 164 * @param type_str type string 165 * @param values text strings of values to be packed 166 * @param data output buffer of values 167 * Return: 0 on success, non-0 on error 168 */ 169 int type_string_pack(const char *type_str, char * const values[], 170 u8 *data) 171 { 172 size_t offset; 173 u32 value; 174 175 for (offset = 0; *type_str; type_str++, values++) { 176 value = simple_strtoul(values[0], NULL, 0); 177 switch (*type_str) { 178 case 'b': 179 data[offset] = value; 180 offset += 1; 181 break; 182 case 'w': 183 put_unaligned_be16(value, data + offset); 184 offset += 2; 185 break; 186 case 'd': 187 put_unaligned_be32(value, data + offset); 188 offset += 4; 189 break; 190 default: 191 return -1; 192 } 193 } 194 195 return 0; 196 } 197 198 /** 199 * Read values defined by a type string from a buffer, and write these values 200 * to environment variables. 201 * 202 * @param type_str type string 203 * @param data input buffer of values 204 * @param vars names of environment variables 205 * Return: 0 on success, non-0 on error 206 */ 207 int type_string_write_vars(const char *type_str, u8 *data, 208 char * const vars[]) 209 { 210 size_t offset; 211 u32 value; 212 213 for (offset = 0; *type_str; type_str++, vars++) { 214 switch (*type_str) { 215 case 'b': 216 value = data[offset]; 217 offset += 1; 218 break; 219 case 'w': 220 value = get_unaligned_be16(data + offset); 221 offset += 2; 222 break; 223 case 'd': 224 value = get_unaligned_be32(data + offset); 225 offset += 4; 226 break; 227 default: 228 return -1; 229 } 230 if (env_set_ulong(*vars, value)) 231 return -1; 232 } 233 234 return 0; 235 } 236 237 static int tpm_show_device(void) 238 { 239 struct udevice *dev; 240 char buf[80]; 241 int n = 0, rc; 242 243 for_each_tpm_device(dev) { 244 rc = tpm_get_desc(dev, buf, sizeof(buf)); 245 if (rc < 0) 246 printf("device %d: can't get info\n", n); 247 else 248 printf("device %d: %s\n", n, buf); 249 250 n++; 251 }; 252 253 return 0; 254 } 255 256 static int tpm_set_device(unsigned long num) 257 { 258 struct udevice *dev; 259 unsigned long n = 0; 260 int rc = CMD_RET_FAILURE; 261 262 for_each_tpm_device(dev) { 263 if (n == num) { 264 rc = 0; 265 break; 266 } 267 268 n++; 269 } 270 271 if (!rc) 272 tpm_dev = dev; 273 274 return rc; 275 } 276 277 int get_tpm(struct udevice **devp) 278 { 279 int rc; 280 281 /* 282 * To keep a backward compatibility with previous code, 283 * if a tpm device is not explicitly set, we set the first one. 284 */ 285 if (!tpm_dev) { 286 rc = tpm_set_device(0); 287 if (rc) { 288 printf("Couldn't set TPM 0 (rc = %d)\n", rc); 289 return CMD_RET_FAILURE; 290 } 291 } 292 293 if (devp) 294 *devp = tpm_dev; 295 296 return 0; 297 } 298 299 int do_tpm_device(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 300 { 301 unsigned long num; 302 int rc; 303 304 if (argc == 2) { 305 num = simple_strtoul(argv[1], NULL, 10); 306 307 rc = tpm_set_device(num); 308 if (rc) 309 printf("Couldn't set TPM %lu (rc = %d)\n", num, rc); 310 } else { 311 rc = tpm_show_device(); 312 } 313 314 return rc; 315 } 316 317 int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 318 { 319 struct udevice *dev; 320 char buf[80]; 321 int rc; 322 323 rc = get_tpm(&dev); 324 if (rc) 325 return rc; 326 rc = tpm_get_desc(dev, buf, sizeof(buf)); 327 if (rc < 0) { 328 printf("Couldn't get TPM info (%d)\n", rc); 329 return CMD_RET_FAILURE; 330 } 331 printf("%s\n", buf); 332 333 return 0; 334 } 335 336 int do_tpm_report_state(cmd_tbl_t *cmdtp, int flag, int argc, 337 char *const argv[]) 338 { 339 struct udevice *dev; 340 char buf[80]; 341 int rc; 342 343 rc = get_tpm(&dev); 344 if (rc) 345 return rc; 346 rc = tpm_report_state(dev, buf, sizeof(buf)); 347 if (rc < 0) { 348 printf("Couldn't get TPM state (%d)\n", rc); 349 return CMD_RET_FAILURE; 350 } 351 printf("%s\n", buf); 352 353 return 0; 354 } 355 356 int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 357 { 358 struct udevice *dev; 359 int rc; 360 361 if (argc != 1) 362 return CMD_RET_USAGE; 363 rc = get_tpm(&dev); 364 if (rc) 365 return rc; 366 367 return report_return_code(tpm_init(dev)); 368 } 369 370 int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 371 { 372 cmd_tbl_t *tpm_commands, *cmd; 373 struct tpm_chip_priv *priv; 374 struct udevice *dev; 375 unsigned int size; 376 int ret; 377 378 if (argc < 2) 379 return CMD_RET_USAGE; 380 381 ret = get_tpm(&dev); 382 if (ret) 383 return ret; 384 385 priv = dev_get_uclass_priv(dev); 386 387 /* Below getters return NULL if the desired stack is not built */ 388 switch (priv->version) { 389 case TPM_V1: 390 tpm_commands = get_tpm1_commands(&size); 391 break; 392 case TPM_V2: 393 tpm_commands = get_tpm2_commands(&size); 394 break; 395 default: 396 tpm_commands = NULL; 397 } 398 399 if (!tpm_commands) 400 return CMD_RET_USAGE; 401 402 cmd = find_cmd_tbl(argv[1], tpm_commands, size); 403 if (!cmd) 404 return CMD_RET_USAGE; 405 406 return cmd->cmd(cmdtp, flag, argc - 1, argv + 1); 407 } 408