From 72b2465c6b897f7ac4a2a151f648dff9239b1cfe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Aug 2019 19:56:10 -0600 Subject: cbfs: Allow CBFS to be used in SPL 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 Reviewed-by: Bin Meng Tested-by: Bin Meng --- fs/cbfs/Kconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'fs/cbfs') diff --git a/fs/cbfs/Kconfig b/fs/cbfs/Kconfig index 16089547a51..03980d830d3 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 is not + available. -- cgit v1.2.3 From fc7b9e16a04610b951a9d36abf41d80edb87e3e5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Aug 2019 19:56:11 -0600 Subject: cbfs: Move declarations above functions At present this file has a function at the top, above declarations. This is normally avoided, so fix it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- fs/cbfs/cbfs.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'fs/cbfs') diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index af4d3c5e564..2a9edcc9a00 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -9,6 +9,11 @@ #include 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) { -- cgit v1.2.3 From 02e4af63a9f5531b7975d21828edea04d6d519d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Aug 2019 19:56:12 -0600 Subject: cbfs: Move static variables into a struct 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 Reviewed-by: Bin Meng Tested-by: Bin Meng --- fs/cbfs/cbfs.c | 91 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 32 deletions(-) (limited to 'fs/cbfs') diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 2a9edcc9a00..daae7162970 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) +static 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; -- cgit v1.2.3 From c7f16934749b054ce1f0b75bd664d22af8b7c588 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Aug 2019 19:56:13 -0600 Subject: cbfs: Move result variable into the struct 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 Reviewed-by: Bin Meng Tested-by: Bin Meng --- fs/cbfs/cbfs.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'fs/cbfs') diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index daae7162970..d9a8562e5c8 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -8,7 +8,6 @@ #include #include -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 @@ static 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,25 +312,28 @@ 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; } @@ -339,7 +347,7 @@ long file_cbfs_read(const struct cbfs_cachenode *file, void *buffer, size = maxsize; memcpy(buffer, file->data, size); + cbfs_s.result = CBFS_SUCCESS; - file_cbfs_result = CBFS_SUCCESS; return size; } -- cgit v1.2.3 From 630b2f39ddabd43a27a98f0356b948df18e97d88 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Aug 2019 19:56:14 -0600 Subject: 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 Reviewed-by: Bin Meng Tested-by: Bin Meng --- fs/cbfs/cbfs.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'fs/cbfs') diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index d9a8562e5c8..35f919afee8 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; -- cgit v1.2.3 From ad79d603aa68a7a523005ce694ee4b43efdf7382 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Aug 2019 19:56:15 -0600 Subject: cbfs: Rename camel-case variables 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 Reviewed-by: Bin Meng Tested-by: Bin Meng --- fs/cbfs/cbfs.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'fs/cbfs') diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 35f919afee8..1aa6f8ee847 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; -- cgit v1.2.3