diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-04-27 21:51:13 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-04-27 21:51:13 -0400 |
commit | cbd6ca05d9c5797f9cfc816342181fb91b600099 (patch) | |
tree | 79775948807839a4d141b13f7cfa28de099e8ecc /src | |
parent | 592323fdb2de5ff4b546d24109070c7614c7ad2b (diff) | |
download | seabios-hppa-cbd6ca05d9c5797f9cfc816342181fb91b600099.zip seabios-hppa-cbd6ca05d9c5797f9cfc816342181fb91b600099.tar.gz seabios-hppa-cbd6ca05d9c5797f9cfc816342181fb91b600099.tar.bz2 |
Add support for compressed option roms.
Diffstat (limited to 'src')
-rw-r--r-- | src/coreboot.c | 69 | ||||
-rw-r--r-- | src/optionroms.c | 9 | ||||
-rw-r--r-- | src/util.h | 2 |
3 files changed, 56 insertions, 24 deletions
diff --git a/src/coreboot.c b/src/coreboot.c index 7392aa2..3782167 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -278,7 +278,7 @@ fail: ****************************************************************/ static int -ulzma(u8 *dst, const u8 *src) +ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen) { CLzmaDecoderState state; int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); @@ -295,8 +295,12 @@ ulzma(u8 *dst, const u8 *src) state.Probs = (CProb *)scratch; u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE); + if (dstlen > maxlen) { + dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen); + return -1; + } u32 inProcessed, outProcessed; - ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, 0xffffffff + ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen , &inProcessed, dst, dstlen, &outProcessed); if (ret) { dprintf(1, "LzmaDecode returned %d\n", ret); @@ -366,8 +370,10 @@ cbfs_search(struct cbfs_file *file) if (file < (struct cbfs_file *)(0xFFFFFFFF - ntohl(CBHDR->romsize))) return NULL; u64 magic = file->magic; - if (magic == CBFS_FILE_MAGIC) + if (magic == CBFS_FILE_MAGIC) { + dprintf(5, "Found CBFS file %s\n", file->filename); return file; + } if (magic == 0) return NULL; file = (void*)file + ntohl(CBHDR->align); @@ -392,9 +398,6 @@ cbfs_getnext(struct cbfs_file *file) static struct cbfs_file * cbfs_findfile(const char *fname) { - if (! CONFIG_COREBOOT_FLASH) - return NULL; - dprintf(3, "Searching CBFS for %s\n", fname); struct cbfs_file *file; for (file = cbfs_getfirst(); file; file = cbfs_getnext(file)) { @@ -405,6 +408,38 @@ cbfs_findfile(const char *fname) return NULL; } +// Copy a file to memory (uncompressing if necessary) +static int +cbfs_copyfile(void *dst, u32 maxlen, const char *fname) +{ + dprintf(3, "Searching CBFS for data file %s\n", fname); + int fnlen = strlen(fname); + struct cbfs_file *file; + for (file = cbfs_getfirst(); file; file = cbfs_getnext(file)) { + if (memcmp(fname, file->filename, fnlen) != 0) + continue; + u32 size = ntohl(file->len); + void *src = (void*)file + ntohl(file->offset); + if (file->filename[fnlen] == '\0') { + // No compression + if (size > maxlen) { + dprintf(1, "File too big to copy\n"); + return -1; + } + dprintf(3, "Copying data file %s\n", file->filename); + memcpy(dst, src, size); + return size; + } + if (strcmp(&file->filename[fnlen], ".lzma") == 0) { + // lzma compressed file + dprintf(3, "Uncompressing data file %s @ %p\n" + , file->filename, src); + return ulzma(dst, maxlen, src, size); + } + } + return -1; +} + const char * cbfs_findNprefix(const char *prefix, int n) { @@ -415,7 +450,6 @@ cbfs_findNprefix(const char *prefix, int n) int len = strlen(prefix); struct cbfs_file *file; for (file = cbfs_getfirst(); file; file = cbfs_getnext(file)) { - dprintf(3, "Found CBFS file %s\n", file->filename); if (memcmp(prefix, file->filename, len) == 0) { if (n <= 0) return file->filename; @@ -442,11 +476,11 @@ hexify4(u16 x) | (getHex(x>>12))); } -void * -cb_find_optionrom(u32 vendev) +int +cb_copy_optionrom(void *dst, u32 maxlen, u32 vendev) { if (! CONFIG_COREBOOT_FLASH) - return NULL; + return -1; char fname[17]; // Ughh - poor man's sprintf of "pci%04x,%04x.rom" @@ -457,12 +491,7 @@ cb_find_optionrom(u32 vendev) *(u32*)&fname[12] = 0x6d6f722e; // ".rom" fname[16] = '\0'; - struct cbfs_file *file = cbfs_findfile(fname); - if (!file) - return NULL; - // Found it. - dprintf(3, "Found rom at %p\n", (void*)file + ntohl(file->offset)); - return (void*)file + ntohl(file->offset); + return cbfs_copyfile(dst, maxlen, fname); } struct cbfs_payload_segment { @@ -487,6 +516,8 @@ struct cbfs_payload { void cbfs_run_payload(const char *filename) { + if (! CONFIG_COREBOOT_FLASH) + return; dprintf(1, "Run %s\n", filename); struct cbfs_file *file = cbfs_findfile(filename); if (!file) @@ -512,13 +543,13 @@ cbfs_run_payload(const char *filename) default: dprintf(3, "Segment %x %d@%p -> %d@%p\n" , seg->type, src_len, src, dest_len, dest); - if (src_len > dest_len) - src_len = dest_len; if (seg->compression == htonl(CBFS_COMPRESS_NONE)) { + if (src_len > dest_len) + src_len = dest_len; memcpy(dest, src, src_len); } else if (CONFIG_LZMA && seg->compression == htonl(CBFS_COMPRESS_LZMA)) { - int ret = ulzma(dest, src); + int ret = ulzma(dest, dest_len, src, src_len); if (ret < 0) return; src_len = ret; diff --git a/src/optionroms.c b/src/optionroms.c index 32fb44b..ac26286 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -187,10 +187,11 @@ lookup_hardcode(u32 vendev) && ((OPTIONROM_VENDEV_2 >> 16) | ((OPTIONROM_VENDEV_2 & 0xffff)) << 16) == vendev) return copy_rom((struct rom_header *)OPTIONROM_MEM_2); - struct rom_header *rom = cb_find_optionrom(vendev); - if (rom) - return copy_rom(rom); - return NULL; + int ret = cb_copy_optionrom((void*)next_rom, BUILD_BIOS_ADDR - next_rom + , vendev); + if (ret < 0) + return NULL; + return (struct rom_header *)next_rom; } // Map the option rom of a given PCI device. @@ -169,7 +169,7 @@ void smbios_init(void); // coreboot.c const char *cbfs_findNprefix(const char *prefix, int n); -void *cb_find_optionrom(u32 vendev); +int cb_copy_optionrom(void *dst, u32 maxlen, u32 vendev); void cbfs_run_payload(const char *filename); void coreboot_setup(); |