[U-Boot] [PATCH 0/6] cbfs: Allow use before relocation / BSS

At present CBFS cannot be used in SPL before BSS is available. This is inconvenient if CBFS holds the FSP code needed to init SDRAM.
The problem is fairly easy to fix, by putting all static variables into a struct that can be allocated.
This series updates CBFS towards this goal, but does not convert all functions. It also tidies up the style a little.
Simon Glass (6): cbfs: Allow CBFS to be used in SPL cbfs: Move declarations above functions cbfs: Move static variables into a struct cbfs: Move result variable into the struct cbfs: Add functions to support multiple CBFSs cbfs: Rename camel-case variables
cmd/cbfs.c | 4 +- fs/Makefile | 1 + fs/cbfs/Kconfig | 12 +++ fs/cbfs/cbfs.c | 231 ++++++++++++++++++++++++++++++++---------------- include/cbfs.h | 29 ++++++ 5 files changed, 198 insertions(+), 79 deletions(-)

Add a new Kconfig option to enable CBFS in SPL. This can be useful when the memory-init code is in CBFS.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/Makefile | 1 + fs/cbfs/Kconfig | 12 ++++++++++++ 2 files changed, 13 insertions(+)
diff --git a/fs/Makefile b/fs/Makefile index 2ed4aeac0e..42e669c40c 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -8,6 +8,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ +obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ else obj-y += fs.o
diff --git a/fs/cbfs/Kconfig b/fs/cbfs/Kconfig index 16089547a5..49eb6aca33 100644 --- a/fs/cbfs/Kconfig +++ b/fs/cbfs/Kconfig @@ -6,3 +6,15 @@ config FS_CBFS on systems that use coreboot as the first boot-loader and then load U-Boot to actually boot the Operating System. You can also enable CMD_CBFS to get command-line access. + +config SPL_FS_CBFS + bool "Enable CBFS (Coreboot Filesystem) in SPL" + help + Define this to enable support for reading from a Coreboot + filesystem. This is a ROM-based filesystem used for accessing files + on systems that use coreboot as the first boot-loader and then load + U-Boot to actually boot the Operating System. + + Note that most functions in the CBFS API do not work with SPL. Only + those which accept a cbfs_priv * can be used, since BSS it not + available.

On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
Add a new Kconfig option to enable CBFS in SPL. This can be useful when the memory-init code is in CBFS.
Signed-off-by: Simon Glass sjg@chromium.org
fs/Makefile | 1 + fs/cbfs/Kconfig | 12 ++++++++++++ 2 files changed, 13 insertions(+)
diff --git a/fs/Makefile b/fs/Makefile index 2ed4aeac0e..42e669c40c 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -8,6 +8,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ +obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ else obj-y += fs.o
diff --git a/fs/cbfs/Kconfig b/fs/cbfs/Kconfig index 16089547a5..49eb6aca33 100644 --- a/fs/cbfs/Kconfig +++ b/fs/cbfs/Kconfig @@ -6,3 +6,15 @@ config FS_CBFS on systems that use coreboot as the first boot-loader and then load U-Boot to actually boot the Operating System. You can also enable CMD_CBFS to get command-line access.
+config SPL_FS_CBFS
bool "Enable CBFS (Coreboot Filesystem) in SPL"
help
Define this to enable support for reading from a Coreboot
filesystem. This is a ROM-based filesystem used for accessing files
on systems that use coreboot as the first boot-loader and then load
U-Boot to actually boot the Operating System.
Note that most functions in the CBFS API do not work with SPL. Only
those which accept a cbfs_priv * can be used, since BSS it not
BSS *is* not
available.
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

