Expand int155f "vgahook" detection.
[seabios.git] / src / coreboot.c
index cdb13ba5da2de2bd5c7e45c03e59f4824bc7ad9b..a7604141e217d6d895a746af1adf936b6e65b732 100644 (file)
@@ -10,6 +10,7 @@
 #include "acpi.h" // struct rsdp_descriptor
 #include "mptable.h" // MPTABLE_SIGNATURE
 #include "biosvar.h" // GET_EBDA
+#include "lzmadecode.h" // LzmaDecode
 
 
 /****************************************************************
@@ -61,8 +62,7 @@ copy_mptable(void *pos)
     memcpy((void*)bios_table_cur_addr, pos, length);
     struct mptable_floating_s *newp = (void*)bios_table_cur_addr;
     newp->physaddr = bios_table_cur_addr + length;
-    newp->checksum = 0;
-    newp->checksum = -checksum(newp, sizeof(*newp));
+    newp->checksum -= checksum(newp, sizeof(*newp));
     memcpy((void*)bios_table_cur_addr + length, (void*)p->physaddr, mpclength);
     bios_table_cur_addr += length + mpclength;
 }
@@ -143,6 +143,16 @@ struct cb_memory {
 #define MEM_RANGE_COUNT(_rec) \
         (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0]))
 
+struct cb_mainboard {
+    u32 tag;
+    u32 size;
+    u8  vendor_idx;
+    u8  part_idx;
+    char  strings[0];
+};
+
+#define CB_TAG_MAINBOARD 0x0003
+
 struct cb_forward {
     u32 tag;
     u32 size;
@@ -260,6 +270,15 @@ coreboot_fill_map()
     // smbios/dmi table is found from coreboot and use that instead.
     smbios_init();
 
+    struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD);
+    if (cbmb) {
+        const char *vendor = &cbmb->strings[cbmb->vendor_idx];
+        const char *part = &cbmb->strings[cbmb->part_idx];
+        dprintf(1, "Found mainboard %s %s\n", vendor, part);
+
+        vgahook_setup(vendor, part);
+    }
+
     return;
 
 fail:
@@ -272,6 +291,44 @@ fail:
 }
 
 
+/****************************************************************
+ * ulzma
+ ****************************************************************/
+
+static int
+ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
+{
+    dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst);
+    CLzmaDecoderState state;
+    int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);
+    if (ret != LZMA_RESULT_OK) {
+        dprintf(1, "LzmaDecodeProperties error - %d\n", ret);
+        return -1;
+    }
+    u8 scratch[15980];
+    int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+    if (need > sizeof(scratch)) {
+        dprintf(1, "LzmaDecode need %d have %d\n", need, sizeof(scratch));
+        return -1;
+    }
+    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, srclen
+                     , &inProcessed, dst, dstlen, &outProcessed);
+    if (ret) {
+        dprintf(1, "LzmaDecode returned %d\n", ret);
+        return -1;
+    }
+    return dstlen;
+}
+
+
 /****************************************************************
  * Coreboot flash format
  ****************************************************************/
@@ -331,8 +388,13 @@ cbfs_search(struct cbfs_file *file)
     for (;;) {
         if (file < (struct cbfs_file *)(0xFFFFFFFF - ntohl(CBHDR->romsize)))
             return NULL;
-        if (file->magic == CBFS_FILE_MAGIC)
+        u64 magic = 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);
     }
 }
@@ -355,19 +417,47 @@ 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)) {
-        dprintf(3, "Found CBFS file %s\n", file->filename);
         if (strcmp(fname, file->filename) == 0)
             return file;
     }
     return NULL;
 }
 
+static int
+data_copy(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
+{
+    dprintf(3, "Copying data %d@%p to %d@%p\n", srclen, src, maxlen, dst);
+    if (srclen > maxlen) {
+        dprintf(1, "File too big to copy\n");
+        return -1;
+    }
+    memcpy(dst, src, srclen);
+    return srclen;
+}
+
+// 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')
+            return data_copy(dst, maxlen, src, size);
+        if (strcmp(&file->filename[fnlen], ".lzma") == 0)
+            return ulzma(dst, maxlen, src, size);
+    }
+    return -1;
+}
+
 const char *
 cbfs_findNprefix(const char *prefix, int n)
 {
@@ -378,7 +468,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;
@@ -405,11 +494,11 @@ hexify4(u16 x)
             | (getHex(x>>12)));
 }
 
-void *
-cb_find_optionrom(u32 vendev)
+int
+cbfs_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"
@@ -420,12 +509,38 @@ cb_find_optionrom(u32 vendev)
     *(u32*)&fname[12] = 0x6d6f722e; // ".rom"
     fname[16] = '\0';
 
-    struct cbfs_file *file = cbfs_findfile(fname);
-    if (!file)
+    return cbfs_copyfile(dst, maxlen, fname);
+}
+
+// Copy the next file with the given prefix - starting at pos 'last'.
+struct cbfs_file *
+cbfs_copyfile_prefix(void *dst, u32 maxlen, const char *prefix
+                     , struct cbfs_file *last)
+{
+    if (! CONFIG_COREBOOT_FLASH)
         return NULL;
-    // Found it.
-    dprintf(3, "Found rom at %p\n", (void*)file + ntohl(file->offset));
-    return (void*)file + ntohl(file->offset);
+    dprintf(3, "Searching CBFS for data file prefix %s\n", prefix);
+    struct cbfs_file *file;
+    if (! last)
+        file = cbfs_getfirst();
+    else
+        file = cbfs_getnext(last);
+    int prefixlen = strlen(prefix);
+    for (; file; file = cbfs_getnext(file)) {
+        if (memcmp(prefix, file->filename, prefixlen) != 0)
+            continue;
+        u32 size = ntohl(file->len);
+        void *src = (void*)file + ntohl(file->offset);
+        int fnamelen = strlen(file->filename);
+        int rv;
+        if (fnamelen > 5 && strcmp(&file->filename[fnamelen-5], ".lzma") == 0)
+            rv = ulzma(dst, maxlen, src, size);
+        else
+            rv = data_copy(dst, maxlen, src, size);
+        if (rv >= 0)
+            return file;
+    }
+    return NULL;
 }
 
 struct cbfs_payload_segment {
@@ -441,6 +556,7 @@ struct cbfs_payload_segment {
 #define PAYLOAD_SEGMENT_ENTRY  0x52544E45
 
 #define CBFS_COMPRESS_NONE  0
+#define CBFS_COMPRESS_LZMA  1
 
 struct cbfs_payload {
     struct cbfs_payload_segment segments[1];
@@ -449,6 +565,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)
@@ -456,11 +574,6 @@ cbfs_run_payload(const char *filename)
     struct cbfs_payload *pay = (void*)file + ntohl(file->offset);
     struct cbfs_payload_segment *seg = pay->segments;
     for (;;) {
-        if (seg->compression != htonl(CBFS_COMPRESS_NONE)) {
-            dprintf(1, "No support for compressed payloads (%x)\n"
-                    , seg->compression);
-            return;
-        }
         void *src = (void*)pay + ntohl(seg->offset);
         void *dest = (void*)ntohl((u32)seg->load_addr);
         u32 src_len = ntohl(seg->len);
@@ -479,9 +592,21 @@ 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;
-            memcpy(dest, src, src_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, dest_len, src, src_len);
+                if (ret < 0)
+                    return;
+                src_len = ret;
+            } else {
+                dprintf(1, "No support for compression type %x\n"
+                        , seg->compression);
+                return;
+            }
             if (dest_len > src_len)
                 memset(dest + src_len, 0, dest_len - src_len);
             break;