These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / seabios / src / fw / multiboot.c
diff --git a/qemu/roms/seabios/src/fw/multiboot.c b/qemu/roms/seabios/src/fw/multiboot.c
new file mode 100644 (file)
index 0000000..d9df067
--- /dev/null
@@ -0,0 +1,111 @@
+// Multiboot interface support.
+//
+// Copyright (C) 2015  Vladimir Serbinenko <phcoder@gmail.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h" // CONFIG_*
+#include "malloc.h" // free
+#include "output.h" // dprintf
+#include "romfile.h" // romfile_add
+#include "std/multiboot.h" // MULTIBOOT_*
+#include "string.h" // memset
+#include "util.h" // multiboot_init
+
+struct mbfs_romfile_s {
+    struct romfile_s file;
+    void *data;
+};
+
+static int
+extract_filename(char *dest, char *src, size_t lim)
+{
+    char *ptr;
+    for (ptr = src; *ptr; ptr++) {
+        if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t'))
+            continue;
+        /* memcmp stops early if it encounters \0 as it doesn't match name=.  */
+        if (memcmp(ptr, "name=", 5) == 0) {
+            int i;
+            char *optr = dest;
+            for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) {
+                *optr++ = *ptr++;
+            }
+            *optr++ = '\0';
+            return 1;
+        }
+    }
+    return 0;
+}
+
+// Copy a file to memory
+static int
+mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen)
+{
+    struct mbfs_romfile_s *cfile;
+    cfile = container_of(file, struct mbfs_romfile_s, file);
+    u32 size = cfile->file.size;
+    void *src = cfile->data;
+
+    // Not compressed.
+    dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
+    if (size > maxlen) {
+        warn_noalloc();
+        return -1;
+    }
+    iomemcpy(dst, src, size);
+    return size;
+}
+
+u32 __VISIBLE entry_elf_eax, entry_elf_ebx;
+
+void
+multiboot_init(void)
+{
+    struct multiboot_info *mbi;
+    if (!CONFIG_MULTIBOOT)
+        return;
+    dprintf(1, "multiboot: eax=%x, ebx=%x\n", entry_elf_eax, entry_elf_ebx);
+    if (entry_elf_eax != MULTIBOOT_BOOTLOADER_MAGIC)
+        return;
+    mbi = (void *)entry_elf_ebx;
+    dprintf(1, "mbptr=%p\n", mbi);
+    dprintf(1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr,
+            mbi->mods_count);
+    if (!(mbi->flags & MULTIBOOT_INFO_MODS))
+        return;
+    int i;
+    struct multiboot_mod_list *mod = (void *)mbi->mods_addr;
+    for (i = 0; i < mbi->mods_count; i++) {
+        struct mbfs_romfile_s *cfile;
+        u8 *copy;
+        u32 len;
+        if (!mod[i].cmdline)
+            continue;
+        len = mod[i].mod_end - mod[i].mod_start;
+        cfile = malloc_tmp(sizeof(*cfile));
+        if (!cfile) {
+            warn_noalloc();
+            return;
+        }
+        memset(cfile, 0, sizeof(*cfile));
+        dprintf(1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len);
+        if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline,
+                              sizeof(cfile->file.name))) {
+            free(cfile);
+            continue;
+        }
+        dprintf(1, "assigned file name <%s>\n", cfile->file.name);
+        cfile->file.size = len;
+        copy = malloc_tmp(len);
+        if (!copy) {
+            warn_noalloc();
+            free(cfile);
+            return;
+        }
+        memcpy(copy, (void *)mod[i].mod_start, len);
+        cfile->file.copy = mbfs_copyfile;
+        cfile->data = copy;
+        romfile_add(&cfile->file);
+    }
+}