vbe_simple.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Verified Boot for Embedded (VBE) 'simple' method
  4. *
  5. * Copyright 2022 Google LLC
  6. * Written by Simon Glass <sjg@chromium.org>
  7. */
  8. #define LOG_CATEGORY LOGC_BOOT
  9. #include <common.h>
  10. #include <bootdev.h>
  11. #include <bootflow.h>
  12. #include <bootmeth.h>
  13. #include <dm.h>
  14. #include <log.h>
  15. #include <memalign.h>
  16. #include <mmc.h>
  17. #include <vbe.h>
  18. #include <dm/device-internal.h>
  19. #include <dm/ofnode.h>
  20. #include <u-boot/crc.h>
  21. #include "vbe_simple.h"
  22. /** struct simple_nvdata - storage format for non-volatile data */
  23. struct simple_nvdata {
  24. u8 crc8;
  25. u8 hdr;
  26. u16 spare1;
  27. u32 fw_vernum;
  28. u8 spare2[0x38];
  29. };
  30. static int simple_read_version(struct udevice *dev, struct blk_desc *desc,
  31. u8 *buf, struct simple_state *state)
  32. {
  33. struct simple_priv *priv = dev_get_priv(dev);
  34. int start;
  35. if (priv->version_size > MMC_MAX_BLOCK_LEN)
  36. return log_msg_ret("ver", -E2BIG);
  37. start = priv->area_start + priv->version_offset;
  38. if (start & (MMC_MAX_BLOCK_LEN - 1))
  39. return log_msg_ret("get", -EBADF);
  40. start /= MMC_MAX_BLOCK_LEN;
  41. if (blk_dread(desc, start, 1, buf) != 1)
  42. return log_msg_ret("read", -EIO);
  43. strlcpy(state->fw_version, buf, MAX_VERSION_LEN);
  44. log_debug("version=%s\n", state->fw_version);
  45. return 0;
  46. }
  47. static int simple_read_nvdata(struct udevice *dev, struct blk_desc *desc,
  48. u8 *buf, struct simple_state *state)
  49. {
  50. struct simple_priv *priv = dev_get_priv(dev);
  51. uint hdr_ver, hdr_size, size, crc;
  52. const struct simple_nvdata *nvd;
  53. int start;
  54. if (priv->state_size > MMC_MAX_BLOCK_LEN)
  55. return log_msg_ret("state", -E2BIG);
  56. start = priv->area_start + priv->state_offset;
  57. if (start & (MMC_MAX_BLOCK_LEN - 1))
  58. return log_msg_ret("get", -EBADF);
  59. start /= MMC_MAX_BLOCK_LEN;
  60. if (blk_dread(desc, start, 1, buf) != 1)
  61. return log_msg_ret("read", -EIO);
  62. nvd = (struct simple_nvdata *)buf;
  63. hdr_ver = (nvd->hdr & NVD_HDR_VER_MASK) >> NVD_HDR_VER_SHIFT;
  64. hdr_size = (nvd->hdr & NVD_HDR_SIZE_MASK) >> NVD_HDR_SIZE_SHIFT;
  65. if (hdr_ver != NVD_HDR_VER_CUR)
  66. return log_msg_ret("hdr", -EPERM);
  67. size = 1 << hdr_size;
  68. if (size > sizeof(*nvd))
  69. return log_msg_ret("sz", -ENOEXEC);
  70. crc = crc8(0, buf + 1, size - 1);
  71. if (crc != nvd->crc8)
  72. return log_msg_ret("crc", -EPERM);
  73. state->fw_vernum = nvd->fw_vernum;
  74. log_debug("version=%s\n", state->fw_version);
  75. return 0;
  76. }
  77. int vbe_simple_read_state(struct udevice *dev, struct simple_state *state)
  78. {
  79. ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN);
  80. struct simple_priv *priv = dev_get_priv(dev);
  81. struct blk_desc *desc;
  82. char devname[16];
  83. const char *end;
  84. int devnum;
  85. int ret;
  86. /* First figure out the block device */
  87. log_debug("storage=%s\n", priv->storage);
  88. devnum = trailing_strtoln_end(priv->storage, NULL, &end);
  89. if (devnum == -1)
  90. return log_msg_ret("num", -ENODEV);
  91. if (end - priv->storage >= sizeof(devname))
  92. return log_msg_ret("end", -E2BIG);
  93. strlcpy(devname, priv->storage, end - priv->storage + 1);
  94. log_debug("dev=%s, %x\n", devname, devnum);
  95. desc = blk_get_dev(devname, devnum);
  96. if (!desc)
  97. return log_msg_ret("get", -ENXIO);
  98. ret = simple_read_version(dev, desc, buf, state);
  99. if (ret)
  100. return log_msg_ret("ver", ret);
  101. ret = simple_read_nvdata(dev, desc, buf, state);
  102. if (ret)
  103. return log_msg_ret("nvd", ret);
  104. return 0;
  105. }
  106. static int vbe_simple_get_state_desc(struct udevice *dev, char *buf,
  107. int maxsize)
  108. {
  109. struct simple_state state;
  110. int ret;
  111. ret = vbe_simple_read_state(dev, &state);
  112. if (ret)
  113. return log_msg_ret("read", ret);
  114. if (maxsize < 30)
  115. return -ENOSPC;
  116. snprintf(buf, maxsize, "Version: %s\nVernum: %x/%x", state.fw_version,
  117. state.fw_vernum >> FWVER_KEY_SHIFT,
  118. state.fw_vernum & FWVER_FW_MASK);
  119. return 0;
  120. }
  121. static int vbe_simple_read_bootflow(struct udevice *dev, struct bootflow *bflow)
  122. {
  123. int ret;
  124. if (CONFIG_IS_ENABLED(BOOTMETH_VBE_SIMPLE_FW)) {
  125. if (vbe_phase() == VBE_PHASE_FIRMWARE) {
  126. ret = vbe_simple_read_bootflow_fw(dev, bflow);
  127. if (ret)
  128. return log_msg_ret("fw", ret);
  129. return 0;
  130. }
  131. }
  132. return -EINVAL;
  133. }
  134. static int vbe_simple_read_file(struct udevice *dev, struct bootflow *bflow,
  135. const char *file_path, ulong addr, ulong *sizep)
  136. {
  137. int ret;
  138. if (vbe_phase() == VBE_PHASE_OS) {
  139. ret = bootmeth_common_read_file(dev, bflow, file_path, addr,
  140. sizep);
  141. if (ret)
  142. return log_msg_ret("os", ret);
  143. }
  144. /* To be implemented */
  145. return -EINVAL;
  146. }
  147. static struct bootmeth_ops bootmeth_vbe_simple_ops = {
  148. .get_state_desc = vbe_simple_get_state_desc,
  149. .read_bootflow = vbe_simple_read_bootflow,
  150. .read_file = vbe_simple_read_file,
  151. };
  152. static int bootmeth_vbe_simple_probe(struct udevice *dev)
  153. {
  154. struct simple_priv *priv = dev_get_priv(dev);
  155. memset(priv, '\0', sizeof(*priv));
  156. if (dev_read_u32(dev, "area-start", &priv->area_start) ||
  157. dev_read_u32(dev, "area-size", &priv->area_size) ||
  158. dev_read_u32(dev, "version-offset", &priv->version_offset) ||
  159. dev_read_u32(dev, "version-size", &priv->version_size) ||
  160. dev_read_u32(dev, "state-offset", &priv->state_offset) ||
  161. dev_read_u32(dev, "state-size", &priv->state_size))
  162. return log_msg_ret("read", -EINVAL);
  163. dev_read_u32(dev, "skip-offset", &priv->skip_offset);
  164. priv->storage = strdup(dev_read_string(dev, "storage"));
  165. if (!priv->storage)
  166. return log_msg_ret("str", -EINVAL);
  167. return 0;
  168. }
  169. static int bootmeth_vbe_simple_bind(struct udevice *dev)
  170. {
  171. struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
  172. plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ?
  173. "VBE simple" : "vbe-simple";
  174. plat->flags = BOOTMETHF_GLOBAL;
  175. return 0;
  176. }
  177. #if CONFIG_IS_ENABLED(OF_REAL)
  178. static const struct udevice_id generic_simple_vbe_simple_ids[] = {
  179. { .compatible = "fwupd,vbe-simple" },
  180. { }
  181. };
  182. #endif
  183. U_BOOT_DRIVER(vbe_simple) = {
  184. .name = "vbe_simple",
  185. .id = UCLASS_BOOTMETH,
  186. .of_match = of_match_ptr(generic_simple_vbe_simple_ids),
  187. .ops = &bootmeth_vbe_simple_ops,
  188. .bind = bootmeth_vbe_simple_bind,
  189. .probe = bootmeth_vbe_simple_probe,
  190. .flags = DM_FLAG_PRE_RELOC,
  191. .priv_auto = sizeof(struct simple_priv),
  192. };