#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"
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;
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) {
}
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;
}
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;
}
}
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;
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) {
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);
}
}