Home | History | Annotate | Download | only in cmd
      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 <asm/unaligned.h>
     10 #include <linux/string.h>
     11 #include <tpm-common.h>
     12 #include "tpm-user-utils.h"
     13 
     14 /**
     15  * Print a byte string in hexdecimal format, 16-bytes per line.
     16  *
     17  * @param data		byte string to be printed
     18  * @param count		number of bytes to be printed
     19  */
     20 void print_byte_string(u8 *data, size_t count)
     21 {
     22 	int i, print_newline = 0;
     23 
     24 	for (i = 0; i < count; i++) {
     25 		printf(" %02x", data[i]);
     26 		print_newline = (i % 16 == 15);
     27 		if (print_newline)
     28 			putc('\n');
     29 	}
     30 	/* Avoid duplicated newline at the end */
     31 	if (!print_newline)
     32 		putc('\n');
     33 }
     34 
     35 /**
     36  * Convert a text string of hexdecimal values into a byte string.
     37  *
     38  * @param bytes		text string of hexdecimal values with no space
     39  *			between them
     40  * @param data		output buffer for byte string.  The caller has to make
     41  *			sure it is large enough for storing the output.  If
     42  *			NULL is passed, a large enough buffer will be allocated,
     43  *			and the caller must free it.
     44  * @param count_ptr	output variable for the length of byte string
     45  * @return pointer to output buffer
     46  */
     47 void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr)
     48 {
     49 	char byte[3];
     50 	size_t count, length;
     51 	int i;
     52 
     53 	if (!bytes)
     54 		return NULL;
     55 	length = strlen(bytes);
     56 	count = length / 2;
     57 
     58 	if (!data)
     59 		data = malloc(count);
     60 	if (!data)
     61 		return NULL;
     62 
     63 	byte[2] = '\0';
     64 	for (i = 0; i < length; i += 2) {
     65 		byte[0] = bytes[i];
     66 		byte[1] = bytes[i + 1];
     67 		data[i / 2] = (u8)simple_strtoul(byte, NULL, 16);
     68 	}
     69 
     70 	if (count_ptr)
     71 		*count_ptr = count;
     72 
     73 	return data;
     74 }
     75 
     76 /**
     77  * report_return_code() - Report any error and return failure or success
     78  *
     79  * @param return_code	TPM command return code
     80  * @return value of enum command_ret_t
     81  */
     82 int report_return_code(int return_code)
     83 {
     84 	if (return_code) {
     85 		printf("Error: %d\n", return_code);
     86 		return CMD_RET_FAILURE;
     87 	} else {
     88 		return CMD_RET_SUCCESS;
     89 	}
     90 }
     91 
     92 /**
     93  * Return number of values defined by a type string.
     94  *
     95  * @param type_str	type string
     96  * @return number of values of type string
     97  */
     98 int type_string_get_num_values(const char *type_str)
     99 {
    100 	return strlen(type_str);
    101 }
    102 
    103 /**
    104  * Return total size of values defined by a type string.
    105  *
    106  * @param type_str	type string
    107  * @return total size of values of type string, or 0 if type string
    108  *  contains illegal type character.
    109  */
    110 size_t type_string_get_space_size(const char *type_str)
    111 {
    112 	size_t size;
    113 
    114 	for (size = 0; *type_str; type_str++) {
    115 		switch (*type_str) {
    116 		case 'b':
    117 			size += 1;
    118 			break;
    119 		case 'w':
    120 			size += 2;
    121 			break;
    122 		case 'd':
    123 			size += 4;
    124 			break;
    125 		default:
    126 			return 0;
    127 		}
    128 	}
    129 
    130 	return size;
    131 }
    132 
    133 /**
    134  * Allocate a buffer large enough to hold values defined by a type
    135  * string.  The caller has to free the buffer.
    136  *
    137  * @param type_str	type string
    138  * @param count		pointer for storing size of buffer
    139  * @return pointer to buffer or NULL on error
    140  */
    141 void *type_string_alloc(const char *type_str, u32 *count)
    142 {
    143 	void *data;
    144 	size_t size;
    145 
    146 	size = type_string_get_space_size(type_str);
    147 	if (!size)
    148 		return NULL;
    149 	data = malloc(size);
    150 	if (data)
    151 		*count = size;
    152 
    153 	return data;
    154 }
    155 
    156 /**
    157  * Pack values defined by a type string into a buffer.  The buffer must have
    158  * large enough space.
    159  *
    160  * @param type_str	type string
    161  * @param values	text strings of values to be packed
    162  * @param data		output buffer of values
    163  * @return 0 on success, non-0 on error
    164  */
    165 int type_string_pack(const char *type_str, char * const values[],
    166 		     u8 *data)
    167 {
    168 	size_t offset;
    169 	u32 value;
    170 
    171 	for (offset = 0; *type_str; type_str++, values++) {
    172 		value = simple_strtoul(values[0], NULL, 0);
    173 		switch (*type_str) {
    174 		case 'b':
    175 			data[offset] = value;
    176 			offset += 1;
    177 			break;
    178 		case 'w':
    179 			put_unaligned_be16(value, data + offset);
    180 			offset += 2;
    181 			break;
    182 		case 'd':
    183 			put_unaligned_be32(value, data + offset);
    184 			offset += 4;
    185 			break;
    186 		default:
    187 			return -1;
    188 		}
    189 	}
    190 
    191 	return 0;
    192 }
    193 
    194 /**
    195  * Read values defined by a type string from a buffer, and write these values
    196  * to environment variables.
    197  *
    198  * @param type_str	type string
    199  * @param data		input buffer of values
    200  * @param vars		names of environment variables
    201  * @return 0 on success, non-0 on error
    202  */
    203 int type_string_write_vars(const char *type_str, u8 *data,
    204 			   char * const vars[])
    205 {
    206 	size_t offset;
    207 	u32 value;
    208 
    209 	for (offset = 0; *type_str; type_str++, vars++) {
    210 		switch (*type_str) {
    211 		case 'b':
    212 			value = data[offset];
    213 			offset += 1;
    214 			break;
    215 		case 'w':
    216 			value = get_unaligned_be16(data + offset);
    217 			offset += 2;
    218 			break;
    219 		case 'd':
    220 			value = get_unaligned_be32(data + offset);
    221 			offset += 4;
    222 			break;
    223 		default:
    224 			return -1;
    225 		}
    226 		if (env_set_ulong(*vars, value))
    227 			return -1;
    228 	}
    229 
    230 	return 0;
    231 }
    232 
    233 int get_tpm(struct udevice **devp)
    234 {
    235 	int rc;
    236 
    237 	rc = uclass_first_device_err(UCLASS_TPM, devp);
    238 	if (rc) {
    239 		printf("Could not find TPM (ret=%d)\n", rc);
    240 		return CMD_RET_FAILURE;
    241 	}
    242 
    243 	return 0;
    244 }
    245 
    246 int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
    247 {
    248 	struct udevice *dev;
    249 	char buf[80];
    250 	int rc;
    251 
    252 	rc = get_tpm(&dev);
    253 	if (rc)
    254 		return rc;
    255 	rc = tpm_get_desc(dev, buf, sizeof(buf));
    256 	if (rc < 0) {
    257 		printf("Couldn't get TPM info (%d)\n", rc);
    258 		return CMD_RET_FAILURE;
    259 	}
    260 	printf("%s\n", buf);
    261 
    262 	return 0;
    263 }
    264 
    265 int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    266 {
    267 	if (argc != 1)
    268 		return CMD_RET_USAGE;
    269 
    270 	return report_return_code(tpm_init());
    271 }
    272 
    273 int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    274 {
    275 	cmd_tbl_t *tpm_commands, *cmd;
    276 	unsigned int size;
    277 
    278 	if (argc < 2)
    279 		return CMD_RET_USAGE;
    280 
    281 	tpm_commands = get_tpm_commands(&size);
    282 
    283 	cmd = find_cmd_tbl(argv[1], tpm_commands, size);
    284 	if (!cmd)
    285 		return CMD_RET_USAGE;
    286 
    287 	return cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
    288 }
    289