aboutsummaryrefslogtreecommitdiff
path: root/hw/xtensa
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2013-03-04 07:07:52 +0400
committerMax Filippov <jcmvbkbc@gmail.com>2014-06-29 02:32:42 +0400
commit364d4802429a5c7d3985f322e54a104024fd3f75 (patch)
treea81bc283e344ab2a3a302bc8baf6c66f8a72021d /hw/xtensa
parentb6edea8b687182bc4572c4e2e8af48f32b213dad (diff)
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 <jcmvbkbc@gmail.com>
Diffstat (limited to 'hw/xtensa')
-rw-r--r--hw/xtensa/xtfpga.c25
1 files changed, 24 insertions, 1 deletions
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) {