[coreboot-gerrit] New patch to review for coreboot: commonlib: add endian related accessor functions

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Thu Sep 17 16:55:16 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/11677

-gerrit

commit fdfb2b0b39caae446424ea63a00036f85a832eb6
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Thu Sep 17 11:24:08 2015 -0500

    commonlib: add endian related accessor functions
    
    This commit adds read/write functions for both big and
    little endian interpretations. Additionally there are
    variants that allow an offse to be provided into the
    source buffer.
    
    Along with this commit is a change to the cbfs locating
    code to use the new API.
    
    BUG=None
    TEST=Wrote test harness for functions.  Also booted ARM QEMU
         through end of payload.
    
    Change-Id: If44c4d489f0dab86a73b73580c039e364c7e517d
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/arch/x86/include/arch/cbfs.h                  |   4 +-
 src/commonlib/include/commonlib/cbfs_serialized.h |   2 +-
 src/commonlib/include/commonlib/endian.h          | 261 ++++++++++++++++++++++
 src/cpu/intel/microcode/microcode.c               |   2 +-
 src/lib/cbfs.c                                    |  38 +++-
 5 files changed, 296 insertions(+), 11 deletions(-)

diff --git a/src/arch/x86/include/arch/cbfs.h b/src/arch/x86/include/arch/cbfs.h
index 195c06f..ff45edb 100644
--- a/src/arch/x86/include/arch/cbfs.h
+++ b/src/arch/x86/include/arch/cbfs.h
@@ -25,7 +25,7 @@
 
 #define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
 
