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