var-service-core.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * SPDX-License-Identifier: GPL-2.0-or-later
  3. *
  4. * uefi vars device
  5. */
  6. #include "qemu/osdep.h"
  7. #include "qemu/crc32c.h"
  8. #include "system/dma.h"
  9. #include "migration/vmstate.h"
  10. #include "hw/uefi/var-service.h"
  11. #include "hw/uefi/var-service-api.h"
  12. #include "hw/uefi/var-service-edk2.h"
  13. #include "trace/trace-hw_uefi.h"
  14. static int uefi_vars_pre_load(void *opaque)
  15. {
  16. uefi_vars_state *uv = opaque;
  17. uefi_vars_clear_all(uv);
  18. uefi_vars_policies_clear(uv);
  19. g_free(uv->buffer);
  20. return 0;
  21. }
  22. static int uefi_vars_post_load(void *opaque, int version_id)
  23. {
  24. uefi_vars_state *uv = opaque;
  25. uefi_vars_update_storage(uv);
  26. uefi_vars_json_save(uv);
  27. uv->buffer = g_malloc(uv->buf_size);
  28. return 0;
  29. }
  30. const VMStateDescription vmstate_uefi_vars = {
  31. .name = "uefi-vars",
  32. .pre_load = uefi_vars_pre_load,
  33. .post_load = uefi_vars_post_load,
  34. .fields = (VMStateField[]) {
  35. VMSTATE_UINT16(sts, uefi_vars_state),
  36. VMSTATE_UINT32(buf_size, uefi_vars_state),
  37. VMSTATE_UINT32(buf_addr_lo, uefi_vars_state),
  38. VMSTATE_UINT32(buf_addr_hi, uefi_vars_state),
  39. VMSTATE_UINT32(pio_xfer_offset, uefi_vars_state),
  40. VMSTATE_VBUFFER_ALLOC_UINT32(pio_xfer_buffer, uefi_vars_state,
  41. 0, NULL, buf_size),
  42. VMSTATE_BOOL(end_of_dxe, uefi_vars_state),
  43. VMSTATE_BOOL(ready_to_boot, uefi_vars_state),
  44. VMSTATE_BOOL(exit_boot_service, uefi_vars_state),
  45. VMSTATE_BOOL(policy_locked, uefi_vars_state),
  46. VMSTATE_UINT64(used_storage, uefi_vars_state),
  47. VMSTATE_QTAILQ_V(variables, uefi_vars_state, 0,
  48. vmstate_uefi_variable, uefi_variable, next),
  49. VMSTATE_QTAILQ_V(var_policies, uefi_vars_state, 0,
  50. vmstate_uefi_var_policy, uefi_var_policy, next),
  51. VMSTATE_END_OF_LIST()
  52. },
  53. };
  54. static uint32_t uefi_vars_cmd_mm(uefi_vars_state *uv, bool dma_mode)
  55. {
  56. hwaddr dma;
  57. mm_header *mhdr;
  58. uint64_t size;
  59. uint32_t retval;
  60. dma = uv->buf_addr_lo | ((hwaddr)uv->buf_addr_hi << 32);
  61. mhdr = (mm_header *) uv->buffer;
  62. if (!uv->buffer || uv->buf_size < sizeof(*mhdr)) {
  63. return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
  64. }
  65. /* read header */
  66. if (dma_mode) {
  67. dma_memory_read(&address_space_memory, dma,
  68. uv->buffer, sizeof(*mhdr),
  69. MEMTXATTRS_UNSPECIFIED);
  70. } else {
  71. memcpy(uv->buffer, uv->pio_xfer_buffer, sizeof(*mhdr));
  72. }
  73. if (uadd64_overflow(sizeof(*mhdr), mhdr->length, &size)) {
  74. return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
  75. }
  76. if (uv->buf_size < size) {
  77. return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
  78. }
  79. /* read buffer (excl header) */
  80. if (dma_mode) {
  81. dma_memory_read(&address_space_memory, dma + sizeof(*mhdr),
  82. uv->buffer + sizeof(*mhdr), mhdr->length,
  83. MEMTXATTRS_UNSPECIFIED);
  84. } else {
  85. memcpy(uv->buffer + sizeof(*mhdr),
  86. uv->pio_xfer_buffer + sizeof(*mhdr),
  87. mhdr->length);
  88. }
  89. memset(uv->buffer + size, 0, uv->buf_size - size);
  90. /* dispatch */
  91. if (qemu_uuid_is_equal(&mhdr->guid, &EfiSmmVariableProtocolGuid)) {
  92. retval = uefi_vars_mm_vars_proto(uv);
  93. } else if (qemu_uuid_is_equal(&mhdr->guid, &VarCheckPolicyLibMmiHandlerGuid)) {
  94. retval = uefi_vars_mm_check_policy_proto(uv);
  95. } else if (qemu_uuid_is_equal(&mhdr->guid, &EfiEndOfDxeEventGroupGuid)) {
  96. trace_uefi_event("end-of-dxe");
  97. uv->end_of_dxe = true;
  98. retval = UEFI_VARS_STS_SUCCESS;
  99. } else if (qemu_uuid_is_equal(&mhdr->guid, &EfiEventReadyToBootGuid)) {
  100. trace_uefi_event("ready-to-boot");
  101. uv->ready_to_boot = true;
  102. retval = UEFI_VARS_STS_SUCCESS;
  103. } else if (qemu_uuid_is_equal(&mhdr->guid, &EfiEventExitBootServicesGuid)) {
  104. trace_uefi_event("exit-boot-service");
  105. uv->exit_boot_service = true;
  106. retval = UEFI_VARS_STS_SUCCESS;
  107. } else {
  108. retval = UEFI_VARS_STS_ERR_NOT_SUPPORTED;
  109. }
  110. /* write buffer */
  111. if (dma_mode) {
  112. dma_memory_write(&address_space_memory, dma,
  113. uv->buffer, sizeof(*mhdr) + mhdr->length,
  114. MEMTXATTRS_UNSPECIFIED);
  115. } else {
  116. memcpy(uv->pio_xfer_buffer + sizeof(*mhdr),
  117. uv->buffer + sizeof(*mhdr),
  118. sizeof(*mhdr) + mhdr->length);
  119. }
  120. return retval;
  121. }
  122. static void uefi_vars_soft_reset(uefi_vars_state *uv)
  123. {
  124. g_free(uv->buffer);
  125. uv->buffer = NULL;
  126. uv->buf_size = 0;
  127. uv->buf_addr_lo = 0;
  128. uv->buf_addr_hi = 0;
  129. }
  130. void uefi_vars_hard_reset(uefi_vars_state *uv)
  131. {
  132. trace_uefi_hard_reset();
  133. uefi_vars_soft_reset(uv);
  134. uv->end_of_dxe = false;
  135. uv->ready_to_boot = false;
  136. uv->exit_boot_service = false;
  137. uv->policy_locked = false;
  138. uefi_vars_clear_volatile(uv);
  139. uefi_vars_policies_clear(uv);
  140. uefi_vars_auth_init(uv);
  141. }
  142. static uint32_t uefi_vars_cmd(uefi_vars_state *uv, uint32_t cmd)
  143. {
  144. switch (cmd) {
  145. case UEFI_VARS_CMD_RESET:
  146. uefi_vars_soft_reset(uv);
  147. return UEFI_VARS_STS_SUCCESS;
  148. case UEFI_VARS_CMD_DMA_MM:
  149. return uefi_vars_cmd_mm(uv, true);
  150. case UEFI_VARS_CMD_PIO_MM:
  151. return uefi_vars_cmd_mm(uv, false);
  152. case UEFI_VARS_CMD_PIO_ZERO_OFFSET:
  153. uv->pio_xfer_offset = 0;
  154. return UEFI_VARS_STS_SUCCESS;
  155. default:
  156. return UEFI_VARS_STS_ERR_NOT_SUPPORTED;
  157. }
  158. }
  159. static uint64_t uefi_vars_read(void *opaque, hwaddr addr, unsigned size)
  160. {
  161. uefi_vars_state *uv = opaque;
  162. uint64_t retval = -1;
  163. void *xfer_ptr;
  164. trace_uefi_reg_read(addr, size);
  165. switch (addr) {
  166. case UEFI_VARS_REG_MAGIC:
  167. retval = UEFI_VARS_MAGIC_VALUE;
  168. break;
  169. case UEFI_VARS_REG_CMD_STS:
  170. retval = uv->sts;
  171. break;
  172. case UEFI_VARS_REG_BUFFER_SIZE:
  173. retval = uv->buf_size;
  174. break;
  175. case UEFI_VARS_REG_DMA_BUFFER_ADDR_LO:
  176. retval = uv->buf_addr_lo;
  177. break;
  178. case UEFI_VARS_REG_DMA_BUFFER_ADDR_HI:
  179. retval = uv->buf_addr_hi;
  180. break;
  181. case UEFI_VARS_REG_PIO_BUFFER_TRANSFER:
  182. if (uv->pio_xfer_offset + size > uv->buf_size) {
  183. retval = 0;
  184. break;
  185. }
  186. xfer_ptr = uv->pio_xfer_buffer + uv->pio_xfer_offset;
  187. switch (size) {
  188. case 1:
  189. retval = *(uint8_t *)xfer_ptr;
  190. break;
  191. case 2:
  192. retval = *(uint16_t *)xfer_ptr;
  193. break;
  194. case 4:
  195. retval = *(uint32_t *)xfer_ptr;
  196. break;
  197. case 8:
  198. retval = *(uint64_t *)xfer_ptr;
  199. break;
  200. }
  201. uv->pio_xfer_offset += size;
  202. break;
  203. case UEFI_VARS_REG_PIO_BUFFER_CRC32C:
  204. retval = crc32c(0xffffffff, uv->pio_xfer_buffer, uv->pio_xfer_offset);
  205. break;
  206. case UEFI_VARS_REG_FLAGS:
  207. retval = 0;
  208. if (uv->use_pio) {
  209. retval |= UEFI_VARS_FLAG_USE_PIO;
  210. }
  211. }
  212. return retval;
  213. }
  214. static void uefi_vars_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
  215. {
  216. uefi_vars_state *uv = opaque;
  217. void *xfer_ptr;
  218. trace_uefi_reg_write(addr, val, size);
  219. switch (addr) {
  220. case UEFI_VARS_REG_CMD_STS:
  221. uv->sts = uefi_vars_cmd(uv, val);
  222. break;
  223. case UEFI_VARS_REG_BUFFER_SIZE:
  224. if (val > MAX_BUFFER_SIZE) {
  225. val = MAX_BUFFER_SIZE;
  226. }
  227. uv->buf_size = val;
  228. g_free(uv->buffer);
  229. g_free(uv->pio_xfer_buffer);
  230. uv->buffer = g_malloc(uv->buf_size);
  231. uv->pio_xfer_buffer = g_malloc(uv->buf_size);
  232. break;
  233. case UEFI_VARS_REG_DMA_BUFFER_ADDR_LO:
  234. uv->buf_addr_lo = val;
  235. break;
  236. case UEFI_VARS_REG_DMA_BUFFER_ADDR_HI:
  237. uv->buf_addr_hi = val;
  238. break;
  239. case UEFI_VARS_REG_PIO_BUFFER_TRANSFER:
  240. if (uv->pio_xfer_offset + size > uv->buf_size) {
  241. break;
  242. }
  243. xfer_ptr = uv->pio_xfer_buffer + uv->pio_xfer_offset;
  244. switch (size) {
  245. case 1:
  246. *(uint8_t *)xfer_ptr = val;
  247. break;
  248. case 2:
  249. *(uint16_t *)xfer_ptr = val;
  250. break;
  251. case 4:
  252. *(uint32_t *)xfer_ptr = val;
  253. break;
  254. case 8:
  255. *(uint64_t *)xfer_ptr = val;
  256. break;
  257. }
  258. uv->pio_xfer_offset += size;
  259. break;
  260. case UEFI_VARS_REG_PIO_BUFFER_CRC32C:
  261. case UEFI_VARS_REG_FLAGS:
  262. default:
  263. break;
  264. }
  265. }
  266. static const MemoryRegionOps uefi_vars_ops = {
  267. .read = uefi_vars_read,
  268. .write = uefi_vars_write,
  269. .endianness = DEVICE_LITTLE_ENDIAN,
  270. .impl = {
  271. .min_access_size = 2,
  272. .max_access_size = 4,
  273. },
  274. };
  275. void uefi_vars_init(Object *obj, uefi_vars_state *uv)
  276. {
  277. QTAILQ_INIT(&uv->variables);
  278. QTAILQ_INIT(&uv->var_policies);
  279. uv->jsonfd = -1;
  280. memory_region_init_io(&uv->mr, obj, &uefi_vars_ops, uv,
  281. "uefi-vars", UEFI_VARS_REGS_SIZE);
  282. }
  283. void uefi_vars_realize(uefi_vars_state *uv, Error **errp)
  284. {
  285. uefi_vars_json_init(uv, errp);
  286. uefi_vars_json_load(uv, errp);
  287. }