Added fields that allows a machine model to specify where the initrd and dtb are loaded. Leaving the fields 0 will use to old default values (previously hardcoded in arm_boot.c)
Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwa...@petalogix.com> --- hw/arm-misc.h | 8 ++++++++ hw/arm_boot.c | 34 ++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/hw/arm-misc.h b/hw/arm-misc.h index 2f46e21..25f3da8 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -31,6 +31,14 @@ struct arm_boot_info { const char *initrd_filename; const char *dtb_filename; target_phys_addr_t loader_start; + /* where to place the initrd relative to loader start. A value of 0 + * will select the default value of loader_start + 0xd00000. + */ + target_phys_addr_t initrd_offset; + /* where to place the dtb relative to loader start. A value of 0 will + * place it immediately after the initrd (page aligned). + */ + target_phys_addr_t dtb_offset; /* multicore boards that use the default secondary core boot functions * need to put the address of the secondary boot code, the boot reg, * and the GIC address in the next 3 values, respectively. boards that diff --git a/hw/arm_boot.c b/hw/arm_boot.c index 7447f5c..302bd17 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -18,7 +18,8 @@ #define KERNEL_ARGS_ADDR 0x100 #define KERNEL_LOAD_ADDR 0x00010000 -#define INITRD_LOAD_ADDR 0x00d00000 + +#define DEFAULT_INITRD_OFFSET 0x00d00000 /* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ static uint32_t bootloader[] = { @@ -107,7 +108,7 @@ static void set_kernel_args(const struct arm_boot_info *info) /* ATAG_INITRD2 */ WRITE_WORD(p, 4); WRITE_WORD(p, 0x54420005); - WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR); + WRITE_WORD(p, info->loader_start + info->initrd_offset); WRITE_WORD(p, initrd_size); } if (info->kernel_cmdline && *info->kernel_cmdline) { @@ -184,7 +185,7 @@ static void set_kernel_args_old(const struct arm_boot_info *info) WRITE_WORD(p, 0); /* initrd_start */ if (initrd_size) - WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR); + WRITE_WORD(p, info->loader_start + info->initrd_offset); else WRITE_WORD(p, 0); /* initrd_size */ @@ -211,7 +212,7 @@ static void set_kernel_args_old(const struct arm_boot_info *info) } } -static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo) +static int load_dtb(const struct arm_boot_info *binfo) { #ifdef CONFIG_FDT uint32_t mem_reg_property[] = { cpu_to_be32(binfo->loader_start), @@ -248,20 +249,21 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo) if (binfo->initrd_size) { rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", - binfo->loader_start + INITRD_LOAD_ADDR); + binfo->loader_start + binfo->initrd_offset); if (rc < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); } rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", - binfo->loader_start + INITRD_LOAD_ADDR + + binfo->loader_start + binfo->initrd_offset + binfo->initrd_size); if (rc < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); } } - cpu_physical_memory_write(addr, fdt, size); + cpu_physical_memory_write(binfo->loader_start + binfo->dtb_offset, + fdt, size); return 0; @@ -362,10 +364,13 @@ void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info) info->entry = entry; if (is_linux) { if (info->initrd_filename) { + if (!info->initrd_offset) { + info->initrd_offset = DEFAULT_INITRD_OFFSET; + } initrd_size = load_image_targphys(info->initrd_filename, info->loader_start - + INITRD_LOAD_ADDR, - ram_size - INITRD_LOAD_ADDR); + + info->initrd_offset, + ram_size - info->initrd_offset); if (initrd_size < 0) { fprintf(stderr, "qemu: could not load initrd '%s'\n", info->initrd_filename); @@ -382,14 +387,15 @@ void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info) * we point to the kernel args. */ if (info->dtb_filename) { - /* Place the DTB after the initrd in memory */ - target_phys_addr_t dtb_start = TARGET_PAGE_ALIGN(info->loader_start - + INITRD_LOAD_ADDR + if (!info->dtb_offset) { + /* Place the DTB after the initrd in memory */ + info->dtb_offset = TARGET_PAGE_ALIGN(info->initrd_offset + initrd_size); - if (load_dtb(dtb_start, info)) { + } + if (load_dtb(info)) { exit(1); } - bootloader[5] = dtb_start; + bootloader[5] = info->loader_start + info->dtb_offset; } else { bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR; } -- 1.7.3.2