patch-2.4.19 linux-2.4.19/arch/ppc/boot/common/relocate.S
Next file: linux-2.4.19/arch/ppc/boot/common/util.S
Previous file: linux-2.4.19/arch/ppc/boot/common/ofcommon.c
Back to the patch index
Back to the overall index
- Lines: 211
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/ppc/boot/common/relocate.S
- Orig date:
Wed Dec 31 16:00:00 1969
diff -urN linux-2.4.18/arch/ppc/boot/common/relocate.S linux-2.4.19/arch/ppc/boot/common/relocate.S
@@ -0,0 +1,210 @@
+/*
+ * arch/ppc/boot/simple/relocate.S
+ *
+ * This is the common part of the loader relocation and initialization
+ * process. All of the board/processor specific initialization is
+ * done before we get here.
+ *
+ * Author: Tom Rini
+ * trini@mvista.com
+ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include "ppc_asm.h"
+
+#define GETSYM(reg, sym) \
+ lis reg, sym@h; ori reg, reg, sym@l
+
+ .text
+ /* We get called from the early initialization code.
+ * Register 3 has the address where we were loaded,
+ * Register 4 contains any residual data passed from the
+ * boot rom.
+ */
+ .globl relocate
+relocate:
+ /* Save r3, r4 for later.
+ * The r8/r11 are legacy registers so I don't have to
+ * rewrite the code below :-).
+ */
+ mr r8, r3
+ mr r11, r4
+
+ /* compute the size of the whole image in words. */
+ GETSYM(r4,start)
+ GETSYM(r5,end)
+
+ addi r5,r5,3 /* round up */
+ sub r5,r5,r4 /* end - start */
+ srwi r5,r5,2
+ mr r7,r5 /* Save for later use. */
+
+ /*
+ * Check if we need to relocate ourselves to the link addr or were
+ * we loaded there to begin with.
+ */
+ cmp cr0,r3,r4
+ beq start_ldr /* If 0, we don't need to relocate */
+
+ /* Move this code somewhere safe. This is max(load + size, end)
+ * BIG ASSUMPTION: Addresses below 0x80000000 are assumed to be
+ * in RAM, and addresses above 0x80000000 are assumed to be in
+ * Flash. The cmpw instruction below does a signed integer
+ * comparison, so when comparing a RAM address to a Flash address
+ * the RAM address will always be greater. This allows the
+ * relocation to work when the load address is in Flash.
+ * r8 == load address
+ */
+ GETSYM(r4, start)
+ GETSYM(r5, end)
+
+ sub r6,r5,r4
+ add r6,r8,r6 /* r6 == phys(load + size) */
+
+ cmpw r5,r6
+ bgt 1f
+ b 2f
+1:
+ mr r6, r5
+2:
+ /* dest is in r6 */
+ /* Ensure alignment --- this code is precautionary */
+ addi r6,r6,4
+ li r5,0x0003
+ andc r6,r6,r5
+
+ /* Find physical address and size of do_relocate */
+ GETSYM(r5, __relocate_start)
+ GETSYM(r4, __relocate_end)
+ GETSYM(r3, start)
+
+ /* Size to copy */
+ sub r4,r4,r5
+ srwi r4,r4,2
+
+ /* Src addr to copy (= __relocate_start - start + where_loaded) */
+ sub r3,r5,r3
+ add r5,r8,r3
+
+ /* Save dest */
+ mr r3, r6
+
+ /* Do the copy */
+ mtctr r4
+3: lwz r4,0(r5)
+ stw r4,0(r3)
+ addi r3,r3,4
+ addi r5,r5,4
+ bdnz 3b
+
+ GETSYM(r4, __relocate_start)
+ GETSYM(r5, do_relocate)
+
+ sub r4,r5,r4 /* Get entry point for do_relocate in */
+ add r6,r6,r4 /* relocated section */
+
+ /* This will return to the relocated do_relocate */
+ mtlr r6
+ b flush_instruction_cache
+
+ .section ".relocate_code","xa"
+
+do_relocate:
+ /* We have 2 cases --- start < load, or start > load
+ * This determines whether we copy from the end, or the start.
+ * Its easier to have 2 loops than to have paramaterised
+ * loops. Sigh.
+ */
+ li r6,0 /* Clear checksum */
+ mtctr r7 /* Setup for a loop */
+
+ GETSYM(r4, start)
+ mr r3,r8 /* Get the load addr */
+
+ cmp cr0,r4,r3 /* If we need to copy from the end, do so */
+ bgt do_relocate_from_end
+
+do_relocate_from_start:
+1: lwz r5,0(r3) /* Load and decrement */
+ stw r5,0(r4) /* Store and decrement */
+ addi r3,r3,4
+ addi r4,r4,4
+ xor r6,r6,r5 /* Update checksum */
+ bdnz 1b /* Are we done? */
+ b do_relocate_out /* Finished */
+
+do_relocate_from_end:
+ GETSYM(r3, end)
+ slwi r4,r7,2
+ add r4,r8,r4 /* Get the physical end */
+1: lwzu r5,-4(r4)
+ stwu r5, -4(r3)
+ xor r6,r6,r5
+ bdnz 1b
+
+do_relocate_out:
+ GETSYM(r3,start_ldr)
+ mtlr r3 /* Easiest way to do an absolute jump */
+/* Some boards don't boot up with the I-cache enabled. Do that
+ * now because the decompress runs much faster that way.
+ * As a side effect, we have to ensure the data cache is not enabled
+ * so we can access the serial I/O without trouble.
+ */
+ b flush_instruction_cache
+
+ .previous
+
+start_ldr:
+/* Clear all of BSS and set up stack for C calls */
+ lis r3,edata@h
+ ori r3,r3,edata@l
+ lis r4,end@h
+ ori r4,r4,end@l
+ subi r3,r3,4
+ subi r4,r4,4
+ li r0,0
+50: stwu r0,4(r3)
+ cmp cr0,r3,r4
+ bne 50b
+90: mr r9,r1 /* Save old stack pointer (in case it matters) */
+ lis r1,.stack@h
+ ori r1,r1,.stack@l
+ addi r1,r1,4096*2
+ subi r1,r1,256
+ li r2,0x000F /* Mask pointer to 16-byte boundary */
+ andc r1,r1,r2
+
+ /*
+ * Exec kernel loader
+ */
+ mr r3,r8 /* Load point */
+ mr r4,r7 /* Program length */
+ mr r5,r6 /* Checksum */
+ mr r6,r11 /* Residual data */
+ bl decompress_kernel
+
+ /*
+ * Make sure the kernel knows we don't have things set in
+ * registers. -- Tom
+ */
+ li r4,0
+ li r6,0
+
+ /*
+ * Start at the begining.
+ */
+ li r9,0x0000
+ mtlr r9
+ blr
+
+ .comm .stack,4096*2,4
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)