aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2009-04-27 21:51:13 -0400
committerKevin O'Connor <kevin@koconnor.net>2009-04-27 21:51:13 -0400
commitcbd6ca05d9c5797f9cfc816342181fb91b600099 (patch)
tree79775948807839a4d141b13f7cfa28de099e8ecc /src
parent592323fdb2de5ff4b546d24109070c7614c7ad2b (diff)
downloadseabios-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.c69
-rw-r--r--src/optionroms.c9
-rw-r--r--src/util.h2
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.
diff --git a/src/util.h b/src/util.h
index bb1a445..0223f7f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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();