vgabios: Unify code to generate the vbe mode list.
[seabios.git] / src / paravirt.c
index da5923bd6486330f4c8257bcc88695bf23a3dc80..9cf77def2892eb51ade6e445a7edb1706603631e 100644 (file)
@@ -7,9 +7,11 @@
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
-#include "config.h"
-#include "ioport.h"
-#include "paravirt.h"
+#include "config.h" // CONFIG_COREBOOT
+#include "util.h" // ntoh[ls]
+#include "ioport.h" // outw
+#include "paravirt.h" // qemu_cfg_port_probe
+#include "smbios.h" // struct smbios_structure_header
 
 int qemu_cfg_present;
 
@@ -22,8 +24,7 @@ qemu_cfg_select(u16 f)
 static void
 qemu_cfg_read(u8 *buf, int len)
 {
-    while (len--)
-        *(buf++) = inb(PORT_QEMU_CFG_DATA);
+    insb(PORT_QEMU_CFG_DATA, buf, len);
 }
 
 static void
@@ -130,6 +131,23 @@ u16 qemu_cfg_smbios_entries(void)
     return cnt;
 }
 
+u32 qemu_cfg_e820_entries(void)
+{
+    u32 cnt;
+
+    if (!qemu_cfg_present)
+        return 0;
+
+    qemu_cfg_read_entry(&cnt, QEMU_CFG_E820_TABLE, sizeof(cnt));
+    return cnt;
+}
+
+void* qemu_cfg_e820_load_next(void *addr)
+{
+    qemu_cfg_read(addr, sizeof(struct e820_reservation));
+    return addr;
+}
+
 struct smbios_header {
     u16 length;
     u8 type;
@@ -180,13 +198,6 @@ size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr)
     return 0;
 }
 
-/* This goes at the beginning of every SMBIOS structure. */
-struct smbios_structure_header {
-       u8 type;
-       u8 length;
-       u16 handle;
-} PACKED;
-
 int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
                                   unsigned *max_struct_size, char *end)
 {
@@ -216,7 +227,7 @@ int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
         }
 
         if (end - *p < sizeof(struct smbios_structure_header)) {
-            dprintf(1, "No more memory for additional smbios tables\n");
+            warn_noalloc();
             break;
         }
 
@@ -238,7 +249,7 @@ int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
 
         /* Read the rest and terminate the entry */
         if (end - *p < table.header.length) {
-            dprintf(1, "No memory for smbios table %d\n", header->type);
+            warn_noalloc();
             *p -= sizeof(struct smbios_structure_header);
             continue;
         }
@@ -293,3 +304,127 @@ u16 qemu_cfg_get_max_cpus(void)
 
     return cnt;
 }
+
+static QemuCfgFile LastFile;
+
+static u32
+__cfg_next_prefix_file(const char *prefix, int prefixlen, u32 prevselect)
+{
+    if (!qemu_cfg_present)
+        return 0;
+
+    u32 count;
+    qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
+    count = ntohl(count);
+    u32 e;
+    for (e = 0; e < count; e++) {
+        qemu_cfg_read((void*)&LastFile, sizeof(LastFile));
+        u32 select = ntohs(LastFile.select);
+        if (select <= prevselect)
+            continue;
+        if (memcmp(prefix, LastFile.name, prefixlen) == 0)
+            return select;
+    }
+    return 0;
+}
+
+u32 qemu_cfg_next_prefix_file(const char *prefix, u32 prevselect)
+{
+    return __cfg_next_prefix_file(prefix, strlen(prefix), prevselect);
+}
+
+u32 qemu_cfg_find_file(const char *name)
+{
+    return __cfg_next_prefix_file(name, strlen(name) + 1, 0);
+}
+
+static int
+__qemu_cfg_set_file(u32 select)
+{
+    if (!qemu_cfg_present || !select)
+        return -1;
+    if (select == ntohs(LastFile.select))
+        return 0;
+
+    u32 count;
+    qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
+    count = ntohl(count);
+    u32 e;
+    for (e = 0; e < count; e++) {
+        qemu_cfg_read((void*)&LastFile, sizeof(LastFile));
+        if (select == ntohs(LastFile.select))
+            return 0;
+    }
+    return -1;
+}
+
+int qemu_cfg_size_file(u32 select)
+{
+    if (__qemu_cfg_set_file(select))
+        return -1;
+    return ntohl(LastFile.size);
+}
+
+const char* qemu_cfg_name_file(u32 select)
+{
+    if (__qemu_cfg_set_file(select))
+        return NULL;
+    return LastFile.name;
+}
+
+int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen)
+{
+    if (__qemu_cfg_set_file(select))
+        return -1;
+    int len = qemu_cfg_size_file(select);
+    if (len < 0 || len > maxlen)
+        return -1;
+    qemu_cfg_read_entry(dst, select, len);
+    return len;
+}
+
+// Helper function to find, malloc_tmphigh, and copy a romfile.  This
+// function adds a trailing zero to the malloc'd copy.
+void *
+romfile_loadfile(const char *name, int *psize)
+{
+    u32 file = romfile_find(name);
+    if (!file)
+        return NULL;
+
+    int filesize = romfile_size(file);
+    if (!filesize)
+        return NULL;
+
+    char *data = malloc_tmphigh(filesize+1);
+    if (!data) {
+        warn_noalloc();
+        return NULL;
+    }
+
+    dprintf(5, "Copying romfile '%s' (len %d)\n", name, filesize);
+    romfile_copy(file, data, filesize);
+    if (psize)
+        *psize = filesize;
+    data[filesize] = '\0';
+    return data;
+}
+
+// Attempt to load an integer from the given file - return 'defval'
+// if unsuccesful.
+u64
+romfile_loadint(const char *name, u64 defval)
+{
+    u32 file = romfile_find(name);
+    if (!file)
+        return defval;
+
+    int filesize = romfile_size(file);
+    if (!filesize || filesize > sizeof(u64) || (filesize & (filesize-1)))
+        // Doesn't look like a valid integer.
+        return defval;
+
+    u64 val = 0;
+    romfile_copy(file, &val, sizeof(val));
+    return val;
+}