summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2019-08-14 19:56:14 -0600
committerBin Meng <bmeng.cn@gmail.com>2019-08-18 21:54:10 +0800
commit630b2f39ddabd43a27a98f0356b948df18e97d88 (patch)
tree4de393a9f9563d12041f6cd3ff60285d398ffd52 /fs
parentc7f16934749b054ce1f0b75bd664d22af8b7c588 (diff)
cbfs: Add functions to support multiple CBFSs
Sometimes an image has multiple CBFS. The current CBFS API is limited to handling only one at time. Also it keeps track of the CBFS internally in BSS, which does not work before relocation, for example. Add a few new functions to overcome these limitations. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Tested-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cbfs/cbfs.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
index d9a8562e5c..35f919afee 100644
--- a/fs/cbfs/cbfs.c
+++ b/fs/cbfs/cbfs.c
@@ -187,6 +187,23 @@ static int file_cbfs_load_header(uintptr_t end_of_rom,
return 0;
}
+static int cbfs_load_header_ptr(struct cbfs_priv *priv, ulong base,
+ struct cbfs_header *header)
+{
+ struct cbfs_header *header_in_rom;
+
+ header_in_rom = (struct cbfs_header *)base;
+ swap_header(header, header_in_rom);
+
+ if (header->magic != good_magic || header->offset >
+ header->rom_size - header->boot_block_size) {
+ priv->result = CBFS_BAD_HEADER;
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
static void cbfs_init(struct cbfs_priv *priv, uintptr_t end_of_rom)
{
u8 *start_of_rom;
@@ -209,6 +226,35 @@ void file_cbfs_init(uintptr_t end_of_rom)
cbfs_init(&cbfs_s, end_of_rom);
}
+int cbfs_init_mem(ulong base, ulong size, struct cbfs_priv **privp)
+{
+ struct cbfs_priv priv_s, *priv = &priv_s;
+ int ret;
+
+ /*
+ * Use a local variable to start with until we know that the CBFS is
+ * valid. Assume that a master header appears at the start, at offset
+ * 0x38.
+ */
+ ret = cbfs_load_header_ptr(priv, base + 0x38, &priv->header);
+ if (ret)
+ return ret;
+
+ file_cbfs_fill_cache(priv, (u8 *)base, priv->header.rom_size,
+ priv->header.align);
+ if (priv->result != CBFS_SUCCESS)
+ return -EINVAL;
+
+ priv->initialized = 1;
+ priv = malloc(sizeof(priv_s));
+ if (!priv)
+ return -ENOMEM;
+ memcpy(priv, &priv_s, sizeof(priv_s));
+ *privp = priv;
+
+ return 0;
+}
+
const struct cbfs_header *file_cbfs_get_header(void)
{
struct cbfs_priv *priv = &cbfs_s;