summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorGabe Black <gabeblack@chromium.org>2011-08-11 02:01:08 -0700
committerSimon Glass <sjg@chromium.org>2011-08-29 10:59:36 -0700
commitf461780a13efe560edf8a16c8df1e7e9b92d7035 (patch)
tree6b34cdb4af6d9f708882e6e91ee18cf699e724ea /fs
parentc13a7dafd73cdce4a65f3ef332267e832ad1080c (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.c180
1 files changed, 115 insertions, 65 deletions
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
index f25689e1c4..5b8debfd10 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;