[coreboot-gerrit] Patch set updated for coreboot: coreboot: add rdevbs (region device byte stream)
Aaron Durbin (adurbin@chromium.org)
gerrit at coreboot.org
Mon Sep 14 03:31:02 CET 2015
Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/11624
-gerrit
commit 916f4ae336a9bac07a035b9cfae6f6903fdf9ec2
Author: Aaron Durbin <adurbin at chromium.org>
Date: Fri Sep 11 09:49:12 2015 -0500
coreboot: add rdevbs (region device byte stream)
Add a region device byte stream object, rdevbs, which
will perform designated endian operations for reading
serialized objects out of a region device. The cbfs
walking code was updated to show usage of the library.
The implementation uses memory region device after
performing a mapping on the original parent. The reason
is absorb the communication costs of dealing with a
controller and its external media.
TEST=Booted glados.
Change-Id: I60feb24ae1b2abadb23b23201f38c85ade5bcfbd
Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
src/include/region.h | 28 ++++++++++++
src/lib/cbfs.c | 32 +++++++-------
src/lib/region.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 16 deletions(-)
diff --git a/src/include/region.h b/src/include/region.h
index 82db854..b1f9789 100644
--- a/src/include/region.h
+++ b/src/include/region.h
@@ -154,4 +154,32 @@ void mmap_helper_device_init(struct mmap_helper_region_device *mdev,
void *mmap_helper_rdev_mmap(const struct region_device *, size_t, size_t);
int mmap_helper_rdev_munmap(const struct region_device *, void *);
+/* Interpret region_device as byte stream operations with endian conversions. */
+struct rdevbs {
+ const struct region_device *parent;
+ size_t current_offset;
+ void *mapping;
+ void (*read)(struct rdevbs *bs, void *dest, size_t size);
+};
+
+/*
+ * Initialize an rdev byte stream from parent for reading stream_size bytes
+ * for the endianness interpretation. Returns 0 on success, < 0 on error.
+ */
+int rdevbs_init_le(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size);
+int rdevbs_init_be(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size);
+
+/* Return 0 on success, < 0 on error. */
+int rdevbs_read(struct rdevbs *bs, void *dest, size_t size);
+
+/* Indicate that the bytream is complete and any resources can be freed. */
+void rdevbs_complete(struct rdevbs *bs);
+
+static inline void rdevbs_skip(struct rdevbs *bs, size_t bytes)
+{
+ bs->current_offset += bytes;
+}
+
#endif /* _REGION_H_ */
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 83cd247..40146ee 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -95,33 +95,33 @@ int cbfs_locate(struct region_device *fh, const struct cbfsd *cbfs,
uint32_t flen;
uint32_t ftype;
uint32_t foffset;
- size_t strmoff;
const size_t fsz = sizeof(struct cbfs_file);
- void *file_mapping;
char *fname;
int name_match;
size_t datasz;
+ struct rdevbs bs;
+ size_t i;
DEBUG("Checking offset %zx\n", offset);
- file_mapping = rdev_mmap(rd, offset, fsz);
-
- if (file_mapping == NULL)
+ if (rdevbs_init_be(&bs, rd, offset, fsz))
break;
- /* Magic is a byte string w/ no endian encoding. */
- memcpy(magic, file_mapping, sizeof(magic));
- strmoff = sizeof(magic);
+ /* Joy. magic is a byte array w/o an endian encoding. */
+ for (i = 0; i < sizeof(magic); i++)
+ if (rdevbs_read(&bs, &magic[i], sizeof(magic[i])))
+ break;
- flen = read_be32(file_mapping, strmoff);
- strmoff += sizeof(flen);
- ftype = read_be32(file_mapping, strmoff);
- strmoff += sizeof(ftype);
- /* Skip the checksum field. */
- strmoff += sizeof(ftype);
- foffset = read_be32(file_mapping, strmoff);
+ if (rdevbs_read(&bs, &flen, sizeof(flen)))
+ break;
+ if (rdevbs_read(&bs, &ftype, sizeof(ftype)))
+ break;
+ /* Skip checksum field. */
+ rdevbs_skip(&bs, sizeof(uint32_t));
+ if (rdevbs_read(&bs, &foffset, sizeof(foffset)))
+ break;
- rdev_munmap(rd, file_mapping);
+ rdevbs_complete(&bs);
if (memcmp(magic, CBFS_FILE_MAGIC, sizeof(magic))) {
offset++;
diff --git a/src/lib/region.c b/src/lib/region.c
index d5d3762..1a34533 100644
--- a/src/lib/region.c
+++ b/src/lib/region.c
@@ -17,6 +17,7 @@
* Foundation, Inc.
*/
+#include <bytestream.h>
#include <region.h>
#include <string.h>
@@ -194,3 +195,122 @@ int mmap_helper_rdev_munmap(const struct region_device *rd, void *mapping)
return 0;
}
+
+static void rdevbs_read_le(struct rdevbs *bs, void *dest, size_t size)
+{
+ uint64_t *ptr64;
+ uint32_t *ptr32;
+ uint16_t *ptr16;
+ uint8_t *ptr8;
+
+ switch (size) {
+ case sizeof(uint64_t):
+ ptr64 = dest;
+ *ptr64 = read_le64(bs->mapping, bs->current_offset);
+ break;
+ case sizeof(uint32_t):
+ ptr32 = dest;
+ *ptr32 = read_le32(bs->mapping, bs->current_offset);
+ break;
+ case sizeof(uint16_t):
+ ptr16 = dest;
+ *ptr16 = read_le16(bs->mapping, bs->current_offset);
+ break;
+ case sizeof(uint8_t):
+ ptr8 = dest;
+ *ptr8 = read_be8(bs->mapping, bs->current_offset);
+ break;
+ }
+}
+
+static void rdevbs_read_be(struct rdevbs *bs, void *dest, size_t size)
+{
+ uint64_t *ptr64;
+ uint32_t *ptr32;
+ uint16_t *ptr16;
+ uint8_t *ptr8;
+
+ switch (size) {
+ case sizeof(uint64_t):
+ ptr64 = dest;
+ *ptr64 = read_be64(bs->mapping, bs->current_offset);
+ break;
+ case sizeof(uint32_t):
+ ptr32 = dest;
+ *ptr32 = read_be32(bs->mapping, bs->current_offset);
+ break;
+ case sizeof(uint16_t):
+ ptr16 = dest;
+ *ptr16 = read_be16(bs->mapping, bs->current_offset);
+ break;
+ case sizeof(uint8_t):
+ ptr8 = dest;
+ *ptr8 = read_be8(bs->mapping, bs->current_offset);
+ break;
+ }
+}
+
+static int rdevbs_init(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size)
+{
+ void *mapping;
+
+ bs->parent = parent;
+ bs->current_offset = 0;
+
+ /*
+ * One needs the object storage in order to read from the stream
+ * efficiently. Otherwise there would be many small round trip
+ * operations to the backing controller. Instead use a mapping of
+ * the size to be consumed.
+ */
+ mapping = rdev_mmap(parent, stream_offset, stream_size);
+
+ if (mapping == NULL)
+ return -1;
+
+ bs->mapping = mapping;
+
+ return 0;
+}
+
+int rdevbs_init_le(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size)
+{
+ bs->read = rdevbs_read_le;
+ return rdevbs_init(bs, parent, stream_offset, stream_size);
+}
+
+int rdevbs_init_be(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size)
+{
+ bs->read = rdevbs_read_be;
+ return rdevbs_init(bs, parent, stream_offset, stream_size);
+}
+
+int rdevbs_read(struct rdevbs *bs, void *dest, size_t size)
+{
+ struct region r = {
+ .offset = bs->current_offset,
+ .size = size,
+ };
+
+ if (size != sizeof(uint64_t) && size != sizeof(uint32_t) &&
+ size != sizeof(uint16_t) && size != sizeof(uint8_t))
+ return -1;
+
+ if (!normalize_and_ok(&bs->parent->region, &r))
+ return -1;
+
+ bs->read(bs, dest, size);
+
+ bs->current_offset += size;
+
+ return 0;
+}
+
+void rdevbs_complete(struct rdevbs *bs)
+{
+ rdev_munmap(bs->parent, bs->mapping);
+ bs->parent = NULL;
+}
More information about the coreboot-gerrit
mailing list