Introduce optimized iomemcpy function for copying from io memory.
[seabios.git] / src / coreboot.c
index 4596ffdd2b79cbcd0f432ab19ef1dd881d4cb1e4..7fa18e4da0698b6806a11997e970de5efc50522e 100644 (file)
@@ -11,6 +11,7 @@
 #include "mptable.h" // MPTABLE_SIGNATURE
 #include "biosvar.h" // GET_EBDA
 #include "lzmadecode.h" // LzmaDecode
+#include "smbios.h" // smbios_init
 
 
 /****************************************************************
@@ -442,6 +443,7 @@ cbfs_findfile(const char *fname)
     return NULL;
 }
 
+// Find next file with the given filename prefix.
 struct cbfs_file *
 cbfs_findprefix(const char *prefix, struct cbfs_file *last)
 {
@@ -463,7 +465,7 @@ cbfs_findprefix(const char *prefix, struct cbfs_file *last)
 
 // Find a file with the given filename (possibly with ".lzma" extension).
 static struct cbfs_file *
-cbfs_finddatafile(const char *fname, int *iscomp)
+cbfs_finddatafile(const char *fname)
 {
     int fnlen = strlen(fname);
     struct cbfs_file *file = NULL;
@@ -471,28 +473,18 @@ cbfs_finddatafile(const char *fname, int *iscomp)
         file = cbfs_findprefix(fname, file);
         if (!file)
             return NULL;
-        if (file->filename[fnlen] == '\0') {
-            *iscomp = 0;
+        if (file->filename[fnlen] == '\0'
+            || strcmp(&file->filename[fnlen], ".lzma") == 0)
             return file;
-        }
-        if (strcmp(&file->filename[fnlen], ".lzma") == 0) {
-            *iscomp = 1;
-            return file;
-        }
     }
 }
 
-// Locate a datafile with the given prefix.
-struct cbfs_file *
-cbfs_finddataprefix(const char *prefix, struct cbfs_file *last, int *iscomp)
+// Determine whether the file has a ".lzma" extension.
+static int
+cbfs_iscomp(struct cbfs_file *file)
 {
-    struct cbfs_file *file = cbfs_findprefix(prefix, last);
-    if (!file)
-        return NULL;
     int fnamelen = strlen(file->filename);
-    *iscomp = (fnamelen > 5
-               && strcmp(&file->filename[fnamelen-5], ".lzma") == 0);
-    return file;
+    return fnamelen > 5 && strcmp(&file->filename[fnamelen-5], ".lzma") == 0;
 }
 
 // Return the filename of a given file.
@@ -504,26 +496,35 @@ cbfs_filename(struct cbfs_file *file)
 
 // Determine the uncompressed size of a datafile.
 u32
-cbfs_datasize(struct cbfs_file *file, int iscomp)
+cbfs_datasize(struct cbfs_file *file)
 {
     void *src = (void*)file + ntohl(file->offset);
-    if (iscomp)
+    if (cbfs_iscomp(file))
         return *(u32*)(src + LZMA_PROPERTIES_SIZE);
     return ntohl(file->len);
 }
 
 // Copy a file to memory (uncompressing if necessary)
 int
-cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen, int iscomp)
+cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen)
 {
     if (! CONFIG_COREBOOT_FLASH || !file)
         return -1;
 
     u32 size = ntohl(file->len);
     void *src = (void*)file + ntohl(file->offset);
-    if (iscomp)
-        // Compressed.
-        return ulzma(dst, maxlen, src, size);
+    if (cbfs_iscomp(file)) {
+        // Compressed - copy to temp ram and uncompress it.
+        u32 asize = ALIGN(size, 4);
+        void *temp = malloc_tmphigh(asize);
+        if (!temp)
+            return -1;
+        iomemcpy(temp, src, asize);
+        int ret = ulzma(dst, maxlen, temp, size);
+        yield();
+        free(temp);
+        return ret;
+    }
 
     // Not compressed.
     dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
@@ -531,27 +532,10 @@ cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen, int iscomp)
         dprintf(1, "File too big to copy\n");
         return -1;
     }
-    memcpy(dst, src, size);
+    iomemcpy(dst, src, size);
     return size;
 }
 
-static char
-getHex(u8 x)
-{
-    if (x <= 9)
-        return '0' + x;
-    return 'a' + x - 10;
-}
-
-static u32
-hexify4(u16 x)
-{
-    return ((getHex(x&0xf) << 24)
-            | (getHex((x>>4)&0xf) << 16)
-            | (getHex((x>>8)&0xf) << 8)
-            | (getHex(x>>12)));
-}
-
 // Find and copy the optionrom for the given vendor/device id.
 int
 cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev)
@@ -560,17 +544,9 @@ cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev)
         return -1;
 
     char fname[17];
-    // Ughh - poor man's sprintf of "pci%04x,%04x.rom"
-    *(u32*)fname = 0x20696370; // "pci "
-    *(u32*)&fname[3] = hexify4(vendev);
-    fname[7] = ',';
-    *(u32*)&fname[8] = hexify4(vendev >> 16);
-    *(u32*)&fname[12] = 0x6d6f722e; // ".rom"
-    fname[16] = '\0';
-
-    int iscomp;
-    struct cbfs_file *file = cbfs_finddatafile(fname, &iscomp);
-    return cbfs_copyfile(file, dst, maxlen, iscomp);
+    snprintf(fname, sizeof(fname), "pci%04x,%04x.rom"
+             , (u16)vendev, vendev >> 16);
+    return cbfs_copyfile(cbfs_finddatafile(fname), dst, maxlen);
 }
 
 struct cbfs_payload_segment {