diff options
author | Gabe Black <gabeblack@chromium.org> | 2011-08-11 02:01:08 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-29 10:59:36 -0700 |
commit | f461780a13efe560edf8a16c8df1e7e9b92d7035 (patch) | |
tree | 6b34cdb4af6d9f708882e6e91ee18cf699e724ea /fs | |
parent | c13a7dafd73cdce4a65f3ef332267e832ad1080c (diff) |
Refactor the CBFS implementation and add a cbfs_file_find_uncached function
If u-boot needs something out of CBFS very early before the heap is
configured, it won't be able to use the normal CBFS support which caches some
information in memory it allocates from the heap. This change adds a new
cbfs_file_find_uncached function which searchs a CBFS instance without touching
the heap. It also refactors the implementation of u-boot's CBFS support to
avoid code duplication, and allows some functions to be used without CBFS being
initialized which sets up the cache on the heap.
BUG=chrome-os-partner:5432
TEST=Built x86-alex, verified that the CBFS commands still work, and with
later changes verified that the device tree could be loaded from CBFS before
the heap is initialized.
Signed-off-by: Gabe Black <gabeblack@google.com>
Change-Id: Ia57a5c553a0cd524073c05ca964501ccf6c5e025
Reviewed-on: http://gerrit.chromium.org/gerrit/5858
Tested-by: Gabe Black <gabeblack@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cbfs/cbfs.c | 180 |
1 files changed, 115 insertions, 65 deletions
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index f25689e1c4c..5b8debfd109 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -69,7 +69,7 @@ static const u8 goodFileMagic[] = "LARCHIVE"; static int initialized; -static struct CbfsHeader header; +static struct CbfsHeader cbfsHeader; static CbfsCacheNode *fileCache; static void @@ -93,23 +93,13 @@ swap_file_header(CbfsFileHeader *dest, CbfsFileHeader *src) dest->offset = be32_to_cpu(src->offset); } -static void -file_cbfs_fill_cache(u8 *start, u32 size, u32 align) +static int +file_cbfs_next_file(u8 *start, u32 size, u32 align, CbfsCacheNode *newNode, + u32 *used) { - CbfsCacheNode *cacheNode; - CbfsCacheNode *newNode; CbfsFileHeader header; - CbfsCacheNode **cacheTail = &fileCache; - /* Clear out old information. */ - cacheNode = fileCache; - while (cacheNode) { - CbfsCacheNode *oldNode = cacheNode; - cacheNode = cacheNode->next; - free(oldNode->name); - free(oldNode); - } - fileCache = NULL; + *used = 0; while (size >= align) { CbfsFileHeader *fileHeader = (CbfsFileHeader *)start; @@ -119,64 +109,106 @@ file_cbfs_fill_cache(u8 *start, u32 size, u32 align) /* Check if there's a file here. */ if (memcmp(goodFileMagic, &(fileHeader->magic), sizeof(fileHeader->magic))) { + *used += align; size -= align; start += align; continue; } - newNode = (CbfsCacheNode *)malloc(sizeof(CbfsCacheNode)); swap_file_header(&header, fileHeader); if (header.offset < sizeof(CbfsFileHeader) || header.offset > header.len) { file_cbfs_result = CBFS_BAD_FILE; - return; + return -1; } newNode->next = NULL; newNode->type = header.type; newNode->data = start + header.offset; newNode->dataLength = header.len; nameLen = header.offset - sizeof(CbfsFileHeader); - /* Add a byte for a NULL terminator. */ - newNode->name = (char *)malloc(nameLen + 1); - strncpy(newNode->name, - ((char *)fileHeader) + sizeof(CbfsFileHeader), - nameLen); - newNode->name[nameLen] = 0; + newNode->name = (char *)fileHeader + sizeof(CbfsFileHeader); newNode->nameLength = nameLen; newNode->checksum = header.checksum; - *cacheTail = newNode; - cacheTail = &newNode->next; step = header.len; if (step % align) step = step + align - step % align; - size -= step; - start += step; + *used += step; + return 1; + } + return 0; +} + +static void +file_cbfs_fill_cache(u8 *start, u32 size, u32 align) +{ + CbfsCacheNode *cacheNode; + CbfsCacheNode *newNode; + CbfsCacheNode **cacheTail = &fileCache; + + /* Clear out old information. */ + cacheNode = fileCache; + while (cacheNode) { + CbfsCacheNode *oldNode = cacheNode; + cacheNode = cacheNode->next; + free(oldNode); + } + fileCache = NULL; + + while (size >= align) { + int result; + u32 used; + + newNode = (CbfsCacheNode *)malloc(sizeof(CbfsCacheNode)); + result = file_cbfs_next_file(start, size, align, + newNode, &used); + + if (result < 0) { + free(newNode); + return; + } else if (result == 0) { + free(newNode); + break; + } + *cacheTail = newNode; + cacheTail = &newNode->next; + + size -= used; + start += used; } file_cbfs_result = CBFS_SUCCESS; } -void -file_cbfs_init(uintptr_t endOfRom) +static int +file_cbfs_load_header(uintptr_t endOfRom, CbfsHeader *header) { CbfsHeader *headerInRom; - u8 *startOfRom; - initialized = 0; headerInRom = (CbfsHeader *)(uintptr_t)*(u32 *)(endOfRom - 3); - swap_header(&header, headerInRom); + swap_header(header, headerInRom); - if (header.magic != goodMagic || header.offset > - header.romSize - header.bootBlockSize) { + if (header->magic != goodMagic || header->offset > + header->romSize - header->bootBlockSize) { file_cbfs_result = CBFS_BAD_HEADER; - return; + return 1; } + return 0; +} - startOfRom = (u8 *)(endOfRom + 1 - header.romSize); +void +file_cbfs_init(uintptr_t endOfRom) +{ + u8 *startOfRom; + initialized = 0; - file_cbfs_fill_cache(startOfRom + header.offset, - header.romSize, header.align); + if (file_cbfs_load_header(endOfRom, &cbfsHeader)) + return; + + startOfRom = (u8 *)(endOfRom + 1 - cbfsHeader.romSize); + + file_cbfs_fill_cache(startOfRom + cbfsHeader.offset, + cbfsHeader.romSize, cbfsHeader.align); if (file_cbfs_result == CBFS_SUCCESS) initialized = 1; } @@ -186,7 +218,7 @@ file_cbfs_get_header(void) { if (initialized) { file_cbfs_result = CBFS_SUCCESS; - return &header; + return &cbfsHeader; } else { file_cbfs_result = CBFS_NOT_INITIALIZED; return NULL; @@ -242,40 +274,63 @@ file_cbfs_find(const char *name) return cacheNode; } -const char * -file_cbfs_name(CbfsFile file) +CbfsFile +file_cbfs_find_uncached(uintptr_t endOfRom, const char *name) { - if (!initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; + u8 *start; + u32 size; + u32 align; + static CbfsCacheNode node; + + if (file_cbfs_load_header(endOfRom, &cbfsHeader)) return NULL; - } else { - file_cbfs_result = CBFS_SUCCESS; - return file->name; + + start = (u8 *)(endOfRom + 1 - cbfsHeader.romSize); + size = cbfsHeader.romSize; + align = cbfsHeader.align; + + while (size >= align) { + int result; + u32 used; + + result = file_cbfs_next_file(start, size, align, &node, &used); + + if (result < 0) { + return NULL; + } else if (result == 0) { + break; + } + + if (!strcmp(name, node.name)) { + return &node; + } + + size -= used; + start += used; } + file_cbfs_result = CBFS_FILE_NOT_FOUND; + return NULL; +} + +const char * +file_cbfs_name(CbfsFile file) +{ + file_cbfs_result = CBFS_SUCCESS; + return file->name; } u32 file_cbfs_size(CbfsFile file) { - if (!initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; - return 0; - } else { - file_cbfs_result = CBFS_SUCCESS; - return file->dataLength; - } + file_cbfs_result = CBFS_SUCCESS; + return file->dataLength; } u32 file_cbfs_type(CbfsFile file) { - if (!initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; - return 0; - } else { - file_cbfs_result = CBFS_SUCCESS; - return file->type; - } + file_cbfs_result = CBFS_SUCCESS; + return file->type; } long @@ -283,11 +338,6 @@ file_cbfs_read(CbfsFile file, void *buffer, unsigned long maxsize) { u32 size; - if (!initialized) { - file_cbfs_result = CBFS_NOT_INITIALIZED; - return -CBFS_NOT_INITIALIZED; - } - size = file->dataLength; if (maxsize && size > maxsize) size = maxsize; |