[coreboot-gerrit] Patch set updated for coreboot: commonlib: Add common cbfs parsing logic to coreboot and cbfstool.

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Mon Jan 4 19:00:04 CET 2016


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12783

-gerrit

commit 40b480b2b153c1144076f80deb04e552a2c49c08
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Tue Dec 15 13:33:51 2015 -0600

    commonlib: Add common cbfs parsing logic to coreboot and cbfstool.
    
    To continue sharing more code between the tools and
    coreboot proper provide cbfs parsing logic in commonlib.
    A cbfs_for_each_file() function was added to allow
    one to act on each file found within a cbfs. cbfs_locate()
    was updated to use that logic.
    
    BUG=chrome-os-partner:48412
    BUG=chromium:445938
    BRANCH=None
    TEST=Utilized and booted on glados.
    
    Change-Id: I1f23841583e78dc3686f106de9eafe1adbef8c9f
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/commonlib/Makefile.inc             |   6 ++
 src/commonlib/cbfs.c                   | 176 +++++++++++++++++++++++++++++++++
 src/commonlib/include/commonlib/cbfs.h |  55 +++++++++++
 src/include/cbfs.h                     |  28 +-----
 src/lib/cbfs.c                         |  72 --------------
 5 files changed, 238 insertions(+), 99 deletions(-)

diff --git a/src/commonlib/Makefile.inc b/src/commonlib/Makefile.inc
index 929bf8e..19f9ba3 100644
--- a/src/commonlib/Makefile.inc
+++ b/src/commonlib/Makefile.inc
@@ -10,3 +10,9 @@ ramstage-y += region.c
 smm-y += region.c
 
 ramstage-$(CONFIG_PLATFORM_USES_FSP1_1) += fsp1_1_relocate.c
