hw/microblaze: Add support for loading initrd images

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2013-05-05 11:06:37 +02:00
parent d0b022a0e9
commit ec426ff808
4 changed files with 45 additions and 3 deletions

View File

@ -26,6 +26,7 @@
#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"
@ -39,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;
@ -49,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) {
@ -58,6 +62,8 @@ static void main_cpu_reset(void *opaque)
static int microblaze_load_dtb(hwaddr addr,
uint32_t ramsize,
uint32_t initrd_start,
uint32_t initrd_end,
const char *kernel_cmdline,
const char *dtb_filename)
{
@ -80,6 +86,14 @@ static int microblaze_load_dtb(hwaddr addr,
}
}
if (initrd_start) {
qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_start);
qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
initrd_end);
}
cpu_physical_memory_write(addr, fdt, fdt_size);
return fdt_size;
}
@ -90,7 +104,9 @@ 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;
@ -151,6 +167,25 @@ 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_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);
@ -158,6 +193,8 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
/* Provide a device-tree. */
boot_info.fdt = boot_info.cmdline + 4096;
microblaze_load_dtb(boot_info.fdt, ram_size,
boot_info.initrd_start,
boot_info.initrd_end,
kernel_cmdline,
dtb_filename);
}

View File

@ -4,7 +4,9 @@
#include "hw/hw.h"
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 *));
#endif /* __MICROBLAZE_BOOT __ */

View File

@ -177,6 +177,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
}
microblaze_load_kernel(cpu, ddr_base, ram_size,
args->initrd_filename,
BINARY_DEVICE_TREE_FILE,
machine_cpu_reset);

View File

@ -108,7 +108,9 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
microblaze_load_kernel(cpu, ddr_base, ram_size,
BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
args->initrd_filename,
BINARY_DEVICE_TREE_FILE,
machine_cpu_reset);
}
static QEMUMachine petalogix_s3adsp1800_machine = {