[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