]> Git Repo - qemu.git/blobdiff - hw/microblaze/boot.c
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[qemu.git] / hw / microblaze / boot.c
index 23cb11d70e69c5a8000997aac7824a1b1c080c42..6bf36d046fdc313d92ac936766adec2d7048fcbc 100644 (file)
 
 #include "qemu/option.h"
 #include "qemu/config-file.h"
+#include "qemu/error-report.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
 #include "hw/loader.h"
 #include "elf.h"
 
@@ -38,6 +40,8 @@ static struct
     void (*machine_cpu_reset)(MicroBlazeCPU *);
     uint32_t bootstrap_pc;
     uint32_t cmdline;
+    uint32_t initrd_start;
+    uint32_t initrd_end;
     uint32_t fdt;
 } boot_info;
 
@@ -48,6 +52,7 @@ static void main_cpu_reset(void *opaque)
 
     cpu_reset(CPU(cpu));
     env->regs[5] = boot_info.cmdline;
+    env->regs[6] = boot_info.initrd_start;
     env->regs[7] = boot_info.fdt;
     env->sregs[SR_PC] = boot_info.bootstrap_pc;
     if (boot_info.machine_cpu_reset) {
@@ -56,12 +61,13 @@ static void main_cpu_reset(void *opaque)
 }
 
 static int microblaze_load_dtb(hwaddr addr,
-                                      uint32_t ramsize,
-                                      const char *kernel_cmdline,
-                                      const char *dtb_filename)
+                               uint32_t ramsize,
+                               uint32_t initrd_start,
+                               uint32_t initrd_end,
+                               const char *kernel_cmdline,
+                               const char *dtb_filename)
 {
     int fdt_size;
-#ifdef CONFIG_FDT
     void *fdt = NULL;
     int r;
 
@@ -73,25 +79,22 @@ static int microblaze_load_dtb(hwaddr addr,
     }
 
     if (kernel_cmdline) {
-        r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
-                                                        kernel_cmdline);
+        r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
+                                    kernel_cmdline);
         if (r < 0) {
             fprintf(stderr, "couldn't set /chosen/bootargs\n");
         }
     }
 
-    cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
-#else
-    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
-       to the kernel.  */
-    if (dtb_filename) {
-        fdt_size = load_image_targphys(dtb_filename, addr, 0x10000);
-    }
-    if (kernel_cmdline) {
-        fprintf(stderr,
-                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+    if (initrd_start) {
+        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                              initrd_start);
+
+        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                              initrd_end);
     }
-#endif
+
+    cpu_physical_memory_write(addr, fdt, fdt_size);
     return fdt_size;
 }
 
@@ -101,24 +104,24 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
 }
 
 void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize, const char *dtb_filename,
+                            uint32_t ramsize,
+                            const char *initrd_filename,
+                            const char *dtb_filename,
                             void (*machine_cpu_reset)(MicroBlazeCPU *))
 {
     QemuOpts *machine_opts;
-    const char *kernel_filename = NULL;
-    const char *kernel_cmdline = NULL;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dtb_arg;
-        kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        kernel_cmdline = qemu_opt_get(machine_opts, "append");
-        dtb_arg = qemu_opt_get(machine_opts, "dtb");
-        if (dtb_arg) { /* Preference a -dtb argument */
-            dtb_filename = dtb_arg;
-        } else { /* default to pcbios dtb as passed by machine_init */
-            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
-        }
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *dtb_arg;
+
+    machine_opts = qemu_get_machine_opts();
+    kernel_filename = qemu_opt_get(machine_opts, "kernel");
+    kernel_cmdline = qemu_opt_get(machine_opts, "append");
+    dtb_arg = qemu_opt_get(machine_opts, "dtb");
+    if (dtb_arg) { /* Preference a -dtb argument */
+        dtb_filename = dtb_arg;
+    } else { /* default to pcbios dtb as passed by machine_init */
+        dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
     }
 
     boot_info.machine_cpu_reset = machine_cpu_reset;
@@ -145,7 +148,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
                                    big_endian, ELF_MACHINE, 0);
         }
         /* Always boot into physical ram.  */
-        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
+        boot_info.bootstrap_pc = (uint32_t)entry;
 
         /* If it wasn't an ELF image, try an u-boot image.  */
         if (kernel_size < 0) {
@@ -164,14 +167,42 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
             high = (ddr_base + kernel_size + 3) & ~3;
         }
 
+        if (initrd_filename) {
+            int initrd_size;
+            uint32_t initrd_offset;
+
+            high = ROUND_UP(high + kernel_size, 4);
+            boot_info.initrd_start = high;
+            initrd_offset = boot_info.initrd_start - ddr_base;
+
+            initrd_size = load_ramdisk(initrd_filename,
+                                       boot_info.initrd_start,
+                                       ram_size - initrd_offset);
+            if (initrd_size < 0) {
+                initrd_size = load_image_targphys(initrd_filename,
+                                                  boot_info.initrd_start,
+                                                  ram_size - initrd_offset);
+            }
+            if (initrd_size < 0) {
+                error_report("qemu: could not load initrd '%s'\n",
+                             initrd_filename);
+                exit(EXIT_FAILURE);
+            }
+            boot_info.initrd_end = boot_info.initrd_start + initrd_size;
+            high = ROUND_UP(high + initrd_size, 4);
+        }
+
         boot_info.cmdline = high + 4096;
         if (kernel_cmdline && strlen(kernel_cmdline)) {
             pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
         }
         /* Provide a device-tree.  */
         boot_info.fdt = boot_info.cmdline + 4096;
-        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
-                                                     dtb_filename);
+        microblaze_load_dtb(boot_info.fdt, ram_size,
+                            boot_info.initrd_start,
+                            boot_info.initrd_end,
+                            kernel_cmdline,
+                            dtb_filename);
     }
 
 }
This page took 0.029154 seconds and 4 git commands to generate.