Naman Govil (namangov@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/6169
-gerrit
commit 7c9e511163197db9e57c874212a1c9574f2a1f47 Author: Naman Govil namangov@gmail.com Date: Mon Jun 30 22:57:11 2014 +0530
Remove unnecessary mappings in cbfs_media
Reducing the sram usage while booting by removing unwanted map()s by creating a structure to replace it with appropriate read()s
Change-Id: If503368553308a2fdd3ecc1a312a11f14c7a707f Signed-off-by: Naman Govil namangov@gmail.com --- src/include/cbfs_core.h | 19 ++++- src/lib/cbfs.c | 72 +++++++++++++------ src/lib/cbfs_core.c | 182 +++++++++++++++++++++++++++++++----------------- 3 files changed, 188 insertions(+), 85 deletions(-)
diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h index a1d8127..6e0193a 100644 --- a/src/include/cbfs_core.h +++ b/src/include/cbfs_core.h @@ -4,6 +4,7 @@ * Copyright (C) 2008 Jordan Crouse jordan@cosmicpenguin.net * Copyright (C) 2012 Google, Inc. * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2014 Naman Govil namangov@gmail.com * * This file is dual-licensed. You can choose between: * - The GNU GPL, version 2, as published by the Free Software Foundation @@ -189,6 +190,13 @@ struct cbfs_optionrom { #define CBFS_MEDIA_INVALID_MAP_ADDRESS ((void*)(0xffffffff)) #define CBFS_DEFAULT_MEDIA ((void*)(0x0))
+struct cbfs_file_handler { + uint32_t found; + uint32_t data_offset; + uint32_t data_len; + struct cbfs_file file; +}; + /* Media for CBFS to load files. */ struct cbfs_media {
@@ -220,9 +228,6 @@ struct cbfs_media { /* returns pointer to a file entry inside CBFS or NULL */ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name);
-/* returns pointer to file content inside CBFS after if type is correct */ -void *cbfs_get_file_content(struct cbfs_media *media, const char *name, - int type, size_t *sz);
/* returns decompressed size on success, 0 on failure */ int cbfs_decompress(int algo, void *src, void *dst, int len); @@ -231,6 +236,14 @@ int cbfs_decompress(int algo, void *src, void *dst, int len); * on failure */ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media);
+/*Returns success (0) on finding the file requested by verifying name/type; -1 if file not found + The absolute data_offset to the file is stored*/ +int cbfs_find_file(struct cbfs_media *media, struct cbfs_file_handler *f, const char *name, int type); + + +/* returns pointer to file content inside CBFS after verifying if type is correct */ +void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type, size_t *sz); + #endif /* __ROMCC__ */
#endif diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index dc08937..d349383 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -3,7 +3,7 @@ * * Copyright (C) 2008, Jordan Crouse jordan@cosmicpenguin.net * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. - * + * Copyright (C) 2014, Naman Govil namangov@gmail.com * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. @@ -119,39 +119,71 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
void * cbfs_load_stage(struct cbfs_media *media, const char *name) { - struct cbfs_stage *stage = (struct cbfs_stage *) - cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL); + struct cbfs_file_handler f; + struct cbfs_stage stage; + int c; + ssize_t value_read; + void * data; + ssize_t v_read; + struct cbfs_media default_media; + + if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to initialize default media.\n"); + return NULL; + } + } + + c = cbfs_find_file(media, &f, name, CBFS_TYPE_STAGE); + if (c == 0) { + value_read = media->read(media, &stage, f.data_offset, sizeof(stage)); /* this is a mess. There is no ntohll. */ /* for now, assume compatible byte order until we solve this. */ uint32_t entry; uint32_t final_size;
- if (stage == NULL) + DEBUG("Read Complete @offset = 0x%x and length = %d\n", f.data_offset, value_read); + if (value_read != sizeof(stage)) return (void *) -1;
LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n", name, - (uint32_t) stage->load, stage->memlen, - stage->entry); - - final_size = cbfs_decompress(stage->compression, - ((unsigned char *) stage) + - sizeof(struct cbfs_stage), - (void *) (uint32_t) stage->load, - stage->len); - if (!final_size) - return (void *) -1; + (uint32_t) stage.load, stage.memlen, + stage.entry);
- /* Stages rely the below clearing so that the bss is initialized. */ - memset((void *)((uintptr_t)stage->load + final_size), 0, - stage->memlen - final_size);
- DEBUG("stage loaded.\n"); + if(stage.compression == CBFS_COMPRESS_NONE) //i.e no compression + { + //No compression; hence we can directly read + DEBUG("Read Done\n"); + v_read = media->read(media, (void *) (uintptr_t) stage.load, f.data_offset + sizeof(stage), f.data_len); + final_size = f.data_len; + } + else + { + data = media->map(media, f.data_offset + sizeof(stage), f.data_len); + DEBUG("Map Done\n"); + final_size = cbfs_decompress(stage.compression, data, + (void *) (uint32_t) stage.load, + stage.len); + + if (!final_size) + return (void *) -1; + }
- entry = stage->entry; - // entry = ntohll(stage->entry); + /* Stages rely the below clearing so that the bss is initialized. */ + memset((void *)((uintptr_t)stage.load + final_size), 0, + stage.memlen - final_size);
+ DEBUG("stage loaded.\n"); + entry = stage.entry; return (void *) entry; + + } else { + ERROR("Stage not loaded\n"); + return (void *)-1; + } }
/* Simple buffer */ diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c index 50c037e..10e23f1 100644 --- a/src/lib/cbfs_core.c +++ b/src/lib/cbfs_core.c @@ -3,6 +3,7 @@ * * Copyright (C) 2011 secunet Security Networks AG * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2014 Naman Govil namangov@gmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -56,8 +57,10 @@ * on failure */ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) { - const struct cbfs_header *header; + struct cbfs_header header; + const struct cbfs_header *h; struct cbfs_media default_media; + ssize_t header_size;
if (media == CBFS_DEFAULT_MEDIA) { media = &default_media; @@ -70,133 +73,188 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) media->open(media); DEBUG("CBFS_HEADER_ROM_ADDRESS: 0x%x/0x%x\n", CBFS_HEADER_ROM_ADDRESS, CONFIG_ROM_SIZE); - header = media->map(media, CBFS_HEADER_ROM_ADDRESS, sizeof(*header)); + header_size = media->read(media, &header, CBFS_HEADER_ROM_ADDRESS, sizeof(header)); + //size of mapping (now read) is 32 bytes media->close(media);
- if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + if (header_size == sizeof(header)) { ERROR("Failed to load CBFS header from 0x%x\n", CBFS_HEADER_ROM_ADDRESS); return CBFS_HEADER_INVALID_ADDRESS; }
- if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { + if (CBFS_HEADER_MAGIC != ntohl(header.magic)) { ERROR("Could not find valid CBFS master header at %x: " "%x vs %x.\n", CBFS_HEADER_ROM_ADDRESS, CBFS_HEADER_MAGIC, - ntohl(header->magic)); - if (header->magic == 0xffffffff) { + ntohl(header.magic)); + if (header.magic == 0xffffffff) { ERROR("Maybe ROM is not mapped properly?\n"); } return CBFS_HEADER_INVALID_ADDRESS; } - return header; + + h = &header; + return h; }
/* public API starts here*/ -struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) +/* This functions finds the absolute data_offset of a file searched for by name/type + Returns 0 on success and -1 on failure + */ +int cbfs_find_file(struct cbfs_media *media, struct cbfs_file_handler *f, const char *name, int type) { - const char *file_name; - uint32_t offset, align, romsize, name_len; - const struct cbfs_header *header; - struct cbfs_file file, *file_ptr; + uint32_t offset, align, romsize,name_len; struct cbfs_media default_media; + const struct cbfs_header *header; + ssize_t value_read; + const char *file_name;
if (media == CBFS_DEFAULT_MEDIA) { media = &default_media; if (init_default_cbfs_media(media) != 0) { ERROR("Failed to initialize default media.\n"); - return NULL; + return -1; } }
if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media))) - return NULL; + return -1; // error
// Logical offset (for source media) of first file. + // Now we know where the file lives offset = ntohl(header->offset); align = ntohl(header->align); romsize = ntohl(header->romsize);
- // TODO Add a "size" in CBFS header for a platform independent way to - // determine the end of CBFS data. #if defined(CONFIG_ARCH_X86) && CONFIG_ARCH_X86 romsize -= htonl(header->bootblocksize); #endif + int catch; DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); - DEBUG("Looking for '%s' starting from 0x%x.\n", name, offset); media->open(media); - while (offset < romsize && - media->read(media, &file, offset, sizeof(file)) == sizeof(file)) { - if (memcmp(CBFS_FILE_MAGIC, file.magic, - sizeof(file.magic)) != 0) { + while (offset < romsize) + { + value_read = media->read(media, &f->file, offset, sizeof(f->file)); + if(value_read != sizeof(f->file)){ + return -1; //error: since read not successful + break; + } + //make all ntohl() at once place to avoid any gibberish later + f->file.len = ntohl(f->file.len); + f->file.offset = ntohl(f->file.offset); + f->file.type = ntohl(f->file.type); + + if (memcmp(CBFS_FILE_MAGIC, f->file.magic, + sizeof(f->file.magic)) != 0) { uint32_t new_align = align; if (offset % align) new_align += align - (offset % align); - ERROR("ERROR: No file header found at 0x%x - " - "try next aligned address: 0x%x.\n", offset, - offset + new_align); + ERROR("ERROR: No file header found at 0x%x - try next aligned address: 0x%x.\n", offset,offset+new_align); offset += new_align; continue; + //continuing with new offset } - name_len = ntohl(file.offset) - sizeof(file); - DEBUG(" - load entry 0x%x file name (%d bytes)...\n", offset, - name_len); - - // load file name (arbitrary length). - file_name = (const char *)media->map( - media, offset + sizeof(file), name_len); - if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("ERROR: Failed to get filename: 0x%x.\n", offset); - } else if (strcmp(file_name, name) == 0) { - int file_offset = ntohl(file.offset), - file_len = ntohl(file.len); - DEBUG("Found file (offset=0x%x, len=%d).\n", - offset + file_offset, file_len); - media->unmap(media, file_name); - file_ptr = media->map(media, offset, - file_offset + file_len); - media->close(media); - return file_ptr; - } else { - DEBUG(" (unmatched file @0x%x: %s)\n", offset, - file_name); - media->unmap(media, file_name); - }
+ f->found = -1; + if(f->file.type == type){ + + name_len = f->file.offset - sizeof(f->file); + DEBUG(" - load entry 0x%x file name (%d bytes)...\n", offset,name_len); + // load file name (arbitrary length). + file_name = (const char *)media->map(media, offset + sizeof(f->file), name_len); + //this mapping done to verify name of file + if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + ERROR("ERROR: Failed to get filename: 0x%x.\n", offset); + } else if (strcmp(file_name, name) == 0) { + f->found = 0; + f->data_offset = offset + f->file.offset; + f->data_len = f->file.len; + media->unmap(media, file_name); + DEBUG("Found file:offset = 0x%x, len=%d\n", f->data_offset, f->data_len); + catch = f->found; + return catch; + } else { + DEBUG("unmatched file offset = 0x%x : %s\n", offset, file_name); + media->unmap(media,file_name); + } + } // Move to next file. - offset += ntohl(file.len) + ntohl(file.offset); + offset += f->file.len + f->file.offset; if (offset % align) offset += align - (offset % align); + DEBUG("Going for next offset\n"); } media->close(media); - LOG("WARNING: '%s' not found.\n", name); - return NULL; + LOG("Warning: '%s' not found\n",name); + return -1; }
-void *cbfs_get_file_content(struct cbfs_media *media, const char *name, - int type, size_t *sz) + +/*Returns pointer to file content inside CBFS after verifying type + */ +void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type, size_t *sz) { - struct cbfs_file *file = cbfs_get_file(media, name); + struct cbfs_file_handler f; + int c; + struct cbfs_media default_media;
+ if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to initialize default media.\n"); + return NULL; + } + } + c = cbfs_find_file(media, &f, name, type); + if (c == 0){ + DEBUG("Found file. Will be mapping it now!\n"); if (sz) *sz = 0;
- if (file == NULL) { - ERROR("Could not find file '%s'.\n", name); + if (f.file.type != type) { + ERROR("File '%s' is of type %x, but we requested %x.\n", name, f.file.type, type); return NULL; }
- if (ntohl(file->type) != type) { - ERROR("File '%s' is of type %x, but we requested %x.\n", name, - ntohl(file->type), type); + if (sz) + *sz = f.data_len; + return media->map(media, f.data_offset, f.data_len + f.file.offset); + } + else { + DEBUG("condition not successful\n"); + ERROR("File Not Found\n"); return NULL; } +}
- if (sz) - *sz = ntohl(file->len); +/*void cbfs_get_data(struct cbfs_media *media, const char *name, int type) +{ + struct cbfs_file_handler f; + ssize_t value_read; + int c; + c = cbfs_find_file(media, &f, name, type); + if (c == 0){ + DEBUG("File has been found and can be read\n"); + uint32_t loop_offset = f.data_offset + f.file.offset; + uint32_t loop_align = f.align; + + while (f.data_len > 0){ + + struct cbfs_file file; + value_read = media->read(media, &file, loop_offset , sizeof(file)); + loop_offset += file.len + file.offset; + if (loop_offset % loop_align) + loop_offset += loop_align = (loop_offset % loop_align); + f.data_len -= sizeof(file); + } + } + else { + ERROR("File not found\n"); + }
- return (void *)CBFS_SUBHEADER(file); } +*/
int cbfs_decompress(int algo, void *src, void *dst, int len) {