summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Ehrenberg <dehrenberg@chromium.org>2014-10-07 14:55:37 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-15 00:09:34 +0000
commit5dc75d16b6d5cb0ebc677e6572a2559c6157b8e4 (patch)
tree1e4aa368d0b787ef3ec535cc541b97c856031efb
parentaaa325727a19366f40c84d45bfdbfd2e4fa92de0 (diff)
downloadvboot-5dc75d16b6d5cb0ebc677e6572a2559c6157b8e4.tar.gz
vboot: new streaming APIs
This patch adds three functions called from vboot into depthcharge to support NAND. NAND needs to stream rather than be accessed randomly in order to skip bad blocks. The intended flow from vboot1 is: - Read the GPT from a NAND disk handle, and depthcharge will silently fill it in with reads from from SPI - When a partition is selected, open a stream on the volume to access NAND - Sequentially read the NAND partition - Close the NAND stream This can be done multiple times when trying different partitions. The stream is associated with the GPT by reading/opening a stream from the same disk handle. This patch includes stub implementations by rspangler to translate the stream calls to block device calls. To reduce vboot code duplication, this flow will be done for all media types eventually, but a STREAMING flag is included to ease the transition. The draft depthcharge code can be found at https://chromium-review.googlesource.com/#/c/222312/ BUG=chromium:403432 TEST=stub implementations pass unit tests; together with upcoming depthcharge and vboot code, actually boots a kernel. This compiles by itself. BRANCH=none Change-Id: I660a89594390c72c2ef6ea2564367ce62bd90cf2 Reviewed-on: https://chromium-review.googlesource.com/221992 Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Daniel Ehrenberg <dehrenberg@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org> Commit-Queue: Randall Spangler <rspangler@chromium.org>
-rw-r--r--Makefile3
-rw-r--r--firmware/include/vboot_api.h45
-rw-r--r--firmware/stub/vboot_api_stub_stream.c87
3 files changed, 134 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 2f7db8c0..a3592ab7 100644
--- a/Makefile
+++ b/Makefile
@@ -323,7 +323,8 @@ VBSF_SRCS += \
VBSLK_SRCS += \
firmware/stub/vboot_api_stub.c \
- firmware/stub/vboot_api_stub_disk.c
+ firmware/stub/vboot_api_stub_disk.c \
+ firmware/stub/vboot_api_stub_stream.c
FWLIB2_SRCS += \
firmware/2lib/2stub.c
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 9b053715..526c1e4a 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -620,6 +620,51 @@ VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
uint64_t lba_count, const void *buffer);
+/* Streaming read interface */
+typedef void *VbExStream_t;
+
+/**
+ * Open a stream on a disk
+ *
+ * @param handle Disk to open the stream against
+ * @param lba_start Starting sector offset within the disk to stream from
+ * @param lba_count Maximum extent of the stream in sectors
+ * @param stream out-paramter for the generated stream
+ *
+ * @return Error code, or VBERROR_SUCCESS.
+ *
+ * lba_start and lba_count are subject to disk type-dependent alignment
+ * restrictions. An invalid value will lead to an error code. In particular,
+ * on raw NAND devices, lba_start and lba_count must be page-aligned after
+ * subtracting the offset of the GPT.
+ */
+VbError_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start,
+ uint64_t lba_count, VbExStream_t *stream_ptr);
+
+/**
+ * Read from a stream on a disk
+ *
+ * @param stream Stream to read from
+ * @param bytes Number of bytes to read
+ * @param buffer Destination to read into
+ *
+ * @return Error code, or VBERROR_SUCCESS. Failure to read as much data as
+ * requested is an error.
+ *
+ * bytes is subject to disk type-dependent alignment restrictions. An invalid
+ * value will lead to an error code. In particular, on raw NAND devices, bytes
+ * must be a page multiple.
+ */
+VbError_t VbExStreamRead(VbExStream_t stream, uint32_t bytes, void *buffer);
+
+/**
+ * Close a stream
+ *
+ * @param stream Stream to close
+ */
+void VbExStreamClose(VbExStream_t stream);
+
+
/*****************************************************************************/
/* Display */
diff --git a/firmware/stub/vboot_api_stub_stream.c b/firmware/stub/vboot_api_stub_stream.c
new file mode 100644
index 00000000..525c8f78
--- /dev/null
+++ b/firmware/stub/vboot_api_stub_stream.c
@@ -0,0 +1,87 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Stub implementations of stream APIs.
+ */
+
+#include <stdint.h>
+
+#define _STUB_IMPLEMENTATION_
+
+#include "vboot_api.h"
+
+/* 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);
+ return;
+}