.globl relocate_new_kernel
 relocate_new_kernel:
 
+       /* Move boot params back to where the kernel expects them */
+
+       ldr     r0,kexec_boot_params_address
+       teq     r0,#0
+       beq     8f
+
+       ldr     r1,kexec_boot_params_copy
+       mov     r6,#KEXEC_BOOT_PARAMS_SIZE/4
+7:
+       ldr     r5,[r1],#4
+       str     r5,[r0],#4
+       subs    r6,r6,#1
+       bne     7b
+
+8:
+       /* Boot params moved, now go on with the kernel */
+
        ldr     r0,kexec_indirection_page
        ldr     r1,kexec_start_address
 
        mov lr,r1
        mov r0,#0
        ldr r1,kexec_mach_type
-       mov r2,#0
+       ldr r2,kexec_boot_params_address
        mov pc,lr
 
        .globl kexec_start_address
 kexec_mach_type:
        .long   0x0
 
+       /* phy addr where new kernel will expect to find boot params */
+       .globl kexec_boot_params_address
+kexec_boot_params_address:
+       .long   0x0
+
+       /* phy addr where old kernel put a copy of orig boot params */
+       .globl kexec_boot_params_copy
+kexec_boot_params_copy:
+       .long   0x0
+
 relocate_new_kernel_end:
 
        .globl relocate_new_kernel_size
 
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/kexec.h>
 
 #include <asm/cpu.h>
 #include <asm/elf.h>
 }
 arch_initcall(customize_machine);
 
+#ifdef CONFIG_KEXEC
+
+/* Physical addr of where the boot params should be for this machine */
+extern unsigned long kexec_boot_params_address;
+
+/* Physical addr of the buffer into which the boot params are copied */
+extern unsigned long kexec_boot_params_copy;
+
+/* Pointer to the boot params buffer, for manipulation and display */
+unsigned long kexec_boot_params;
+EXPORT_SYMBOL(kexec_boot_params);
+
+/* The buffer itself - make sure it is sized correctly */
+static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
+
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
        struct tag *tags = (struct tag *)&init_tags;
        else if (mdesc->boot_params)
                tags = phys_to_virt(mdesc->boot_params);
 
+#ifdef CONFIG_KEXEC
+       kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
+       kexec_boot_params = (unsigned long)kexec_boot_params_buf;
+       if (__atags_pointer) {
+               kexec_boot_params_address = __atags_pointer;
+               memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
+       } else if (mdesc->boot_params) {
+               kexec_boot_params_address = mdesc->boot_params;
+               memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
+       }
+#endif
+
        /*
         * If we have the old style parameters, convert them to
         * a tag list.