184 lines
4.1 KiB
ArmAsm
184 lines
4.1 KiB
ArmAsm
|
/******************************************************************************
|
||
|
* 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 <rtas.h>
|
||
|
|
||
|
/*
|
||
|
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
|
||
|
|
||
|
|
||
|
|