//
// 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;
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
return v;
}
+int qemu_cfg_irq0_override(void)
+{
+ u8 v;
+
+ if (!qemu_cfg_present)
+ return 0;
+
+ qemu_cfg_read_entry(&v, QEMU_CFG_IRQ0_OVERRIDE, sizeof(v));
+
+ return v;
+}
+
u16 qemu_cfg_acpi_additional_tables(void)
{
u16 cnt;
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;
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)
{
}
if (end - *p < sizeof(struct smbios_structure_header)) {
- dprintf(1, "No more memory for additional smbios tables\n");
+ warn_noalloc();
break;
}
/* 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;
}
return 0;
}
+int qemu_cfg_get_numa_nodes(void)
+{
+ u64 cnt;
+
+ qemu_cfg_read_entry(&cnt, QEMU_CFG_NUMA, sizeof(cnt));
+
+ return (int)cnt;
+}
+
+void qemu_cfg_get_numa_data(u64 *data, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ qemu_cfg_read((u8*)(data + i), sizeof(u64));
+}
+
+u16 qemu_cfg_get_max_cpus(void)
+{
+ u16 cnt;
+
+ if (!qemu_cfg_present)
+ return 0;
+
+ qemu_cfg_read_entry(&cnt, QEMU_CFG_MAX_CPUS, sizeof(cnt));
+
+ 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;
+}