Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / bootcode_load.c
diff --git a/qemu/roms/openbios/libopenbios/bootcode_load.c b/qemu/roms/openbios/libopenbios/bootcode_load.c
new file mode 100644 (file)
index 0000000..0fabf55
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+ * Raw bootcode loader (CHRP/Apple %BOOT)
+ * Written by Mark Cave-Ayland 2013
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/bootcode_load.h"
+#include "libc/diskio.h"
+#include "drivers/drivers.h"
+#define printf printk
+#define debug printk
+
+
+int 
+bootcode_load(ihandle_t dev)
+{
+    int retval = -1, count = 0, fd;
+    unsigned long bootcode, loadbase, entry, size, offset;
+    ihandle_t bootcode_info;
+
+    /* Mark the saved-program-state as invalid */
+    feval("0 state-valid !");
+
+    fd = open_ih(dev);
+    if (fd == -1) {
+        goto out;
+    }
+
+    /* If we don't have the get-bootcode-info word then we don't support
+       loading bootcode via %BOOT */
+    bootcode_info = find_ih_method("get-bootcode-info", dev);
+    if (!bootcode_info) {
+        goto out;
+    }
+    
+    /* Default to loading at load-base */
+    fword("load-base");
+    loadbase = POP();
+    entry = loadbase;
+    size = 0;
+    
+#ifdef CONFIG_PPC
+    /*
+     * Apple OF does not honor load-base and instead uses pmBootLoad
+     * value from the boot partition descriptor.
+     *
+     * Tested with:
+     *   a debian image with QUIK installed
+     *   a debian image with iQUIK installed (https://github.com/andreiw/quik)
+     *   an IQUIK boot floppy
+     *   a NetBSD boot floppy (boots stage 2)
+     */
+    if (is_apple()) {
+        PUSH(bootcode_info);
+        fword("execute");
+
+        loadbase = POP();
+        entry = POP();
+        size = POP();
+    }
+#endif
+    
+    bootcode = loadbase;
+    offset = 0;
+    
+    while(1) {
+        if (seek_io(fd, offset) == -1)
+            break;
+        count = read_io(fd, (void *)bootcode, 512);
+        offset += count;
+        bootcode += count;
+    }
+
+    /* If we didn't read anything then exit */
+    if (!count) {
+        goto out;
+    }
+
+    /* Use proper file size if we got it from bootcode info */
+    if (size == 0) {
+        size = offset;
+    }
+    
+    /* Initialise saved-program-state */
+    PUSH(entry);
+    feval("saved-program-state >sps.entry !");
+    PUSH(size);
+    feval("saved-program-state >sps.file-size !");
+    feval("bootcode saved-program-state >sps.file-type !");
+
+    feval("-1 state-valid !");
+
+out:
+    close_io(fd);
+    return retval;
+}
+