vboot: Add support for new streaming APIs

This implementation is the same as the stub implementations in
vboot_reference, and translates calls to the new streaming APIs to the
old VbExDiskRead() function.  This will allow the vboot_reference
change which uses the new VbExStream*() APIs to commit.

We are not actively developing on u-boot, so we'll likely just leave
this code in u-boot.  It has negligible overhead.

BUG=chromium:403432
BRANCH=none
TEST=The vboot_reference code which calls these APIs hasn't been
     committed yet.  The same code is compiled and tested as part of
     the vboot code unit tests, and boots when compiled into depthcharge,
     so it works in other contexts.
CQ-DEPEND=CL:221992

Change-Id: I43f2d7692a093d13e82747a70c206bb3ea9beb57
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/222945
Reviewed-by: Daniel Ehrenberg <dehrenberg@chromium.org>
diff --git a/cros/vboot/boot_device.c b/cros/vboot/boot_device.c
index 22ea825..5317f5e 100644
--- a/cros/vboot/boot_device.c
+++ b/cros/vboot/boot_device.c
@@ -200,3 +200,84 @@
 
 	return VBERROR_SUCCESS;
 }
+
+/*
+ * Simple implementation of new streaming APIs.  This turns them into calls to
+ * the sector-based disk read/write functions above.  This will be replaced
+ * imminently with fancier streaming.  In the meantime, this will allow the
+ * vboot_reference change which uses the streaming APIs to commit.
+ */
+
+/* The stub implementation assumes 512-byte disk sectors */
+#define LBA_BYTES 512
+
+/* Internal struct to simulate a stream for sector-based disks */
+struct disk_stream {
+	/* Disk handle */
+	VbExDiskHandle_t handle;
+
+	/* Next sector to read */
+	uint64_t sector;
+
+	/* Number of sectors left in partition */
+	uint64_t sectors_left;
+};
+
+VbError_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start,
+			 uint64_t lba_count, VbExStream_t *stream)
+{
+	struct disk_stream *s;
+
+	if (!handle) {
+		*stream = NULL;
+		return VBERROR_UNKNOWN;
+	}
+
+	s = VbExMalloc(sizeof(*s));
+	s->handle = handle;
+	s->sector = lba_start;
+	s->sectors_left = lba_count;
+
+	*stream = (void *)s;
+
+	return VBERROR_SUCCESS;
+}
+
+VbError_t VbExStreamRead(VbExStream_t stream, uint32_t bytes, void *buffer)
+{
+	struct disk_stream *s = (struct disk_stream *)stream;
+	uint64_t sectors;
+	VbError_t rv;
+
+	if (!s)
+		return VBERROR_UNKNOWN;
+
+	/* For now, require reads to be a multiple of the LBA size */
+	if (bytes % LBA_BYTES)
+		return VBERROR_UNKNOWN;
+
+	/* Fail on overflow */
+	sectors = bytes / LBA_BYTES;
+	if (sectors > s->sectors_left)
+		return VBERROR_UNKNOWN;
+
+	rv = VbExDiskRead(s->handle, s->sector, sectors, buffer);
+	if (rv != VBERROR_SUCCESS)
+		return rv;
+
+	s->sector += sectors;
+	s->sectors_left -= sectors;
+
+	return VBERROR_SUCCESS;
+}
+
+void VbExStreamClose(VbExStream_t stream)
+{
+	struct disk_stream *s = (struct disk_stream *)stream;
+
+	/* Allow freeing a null pointer */
+	if (!s)
+		return;
+
+	VbExFree(s);
+}