From 3f2546b2ef55b661fd8dd69682b38992225e86f6 Mon Sep 17 00:00:00 2001
From: fishsoupisgood <github@madingley.org>
Date: Mon, 29 Apr 2019 01:17:54 +0100
Subject: Initial import of qemu-2.4.1

---
 roms/SLOF/rtas/Makefile.inc                 |  89 +++++++++
 roms/SLOF/rtas/flash/block_lists.c          | 275 ++++++++++++++++++++++++++++
 roms/SLOF/rtas/flash/block_lists.h          |  23 +++
 roms/SLOF/rtas/flash/tmpXXX.update-comments |  11 ++
 roms/SLOF/rtas/reloc.S                      | 183 ++++++++++++++++++
 roms/SLOF/rtas/rtas.lds                     |  49 +++++
 roms/SLOF/rtas/rtas_call.c                  |  93 ++++++++++
 roms/SLOF/rtas/rtas_common.S                |  87 +++++++++
 roms/SLOF/rtas/rtas_entry.S                 |  72 ++++++++
 9 files changed, 882 insertions(+)
 create mode 100644 roms/SLOF/rtas/Makefile.inc
 create mode 100644 roms/SLOF/rtas/flash/block_lists.c
 create mode 100644 roms/SLOF/rtas/flash/block_lists.h
 create mode 100644 roms/SLOF/rtas/flash/tmpXXX.update-comments
 create mode 100644 roms/SLOF/rtas/reloc.S
 create mode 100644 roms/SLOF/rtas/rtas.lds
 create mode 100644 roms/SLOF/rtas/rtas_call.c
 create mode 100644 roms/SLOF/rtas/rtas_common.S
 create mode 100644 roms/SLOF/rtas/rtas_entry.S

(limited to 'roms/SLOF/rtas')

diff --git a/roms/SLOF/rtas/Makefile.inc b/roms/SLOF/rtas/Makefile.inc
new file mode 100644
index 00000000..4297f86a
--- /dev/null
+++ b/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/roms/SLOF/rtas/flash/block_lists.c b/roms/SLOF/rtas/flash/block_lists.c
new file mode 100644
index 00000000..e632fd0b
--- /dev/null
+++ b/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/roms/SLOF/rtas/flash/block_lists.h b/roms/SLOF/rtas/flash/block_lists.h
new file mode 100644
index 00000000..b24b6506
--- /dev/null
+++ b/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/roms/SLOF/rtas/flash/tmpXXX.update-comments b/roms/SLOF/rtas/flash/tmpXXX.update-comments
new file mode 100644
index 00000000..cd3d1376
--- /dev/null
+++ b/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/roms/SLOF/rtas/reloc.S b/roms/SLOF/rtas/reloc.S
new file mode 100644
index 00000000..e24d293d
--- /dev/null
+++ b/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/roms/SLOF/rtas/rtas.lds b/roms/SLOF/rtas/rtas.lds
new file mode 100644
index 00000000..a5ba1daa
--- /dev/null
+++ b/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/roms/SLOF/rtas/rtas_call.c b/roms/SLOF/rtas/rtas_call.c
new file mode 100644
index 00000000..8c7532c0
--- /dev/null
+++ b/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/roms/SLOF/rtas/rtas_common.S b/roms/SLOF/rtas/rtas_common.S
new file mode 100644
index 00000000..35cd9a9f
--- /dev/null
+++ b/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/roms/SLOF/rtas/rtas_entry.S b/roms/SLOF/rtas/rtas_entry.S
new file mode 100644
index 00000000..74693aa4
--- /dev/null
+++ b/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
-- 
cgit v1.2.3