aboutsummaryrefslogtreecommitdiff
path: root/hw/arm_boot.c
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2009-11-11 18:07:53 +0000
committerPaul Brook <paul@codesourcery.com>2009-11-11 18:07:53 +0000
commitf2d74978764f62d832d61ac17bb5d934ade58816 (patch)
tree93c836769cf2da4b27d73e1bbf2accda18dee31a /hw/arm_boot.c
parent715a664ac4ca3b9e44ffbc0ca41ecd91fbe96656 (diff)
downloadqemu-f2d74978764f62d832d61ac17bb5d934ade58816.zip
qemu-f2d74978764f62d832d61ac17bb5d934ade58816.tar.gz
qemu-f2d74978764f62d832d61ac17bb5d934ade58816.tar.bz2
Fix ARM system emulation
Since 45a50b1 load_image_targphys should only be called once. ARM boards incorrectly call it every time the system is reset. Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'hw/arm_boot.c')
-rw-r--r--hw/arm_boot.c65
1 files changed, 37 insertions, 28 deletions
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index a8a38c5..28e9dbd 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -44,17 +44,6 @@ static uint32_t smpboot[] = {
0xe12fff11 /* bx r1 */
};
-static void main_cpu_reset(void *opaque)
-{
- CPUState *env = opaque;
-
- cpu_reset(env);
- if (env->boot_info)
- arm_load_kernel(env, env->boot_info);
-
- /* TODO: Reset secondary CPUs. */
-}
-
#define WRITE_WORD(p, value) do { \
stl_phys_notdirty(p, value); \
p += 4; \
@@ -186,6 +175,29 @@ static void set_kernel_args_old(struct arm_boot_info *info,
}
}
+static void main_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+ struct arm_boot_info *info = env->boot_info;
+
+ cpu_reset(env);
+ if (info) {
+ if (!info->is_linux) {
+ /* Jump to the entry point. */
+ env->regs[15] = info->entry & 0xfffffffe;
+ env->thumb = info->entry & 1;
+ } else {
+ if (old_param) {
+ set_kernel_args_old(info, info->initrd_size,
+ info->loader_start);
+ } else {
+ set_kernel_args(info, info->initrd_size, info->loader_start);
+ }
+ }
+ }
+ /* TODO: Reset secondary CPUs. */
+}
+
void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
{
int kernel_size;
@@ -202,12 +214,9 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
exit(1);
}
- if (!env->boot_info) {
- if (info->nb_cpus == 0)
- info->nb_cpus = 1;
- env->boot_info = info;
- qemu_register_reset(main_cpu_reset, env);
- }
+ if (info->nb_cpus == 0)
+ info->nb_cpus = 1;
+ env->boot_info = info;
#ifdef TARGET_WORDS_BIGENDIAN
big_endian = 1;
@@ -234,11 +243,8 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
info->kernel_filename);
exit(1);
}
- if (!is_linux) {
- /* Jump to the entry point. */
- env->regs[15] = entry & 0xfffffffe;
- env->thumb = entry & 1;
- } else {
+ info->entry = entry;
+ if (is_linux) {
if (info->initrd_filename) {
initrd_size = load_image_targphys(info->initrd_filename,
info->loader_start
@@ -257,16 +263,19 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
bootloader[6] = entry;
for (n = 0; n < sizeof(bootloader) / 4; n++) {
- stl_phys_notdirty(info->loader_start + (n * 4), bootloader[n]);
+ bootloader[n] = tswap32(bootloader[n]);
}
+ rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
+ info->loader_start);
if (info->nb_cpus > 1) {
for (n = 0; n < sizeof(smpboot) / 4; n++) {
- stl_phys_notdirty(info->smp_loader_start + (n * 4), smpboot[n]);
+ smpboot[n] = tswap32(smpboot[n]);
}
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+ info->smp_loader_start);
}
- if (old_param)
- set_kernel_args_old(info, initrd_size, info->loader_start);
- else
- set_kernel_args(info, initrd_size, info->loader_start);
+ info->initrd_size = initrd_size;
}
+ info->is_linux = is_linux;
+ qemu_register_reset(main_cpu_reset, env);
}