At present this file has a function at the top, above declarations. This is normally avoided, so fix it.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index af4d3c5e56..2a9edcc9a0 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -9,6 +9,11 @@ #include <asm/byteorder.h>
enum cbfs_result file_cbfs_result; +static const u32 good_magic = 0x4f524243; +static const u8 good_file_magic[] = "LARCHIVE"; +static int initialized; +static struct cbfs_header cbfs_header; +static struct cbfs_cachenode *file_cache;
const char *file_cbfs_error(void) { @@ -28,15 +33,6 @@ const char *file_cbfs_error(void) } }
- -static const u32 good_magic = 0x4f524243; -static const u8 good_file_magic[] = "LARCHIVE"; - - -static int initialized; -static struct cbfs_header cbfs_header; -static struct cbfs_cachenode *file_cache; - /* Do endian conversion on the CBFS header structure. */ static void swap_header(struct cbfs_header *dest, struct cbfs_header *src) {

On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
At present this file has a function at the top, above declarations. This is normally avoided, so fix it.
Signed-off-by: Simon Glass sjg@chromium.org
fs/cbfs/cbfs.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

At present there are a number of static variables in BSS. This cannot work with SPL, at least until BSS is available in board_init_r().
Move the variables into a struct, so it is possible to malloc() it and use it before BSS is available.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 96 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 33 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 2a9edcc9a0..f4298d7320 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -11,9 +11,14 @@ enum cbfs_result file_cbfs_result; static const u32 good_magic = 0x4f524243; static const u8 good_file_magic[] = "LARCHIVE"; -static int initialized; -static struct cbfs_header cbfs_header; -static struct cbfs_cachenode *file_cache; + +struct cbfs_priv { + int initialized; + struct cbfs_header header; + struct cbfs_cachenode *file_cache; +}; + +static struct cbfs_priv cbfs_s;
const char *file_cbfs_error(void) { @@ -69,8 +74,9 @@ static void swap_file_header(struct cbfs_fileheader *dest, * * @return 1 if a file is found, 0 if one isn't. */ -static int file_cbfs_next_file(u8 *start, u32 size, u32 align, - struct cbfs_cachenode *newNode, u32 *used) +static int file_cbfs_next_file(struct cbfs_priv *priv, u8 *start, u32 size, + u32 align, struct cbfs_cachenode *newNode, + u32 *used) { struct cbfs_fileheader header;
@@ -117,20 +123,21 @@ static int file_cbfs_next_file(u8 *start, u32 size, u32 align, }
/* Look through a CBFS instance and copy file metadata into regular memory. */ -static void file_cbfs_fill_cache(u8 *start, u32 size, u32 align) +static void file_cbfs_fill_cache(struct cbfs_priv *priv, u8 *start, u32 size, + u32 align) { struct cbfs_cachenode *cache_node; struct cbfs_cachenode *newNode; - struct cbfs_cachenode **cache_tail = &file_cache; + struct cbfs_cachenode **cache_tail = &priv->file_cache;
/* Clear out old information. */ - cache_node = file_cache; + cache_node = priv->file_cache; while (cache_node) { struct cbfs_cachenode *oldNode = cache_node; cache_node = cache_node->next; free(oldNode); } - file_cache = NULL; + priv->file_cache = NULL;
while (size >= align) { int result; @@ -138,8 +145,8 @@ static void file_cbfs_fill_cache(u8 *start, u32 size, u32 align)
newNode = (struct cbfs_cachenode *) malloc(sizeof(struct cbfs_cachenode)); - result = file_cbfs_next_file(start, size, align, - newNode, &used); + result = file_cbfs_next_file(priv, start, size, align, newNode, + &used);
if (result < 0) { free(newNode); @@ -175,27 +182,35 @@ static int file_cbfs_load_header(uintptr_t end_of_rom, return 0; }
-void file_cbfs_init(uintptr_t end_of_rom) +void cbfs_init(struct cbfs_priv *priv, uintptr_t end_of_rom) { u8 *start_of_rom; - initialized = 0;
- if (file_cbfs_load_header(end_of_rom, &cbfs_header)) + priv->initialized = 0; + + if (file_cbfs_load_header(end_of_rom, &priv->header)) return;
- start_of_rom = (u8 *)(end_of_rom + 1 - cbfs_header.rom_size); + start_of_rom = (u8 *)(end_of_rom + 1 - priv->header.rom_size);
- file_cbfs_fill_cache(start_of_rom, cbfs_header.rom_size, - cbfs_header.align); + file_cbfs_fill_cache(priv, start_of_rom, priv->header.rom_size, + priv->header.align); if (file_cbfs_result == CBFS_SUCCESS) - initialized = 1; + priv->initialized = 1; +} + +void file_cbfs_init(uintptr_t end_of_rom) +{ + cbfs_init(&cbfs_s, end_of_rom); }
const struct cbfs_header *file_cbfs_get_header(void) { - if (initialized) { + struct cbfs_priv *priv = &cbfs_s; + + if (priv->initialized) { file_cbfs_result = CBFS_SUCCESS; - return &cbfs_header; + return &priv->header; } else { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL; @@ -204,20 +219,24 @@ const struct cbfs_header *file_cbfs_get_header(void)
const struct cbfs_cachenode *file_cbfs_get_first(void) { - if (!initialized) { + struct cbfs_priv *priv = &cbfs_s; + + if (!priv->initialized) { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL; } else { file_cbfs_result = CBFS_SUCCESS; - return file_cache; + return priv->file_cache; } }
void file_cbfs_get_next(const struct cbfs_cachenode **file) { - if (!initialized) { + struct cbfs_priv *priv = &cbfs_s; + + if (!priv->initialized) { file_cbfs_result = CBFS_NOT_INITIALIZED; - file = NULL; + *file = NULL; return; }
@@ -226,11 +245,12 @@ void file_cbfs_get_next(const struct cbfs_cachenode **file) file_cbfs_result = CBFS_SUCCESS; }
-const struct cbfs_cachenode *file_cbfs_find(const char *name) +const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *priv, + const char *name) { - struct cbfs_cachenode *cache_node = file_cache; + struct cbfs_cachenode *cache_node = priv->file_cache;
- if (!initialized) { + if (!priv->initialized) { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL; } @@ -248,26 +268,33 @@ const struct cbfs_cachenode *file_cbfs_find(const char *name) return cache_node; }
+const struct cbfs_cachenode *file_cbfs_find(const char *name) +{ + return cbfs_find_file(&cbfs_s, name); +} + const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom, const char *name) { + struct cbfs_priv *priv = &cbfs_s; u8 *start; u32 size; u32 align; static struct cbfs_cachenode node;
- if (file_cbfs_load_header(end_of_rom, &cbfs_header)) + if (file_cbfs_load_header(end_of_rom, &priv->header)) return NULL;
- start = (u8 *)(end_of_rom + 1 - cbfs_header.rom_size); - size = cbfs_header.rom_size; - align = cbfs_header.align; + start = (u8 *)(end_of_rom + 1 - priv->header.rom_size); + size = priv->header.rom_size; + align = priv->header.align;
while (size >= align) { int result; u32 used;
- result = file_cbfs_next_file(start, size, align, &node, &used); + result = file_cbfs_next_file(priv, start, size, align, &node, + &used);
if (result < 0) return NULL; @@ -287,18 +314,21 @@ const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom, const char *file_cbfs_name(const struct cbfs_cachenode *file) { file_cbfs_result = CBFS_SUCCESS; + return file->name; }
u32 file_cbfs_size(const struct cbfs_cachenode *file) { file_cbfs_result = CBFS_SUCCESS; + return file->data_length; }
u32 file_cbfs_type(const struct cbfs_cachenode *file) { file_cbfs_result = CBFS_SUCCESS; + return file->type; }
@@ -312,7 +342,7 @@ long file_cbfs_read(const struct cbfs_cachenode *file, void *buffer, size = maxsize;
memcpy(buffer, file->data, size); - file_cbfs_result = CBFS_SUCCESS; + return size; }

Hi Simon,
On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
At present there are a number of static variables in BSS. This cannot work with SPL, at least until BSS is available in board_init_r().
Move the variables into a struct, so it is possible to malloc() it and use it before BSS is available.
Signed-off-by: Simon Glass sjg@chromium.org
fs/cbfs/cbfs.c | 96 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 33 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 2a9edcc9a0..f4298d7320 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -11,9 +11,14 @@ enum cbfs_result file_cbfs_result; static const u32 good_magic = 0x4f524243; static const u8 good_file_magic[] = "LARCHIVE"; -static int initialized; -static struct cbfs_header cbfs_header; -static struct cbfs_cachenode *file_cache;
+struct cbfs_priv {
int initialized;
struct cbfs_header header;
struct cbfs_cachenode *file_cache;
+};
Could we move this struct define to cbfs.h?
+static struct cbfs_priv cbfs_s;
const char *file_cbfs_error(void) { @@ -69,8 +74,9 @@ static void swap_file_header(struct cbfs_fileheader *dest,
- @return 1 if a file is found, 0 if one isn't.
*/ -static int file_cbfs_next_file(u8 *start, u32 size, u32 align,
struct cbfs_cachenode *newNode, u32 *used)
+static int file_cbfs_next_file(struct cbfs_priv *priv, u8 *start, u32 size,
u32 align, struct cbfs_cachenode *newNode,
u32 *used)
{ struct cbfs_fileheader header;
@@ -117,20 +123,21 @@ static int file_cbfs_next_file(u8 *start, u32 size, u32 align, }
/* Look through a CBFS instance and copy file metadata into regular memory. */ -static void file_cbfs_fill_cache(u8 *start, u32 size, u32 align) +static void file_cbfs_fill_cache(struct cbfs_priv *priv, u8 *start, u32 size,
u32 align)
{ struct cbfs_cachenode *cache_node; struct cbfs_cachenode *newNode;
struct cbfs_cachenode **cache_tail = &file_cache;
struct cbfs_cachenode **cache_tail = &priv->file_cache; /* Clear out old information. */
cache_node = file_cache;
cache_node = priv->file_cache; while (cache_node) { struct cbfs_cachenode *oldNode = cache_node; cache_node = cache_node->next; free(oldNode); }
file_cache = NULL;
priv->file_cache = NULL; while (size >= align) { int result;
@@ -138,8 +145,8 @@ static void file_cbfs_fill_cache(u8 *start, u32 size, u32 align)
newNode = (struct cbfs_cachenode *) malloc(sizeof(struct cbfs_cachenode));
result = file_cbfs_next_file(start, size, align,
newNode, &used);
result = file_cbfs_next_file(priv, start, size, align, newNode,
&used); if (result < 0) { free(newNode);
@@ -175,27 +182,35 @@ static int file_cbfs_load_header(uintptr_t end_of_rom, return 0; }
-void file_cbfs_init(uintptr_t end_of_rom) +void cbfs_init(struct cbfs_priv *priv, uintptr_t end_of_rom)
nits: this should be static
{ u8 *start_of_rom;
initialized = 0;
if (file_cbfs_load_header(end_of_rom, &cbfs_header))
priv->initialized = 0;
if (file_cbfs_load_header(end_of_rom, &priv->header)) return;
start_of_rom = (u8 *)(end_of_rom + 1 - cbfs_header.rom_size);
start_of_rom = (u8 *)(end_of_rom + 1 - priv->header.rom_size);
file_cbfs_fill_cache(start_of_rom, cbfs_header.rom_size,
cbfs_header.align);
file_cbfs_fill_cache(priv, start_of_rom, priv->header.rom_size,
priv->header.align); if (file_cbfs_result == CBFS_SUCCESS)
initialized = 1;
priv->initialized = 1;
+}
+void file_cbfs_init(uintptr_t end_of_rom) +{
cbfs_init(&cbfs_s, end_of_rom);
}
const struct cbfs_header *file_cbfs_get_header(void) {
if (initialized) {
struct cbfs_priv *priv = &cbfs_s;
if (priv->initialized) { file_cbfs_result = CBFS_SUCCESS;
return &cbfs_header;
return &priv->header; } else { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL;
@@ -204,20 +219,24 @@ const struct cbfs_header *file_cbfs_get_header(void)
const struct cbfs_cachenode *file_cbfs_get_first(void) {
if (!initialized) {
struct cbfs_priv *priv = &cbfs_s;
if (!priv->initialized) { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL; } else { file_cbfs_result = CBFS_SUCCESS;
return file_cache;
return priv->file_cache; }
}
void file_cbfs_get_next(const struct cbfs_cachenode **file) {
if (!initialized) {
struct cbfs_priv *priv = &cbfs_s;
if (!priv->initialized) { file_cbfs_result = CBFS_NOT_INITIALIZED;
file = NULL;
*file = NULL; return; }
@@ -226,11 +245,12 @@ void file_cbfs_get_next(const struct cbfs_cachenode **file) file_cbfs_result = CBFS_SUCCESS; }
-const struct cbfs_cachenode *file_cbfs_find(const char *name) +const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *priv,
const char *name)
{
struct cbfs_cachenode *cache_node = file_cache;
struct cbfs_cachenode *cache_node = priv->file_cache;
if (!initialized) {
if (!priv->initialized) { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL; }
@@ -248,26 +268,33 @@ const struct cbfs_cachenode *file_cbfs_find(const char *name) return cache_node; }
+const struct cbfs_cachenode *file_cbfs_find(const char *name) +{
return cbfs_find_file(&cbfs_s, name);
+}
const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom, const char *name) {
struct cbfs_priv *priv = &cbfs_s; u8 *start; u32 size; u32 align; static struct cbfs_cachenode node;
if (file_cbfs_load_header(end_of_rom, &cbfs_header))
if (file_cbfs_load_header(end_of_rom, &priv->header)) return NULL;
start = (u8 *)(end_of_rom + 1 - cbfs_header.rom_size);
size = cbfs_header.rom_size;
align = cbfs_header.align;
start = (u8 *)(end_of_rom + 1 - priv->header.rom_size);
size = priv->header.rom_size;
align = priv->header.align; while (size >= align) { int result; u32 used;
result = file_cbfs_next_file(start, size, align, &node, &used);
result = file_cbfs_next_file(priv, start, size, align, &node,
&used); if (result < 0) return NULL;
@@ -287,18 +314,21 @@ const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom, const char *file_cbfs_name(const struct cbfs_cachenode *file) { file_cbfs_result = CBFS_SUCCESS;
I would move these changes to the next patch that touch this function.
return file->name;
}
u32 file_cbfs_size(const struct cbfs_cachenode *file) { file_cbfs_result = CBFS_SUCCESS;
ditto, please fix the following 2 as well
return file->data_length;
}
u32 file_cbfs_type(const struct cbfs_cachenode *file) { file_cbfs_result = CBFS_SUCCESS;
return file->type;
}
@@ -312,7 +342,7 @@ long file_cbfs_read(const struct cbfs_cachenode *file, void *buffer, size = maxsize;
memcpy(buffer, file->data, size);
file_cbfs_result = CBFS_SUCCESS;
return size;
}
Other than above, Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

Hi Bin,
On Wed, 14 Aug 2019 at 02:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
At present there are a number of static variables in BSS. This cannot work with SPL, at least until BSS is available in board_init_r().
Move the variables into a struct, so it is possible to malloc() it and use it before BSS is available.
Signed-off-by: Simon Glass sjg@chromium.org
fs/cbfs/cbfs.c | 96 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 33 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 2a9edcc9a0..f4298d7320 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -11,9 +11,14 @@ enum cbfs_result file_cbfs_result; static const u32 good_magic = 0x4f524243; static const u8 good_file_magic[] = "LARCHIVE"; -static int initialized; -static struct cbfs_header cbfs_header; -static struct cbfs_cachenode *file_cache;
+struct cbfs_priv {
int initialized;
struct cbfs_header header;
struct cbfs_cachenode *file_cache;
+};
Could we move this struct define to cbfs.h?
We could, but I would prefer to keep it opaque. I don't think outside code needs to look at it.
[...]
Regards, Simon

Move the result variable into the struct also, so that it can be used when BSS is not available. Add a function to read it.
Note that all functions sill use the BSS version of the data.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/cbfs.c | 4 ++-- fs/cbfs/cbfs.c | 45 +++++++++++++++++++++++++-------------------- include/cbfs.h | 7 +++++++ 3 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/cmd/cbfs.c b/cmd/cbfs.c index 3d1fc95972..98e652a4e7 100644 --- a/cmd/cbfs.c +++ b/cmd/cbfs.c @@ -29,7 +29,7 @@ static int do_cbfs_init(cmd_tbl_t *cmdtp, int flag, int argc, } } file_cbfs_init(end_of_rom); - if (file_cbfs_result != CBFS_SUCCESS) { + if (cbfs_get_result() != CBFS_SUCCESS) { printf("%s.\n", file_cbfs_error()); return 1; } @@ -67,7 +67,7 @@ static int do_cbfs_fsload(cmd_tbl_t *cmdtp, int flag, int argc,
file = file_cbfs_find(argv[2]); if (!file) { - if (file_cbfs_result == CBFS_FILE_NOT_FOUND) + if (cbfs_get_result() == CBFS_FILE_NOT_FOUND) printf("%s: %s\n", file_cbfs_error(), argv[2]); else printf("%s.\n", file_cbfs_error()); diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index f4298d7320..dafdfb1a07 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -8,7 +8,6 @@ #include <malloc.h> #include <asm/byteorder.h>
-enum cbfs_result file_cbfs_result; static const u32 good_magic = 0x4f524243; static const u8 good_file_magic[] = "LARCHIVE";
@@ -16,13 +15,14 @@ struct cbfs_priv { int initialized; struct cbfs_header header; struct cbfs_cachenode *file_cache; + enum cbfs_result result; };
static struct cbfs_priv cbfs_s;
const char *file_cbfs_error(void) { - switch (file_cbfs_result) { + switch (cbfs_s.result) { case CBFS_SUCCESS: return "Success"; case CBFS_NOT_INITIALIZED: @@ -38,6 +38,11 @@ const char *file_cbfs_error(void) } }
+enum cbfs_result cbfs_get_result(void) +{ + return cbfs_s.result; +} + /* Do endian conversion on the CBFS header structure. */ static void swap_header(struct cbfs_header *dest, struct cbfs_header *src) { @@ -99,7 +104,7 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, u8 *start, u32 size,
swap_file_header(&header, fileHeader); if (header.offset < sizeof(struct cbfs_fileheader)) { - file_cbfs_result = CBFS_BAD_FILE; + priv->result = CBFS_BAD_FILE; return -1; } newNode->next = NULL; @@ -161,7 +166,7 @@ static void file_cbfs_fill_cache(struct cbfs_priv *priv, u8 *start, u32 size, size -= used; start += used; } - file_cbfs_result = CBFS_SUCCESS; + priv->result = CBFS_SUCCESS; }
/* Get the CBFS header out of the ROM and do endian conversion. */ @@ -176,7 +181,7 @@ static int file_cbfs_load_header(uintptr_t end_of_rom,
if (header->magic != good_magic || header->offset > header->rom_size - header->boot_block_size) { - file_cbfs_result = CBFS_BAD_HEADER; + cbfs_s.result = CBFS_BAD_HEADER; return 1; } return 0; @@ -195,7 +200,7 @@ void cbfs_init(struct cbfs_priv *priv, uintptr_t end_of_rom)
file_cbfs_fill_cache(priv, start_of_rom, priv->header.rom_size, priv->header.align); - if (file_cbfs_result == CBFS_SUCCESS) + if (priv->result == CBFS_SUCCESS) priv->initialized = 1; }
@@ -209,10 +214,10 @@ const struct cbfs_header *file_cbfs_get_header(void) struct cbfs_priv *priv = &cbfs_s;
if (priv->initialized) { - file_cbfs_result = CBFS_SUCCESS; + priv->result = CBFS_SUCCESS; return &priv->header; } else { - file_cbfs_result = CBFS_NOT_INITIALIZED; + priv->result = CBFS_NOT_INITIALIZED; return NULL; } } @@ -222,10 +227,10 @@ const struct cbfs_cachenode *file_cbfs_get_first(void) struct cbfs_priv *priv = &cbfs_s;
if (!priv->initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; + priv->result = CBFS_NOT_INITIALIZED; return NULL; } else { - file_cbfs_result = CBFS_SUCCESS; + priv->result = CBFS_SUCCESS; return priv->file_cache; } } @@ -235,14 +240,14 @@ void file_cbfs_get_next(const struct cbfs_cachenode **file) struct cbfs_priv *priv = &cbfs_s;
if (!priv->initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; + priv->result = CBFS_NOT_INITIALIZED; *file = NULL; return; }
if (*file) *file = (*file)->next; - file_cbfs_result = CBFS_SUCCESS; + priv->result = CBFS_SUCCESS; }
const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *priv, @@ -251,7 +256,7 @@ const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *priv, struct cbfs_cachenode *cache_node = priv->file_cache;
if (!priv->initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; + priv->result = CBFS_NOT_INITIALIZED; return NULL; }
@@ -261,9 +266,9 @@ const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *priv, cache_node = cache_node->next; } if (!cache_node) - file_cbfs_result = CBFS_FILE_NOT_FOUND; + priv->result = CBFS_FILE_NOT_FOUND; else - file_cbfs_result = CBFS_SUCCESS; + priv->result = CBFS_SUCCESS;
return cache_node; } @@ -307,27 +312,27 @@ const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom, size -= used; start += used; } - file_cbfs_result = CBFS_FILE_NOT_FOUND; + cbfs_s.result = CBFS_FILE_NOT_FOUND; return NULL; }
const char *file_cbfs_name(const struct cbfs_cachenode *file) { - file_cbfs_result = CBFS_SUCCESS; + cbfs_s.result = CBFS_SUCCESS;
return file->name; }
u32 file_cbfs_size(const struct cbfs_cachenode *file) { - file_cbfs_result = CBFS_SUCCESS; + cbfs_s.result = CBFS_SUCCESS;
return file->data_length; }
u32 file_cbfs_type(const struct cbfs_cachenode *file) { - file_cbfs_result = CBFS_SUCCESS; + cbfs_s.result = CBFS_SUCCESS;
return file->type; } @@ -342,7 +347,7 @@ long file_cbfs_read(const struct cbfs_cachenode *file, void *buffer, size = maxsize;
memcpy(buffer, file->data, size); - file_cbfs_result = CBFS_SUCCESS; + cbfs_s.result = CBFS_SUCCESS;
return size; } diff --git a/include/cbfs.h b/include/cbfs.h index b8d1dabbf6..742e34e24f 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -90,6 +90,13 @@ extern enum cbfs_result file_cbfs_result; */ const char *file_cbfs_error(void);
+/** + * cbfs_get_result() - Get the result of the last CBFS operation + * + *@return last result + */ +enum cbfs_result cbfs_get_result(void); + /** * file_cbfs_init() - Initialize the CBFS driver and load metadata into RAM. *

On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
Move the result variable into the struct also, so that it can be used when BSS is not available. Add a function to read it.
Note that all functions sill use the BSS version of the data.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/cbfs.c | 4 ++-- fs/cbfs/cbfs.c | 45 +++++++++++++++++++++++++-------------------- include/cbfs.h | 7 +++++++ 3 files changed, 34 insertions(+), 22 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

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 ---
fs/cbfs/cbfs.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/cbfs.h | 22 ++++++++++++++++++++++ 2 files changed, 68 insertions(+)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index dafdfb1a07..bb795e7288 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; +} + 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; diff --git a/include/cbfs.h b/include/cbfs.h index 742e34e24f..6d4c4d4b06 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -135,6 +135,28 @@ void file_cbfs_get_next(const struct cbfs_cachenode **file); */ const struct cbfs_cachenode *file_cbfs_find(const char *name);
+struct cbfs_priv *priv; + +/** + * cbfs_find_file() - Find a file in a given CBFS + * + * @cbfs: CBFS to look in (use cbfs_init_mem() to set it up) + * @name: Filename to look for + * @return pointer to CBFS node if found, else NULL + */ +const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *cbfs, + const char *name); + +/** + * cbfs_init_mem() - Set up a new CBFS + * + * @base: Base address of CBFS + * @size: Size of CBFS in bytes + * @cbfsp: Returns a pointer to CBFS on success + * @return 0 if OK, -ve on error + */ +int cbfs_init_mem(ulong base, ulong size, struct cbfs_priv **privp); +
/***************************************************************************/ /* All of the functions below can be used without first initializing CBFS. */

On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
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
fs/cbfs/cbfs.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/cbfs.h | 22 ++++++++++++++++++++++ 2 files changed, 68 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Rename some camel-case variables to match U-Boot style.
Camel case is not generally allowed in U-Boot. Rename this variable to fit in with the style.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index bb795e7288..aaf9ce941b 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -73,14 +73,14 @@ static void swap_file_header(struct cbfs_fileheader *dest, * @param start The location in memory to start from. * @param size The size of the memory region to search. * @param align The alignment boundaries to check on. - * @param newNode A pointer to the file structure to load. + * @param new_node A pointer to the file structure to load. * @param used A pointer to the count of of bytes scanned through, * including the file if one is found. * * @return 1 if a file is found, 0 if one isn't. */ static int file_cbfs_next_file(struct cbfs_priv *priv, u8 *start, u32 size, - u32 align, struct cbfs_cachenode *newNode, + u32 align, struct cbfs_cachenode *new_node, u32 *used) { struct cbfs_fileheader header; @@ -88,34 +88,34 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, u8 *start, u32 size, *used = 0;
while (size >= align) { - const struct cbfs_fileheader *fileHeader = + const struct cbfs_fileheader *file_header = (const struct cbfs_fileheader *)start; u32 name_len; u32 step;
/* Check if there's a file here. */ - if (memcmp(good_file_magic, &(fileHeader->magic), - sizeof(fileHeader->magic))) { + if (memcmp(good_file_magic, &file_header->magic, + sizeof(file_header->magic))) { *used += align; size -= align; start += align; continue; }
- swap_file_header(&header, fileHeader); + swap_file_header(&header, file_header); if (header.offset < sizeof(struct cbfs_fileheader)) { priv->result = CBFS_BAD_FILE; return -1; } - newNode->next = NULL; - newNode->type = header.type; - newNode->data = start + header.offset; - newNode->data_length = header.len; + new_node->next = NULL; + new_node->type = header.type; + new_node->data = start + header.offset; + new_node->data_length = header.len; name_len = header.offset - sizeof(struct cbfs_fileheader); - newNode->name = (char *)fileHeader + + new_node->name = (char *)file_header + sizeof(struct cbfs_fileheader); - newNode->name_length = name_len; - newNode->attributes_offset = header.attributes_offset; + new_node->name_length = name_len; + new_node->attributes_offset = header.attributes_offset;
step = header.len; if (step % align) @@ -132,15 +132,15 @@ static void file_cbfs_fill_cache(struct cbfs_priv *priv, u8 *start, u32 size, u32 align) { struct cbfs_cachenode *cache_node; - struct cbfs_cachenode *newNode; + struct cbfs_cachenode *new_node; struct cbfs_cachenode **cache_tail = &priv->file_cache;
/* Clear out old information. */ cache_node = priv->file_cache; while (cache_node) { - struct cbfs_cachenode *oldNode = cache_node; + struct cbfs_cachenode *old_node = cache_node; cache_node = cache_node->next; - free(oldNode); + free(old_node); } priv->file_cache = NULL;
@@ -148,20 +148,20 @@ static void file_cbfs_fill_cache(struct cbfs_priv *priv, u8 *start, u32 size, int result; u32 used;
- newNode = (struct cbfs_cachenode *) + new_node = (struct cbfs_cachenode *) malloc(sizeof(struct cbfs_cachenode)); - result = file_cbfs_next_file(priv, start, size, align, newNode, + result = file_cbfs_next_file(priv, start, size, align, new_node, &used);
if (result < 0) { - free(newNode); + free(new_node); return; } else if (result == 0) { - free(newNode); + free(new_node); break; } - *cache_tail = newNode; - cache_tail = &newNode->next; + *cache_tail = new_node; + cache_tail = &new_node->next;
size -= used; start += used;

On Wed, Aug 14, 2019 at 11:09 AM Simon Glass sjg@chromium.org wrote:
Rename some camel-case variables to match U-Boot style.
Camel case is not generally allowed in U-Boot. Rename this variable to fit in with the style.
Signed-off-by: Simon Glass sjg@chromium.org
fs/cbfs/cbfs.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
participants (2)
-
Bin Meng
-
Simon Glass