/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ #include /* Function: Input: r3: Destination to copy rtas code to r4: Configuration Output: r3: Entry point for rtas calls Decription: Called by OpenFirmware to instantiate rtas, needs to copy itself to destination, also do a relocations. */ .extern rtas_entry .extern .stack .extern _got .extern _got_end .extern __bss_start .extern __bss_end .extern rtas_config .section ".rtasstart","ax"; .align 3 .globl _rtas_start _rtas_start: mflr r10 # save link register bcl 20,31,.over # branch (always) to .over .base: .align 3 /* Our Open Firmware needs to know the size of the RTAS binary and the * size & address of the RTAS function jump table. SLOF always looks for this * information in the following three quads here at the very beginning of the * RTAS binary at offset 8. So DO NOT DELETE/MOVE them! */ ._rtas_size: .quad _rtas_end-_rtas_start ._ptr_to_func_tab: .quad rtas_func_tab-_rtas_start ._ptr_to_func_tab_size: .quad rtas_func_tab_size-_rtas_start /* The other variables are not accessed by SLOF anymore: */ ._rel_offset: .quad _reloc_table_start-_rtas_start ._rel_end_offset: .quad _reloc_table_end-_rtas_start ._bss_offset: .quad __bss_start-_rtas_start ._bss_end_offset: .quad __bss_end-_rtas_start ._rtas_entry_offset: .quad rtas_entry-_rtas_start ._rtas_config_offset: .quad rtas_config-_rtas_start ._rtas_stack: .quad .stack-_rtas_start+RTAS_STACKSIZE-0x60 ._rtas_toc: .quad _got-_rtas_start .over: mflr r8 # gpr 8 is the base addi r8,r8,_rtas_start-.base # points to _rtas_start mr r11,r4 # Save config value # Copy rtas code ld r5,._rtas_size-_rtas_start(r8) mr r4,r8 # Start of rtas addi r6,r3,-8 # Destination addi r4,r4,-8 # Source srdi r5,r5,3 # Count in quads mtctr r5 0: ldu r0,8(r4) stdu r0,8(r6) bdnz 0b # Clear bss ld r4,._bss_offset-_rtas_start(r8) ld r5,._bss_end_offset-_rtas_start(r8) li r0,0 add r6,r3,r4 # Address bss in copied code addi r6,r6,-8 sub r5,r5,r4 # Calculate bss size srdi r5,r5,3 # Count in quads mtctr r5 0: stdu r0,8(r6) bdnz 0b # Relocate got ld r4, ._rel_offset-_rtas_start(r8) ld r5, ._rel_end_offset-_rtas_start(r8) sub r5, r5,r4 # Calculate reloc table size cmpdi r5, 0 # No reloc table ? beq 1f add r4, r4, r3 # Calculate reloc table address addi r4, r4, -4 srdi r5, r5, 2 # Count in words mtctr r5 0: lwzu r6, 4(r4) # Load offset out of reloc table ldx r0, r6, r3 # Load value add r0, r0, r3 # Add relocation offset = load address stdx r0, r6, r3 bdnz 0b 1: # Save config data ld r5,._rtas_config_offset-_rtas_start(r8) add r5,r5,r3 std r11,0(r5) # Flush to memory mr r4,r3 # Destination address ld r5,._rtas_size-_rtas_start(r8) add r5,r5,r4 addi r5,r5,127 rlwinm r4,r4,0,0,24 rlwinm r5,r5,0,0,24 sub r5,r5,r4 srwi r5,r5,7 mtctr r5 0: dcbst 0,r4 sync icbi 0,r4 sync isync addi r4,r4,128 bdnz 0b # Call init function mfmsr r11 # Switch to 64 bit mode mr r7,r11 rotldi r11,r11,1 ori r11,r11,1 rotldi r11,r11,63 mtmsrd r11 isync mr r9,r1 # save old stack pointer ld r1,._rtas_stack-_rtas_start(r8) # load new stack pointer add r1,r1,r3 std r9,0(r1) # save stack pointer std r2,64(r1) # save toc std r7,72(r1) # save old msr value ld r2,._rtas_toc-_rtas_start(r8) # load got pointer add r2,r2,r3 bl save_regs_r3_r12 bl .rtas_init bl restore_regs_r3_r12 ld r11,72(r1) # restore msr value ld r2,64(r1) # restore toc ld r1,0(r1) # get old stack mtmsrd r11 # restore msr isync # Return rtas entry ld r4,._rtas_entry_offset-_rtas_start(r8) add r3,r3,r4 mtlr r10 blr