+
+bootblock-y += cbfs.c
+verstage-y += cbfs.c
+romstage-y += cbfs.c
+ramstage-y += cbfs.c
+smm-y += cbfs.c
diff --git a/src/commonlib/cbfs.c b/src/commonlib/cbfs.c
new file mode 100644
index 0000000..06d31ed
--- /dev/null
+++ b/src/commonlib/cbfs.c
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#include <console/console.h>
+#include <commonlib/cbfs.h>
+#include <commonlib/endian.h>
+#include <commonlib/helpers.h>
+#include <string.h>
+
+#if !defined(ERROR)
+#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
+#endif
+#if !defined(LOG)
+#define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
+#endif
+#if defined(IS_ENABLED)
+
+#if IS_ENABLED(CONFIG_DEBUG_CBFS)
+#define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x)
+#else
+#define DEBUG(x...)
+#endif
+
+#elif !defined(DEBUG)
+#define DEBUG(x...)
+#endif
+
+static size_t cbfs_next_offset(const struct region_device *cbfs,
+				const struct cbfsf *f)
+{
+	size_t offset;
+
+	if (f == NULL)
+		return 0;
+
+	/* The region_device objects store absolute offets over the whole
+	 * region. Therefore a relative offset needs to be calculated. */
+	offset = rdev_relative_offset(cbfs, &f->data);
+	offset += region_device_sz(&f->data);
+
+	return ALIGN_UP(offset, CBFS_ALIGNMENT);
+}
+
+static int cbfs_end(const struct region_device *cbfs, size_t offset)
+{
+	if (offset >= region_device_sz(cbfs))
+		return 1;
+
+	return 0;
+}
+
+int cbfs_for_each_file(const struct region_device *cbfs,
+			const struct cbfsf *prev, struct cbfsf *fh)
+{
+	size_t offset;
+
+	offset = cbfs_next_offset(cbfs, prev);
+
+	/* Try to scan the entire cbfs region looking for file name. */
+	while (1) {
+		struct cbfs_file file;
+		const size_t fsz = sizeof(file);
+
+		 DEBUG("Checking offset %zx\n", offset);
+
+		/* End of region. */
+		if (cbfs_end(cbfs, offset))
+			return 1;
+
+		/* Can't read file. Nothing else to do but bail out. */
+		if (rdev_readat(cbfs, &file, offset, fsz) != fsz)
+			break;
+
+		if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.magic))) {
+			offset++;
+			offset = ALIGN_UP(offset, CBFS_ALIGNMENT);
+			continue;
+		}
+
+		file.len = read_be32(&file.len);
+		file.offset = read_be32(&file.offset);
+
+		DEBUG("File @ offset %zx size %x\n", offset, file.len);
+
+		/* Keep track of both the metadata and the data for the file. */
+		if (rdev_chain(&fh->metadata, cbfs, offset, file.offset))
+			break;
+
+		if (rdev_chain(&fh->data, cbfs, offset + file.offset, file.len))
+			break;
+
+		/* Success. */
+		return 0;
+	}
+
+	return -1;
+}
+
+int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
+		const char *name, uint32_t *type)
+{
+	struct cbfsf *prev;
+
+	LOG("Locating '%s'\n", name);
+
+	prev = NULL;
+
+	while (1) {
+		int ret;
+		char *fname;
+		int name_match;
+		const size_t fsz = sizeof(struct cbfs_file);
+
+		ret = cbfs_for_each_file(cbfs, prev, fh);
+		prev = fh;
+
+		/* Either failed to read or hit the end of the region. */
+		if (ret < 0 || ret > 0)
+			break;
+
+		fname = rdev_mmap(&fh->metadata, fsz,
+				region_device_sz(&fh->metadata) - fsz);
+
+		if (fname == NULL)
+			break;
+
+		name_match = !strcmp(fname, name);
+		rdev_munmap(&fh->metadata, fname);
+
+		if (!name_match) {
+			DEBUG(" Unmatched '%s' at %zx\n", fname,
+				rdev_relative_offset(cbfs, &fh->metadata));
+			continue;
+		}
+
+		if (type != NULL) {
+			uint32_t ftype;
+
+			if (rdev_readat(&fh->metadata, &ftype,
+					offsetof(struct cbfs_file, type),
+					sizeof(ftype)) != sizeof(ftype))
+				break;
+
+			ftype = read_be32(&ftype);
+
+			if (*type != ftype) {
+				DEBUG(" Unmatched type %x at %zx\n", ftype,
+					rdev_relative_offset(cbfs,
+							&fh->metadata));
+				continue;
+			}
+		}
+
+		LOG("Found @ offset %zx size %zx\n",
+			rdev_relative_offset(cbfs, &fh->metadata),
+			region_device_sz(&fh->data));
+
+		/* Success. */
+		return 0;
+	}
+
+	LOG("'%s' not found.\n", name);
+	return -1;
+}
diff --git a/src/commonlib/include/commonlib/cbfs.h b/src/commonlib/include/commonlib/cbfs.h
new file mode 100644
index 0000000..b0a468c
--- /dev/null
+++ b/src/commonlib/include/commonlib/cbfs.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef _COMMONLIB_CBFS_H_
+#define _COMMONLIB_CBFS_H_
+
+#include <commonlib/cbfs_serialized.h>
+#include <commonlib/region.h>
+
+/* Object representing cbfs files. */
+struct cbfsf {
+	struct region_device metadata;
+	struct region_device data;
+};
+
+/* Locate file by name and optional type. Returns 0 on succcess else < 0 on
+ * error.*/
+int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
+		const char *name, uint32_t *type);
+
+static inline void cbfs_file_data(struct region_device *data,
+					const struct cbfsf *file)
+{
+	rdev_chain(data, &file->data, 0, region_device_sz(&file->data));
+}
+
+static inline void cbfs_file_metadata(struct region_device *metadata,
+					const struct cbfsf *file)
+{
+	rdev_chain(metadata, &file->metadata, 0,
+			region_device_sz(&file->metadata));
+}
+
+/*
+ * Provide a handle to each cbfs file within a cbfs. The prev pointer represents
+ * the previous file (NULL on first invocation). The next object gets filled
+ * out with the next file. This returns < 0 on error, 0 on finding the next
+ * file, and > 0 at end of cbfs.
+ */
+int cbfs_for_each_file(const struct region_device *cbfs,
+			const struct cbfsf *prev, struct cbfsf *fh);
+
+#endif
diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index 7848d6d..0d95387 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -16,19 +16,9 @@
 #ifndef _CBFS_H_
 #define _CBFS_H_
 
