[coreboot-gerrit] New patch to review for coreboot: coreboot: add rdevbs (region device byte stream)
Aaron Durbin (adurbin@chromium.org)
gerrit at coreboot.org
Fri Sep 11 15:34:19 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 991d8f8029b9a04414f9c03cbccf932dc3a389d0
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 | 51 +++++++++++++++++++++-----------
src/lib/region.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 144 insertions(+), 17 deletions(-)
diff --git a/src/include/region.h b/src/include/region.h
index 82db854..1c9cb6d 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;
+
+enum {
+ BE_BS, /* Big Endian */
+ LE_BS, /* Little Endian */
+};
+/*
+ * Initialize an rdev byte stream from parent for reading stream_size bytes
+ * using the providded endianness interpretation. Returns 0 on success, < 0
+ * on error.
+ */
+int rdevbs_init(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size, int endianness);
+
+/* 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);
+
+struct rdevbs {
+ const struct region_device *parent;
+ struct mem_region_device memdev;
+ size_t current_offset;
+ int endianness;
+};
+
#endif /* _REGION_H_ */
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index abc4077..4075b7f 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -90,30 +90,47 @@ int cbfs_locate(struct region_device *fh, const struct cbfsd *cbfs,
/* Try to scan the entire cbfs region looking for file name. */
while (1) {
- struct cbfs_file file;
- const size_t fsz = sizeof(file);
+ uint8_t magic[8];
+ uint32_t flen;
+ uint32_t ftype;
+ uint32_t fchecksum;
+ uint32_t foffset;
+ const size_t fsz = sizeof(struct cbfs_file);
char *fname;
int name_match;
size_t datasz;
+ struct rdevbs bs;
+ size_t i;
DEBUG("Checking offset %zx\n", offset);
- /* Can't read file. Nothing else to do but bail out. */
- if (rdev_readat(rd, &file, offset, fsz) != fsz)
+ if (rdevbs_init(&bs, rd, offset, fsz, BE_BS))
break;
- if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.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;
+
+ if (rdevbs_read(&bs, &flen, sizeof(flen)))
+ break;
+ if (rdevbs_read(&bs, &ftype, sizeof(ftype)))
+ break;
+ if (rdevbs_read(&bs, &fchecksum, sizeof(fchecksum)))
+ break;
+ if (rdevbs_read(&bs, &foffset, sizeof(foffset)))
+ break;
+
+ rdevbs_complete(&bs);
+
+ if (memcmp(magic, CBFS_FILE_MAGIC, sizeof(magic))) {
offset++;
offset = ALIGN_UP(offset, CBFS_ALIGNMENT);
continue;
}
- file.len = ntohl(file.len);
- file.type = ntohl(file.type);
- file.offset = ntohl(file.offset);
-
/* See if names match. */
- fname = rdev_mmap(rd, offset + fsz, file.offset - fsz);
+ fname = rdev_mmap(rd, offset + fsz, foffset - fsz);
if (fname == NULL)
break;
@@ -123,23 +140,23 @@ int cbfs_locate(struct region_device *fh, const struct cbfsd *cbfs,
if (!name_match) {
DEBUG(" Unmatched '%s' at %zx\n", fname, offset);
- offset += file.offset + file.len;
+ offset += foffset + flen;
offset = ALIGN_UP(offset, CBFS_ALIGNMENT);
continue;
}
- if (type != NULL && *type != file.type) {
- DEBUG(" Unmatched type %x at %zx\n", file.type, offset);
- offset += file.offset + file.len;
+ if (type != NULL && *type != ftype) {
+ DEBUG(" Unmatched type %x at %zx\n", ftype, offset);
+ offset += foffset + flen;
offset = ALIGN_UP(offset, CBFS_ALIGNMENT);
continue;
}
- LOG("Found @ offset %zx size %x\n", offset, file.len);
+ LOG("Found @ offset %zx size %x\n", offset, flen);
/* File and type match. Create a chained region_device to
* represent the cbfs file. */
- offset += file.offset;
- datasz = file.len;
+ offset += foffset;
+ datasz = flen;
if (rdev_chain(fh, rd, offset, datasz))
break;
diff --git a/src/lib/region.c b/src/lib/region.c
index d5d3762..4dd4adc 100644
--- a/src/lib/region.c
+++ b/src/lib/region.c
@@ -17,6 +17,7 @@
* Foundation, Inc.
*/
+#include <endian.h>
#include <region.h>
#include <string.h>
@@ -194,3 +195,84 @@ int mmap_helper_rdev_munmap(const struct region_device *rd, void *mapping)
return 0;
}
+
+int rdevbs_init(struct rdevbs *bs, const struct region_device *parent,
+ size_t stream_offset, size_t stream_size, int endianness)
+{
+ void *mapping;
+
+ bs->parent = parent;
+ bs->current_offset = 0;
+ bs->endianness = endianness;
+ if (endianness != LE_BS && endianness != BE_BS)
+ return -1;
+
+ /*
+ * 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;
+
+ mem_region_device_init(&bs->memdev, mapping, stream_size);
+
+ return 0;
+}
+
+int rdevbs_read(struct rdevbs *bs, void *dest, size_t size)
+{
+ union {
+ uint64_t bits64;
+ uint32_t bits32;
+ uint16_t bits16;
+ uint8_t bits8;
+ } b;
+
+ if (size != sizeof(b.bits64) && size != sizeof(b.bits32) &&
+ size != sizeof(b.bits16) && size != sizeof(b.bits8))
+ return -1;
+
+ if (rdev_readat(&bs->memdev.rdev, &b, bs->current_offset, size) != size)
+ return -1;
+
+ if (bs->endianness == LE_BS) {
+ switch (size) {
+ case sizeof(b.bits64):
+ b.bits64 = le64toh(b.bits64);
+ break;
+ case sizeof(b.bits32):
+ b.bits32 = le32toh(b.bits32);
+ break;
+ case sizeof(b.bits16):
+ b.bits16 = le16toh(b.bits16);
+ break;
+ }
+ } else {
+ switch (size) {
+ case sizeof(b.bits64):
+ b.bits64 = be64toh(b.bits64);
+ break;
+ case sizeof(b.bits32):
+ b.bits32 = be32toh(b.bits32);
+ break;
+ case sizeof(b.bits16):
+ b.bits16 = be16toh(b.bits16);
+ break;
+ }
+ }
+
+ memcpy(dest, &b, size);
+ bs->current_offset += size;
+
+ return 0;
+}
+
+void rdevbs_complete(struct rdevbs *bs)
+{
+ rdev_munmap(bs->parent, bs->memdev.base);
+ bs->parent = NULL;
+}
More information about the coreboot-gerrit
mailing list