From 37ed7c4b24f265c2a8c7248666544c9755514ec2 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 20 Jun 2014 18:02:10 +0400 Subject: [PATCH 01/10] hw/xtensa/xtfpga: fix FLASH mapping to boot region for KC705 On KC705 bootloader area is located at FLASH offset 0x06000000, not 0 as on older xtfpga boards. Cc: qemu-stable@nongnu.org Signed-off-by: Max Filippov --- hw/xtensa/xtensa_lx60.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c index 507dd88452..183527f6a7 100644 --- a/hw/xtensa/xtensa_lx60.c +++ b/hw/xtensa/xtensa_lx60.c @@ -42,6 +42,7 @@ typedef struct LxBoardDesc { hwaddr flash_base; size_t flash_size; + size_t flash_boot_base; size_t flash_sector_size; size_t sram_size; } LxBoardDesc; @@ -266,9 +267,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); memory_region_init_alias(flash_io, NULL, "lx60.flash", - flash_mr, 0, - board->flash_size < 0x02000000 ? - board->flash_size : 0x02000000); + flash_mr, board->flash_boot_base, + board->flash_size - board->flash_boot_base < 0x02000000 ? + board->flash_size - board->flash_boot_base : 0x02000000); memory_region_add_subregion(system_memory, 0xfe000000, flash_io); } @@ -313,6 +314,7 @@ static void xtensa_kc705_init(MachineState *machine) static const LxBoardDesc kc705_board = { .flash_base = 0xf0000000, .flash_size = 0x08000000, + .flash_boot_base = 0x06000000, .flash_sector_size = 0x20000, .sram_size = 0x2000000, }; From b707ab757e66e05a8447b4efe15733b10659a3dd Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 10:39:58 +0400 Subject: [PATCH 02/10] hw/xtensa: remove extraneous xtensa_ prefix from file names While at it rename lx60 (named after the first board of the family) to more generic xtfpga (the family name). Signed-off-by: Max Filippov --- hw/xtensa/Makefile.objs | 4 ++-- hw/xtensa/{xtensa_bootparam.h => bootparam.h} | 0 hw/xtensa/{xtensa_sim.c => sim.c} | 0 hw/xtensa/{xtensa_lx60.c => xtfpga.c} | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename hw/xtensa/{xtensa_bootparam.h => bootparam.h} (100%) rename hw/xtensa/{xtensa_sim.c => sim.c} (100%) rename hw/xtensa/{xtensa_lx60.c => xtfpga.c} (99%) diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs index 6ead7820c4..cb77dc3793 100644 --- a/hw/xtensa/Makefile.objs +++ b/hw/xtensa/Makefile.objs @@ -1,3 +1,3 @@ obj-y += pic_cpu.o -obj-y += xtensa_sim.o -obj-y += xtensa_lx60.o +obj-y += sim.o +obj-y += xtfpga.o diff --git a/hw/xtensa/xtensa_bootparam.h b/hw/xtensa/bootparam.h similarity index 100% rename from hw/xtensa/xtensa_bootparam.h rename to hw/xtensa/bootparam.h diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/sim.c similarity index 100% rename from hw/xtensa/xtensa_sim.c rename to hw/xtensa/sim.c diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtfpga.c similarity index 99% rename from hw/xtensa/xtensa_lx60.c rename to hw/xtensa/xtfpga.c index 183527f6a7..0b8a2eda06 100644 --- a/hw/xtensa/xtensa_lx60.c +++ b/hw/xtensa/xtfpga.c @@ -37,7 +37,7 @@ #include "hw/block/flash.h" #include "sysemu/blockdev.h" #include "sysemu/char.h" -#include "xtensa_bootparam.h" +#include "bootparam.h" typedef struct LxBoardDesc { hwaddr flash_base; From 8488ab021ba40383f4ab3a595f006fe920737397 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 16:14:56 +0400 Subject: [PATCH 03/10] hw/xtensa: replace fprintfs with error_report Signed-off-by: Max Filippov --- hw/xtensa/sim.c | 6 ++++-- hw/xtensa/xtfpga.c | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index 89da43c160..9642bf54c7 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -31,6 +31,7 @@ #include "elf.h" #include "exec/memory.h" #include "exec/address-spaces.h" +#include "qemu/error-report.h" static uint64_t translate_phys_addr(void *opaque, uint64_t addr) { @@ -63,8 +64,9 @@ static void xtensa_sim_init(MachineState *machine) for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); + error_report("unable to find CPU definition '%s'\n", + cpu_model); + exit(EXIT_FAILURE); } env = &cpu->env; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 0b8a2eda06..75bc479e36 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -37,6 +37,7 @@ #include "hw/block/flash.h" #include "sysemu/blockdev.h" #include "sysemu/char.h" +#include "qemu/error-report.h" #include "bootparam.h" typedef struct LxBoardDesc { @@ -185,8 +186,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); + error_report("unable to find CPU definition '%s'\n", + cpu_model); + exit(EXIT_FAILURE); } env = &cpu->env; @@ -227,8 +229,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) board->flash_size / board->flash_sector_size, 4, 0x0000, 0x0000, 0x0000, 0x0000, be); if (flash == NULL) { - fprintf(stderr, "Unable to mount pflash\n"); - exit(1); + error_report("unable to mount pflash\n"); + exit(EXIT_FAILURE); } } From 37b259d034c4e6eda5e7a677238d8a5efb666e9f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 23 Jun 2014 18:42:39 +0400 Subject: [PATCH 04/10] hw/xtensa/xtfpga: retrieve parameters from machine_opts Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 75bc479e36..0aa3eeb046 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -174,9 +174,10 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) MemoryRegion *ram, *rom, *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; + QemuOpts *machine_opts = qemu_get_machine_opts(); const char *cpu_model = machine->cpu_model; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); int n; if (!cpu_model) { From 62dbaede80b396aaae5394a9b6922b51be835e86 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 10:29:29 +0400 Subject: [PATCH 05/10] hw/xtensa/xtfpga: use symbolic constants for bootparam tags Import bootparam tag names from linux/arch/xtensa/include/asm/bootparam.h No functional changes. Signed-off-by: Max Filippov --- hw/xtensa/bootparam.h | 10 ++++++++++ hw/xtensa/xtfpga.c | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index 38ef32bdb6..e6cf3b1492 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -1,6 +1,16 @@ #ifndef HW_XTENSA_BOOTPARAM #define HW_XTENSA_BOOTPARAM +#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ +#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ +#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ +#define BP_TAG_SERIAL_BAUDRATE 0x1004 /* baud rate of current console. */ +#define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ +#define BP_TAG_FDT 0x1006 /* flat device tree addr */ + +#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */ +#define BP_TAG_LAST 0x7E0B /* last tag */ + typedef struct BpTag { uint16_t tag; uint16_t size; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 0aa3eeb046..6d070b0d64 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -250,12 +250,12 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) env->regs[2] = tagptr; - tagptr = put_tag(tagptr, 0x7b0b, 0, NULL); + tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); if (cmdline_size > 1) { - tagptr = put_tag(tagptr, 0x1001, + tagptr = put_tag(tagptr, BP_TAG_COMMAND_LINE, cmdline_size, kernel_cmdline); } - tagptr = put_tag(tagptr, 0x7e0b, 0, NULL); + tagptr = put_tag(tagptr, BP_TAG_LAST, 0, NULL); } uint64_t elf_entry; uint64_t elf_lowaddr; From a9a28591fbd4dc20d19b6408361b45c9b7300434 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 13:10:38 +0400 Subject: [PATCH 06/10] hw/xtensa/xtfpga: refactor bootparameters filling Separate filling first/last tag and size calculation from the kernel command line setup. Signed-off-by: Max Filippov --- hw/xtensa/bootparam.h | 5 +++++ hw/xtensa/xtfpga.c | 30 +++++++++++++++++------------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index e6cf3b1492..e839bee576 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -16,6 +16,11 @@ typedef struct BpTag { uint16_t size; } BpTag; +static inline size_t get_tag_size(size_t data_size) +{ + return data_size + sizeof(BpTag) + 4; +} + static inline ram_addr_t put_tag(ram_addr_t addr, uint16_t tag, size_t size, const void *data) { diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 6d070b0d64..689d07843b 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -237,26 +237,30 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { + size_t bp_size = 2 * get_tag_size(0); + uint32_t tagptr = 0xfe000000 + board->sram_size; + uint32_t cur_tagptr; + rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); vmstate_register_ram_global(rom); memory_region_add_subregion(system_memory, 0xfe000000, rom); - /* Put kernel bootparameters to the end of that SRAM */ if (kernel_cmdline) { - size_t cmdline_size = strlen(kernel_cmdline) + 1; - size_t bp_size = sizeof(BpTag[4]) + cmdline_size; - uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff; - - env->regs[2] = tagptr; - - tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); - if (cmdline_size > 1) { - tagptr = put_tag(tagptr, BP_TAG_COMMAND_LINE, - cmdline_size, kernel_cmdline); - } - tagptr = put_tag(tagptr, BP_TAG_LAST, 0, NULL); + bp_size += get_tag_size(strlen(kernel_cmdline) + 1); } + + /* Put kernel bootparameters to the end of that SRAM */ + tagptr = (tagptr - bp_size) & ~0xff; + cur_tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); + + if (kernel_cmdline) { + cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, + strlen(kernel_cmdline) + 1, kernel_cmdline); + } + cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); + env->regs[2] = tagptr; + uint64_t elf_entry; uint64_t elf_lowaddr; int success = load_elf(kernel_filename, translate_phys_addr, cpu, From b6edea8b687182bc4572c4e2e8af48f32b213dad Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 23 Jun 2014 17:24:48 +0400 Subject: [PATCH 07/10] hw/xtensa/xtfpga: add memory info to bootparam Signed-off-by: Max Filippov --- hw/xtensa/bootparam.h | 9 +++++++++ hw/xtensa/xtfpga.c | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index e839bee576..955f4e86e3 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -16,6 +16,15 @@ typedef struct BpTag { uint16_t size; } BpTag; +typedef struct BpMemInfo { + uint32_t type; + uint32_t start; + uint32_t end; +} BpMemInfo; + +#define MEMORY_TYPE_CONVENTIONAL 0x1000 +#define MEMORY_TYPE_NONE 0x2000 + static inline size_t get_tag_size(size_t data_size) { return data_size + sizeof(BpTag) + 4; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 689d07843b..97e5842e6d 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -237,9 +237,14 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { - size_t bp_size = 2 * get_tag_size(0); + size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ uint32_t tagptr = 0xfe000000 + board->sram_size; uint32_t cur_tagptr; + BpMemInfo memory_location = { + .type = tswap32(MEMORY_TYPE_CONVENTIONAL), + .start = tswap32(0), + .end = tswap32(machine->ram_size), + }; rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); @@ -253,6 +258,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; cur_tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_MEMORY, + sizeof(memory_location), &memory_location); if (kernel_cmdline) { cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, From 364d4802429a5c7d3985f322e54a104024fd3f75 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 4 Mar 2013 07:07:52 +0400 Subject: [PATCH 08/10] hw/xtensa/xtfpga: implement uImage loading Provide a simple bootloader code at the reset address that jumps to the loaded image entry point when it's not equal to the reset address. This is needed because the old method of setting pc doesn't work due to cpu reset done after the machine setup. Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 97e5842e6d..0e0d825556 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -237,6 +237,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { + uint32_t entry_point = env->pc; size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ uint32_t tagptr = 0xfe000000 + board->sram_size; uint32_t cur_tagptr; @@ -273,7 +274,29 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) int success = load_elf(kernel_filename, translate_phys_addr, cpu, &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0); if (success > 0) { - env->pc = elf_entry; + entry_point = elf_entry; + } else { + hwaddr ep; + int is_linux; + success = load_uimage(kernel_filename, &ep, NULL, &is_linux); + if (success > 0 && is_linux) { + entry_point = ep; + } else { + error_report("could not load kernel '%s'\n", + kernel_filename); + exit(EXIT_FAILURE); + } + } + if (entry_point != env->pc) { + static const uint8_t jx_a0[] = { +#ifdef TARGET_WORDS_BIGENDIAN + 0x0a, 0, 0, +#else + 0xa0, 0, 0, +#endif + }; + env->regs[0] = entry_point; + cpu_physical_memory_write(env->pc, jx_a0, sizeof(jx_a0)); } } else { if (flash) { From 996dfe98ed6bd57290f198ca29d0d9c614b4feef Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 23 Jun 2014 18:45:43 +0400 Subject: [PATCH 09/10] hw/xtensa/xtfpga: implement DTB loading Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 0e0d825556..01825d61c2 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -37,6 +37,7 @@ #include "hw/block/flash.h" #include "sysemu/blockdev.h" #include "sysemu/char.h" +#include "sysemu/device_tree.h" #include "qemu/error-report.h" #include "bootparam.h" @@ -178,6 +179,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) const char *cpu_model = machine->cpu_model; const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); + const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); int n; if (!cpu_model) { @@ -246,6 +248,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) .start = tswap32(0), .end = tswap32(machine->ram_size), }; + uint32_t lowmem_end = machine->ram_size < 0x08000000 ? + machine->ram_size : 0x08000000; + uint32_t cur_lowmem = QEMU_ALIGN_UP(lowmem_end / 2, 4096); rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); @@ -255,6 +260,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (kernel_cmdline) { bp_size += get_tag_size(strlen(kernel_cmdline) + 1); } + if (dtb_filename) { + bp_size += get_tag_size(sizeof(uint32_t)); + } /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; @@ -266,6 +274,21 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, strlen(kernel_cmdline) + 1, kernel_cmdline); } + if (dtb_filename) { + int fdt_size; + void *fdt = load_device_tree(dtb_filename, &fdt_size); + uint32_t dtb_addr = tswap32(cur_lowmem); + + if (!fdt) { + error_report("could not load DTB '%s'\n", dtb_filename); + exit(EXIT_FAILURE); + } + + cpu_physical_memory_write(cur_lowmem, fdt, fdt_size); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_FDT, + sizeof(dtb_addr), &dtb_addr); + cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4096); + } cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); env->regs[2] = tagptr; From f55b32e7499b291058a0d0fd7d35b14c24791684 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 13:35:35 +0400 Subject: [PATCH 10/10] hw/xtensa/xtfpga: implement initrd loading Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 01825d61c2..a2dff5a13e 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -180,6 +180,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); + const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); int n; if (!cpu_model) { @@ -263,6 +264,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (dtb_filename) { bp_size += get_tag_size(sizeof(uint32_t)); } + if (initrd_filename) { + bp_size += get_tag_size(sizeof(BpMemInfo)); + } /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; @@ -289,6 +293,26 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) sizeof(dtb_addr), &dtb_addr); cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4096); } + if (initrd_filename) { + BpMemInfo initrd_location = { 0 }; + int initrd_size = load_ramdisk(initrd_filename, cur_lowmem, + lowmem_end - cur_lowmem); + + if (initrd_size < 0) { + initrd_size = load_image_targphys(initrd_filename, + cur_lowmem, + lowmem_end - cur_lowmem); + } + if (initrd_size < 0) { + error_report("could not load initrd '%s'\n", initrd_filename); + exit(EXIT_FAILURE); + } + initrd_location.start = tswap32(cur_lowmem); + initrd_location.end = tswap32(cur_lowmem + initrd_size); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_INITRD, + sizeof(initrd_location), &initrd_location); + cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + initrd_size, 4096); + } cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); env->regs[2] = tagptr;