-static struct cbfs_file *walkcbfs_head(char *target)
+static struct cbfs_file_serialized *walkcbfs_head(char *target)
 {
 	void *entry;
 	asm volatile (
@@ -37,7 +37,7 @@ static struct cbfs_file *walkcbfs_head(char *target)
 
 static void *walkcbfs(char *target)
 {
-	struct cbfs_file *head = walkcbfs_head(target);
+	struct cbfs_file_serialized *head = walkcbfs_head(target);
 	if ((u32)head != 0)
 		return CBFS_SUBHEADER(head);
 
diff --git a/src/commonlib/include/commonlib/cbfs_serialized.h b/src/commonlib/include/commonlib/cbfs_serialized.h
index f672095..c655fc1 100644
--- a/src/commonlib/include/commonlib/cbfs_serialized.h
+++ b/src/commonlib/include/commonlib/cbfs_serialized.h
@@ -128,7 +128,7 @@ struct cbfs_header {
 
 #define CBFS_FILE_MAGIC "LARCHIVE"
 
-struct cbfs_file {
+struct cbfs_file_serialized {
 	char magic[8];
 	uint32_t len;
 	uint32_t type;
diff --git a/src/commonlib/include/commonlib/endian.h b/src/commonlib/include/commonlib/endian.h
new file mode 100644
index 0000000..bcd3b39
--- /dev/null
+++ b/src/commonlib/include/commonlib/endian.h
@@ -0,0 +1,261 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#ifndef _COMMONLIB_ENDIAN_H_
+#define _COMMONLIB_ENDIAN_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* Endian agnostic functions working on single byte. */
+
+static inline uint8_t read_ble8(const void *src)
+{
+	const uint8_t *s = src;
+	return *s;
+}
+
+static inline uint8_t read_at_ble8(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_ble8(s);
+}
+
+static inline void write_ble8(void *dest, uint8_t val)
+{
+	*(uint8_t *)dest = val;
+}
+
+static inline void write_at_ble8(void *dest, uint8_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_ble8(d, val);
+}
+
+/* Big Endian functions. */
+
+static inline uint8_t read_be8(const void *src)
+{
+	return read_ble8(src);
+}
+
+static inline uint8_t read_at_be8(const void *src, size_t offset)
+{
+	return read_at_ble8(src, offset);
+}
+
+static inline void write_be8(void *dest, uint8_t val)
+{
+	write_ble8(dest, val);
+}
+
+static inline void write_at_be8(void *dest, uint8_t val, size_t offset)
+{
+	write_at_ble8(dest, val, offset);
+}
+
+static inline uint16_t read_be16(const void *src)
+{
+	const uint8_t *s = src;
+	return (((uint16_t)s[0]) << 8) | (((uint16_t)s[1]) << 0);
+}
+
+static inline uint16_t read_at_be16(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_be16(s);
+}
+
+static inline void write_be16(void *dest, uint16_t val)
+{
+	write_be8(dest, val >> 8);
+	write_at_be8(dest, val >> 0, sizeof(uint8_t));
+}
+
+static inline void write_at_be16(void *dest, uint16_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_be16(d, val);
+}
+
+static inline uint32_t read_be32(const void *src)
+{
+	const uint8_t *s = src;
+	return (((uint32_t)s[0]) << 24) | (((uint32_t)s[1]) << 16) |
+		(((uint32_t)s[2]) << 8) | (((uint32_t)s[3]) << 0);
+}
+
+static inline uint32_t read_at_be32(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_be32(s);
+}
+
+static inline void write_be32(void *dest, uint32_t val)
+{
+	write_be16(dest, val >> 16);
+	write_at_be16(dest, val >> 0, sizeof(uint16_t));
+}
+
+static inline void write_at_be32(void *dest, uint32_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_be32(d, val);
+}
+
+static inline uint64_t read_be64(const void *src)
+{
+	uint64_t val;
+	val = read_be32(src);
+	val <<= 32;
+	val |= read_at_be32(src, sizeof(uint32_t));
+	return val;
+}
+
+static inline uint64_t read_at_be64(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_be64(s);
+}
+
+static inline void write_be64(void *dest, uint64_t val)
+{
+	write_be32(dest, val >> 32);
+	write_at_be32(dest, val >> 0, sizeof(uint32_t));
+}
+
+static inline void write_at_be64(void *dest, uint64_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_be64(d, val);
+}
+
+/* Little Endian functions. */
+
+static inline uint8_t read_le8(const void *src)
+{
+	return read_ble8(src);
+}
+
+static inline uint8_t read_at_le8(const void *src, size_t offset)
+{
+	return read_at_ble8(src, offset);
+}
+
+static inline void write_le8(void *dest, uint8_t val)
+{
+	write_ble8(dest, val);
+}
+
+static inline void write_at_le8(void *dest, uint8_t val, size_t offset)
+{
+	write_at_ble8(dest, val, offset);
+}
+
+static inline uint16_t read_le16(const void *src)
+{
+	const uint8_t *s = src;
+	return (((uint16_t)s[1]) << 8) | (((uint16_t)s[0]) << 0);
+}
+
+static inline uint16_t read_at_le16(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_le16(s);
+}
+
+static inline void write_le16(void *dest, uint16_t val)
+{
+	write_le8(dest, val >> 0);
+	write_at_le8(dest, val >> 8, sizeof(uint8_t));
+}
+
+static inline void write_at_le16(void *dest, uint16_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_le16(d, val);
+}
+
+static inline uint32_t read_le32(const void *src)
+{
+	const uint8_t *s = src;
+	return (((uint32_t)s[3]) << 24) | (((uint32_t)s[2]) << 16) |
+		(((uint32_t)s[1]) << 8) | (((uint32_t)s[0]) << 0);
+}
+
+static inline uint32_t read_at_le32(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_le32(s);
+}
+
+static inline void write_le32(void *dest, uint32_t val)
+{
+	write_le16(dest, val >> 0);
+	write_at_le16(dest, val >> 16, sizeof(uint16_t));
+}
+
+static inline void write_at_le32(void *dest, uint32_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_le32(d, val);
+}
+
+static inline uint64_t read_le64(const void *src)
+{
+	uint64_t val;
+	val = read_at_le32(src, sizeof(uint32_t));
+	val <<= 32;
+	val |= read_le32(src);
+	return val;
+}
+
+static inline uint64_t read_at_le64(const void *src, size_t offset)
+{
+	const uint8_t *s = src;
+	s += offset;
+	return read_le64(s);
+}
+
+static inline void write_le64(void *dest, uint64_t val)
+{
+	write_le32(dest, val >> 0);
+	write_at_le32(dest, val >> 32, sizeof(uint32_t));
+}
+
+static inline void write_at_le64(void *dest, uint64_t val, size_t offset)
+{
+	uint8_t *d = dest;
+	d += offset;
+	write_le64(d, val);
+}
+
+#endif
diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c
index 8791a2e..1cee30f 100644
--- a/src/cpu/intel/microcode/microcode.c
+++ b/src/cpu/intel/microcode/microcode.c
@@ -126,7 +126,7 @@ const void *intel_microcode_find(void)
 	msr_t msr;
 
 #ifdef __PRE_RAM__
-	struct cbfs_file *microcode_file;
+	struct cbfs_file_serialized *microcode_file;
 
 	microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE);
 	if (!microcode_file)
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index abc4077..c4eff5b 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <boot_device.h>
 #include <cbfs.h>
-#include <endian.h>
+#include <commonlib/endian.h>
 #include <lib.h>
 #include <symbols.h>
 
@@ -35,6 +35,30 @@
 #define DEBUG(x...)
 #endif
 
+struct cbfs_file {
+	char magic[8];
+	uint32_t len;
+	uint32_t type;
+	uint32_t checksum;
+	uint32_t offset;
+};
+
+static void cbfs_file_deserialize(struct cbfs_file *f, void *from)
+{
+	size_t off;
+
+	off = 0;
+	memcpy(&f->magic, from, sizeof(f->magic));
+	off += sizeof(f->magic);
+	f->len = read_at_be32(from, off);
+	off += sizeof(f->len);
+	f->type = read_at_be32(from, off);
+	off += sizeof(f->type);
+	f->checksum = read_at_be32(from, off);
+	off += sizeof(f->checksum);
+	f->offset = read_at_be32(from, off);
+}
+
 int cbfs_boot_locate(struct region_device *fh, const char *name, uint32_t *type)
 {
 	struct cbfsd cbfs;
@@ -91,16 +115,20 @@ 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);
+		const size_t fsz = sizeof(struct cbfs_file_serialized);
 		char *fname;
 		int name_match;
 		size_t datasz;
+		void *mapping;
 
 		DEBUG("Checking offset %zx\n", offset);
 
+		mapping = rdev_mmap(rd, offset, fsz);
 		/* Can't read file. Nothing else to do but bail out. */
-		if (rdev_readat(rd, &file, offset, fsz) != fsz)
+		if (mapping == NULL)
 			break;
+		cbfs_file_deserialize(&file, mapping);
+		rdev_munmap(rd, mapping);
 
 		if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.magic))) {
 			offset++;
@@ -108,10 +136,6 @@ int cbfs_locate(struct region_device *fh, const struct cbfsd *cbfs,
 			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);
 



More information about the coreboot-gerrit mailing list