tpm-common.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2013 The Chromium OS Authors.
  4. * Coypright (c) 2013 Guntermann & Drunck GmbH
  5. */
  6. #define LOG_CATEGORY UCLASS_TPM
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <asm/unaligned.h>
  10. #include <tpm-common.h>
  11. #include "tpm-utils.h"
  12. int pack_byte_string(u8 *str, size_t size, const char *format, ...)
  13. {
  14. va_list args;
  15. size_t offset = 0, length = 0;
  16. u8 *data = NULL;
  17. u32 value = 0;
  18. va_start(args, format);
  19. for (; *format; format++) {
  20. switch (*format) {
  21. case 'b':
  22. offset = va_arg(args, size_t);
  23. value = va_arg(args, int);
  24. length = 1;
  25. break;
  26. case 'w':
  27. offset = va_arg(args, size_t);
  28. value = va_arg(args, int);
  29. length = 2;
  30. break;
  31. case 'd':
  32. offset = va_arg(args, size_t);
  33. value = va_arg(args, u32);
  34. length = 4;
  35. break;
  36. case 's':
  37. offset = va_arg(args, size_t);
  38. data = va_arg(args, u8 *);
  39. length = va_arg(args, u32);
  40. break;
  41. default:
  42. debug("Couldn't recognize format string\n");
  43. va_end(args);
  44. return -1;
  45. }
  46. if (offset + length > size) {
  47. va_end(args);
  48. return -1;
  49. }
  50. switch (*format) {
  51. case 'b':
  52. str[offset] = value;
  53. break;
  54. case 'w':
  55. put_unaligned_be16(value, str + offset);
  56. break;
  57. case 'd':
  58. put_unaligned_be32(value, str + offset);
  59. break;
  60. case 's':
  61. memcpy(str + offset, data, length);
  62. break;
  63. }
  64. }
  65. va_end(args);
  66. return 0;
  67. }
  68. int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
  69. {
  70. va_list args;
  71. size_t offset = 0, length = 0;
  72. u8 *ptr8 = NULL;
  73. u16 *ptr16 = NULL;
  74. u32 *ptr32 = NULL;
  75. va_start(args, format);
  76. for (; *format; format++) {
  77. switch (*format) {
  78. case 'b':
  79. offset = va_arg(args, size_t);
  80. ptr8 = va_arg(args, u8 *);
  81. length = 1;
  82. break;
  83. case 'w':
  84. offset = va_arg(args, size_t);
  85. ptr16 = va_arg(args, u16 *);
  86. length = 2;
  87. break;
  88. case 'd':
  89. offset = va_arg(args, size_t);
  90. ptr32 = va_arg(args, u32 *);
  91. length = 4;
  92. break;
  93. case 's':
  94. offset = va_arg(args, size_t);
  95. ptr8 = va_arg(args, u8 *);
  96. length = va_arg(args, u32);
  97. break;
  98. default:
  99. va_end(args);
  100. debug("Couldn't recognize format string\n");
  101. return -1;
  102. }
  103. if (offset + length > size) {
  104. va_end(args);
  105. log_err("Failed to read: size=%d, offset=%x, len=%x\n",
  106. size, offset, length);
  107. return -1;
  108. }
  109. switch (*format) {
  110. case 'b':
  111. *ptr8 = str[offset];
  112. break;
  113. case 'w':
  114. *ptr16 = get_unaligned_be16(str + offset);
  115. break;
  116. case 'd':
  117. *ptr32 = get_unaligned_be32(str + offset);
  118. break;
  119. case 's':
  120. memcpy(ptr8, str + offset, length);
  121. break;
  122. }
  123. }
  124. va_end(args);
  125. return 0;
  126. }
  127. u32 tpm_command_size(const void *command)
  128. {
  129. const size_t command_size_offset = 2;
  130. return get_unaligned_be32(command + command_size_offset);
  131. }
  132. u32 tpm_return_code(const void *response)
  133. {
  134. const size_t return_code_offset = 6;
  135. return get_unaligned_be32(response + return_code_offset);
  136. }
  137. u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
  138. void *response, size_t *size_ptr)
  139. {
  140. int err, ret;
  141. u8 response_buffer[COMMAND_BUFFER_SIZE];
  142. size_t response_length;
  143. int i;
  144. if (response) {
  145. response_length = *size_ptr;
  146. } else {
  147. response = response_buffer;
  148. response_length = sizeof(response_buffer);
  149. }
  150. err = tpm_xfer(dev, command, tpm_command_size(command),
  151. response, &response_length);
  152. if (err < 0)
  153. return err;
  154. if (size_ptr)
  155. *size_ptr = response_length;
  156. ret = tpm_return_code(response);
  157. log_debug("TPM response [ret:%d]: ", ret);
  158. for (i = 0; i < response_length; i++)
  159. log_debug("%02x ", ((u8 *)response)[i]);
  160. log_debug("\n");
  161. return ret;
  162. }
  163. int tpm_init(struct udevice *dev)
  164. {
  165. return tpm_open(dev);
  166. }