diff options
author | 2015-08-28 09:58:54 +0800 | |
---|---|---|
committer | 2015-09-01 12:44:00 +0800 | |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/SLOF/rtas | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/SLOF/rtas')
-rw-r--r-- | qemu/roms/SLOF/rtas/Makefile.inc | 89 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/flash/block_lists.c | 275 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/flash/block_lists.h | 23 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/flash/tmpXXX.update-comments | 11 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/reloc.S | 183 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/rtas.lds | 49 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/rtas_call.c | 93 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/rtas_common.S | 87 | ||||
-rw-r--r-- | qemu/roms/SLOF/rtas/rtas_entry.S | 72 |
9 files changed, 882 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/rtas/Makefile.inc b/qemu/roms/SLOF/rtas/Makefile.inc new file mode 100644 index 000000000..4297f86a9 --- /dev/null +++ b/qemu/roms/SLOF/rtas/Makefile.inc @@ -0,0 +1,89 @@ +# ***************************************************************************** +# * 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 +# ****************************************************************************/ + +# Before including this Makefile, you should specify the following variables +# in your Makefile: +# - RTASCMNDIR : Points to the common RTAS directory +# - RTASBRDDIR : Points to the board specific RTAS directory +# - TOOLSDIR : Points to the common tools directory +# - OBJS : A list with all object files that should be linked into rtas.bin +# - BOARD_SRCS : A list with all board specific source code files +# (needed for "make depend") + + +LDFLAGS = -nostdlib +CPPFLAGS += -I$(RTASBRDDIR) -I$(RTASCMNDIR) \ + -I$(INCLCMNDIR) -I$(INCLBRDDIR) \ + -I$(LIBCMNDIR)/libc/include \ + -I$(INCLCMNDIR)/$(CPUARCH) +ASFLAGS = -Wa,-mregnames $(FLAG) +CFLAGS += -g -nostdinc -ffreestanding -Wall -Wextra -O2 -msoft-float \ + -mno-altivec -mabi=no-altivec $(FLAG) + +# Common RTAS files: +RTAS_SRC_ASM = reloc.S rtas_common.S rtas_entry.S rtas_term.S \ + rtas_cpu.S rtas_flash_asm.S rtas_mem.S rtas_ras.S +RTAS_SRC_C = rtas_call.c rtas_flash_c.c rtas_h8.c \ + rtas_nvramlog.c rtas_sensor.c rtas_init.c \ + rtas_flash_cfi.c +RTAS_SRCS = $(RTAS_SRC_ASM) $(RTAS_SRC_C) +RTAS_OBJ_ASM = $(RTAS_SRC_ASM:%.S=%.o) +RTAS_OBJ_C = $(RTAS_SRC_C:%.c=%.o) + +# Common build rules: +$(RTAS_OBJ_C): + $(CC) $(CPPFLAGS) $(CFLAGS) -c $(@:%.o=$(RTASCMNDIR)/%.c) -o $@ + +$(RTAS_OBJ_ASM): + $(CC) $(CPPFLAGS) $(ASFLAGS) -c $(@:%.o=$(RTASCMNDIR)/%.S) -o $@ + +$(TOOLSDIR)/gen_reloc_table: $(TOOLSDIR)/gen_reloc_table.c + $(MAKE) -C $(TOOLSDIR) gen_reloc_table + + +# Rules for building rtas.bin: +rtas.bin: rtas + $(OBJCOPY) -O binary $< $@ + +rtas: $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o $(LIBCMNDIR)/libc.a + $(LD) $(LDFLAGS) -o $@ -T $(RTASCMNDIR)/rtas.lds $(OBJS) \ + reloc_table.o $(LIBCMNDIR)/libc.a + +reloc_table.o: $(TOOLSDIR)/gen_reloc_table $(OBJS) $(LIBCMNDIR)/libc.a + $(TOOLSDIR)/create_reloc_table.sh --ld "$(ONLY_LD)" --ldflags "$(LDFLAGS)" \ + --lds "$(RTASCMNDIR)/rtas.lds" --objcopy "$(OBJCOPY)" $(OBJS) $(LIBCMNDIR)/libc.a + + +$(LIBCMNDIR)/libc.a: + $(MAKE) -C $(LIBCMNDIR) libc + + +# Rules for cleaning up: +clean_rtas: + rm -f $(OBJS) reloc_table.o rtas rtas.bin + rm -f $(RTASCMNDIR)/*~ $(RTASCMNDIR)/*.o + +distclean_rtas: clean_rtas + rm -f Makefile.dep + + +# Rules for creating the dependency file: +depend: + rm -f Makefile.dep + $(MAKE) Makefile.dep + +Makefile.dep: Makefile $(RTASCMNDIR)/Makefile.inc + $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(RTAS_SRCS:%=$(RTASCMNDIR)/%) > Makefile.dep + $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(BOARD_SRCS) >> Makefile.dep + +# Include dependency file if available: +-include Makefile.dep diff --git a/qemu/roms/SLOF/rtas/flash/block_lists.c b/qemu/roms/SLOF/rtas/flash/block_lists.c new file mode 100644 index 000000000..e632fd0bd --- /dev/null +++ b/qemu/roms/SLOF/rtas/flash/block_lists.c @@ -0,0 +1,275 @@ +/****************************************************************************** + * 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 <product.h> +#include <stdio.h> +#include "block_lists.h" + +unsigned char sig_org[] = FLASHFS_PLATFORM_MAGIC; + +/* this function is part of the crc_lib assembler code */ +unsigned long check_flash_image(unsigned long, unsigned long, unsigned long); + +/* this functions needs to be implemented by the board specific flash code + * the functions always get 32 bytes and needs to deal with the data */ +void write_flash(unsigned long, unsigned short *); + +int progress = 0; + +int +print_progress(void) +{ + static int i = 3; + switch (i--) { + case 3: + printf("\b|"); + break; + case 2: + printf("\b/"); + break; + case 1: + printf("\b-"); + break; + case 0: + printf("\b\\"); + default: + i = 3; + } + return 0; +} + +void +print_hash(void) +{ + printf("\b# "); +} + +void +print_writing(void) +{ + int counter = 42; + printf("\nWriting Flash: |"); + while (counter--) + printf(" "); + printf("|"); + counter = 41; + while (counter--) + printf("\b"); + +} + +int +get_block_list_version(unsigned char *data) +{ + if (data[0] == 0x01) + return 1; + return 0; +} + +static long +get_image_size(unsigned long *data, unsigned long length) +{ + long size = 0; + unsigned long i; + for (i = 0; i < length / 8; i += 2) { + size += data[1 + i]; + } + return size; +} + +static long +get_image_size_v0(unsigned long *data) +{ + unsigned long bl_size = data[0]; + return get_image_size(data + 1, bl_size - 8); +} + +static long +get_image_size_v1(unsigned long *data) +{ + unsigned long *bl_addr = data; + unsigned long bl_size; + unsigned long *next; + long size = 0; + while (bl_addr) { + bl_size = bl_addr[0]; + next = (unsigned long *) bl_addr[1]; + bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; + size += get_image_size(bl_addr + 2, bl_size - 0x10); + bl_addr = next; + } + return size; +} + +long +get_size(unsigned long *data, int version) +{ + if (version == 1) + return get_image_size_v1(data); + return get_image_size_v0(data); +} + +static unsigned long +write_one_block(unsigned long *block, unsigned long length, + unsigned long offset) +{ + unsigned long block_addr = (unsigned long) block; + unsigned long i = 0; + static unsigned int hash; + if (offset == 0) + hash = 0; + + for (i = 0; i < length; i += 32, offset += 32, block_addr += 32) { + write_flash(offset, (unsigned short *) block_addr); + if (offset % 10 == 0) { + print_progress(); + } + if (offset > hash * progress) { + print_hash(); + hash++; + } + } + + return offset; +} + +static unsigned long +write_one_list(unsigned long *bl, unsigned long length, unsigned long offset) +{ + unsigned long i; + // 0x10: /8 for pointer /2 it has to be done in steps of 2 + for (i = 0; i < length / 0x10; i++) { + offset = + write_one_block((unsigned long *) *bl, *(bl + 1), offset); + bl += 2; + } + return offset; +} + +void +write_block_list(unsigned long *bl, int version) +{ + unsigned long offset = 0; + unsigned long *bl_addr = bl; + unsigned long bl_size; + unsigned long *next; + + if (version == 0) { + // -8 = removed header length + write_one_list(bl + 1, *(bl) - 8, offset); + return; + } + + while (bl_addr) { + bl_size = bl_addr[0]; + next = (unsigned long *) bl_addr[1]; + bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; + // -0x10 = removed header length + offset = write_one_list(bl_addr + 2, bl_size - 0x10, offset); + bl_addr = next; + } + +} + +static int +check_one_list(unsigned long *bl, unsigned long length, unsigned long crc) +{ + unsigned long i; + // 0x10: /8 for pointer /2 it has to be done in steps of 2 + for (i = 0; i < length / 0x10; i++) { + crc = check_flash_image((unsigned long) *bl, *(bl + 1), crc); + bl += 2; + } + return crc; +} + +int +image_check_crc(unsigned long *bl, int version) +{ + unsigned long *bl_addr = bl; + unsigned long bl_size; + unsigned long *next; + unsigned long crc = 0; + + if (version == 0) { + // -8 = removed header length + return check_one_list(bl + 1, *(bl) - 8, crc); + } + + while (bl_addr) { + bl_size = bl_addr[0]; + next = (unsigned long *) bl_addr[1]; + bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; + // -0x10 = removed header length + crc = check_one_list(bl_addr + 2, bl_size - 0x10, crc); + bl_addr = next; + } + return crc; +} + +static int +check_platform_one_list(unsigned long *bl, unsigned long bytesec) +{ + unsigned long pos = bytesec; + unsigned char *sig_tmp, *sig; + unsigned long size = 0; + sig = sig_org; + + while (size < bytesec) { + size += bl[1]; + + while (size > pos) { // 32 == FLASHFS_PLATFORM_MAGIC length + sig_tmp = (unsigned char *) (bl[0] + pos); + if (*sig++ != *sig_tmp) + return -1; + if (*sig_tmp == '\0' || (pos == bytesec + 32)) { + pos = bytesec + 32; + break; + } + pos++; + } + if (pos == (bytesec + 32)) + return 0; + bl += 2; + } + return 0; +} + +int +check_platform(unsigned long *bl, unsigned int bytesec, int version) +{ + unsigned long *bl_addr = bl; + unsigned long bl_size; + unsigned long *next; + unsigned long *ptr; + ptr = bl; + + if (version == 0) { + ptr += 1; // -8 = removed header length + return check_platform_one_list(ptr, bytesec); + } + while (bl_addr) { + ptr = bl_addr + 2; // -0x10 = removed header length + bl_size = bl_addr[0]; + next = (unsigned long *) bl_addr[1]; + bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL; + if ((bl_size - 0x10) == 0) { + bl_addr = next; + continue; + } + if (check_platform_one_list(ptr, bytesec) == 0) + return 0; + + bl_addr = next; + } + return -1; +} diff --git a/qemu/roms/SLOF/rtas/flash/block_lists.h b/qemu/roms/SLOF/rtas/flash/block_lists.h new file mode 100644 index 000000000..b24b65064 --- /dev/null +++ b/qemu/roms/SLOF/rtas/flash/block_lists.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +extern int progress; +extern unsigned char sig_org[]; + +int print_progress(void); +void print_hash(void); +int get_block_list_version(unsigned char *); +int image_check_crc(unsigned long *, int); +long get_size(unsigned long *, int); +void print_writing(void); +void write_block_list(unsigned long *, int); +int check_platform(unsigned long *, unsigned int, int); diff --git a/qemu/roms/SLOF/rtas/flash/tmpXXX.update-comments b/qemu/roms/SLOF/rtas/flash/tmpXXX.update-comments new file mode 100644 index 000000000..cd3d1376d --- /dev/null +++ b/qemu/roms/SLOF/rtas/flash/tmpXXX.update-comments @@ -0,0 +1,11 @@ +# ***************************************************************************** +# * 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 +# ****************************************************************************/ diff --git a/qemu/roms/SLOF/rtas/reloc.S b/qemu/roms/SLOF/rtas/reloc.S new file mode 100644 index 000000000..e24d293d4 --- /dev/null +++ b/qemu/roms/SLOF/rtas/reloc.S @@ -0,0 +1,183 @@ +/****************************************************************************** + * 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+0x8000 + +.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 + + + diff --git a/qemu/roms/SLOF/rtas/rtas.lds b/qemu/roms/SLOF/rtas/rtas.lds new file mode 100644 index 000000000..a5ba1daaf --- /dev/null +++ b/qemu/roms/SLOF/rtas/rtas.lds @@ -0,0 +1,49 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc") +OUTPUT_ARCH(powerpc:common64) + +SECTIONS { + .text 0: + { + *(.rtasstart) + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.sfpr .glink) + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.opd) + } =0x60000000 + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + } + .got : + { + _got = .; + *(.got .toc) + } + .reloc : + { + . = ALIGN(4); + _reloc_table_start = .; + *(.reloc) + _reloc_table_end = .; + } + .bss : + { + __bss_start = .; + *(*COM* .bss .sbss .gnu.linkonce.b.*) + __bss_end = .; + } + __bss_size = (__bss_end - __bss_start); + _rtas_end = .; +} diff --git a/qemu/roms/SLOF/rtas/rtas_call.c b/qemu/roms/SLOF/rtas/rtas_call.c new file mode 100644 index 000000000..8c7532c01 --- /dev/null +++ b/qemu/roms/SLOF/rtas/rtas_call.c @@ -0,0 +1,93 @@ +/****************************************************************************** + * 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 <stdint.h> +#include <rtas.h> +#include "rtas_table.h" + + +//#define _RTAS_TRACE +//#define _RTAS_COUNT_CALLS + + +#ifdef _RTAS_COUNT_CALLS +int rtas_callcount[0x40] __attribute__((aligned (16))); +#endif + +/* rtas_config is used to store the run-time configuration flags (which are + * provided by SLOF during instantiate-rtas) */ +long rtas_config; + + +/* Prototype */ +void rtas_call (rtas_args_t *rtas_args); + + +/* +Function: rtas_call + Input: + rtas_args: pointer to RTAS arguments structure + Output: + +Decription: Handle RTAS call. This C function is called + from the asm function rtas_entry. +*/ + +void +rtas_call (rtas_args_t *rtas_args) +{ + int idx; + +#ifdef _RTAS_COUNT_CALLS + /* Count how often every RTAS function is called. */ + if (rtas_args->token < (int)(sizeof(rtas_callcount)/sizeof(rtas_callcount[0]))) { + static int callcount_initialized = 0; + /* If the array is used the first time, we have to set all entries to 0 */ + if (!callcount_initialized) { + unsigned int i; + callcount_initialized = 1; + for (i = 0; i < sizeof(rtas_callcount)/sizeof(rtas_callcount[0]); i++) + rtas_callcount[i] = 0; + } + /* Increment the counter of the RTAS call */ + rtas_callcount[rtas_args->token] += 1; + } +#endif + +#ifdef _RTAS_TRACE + unsigned int parCnt = rtas_args->nargs; + unsigned int *pInt = rtas_args->args; + printf("\n\r*** rtas_call=0x%x", rtas_args->token); +#ifdef _RTAS_COUNT_CALLS + printf(" count=0x%x", rtas_callcount[rtas_args->token]); +#endif + printf(" len=0x%x", parCnt); + printf("\n\r "); + while(parCnt--) { + printf("0x%x ", *pInt++); + } +#endif + + idx = rtas_args->token - 1; + + /* Check if there's a function for the token: */ + if (idx >= 0 && idx < rtas_func_tab_size + && rtas_func_tab[idx].func != NULL) { + /* Now jump to the RTAS function: */ + rtas_func_tab[idx].func(rtas_args); + } + else { + /* We didn't find a function - return error code: */ + rtas_args->args[rtas_args->nargs] = -1; + } + +} diff --git a/qemu/roms/SLOF/rtas/rtas_common.S b/qemu/roms/SLOF/rtas/rtas_common.S new file mode 100644 index 000000000..35cd9a9f5 --- /dev/null +++ b/qemu/roms/SLOF/rtas/rtas_common.S @@ -0,0 +1,87 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +.globl save_regs_r3_r12 +.globl restore_regs_r3_r12 +.globl save_regs_r13_r25 +.globl restore_regs_r13_r25 + + +save_regs_r3_r12: + stdu r1,-0x80(r1) # allocate space on stack + + std r3,0x30(r1) + std r4,0x38(r1) + std r5,0x40(r1) + std r6,0x48(r1) + std r7,0x50(r1) + std r8,0x58(r1) + std r9,0x60(r1) + std r10,0x68(r1) + std r11,0x70(r1) + std r12,0x78(r1) + + blr + +restore_regs_r3_r12: + ld r3,0x30(r1) + ld r4,0x38(r1) + ld r5,0x40(r1) + ld r6,0x48(r1) + ld r7,0x50(r1) + ld r8,0x58(r1) + ld r9,0x60(r1) + ld r10,0x68(r1) + ld r11,0x70(r1) + ld r12,0x78(r1) + + addi r1,r1,0x80 # cleanup stack + + blr + +save_regs_r13_r25: + stdu r1,-0x98(r1) # allocate space on stack + + std r13,0x30(r1) + std r14,0x38(r1) + std r15,0x40(r1) + std r16,0x48(r1) + std r17,0x50(r1) + std r18,0x58(r1) + std r19,0x60(r1) + std r20,0x68(r1) + std r21,0x70(r1) + std r22,0x78(r1) + std r23,0x80(r1) + std r24,0x88(r1) + std r25,0x90(r1) + + blr + +restore_regs_r13_r25: + ld r13,0x30(r1) # restore registers from stack + ld r14,0x38(r1) + ld r15,0x40(r1) + ld r16,0x48(r1) + ld r17,0x50(r1) + ld r18,0x58(r1) + ld r19,0x60(r1) + ld r20,0x68(r1) + ld r21,0x70(r1) + ld r22,0x78(r1) + ld r23,0x80(r1) + ld r24,0x88(r1) + ld r25,0x90(r1) + + addi r1,r1,0x98 # cleanup stack + + blr diff --git a/qemu/roms/SLOF/rtas/rtas_entry.S b/qemu/roms/SLOF/rtas/rtas_entry.S new file mode 100644 index 000000000..74693aa48 --- /dev/null +++ b/qemu/roms/SLOF/rtas/rtas_entry.S @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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: rtas parm structure + r4: base address + Output: + +Decription: Main entry point, called from OS. Second parameter is not + used. + +*/ + .globl rtas_entry +rtas_entry: + mfmsr r11 # Get MSR to enable 64-bit mode + mr r7,r11 + rotldi r11,r11,1 + ori r11,r11,1 # Always enable 64-bit mode flag + rotldi r11,r11,63 + mtmsrd r11 # Switch to 64-bit mode + isync + + mr r9,r1 # save old stack pointer + mflr r10 # save link register + bcl 20,31,.over # branch to over +.base: + .align 3 +..got: .quad _got-.base+0x8000 +..stack: .quad .stack+RTAS_STACKSIZE-0x60-.base +.over: + mflr r8 # gpr 8 is the base + ld r1,..stack-.base(r8) # load new stack pointer + add r1,r1,r8 # add base + std r2,64(r1) # save toc + ld r2,..got-.base(r8) # load got pointer + std r7,72(r1) # save original msr + std r10,80(r1) # save link register + std r9,0(r1) # save stack pointer + add r2,r2,r8 # add base + + bl save_regs_r3_r12 + bl .rtas_call + bl restore_regs_r3_r12 + +rtas_return: + ld r11,72(r1) # restore msr value + ld r0,80(r1) # restore link register value + ld r2,64(r1) # restore toc + ld r1,0(r1) # get old stack + mtmsrd r11 # restore msr (32 bit ?) + isync + mtlr r0 + blr + + + + .globl .stack + .lcomm .stack,RTAS_STACKSIZE |