cbfs: new API and better program loading

A new CBFS API is introduced to allow making CBFS access
easier for providing multiple CBFS sources. That is achieved
by decoupling the cbfs source from a CBFS file. A CBFS
source is described by a descriptor. It contains the necessary
properties for walking a CBFS to locate a file. The CBFS
file is then decoupled from the CBFS descriptor in that it's
no longer needed to access the contents of the file.

All of this is accomplished using the regions infrastructure
by repsenting CBFS sources and files as region_devices. Because
region_devices can be chained together forming subregions this
allows one to decouple a CBFS source from a file. This also allows
one to provide CBFS files that came from other sources for
payload and/or stage loading.

The program loading takes advantage of those very properties
by allowing multiple sources for locating a program. Because of
this we can reduce the overhead of loading programs because
it's all done in the common code paths. Only locating the
program is per source.

Change-Id: I339b84fce95f03d1dbb63a0f54a26be5eb07f7c8
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/9134
Tested-by: build bot (Jenkins)
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index 8db87e3..00c43f2 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -1,14 +1,8 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
- * Copyright (C) 2013-2015 Google, Inc.
+ * Copyright 2015 Google Inc.
  *
- * This file is dual-licensed. You can choose between:
- *   - The GNU GPL, version 2, as published by the Free Software Foundation
- *   - The revised BSD license (without advertising clause)
- *
- * ---------------------------------------------------------------------------
  * 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.
@@ -21,74 +15,71 @@
  * 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.
- * ---------------------------------------------------------------------------
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ---------------------------------------------------------------------------
  */
 
 #ifndef _CBFS_H_
 #define _CBFS_H_
 
-#include <cbfs_core.h>
-
-int init_backing_media(struct cbfs_media **media, struct cbfs_media *backing);
-void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
-			  uint16_t device, void * dest);
-void *cbfs_load_stage(struct cbfs_media *media, const char *name);
-void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset);
-/* Load a stage from a prog structure. Returns < 0 on error. 0 on success. */
-struct prog;
-int cbfs_load_prog_stage(struct cbfs_media *media, struct prog *prog);
-int cbfs_load_prog_stage_by_offset(struct cbfs_media *media,
-					struct prog *prog, ssize_t offset);
-
-/* Simple buffer for streaming media. */
-struct cbfs_simple_buffer {
-	char *buffer;
-	size_t allocated;
-	size_t size;
-	size_t last_allocate;
-};
-
-void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer,
-			     struct cbfs_media *media,
-			     size_t offset, size_t count);
-
-void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer,
-			       const void *address);
-
+#include <cbfs_serialized.h>
+#include <program_loading.h>
+#include <region.h>
 
 /*
- * Defined in individual arch / board implementation.
- *
- * it returns 0 on success and non-zero on error.
+ * CBFS operations consist of the following concepts:
+ * - region_device for the boot media
+ * - cbfsd which is a descriptor for representing a cbfs instance
  */
-int init_default_cbfs_media(struct cbfs_media *media);
 
-#if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES))
-void cbfs_set_header_offset(size_t offset);
-#else
-static inline void cbfs_set_header_offset(size_t offset) {}
-#endif
+/* Descriptor for cbfs lookup operations. */
+struct cbfsd;
+
+/***********************************************
+ * Perform CBFS operations on the boot device. *
+ ***********************************************/
+
+/* Return mapping of option rom found in boot device. NULL on error. */
+void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device);
+/* Load stage by name into memory. Returns entry address on success. NULL on
+ * failure. */
+void *cbfs_boot_load_stage_by_name(const char *name);
+/* Locate file by name and optional type. Return 0 on success. < 0 on error. */
+int cbfs_boot_locate(struct region_device *fh, const char *name,
+			uint32_t *type);
+/* Map file into memory leaking the mapping. Only should be used when
+ * leaking mappings are a no-op. Returns NULL on error, else returns
+ * the mapping and sets the size of the file. */
+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 region_device *fh, const struct cbfsd *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 cbfsd {
+	const struct region_device *rdev;
+	size_t align;
+};
+
+/* The cbfs_props struct describes the properties associated with a CBFS. */
+struct cbfs_props {
+	/* Each file is aligned. */
+	size_t align;
+	/* CBFS starts at the following offset within the boot region. */
+	size_t offset;
+	/* CBFS size. */
+	size_t size;
+};
+
+/* Return < 0 on error otherwise props are filled out accordingly. */
+int cbfs_boot_region_properties(struct cbfs_props *props);
+
 #endif
diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h
deleted file mode 100644
index f00a26c..0000000
--- a/src/include/cbfs_core.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
- * Copyright (C) 2012 Google, Inc.
- * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
- *
- * This file is dual-licensed. You can choose between:
- *   - The GNU GPL, version 2, as published by the Free Software Foundation
- *   - The revised BSD license (without advertising clause)
- *
- * ---------------------------------------------------------------------------
- * 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.
- * ---------------------------------------------------------------------------
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ---------------------------------------------------------------------------
- */
-
-#ifndef _CBFS_CORE_H_
-#define _CBFS_CORE_H_
-
-#include <endian.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <cbfs_serialized.h>
-
-#define CBFS_HEADER_INVALID_ADDRESS	((void*)(0xffffffff))
-
-#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file))
-#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
-
-/*
- * ROMCC does not understand uint64_t, so we hide future definitions as they are
- * unlikely to be ever needed from ROMCC
- */
-#ifndef __ROMCC__
-
-#define CBFS_MEDIA_INVALID_MAP_ADDRESS	((void*)(0xffffffff))
-#define CBFS_DEFAULT_MEDIA		((void*)(0x0))
-
-/* Media for CBFS to load files. */
-struct cbfs_media {
-
-	/* implementation dependent context, to hold resource references */
-	void *context;
-
-	/* opens media and returns 0 on success, -1 on failure */
-	int (*open)(struct cbfs_media *media);
-
-	/* returns number of bytes read from media into dest, starting from
-	 * offset for count of bytes */
-	size_t (*read)(struct cbfs_media *media, void *dest, size_t offset,
-		       size_t count);
-
-	/* returns a pointer to memory with count of bytes from media source
-	 * starting from offset, or CBFS_MEDIA_INVALID_MAP_ADDRESS on failure.
-	 * Note: mapped data can't be free unless unmap is called, even if you
-	 * do close first. */
-	void * (*map)(struct cbfs_media *media, size_t offset, size_t count);
-
-	/* returns NULL and releases the memory by address, which was allocated
-	 * by map */
-	void * (*unmap)(struct cbfs_media *media, const void *address);
-
-	/* closes media and returns 0 on success, -1 on failure. */
-	int (*close)(struct cbfs_media *media);
-};
-
-/*
- * Locate file by name and fill in cbfs_file in host byte order. Returns
- * < 0 on error, else the offset of the file data.
- */
-ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file,
-				const char *name);
-
-/* Read count bytes at offset into dest. Return number of bytes read. */
-size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset,
-			size_t count);
-
-/* returns pointer to a file entry inside CBFS or NULL */
-struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name);
-
-/* returns pointer to file content inside CBFS after if type is correct */
-void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
-			    int type, size_t *sz);
-
-/* returns decompressed size on success, 0 on failure */
-int cbfs_decompress(int algo, void *src, void *dst, int len);
-
-/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS
- *  on failure */
-const struct cbfs_header *cbfs_get_header(struct cbfs_media *media);
-
-#endif /* __ROMCC__ */
-
-#endif
diff --git a/src/include/fallback.h b/src/include/fallback.h
index 7f3c823..740f130 100644
--- a/src/include/fallback.h
+++ b/src/include/fallback.h
@@ -1,7 +1,7 @@
 #ifndef FALLBACK_H
 #define FALLBACK_H
 
-#if !defined(__ASSEMBLER__) && !defined(__PRE_RAM__)
+#if !defined(__ASSEMBLER__)
 
 void boot_successful(void);
 
diff --git a/src/include/memlayout.h b/src/include/memlayout.h
index 651e60d..2771f2fe 100644
--- a/src/include/memlayout.h
+++ b/src/include/memlayout.h
@@ -102,6 +102,4 @@
 		. += sz;
 #endif
 
-#define CBFS_HEADER_OFFSET(addr) REGION(cbfs_header_offset, addr, 4, 4)
-
 #endif /* __MEMLAYOUT_H */
diff --git a/src/include/program_loading.h b/src/include/program_loading.h
index 981bd7b..eb99350 100644
--- a/src/include/program_loading.h
+++ b/src/include/program_loading.h
@@ -22,6 +22,7 @@
 
 #include <stdint.h>
 #include <stddef.h>
