[PATCH v2 08/22] vbe: Move reading the nvdata into the common file

Simon Glass sjg at chromium.org
Thu Jan 16 02:27:09 CET 2025


All VBE methods read non-volatile data, so move this function into a
common file.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2:
- Split patch into several pieces

 boot/vbe_common.c | 41 +++++++++++++++++++++++++++++++++++++++++
 boot/vbe_common.h | 16 ++++++++++++++++
 boot/vbe_simple.c | 44 ++++++++------------------------------------
 3 files changed, 65 insertions(+), 36 deletions(-)

diff --git a/boot/vbe_common.c b/boot/vbe_common.c
index 8bbcc37e67e..672878fe6fe 100644
--- a/boot/vbe_common.c
+++ b/boot/vbe_common.c
@@ -9,6 +9,7 @@
 #include <blk.h>
 #include <memalign.h>
 #include <spl.h>
+#include <u-boot/crc.h>
 #include "vbe_common.h"
 
 int vbe_get_blk(const char *storage, struct udevice **blkp)
@@ -59,3 +60,43 @@ int vbe_read_version(struct udevice *blk, ulong offset, char *version,
 
 	return 0;
 }
+
+int vbe_read_nvdata(struct udevice *blk, ulong offset, ulong size, u8 *buf)
+{
+	uint hdr_ver, hdr_size, data_size, crc;
+	const struct vbe_nvdata *nvd;
+
+	/* we can use an assert() here since we already read only one block */
+	assert(size <= MMC_MAX_BLOCK_LEN);
+
+	/*
+	 * We can use an assert() here since reading the wrong block will just
+	 * cause invalid state to be (safely) read. If the crc passes, then we
+	 * obtain invalid state and it will likely cause booting to fail.
+	 *
+	 * VBE relies on valid values being in U-Boot's devicetree, so this
+	 * should not every be wrong on a production device.
+	 */
+	assert(!(offset & (MMC_MAX_BLOCK_LEN - 1)));
+
+	if (offset & (MMC_MAX_BLOCK_LEN - 1))
+		return log_msg_ret("get", -EBADF);
+	offset /= MMC_MAX_BLOCK_LEN;
+
+	if (blk_read(blk, offset, 1, buf) != 1)
+		return log_msg_ret("read", -EIO);
+	nvd = (struct vbe_nvdata *)buf;
+	hdr_ver = (nvd->hdr & NVD_HDR_VER_MASK) >> NVD_HDR_VER_SHIFT;
+	hdr_size = (nvd->hdr & NVD_HDR_SIZE_MASK) >> NVD_HDR_SIZE_SHIFT;
+	if (hdr_ver != NVD_HDR_VER_CUR)
+		return log_msg_ret("hdr", -EPERM);
+	data_size = 1 << hdr_size;
+	if (!data_size || data_size > sizeof(*nvd))
+		return log_msg_ret("sz", -EPERM);
+
+	crc = crc8(0, buf + 1, data_size - 1);
+	if (crc != nvd->crc8)
+		return log_msg_ret("crc", -EPERM);
+
+	return 0;
+}
diff --git a/boot/vbe_common.h b/boot/vbe_common.h
index a122bead93e..37a81330325 100644
--- a/boot/vbe_common.h
+++ b/boot/vbe_common.h
@@ -78,4 +78,20 @@ int vbe_get_blk(const char *storage, struct udevice **blkp);
 int vbe_read_version(struct udevice *blk, ulong offset, char *version,
 		     int max_size);
 
+/**
+ * vbe_read_nvdata() - Read non-volatile data from a block device
+ *
+ * Reads the VBE nvdata from a device. This function reads a single block from
+ * the device, so the nvdata cannot be larger than that.
+ *
+ * @blk: Device to read from
+ * @offset: Offset to read, in bytes
+ * @size: Number of bytes to read
+ * @buf: Buffer to hold the data
+ * Return: 0 if OK, -E2BIG if @size > block size, -EBADF if the offset is not
+ * block-aligned, -EIO if an I/O error occurred, -EPERM if the header version is
+ * incorrect, the header size is invalid or the data fails its CRC check
+ */
+int vbe_read_nvdata(struct udevice *blk, ulong offset, ulong size, u8 *buf);
+
 #endif /* __VBE_ABREC_H */
diff --git a/boot/vbe_simple.c b/boot/vbe_simple.c
index ce385065321..c6766c532f2 100644
--- a/boot/vbe_simple.c
+++ b/boot/vbe_simple.c
@@ -18,48 +18,21 @@
 #include <vbe.h>
 #include <dm/device-internal.h>
 #include <dm/ofnode.h>
-#include <u-boot/crc.h>
 #include "vbe_simple.h"
 
 static int simple_read_nvdata(const struct simple_priv *priv,
-			      struct udevice *blk, u8 *buf,
-			      struct simple_state *state)
+			      struct udevice *blk, struct simple_state *state)
 {
-	uint hdr_ver, hdr_size, size, crc;
+	ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN);
 	const struct vbe_nvdata *nvd;
-	int start;
-
-	/* we can use an assert() here since we already read only one block */
-	assert(priv->state_size <= MMC_MAX_BLOCK_LEN);
-
-	start = priv->area_start + priv->state_offset;
-
-	/*
-	 * We can use an assert() here since reading the wrong block will just
-	 * cause invalid state to be (safely) read. If the crc passes, then we
-	 * obtain invalid state and it will likely cause booting to fail.
-	 *
-	 * VBE relies on valid values being in U-Boot's devicetree, so this
-	 * should not every be wrong on a production device.
-	 */
-	assert(!(start & (MMC_MAX_BLOCK_LEN - 1)));
+	int ret;
 
-	start /= MMC_MAX_BLOCK_LEN;
+	ret = vbe_read_nvdata(blk, priv->area_start + priv->state_offset,
+			      priv->state_size, buf);
+	if (ret)
+		return log_msg_ret("nv", ret);
 
-	if (blk_read(blk, start, 1, buf) != 1)
-		return log_msg_ret("read", -EIO);
 	nvd = (struct vbe_nvdata *)buf;
-	hdr_ver = (nvd->hdr & NVD_HDR_VER_MASK) >> NVD_HDR_VER_SHIFT;
-	hdr_size = (nvd->hdr & NVD_HDR_SIZE_MASK) >> NVD_HDR_SIZE_SHIFT;
-	if (hdr_ver != NVD_HDR_VER_CUR)
-		return log_msg_ret("hdr", -EPERM);
-	size = 1 << hdr_size;
-	if (!size || size > sizeof(*nvd))
-		return log_msg_ret("sz", -ENOEXEC);
-
-	crc = crc8(0, buf + 1, size - 1);
-	if (crc != nvd->crc8)
-		return log_msg_ret("crc", -EPERM);
 	state->fw_vernum = nvd->fw_vernum;
 
 	log_debug("version=%s\n", state->fw_version);
@@ -69,7 +42,6 @@ static int simple_read_nvdata(const struct simple_priv *priv,
 
 int vbe_simple_read_state(struct udevice *dev, struct simple_state *state)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN);
 	struct simple_priv *priv = dev_get_priv(dev);
 	struct udevice *blk;
 	int ret;
@@ -83,7 +55,7 @@ int vbe_simple_read_state(struct udevice *dev, struct simple_state *state)
 	if (ret)
 		return log_msg_ret("ver", ret);
 
-	ret = simple_read_nvdata(priv, blk, buf, state);
+	ret = simple_read_nvdata(priv, blk, state);
 	if (ret)
 		return log_msg_ret("nvd", ret);
 
-- 
2.34.1



More information about the U-Boot mailing list