-#include <commonlib/cbfs_serialized.h>
-#include <commonlib/region.h>
+#include <commonlib/cbfs.h>
 #include <program_loading.h>
 
-/*
- * CBFS operations consist of the following concepts:
- * - region_device for the boot media
- * - cbfsd which is a descriptor for representing a cbfs instance
- */
-
-/* Object representing cbfs files. */
-struct cbfsf;
-
 /***********************************************
  * Perform CBFS operations on the boot device. *
  ***********************************************/
@@ -48,28 +38,12 @@ void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size);
 /* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
 int cbfs_prog_stage_load(struct prog *prog);
 
-/* Locate file by name and optional type. Returns 0 on succcess else < 0 on
- * error.*/
-int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
-		const char *name, uint32_t *type);
-
 /*****************************************************************
  * Support structures and functions. Direct field access should  *
  * only be done by implementers of cbfs regions -- Not the above *
  * API.                                                          *
  *****************************************************************/
 
-struct cbfsf {
-	struct region_device metadata;
-	struct region_device data;
-};
-
-static inline void cbfs_file_data(struct region_device *data,
-					const struct cbfsf *file)
-{
-	rdev_chain(data, &file->data, 0, region_device_sz(&file->data));
-}
-
 /* The cbfs_props struct describes the properties associated with a CBFS. */
 struct cbfs_props {
 	/* CBFS starts at the following offset within the boot region. */
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index d68aa39..55a8536 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -68,78 +68,6 @@ void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size)
 	return rdev_mmap(&fh.data, 0, fsize);
 }
 
-int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
-		const char *name, uint32_t *type)
-{
-	size_t offset = 0;
-
-	LOG("Locating '%s'\n", name);
-
-	/* Try to scan the entire cbfs region looking for file name. */
-	while (1) {
-		struct cbfs_file file;
-		const size_t fsz = sizeof(file);
-		char *fname;
-		int name_match;
-		size_t datasz;
-
-		DEBUG("Checking offset %zx\n", offset);
-
-		/* Can't read file. Nothing else to do but bail out. */
-		if (rdev_readat(cbfs, &file, offset, fsz) != fsz)
-			break;
-
-		if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.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(cbfs, offset + fsz, file.offset - fsz);
-
-		if (fname == NULL)
-			break;
-
-		name_match = !strcmp(fname, name);
-		rdev_munmap(cbfs, fname);
-
-		if (!name_match) {
-			DEBUG(" Unmatched '%s' at %zx\n", fname, offset);
-			offset += file.offset + file.len;
-			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;
-			offset = ALIGN_UP(offset, CBFS_ALIGNMENT);
-			continue;
-		}
-
-		LOG("Found @ offset %zx size %x\n", offset, file.len);
-		/* File and type match. Keep track of both the metadata and
-		 * the data for the file. */
-		if (rdev_chain(&fh->metadata, cbfs, offset, file.offset))
-			break;
-		offset += file.offset;
-		datasz = file.len;
-		if (rdev_chain(&fh->data, cbfs, offset, datasz))
-			break;
-
-		/* Success. */
-		return 0;
-	}
-
-	LOG("'%s' not found.\n", name);
-	return -1;
-}
-
 static size_t inflate(void *src, void *dst)
 {
 	if (ENV_BOOTBLOCK || ENV_VERSTAGE)



More information about the coreboot-gerrit mailing list