// This file may be distributed under the terms of the GNU LGPLv3 license.
#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
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 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;
}
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 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;
+}