+#include <region.h>
 
 enum {
 	/* Last segment of program. Can be used to take different actions for
@@ -42,17 +43,22 @@
 	PROG_VERSTAGE,
 	PROG_ROMSTAGE,
 	PROG_RAMSTAGE,
+	PROG_REFCODE,
 	PROG_PAYLOAD,
+	PROG_BL31,
 };
 
 /* Representation of a program. */
 struct prog {
 	enum prog_type type;
 	const char *name;
+	/* Source of program content to load. */
+	struct region_device rdev;
 	/* The area can mean different things depending on what type the
-	 * program is. e.g. a payload prog uses this field for the backing
-	 * store of the payload_segments and data. After loading the segments
-	 * area is updated to reflect the bounce buffer used. */
+	 * program is. A stage after being loaded reflects the memory occupied
+	 * by the program, Since payloads are multi-segment one can't express
+	 * the memory layout with one range. Instead this field is updated
+	 * to reflect the bounce buffer used. */
 	struct buffer_area area;
 	/* Entry to program with optional argument. It's up to the architecture
 	 * to decide if argument is passed. */
@@ -92,6 +98,8 @@
 	prog->arg = arg;
 }
 
+/* Locate the identified program to run. Return 0 on success. < 0 on error. */
+int prog_locate(struct prog *prog);
 /* Run the program described by prog. */
 void prog_run(struct prog *prog);
 /* Per architecture implementation running a program. */
@@ -107,10 +115,10 @@
 	/* Determine if the loader is the active one. If so returns 1 else 0
 	 * or < 0 on error. */
 	int (*is_loader_active)(struct prog *prog);
-	/* Returns < 0 on error or 0 on success. This function needs to do
-	 * different things depending on the prog type. See definition
-	 * of struct prog above. */
-	int (*prepare)(struct prog *prog);
+	/* Returns < 0 on error or 0 on success. This function locates
+	 * the rdev representing the file data associated with the passed in
+	 * prog. */
+	int (*locate)(struct prog *prog);
 };
 
 /************************
diff --git a/src/include/rmodule.h b/src/include/rmodule.h
index c42614a..719c6a6 100644
--- a/src/include/rmodule.h
+++ b/src/include/rmodule.h
@@ -54,7 +54,6 @@
 /* Support for loading rmodule stages. This API is only available when
  * using dynamic cbmem because it uses the dynamic cbmem API to obtain
  * the backing store region for the stage. */
-struct cbfs_stage;
 struct prog;
 
 struct rmod_stage_load {
@@ -63,8 +62,7 @@
 };
 
 /* Both of the following functions return 0 on success, -1 on error. */
-int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage);
-int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl);
+int rmodule_stage_load(struct rmod_stage_load *rsl);
 
 struct rmodule {
 	void *location;
diff --git a/src/include/romstage_handoff.h b/src/include/romstage_handoff.h
index b92c884..3b0050b 100644
--- a/src/include/romstage_handoff.h
+++ b/src/include/romstage_handoff.h
@@ -38,8 +38,6 @@
 	uint8_t reserved[2];
 };
 
-#if defined(__ROMSTAGE__)
-#if CONFIG_EARLY_CBMEM_INIT
 /* The romstage_handoff_find_or_add() function provides the necessary logic
  * for initializing the romstage_handoff structure in cbmem. Different components
  * of the romstage may be responsible for setting up different fields. Therefore
@@ -62,14 +60,6 @@
 
 	return handoff;
 }
-#else /* CONFIG_EARLY_CBMEM_INIT */
-static inline struct romstage_handoff *romstage_handoff_find_or_add(void)
-{
-	return NULL;
-}
-#endif /* CONFIG_EARLY_CBMEM_INIT */
-
-#endif /* defined(__PRE_RAM__) */
 
 #endif /* ROMSTAGE_HANDOFF_H */
 
diff --git a/src/include/symbols.h b/src/include/symbols.h
index b47c886..4a47de1 100644
--- a/src/include/symbols.h
+++ b/src/include/symbols.h
@@ -27,7 +27,6 @@
 #define _sram_size (_esram - _sram)
 
 extern u8 _dram[];
-extern u32 _cbfs_header_offset[];
 
 extern u8 _preram_cbmem_console[];
 extern u8 _epreram_cbmem_console[];