[OpenBIOS] [RFC 3/3] ppc: RTAS WIP

Andreas Färber andreas.faerber at web.de
Fri Oct 15 00:17:15 CEST 2010


Move RTAS code into an external binary blob.
Implement the display-character token, add some debug output.

The serial_putchar() calls are working now.
Hangs on return of the first RTAS call though.
---
 arch/ppc/build.xml          |   26 ++++++++++++-
 arch/ppc/qemu/init.c        |    7 +++-
 arch/ppc/qemu/kernel.h      |    1 -
 arch/ppc/qemu/methods.c     |   11 +++--
 arch/ppc/qemu/rtas-ldscript |   47 +++++++++++++++++++++++
 arch/ppc/qemu/rtas-tokens.c |   63 ++++++++++++++++++++++++++++++
 arch/ppc/qemu/rtas.S        |   88 +++++++++++++++++++++++++++++++++++++++++++
 arch/ppc/qemu/start.S       |    7 ---
 8 files changed, 236 insertions(+), 14 deletions(-)
 create mode 100644 arch/ppc/qemu/rtas-ldscript
 create mode 100644 arch/ppc/qemu/rtas-tokens.c
 create mode 100644 arch/ppc/qemu/rtas.S

diff --git a/arch/ppc/build.xml b/arch/ppc/build.xml
index 9778a43..f893abc 100644
--- a/arch/ppc/build.xml
+++ b/arch/ppc/build.xml
@@ -89,6 +89,22 @@
 	$(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/mol/kernel.c, "  CC    $(TARGET_DIR)$@")]]></rule>
  </executable>
 
+
+ <executable name="target/include/qemu-rtas.h" target="target" condition="QEMU">
+  <rule><![CDATA[
+	$(call quiet-command,true, "  GEN   $(TARGET_DIR)$@")
+	@echo "static const char rtas_binary[] = {" > $@
+	@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+					| sed 's/0x  ,//g' >> $@
+	@echo "};" >> $@]]></rule>
+  <external-object source="rtas-qemu.bin"/>
+ </executable>
+
+ <executable name="target/arch/ppc/qemu/methods.o" target="target" condition="QEMU">
+  <rule><![CDATA[ $(SRCDIR)/arch/ppc/qemu/methods.c $(ODIR)/target/include/qemu-rtas.h
+	$(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -I$(SRCDIR)/arch/ppc -c -o $@ $(SRCDIR)/arch/ppc/qemu/methods.c, "  CC    $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
  <!-- END OF HACK ALERT -->
 
  <library name="briq" target="target" type="static" condition="BRIQ">
@@ -123,7 +139,7 @@
   <object source="qemu/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
   <external-object source="target/arch/ppc/qemu/kernel.o"/>
   <object source="qemu/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
-  <object source="qemu/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+  <external-object source="target/arch/ppc/qemu/methods.o"/>
   <object source="qemu/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
   <object source="qemu/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
  </library>
@@ -193,6 +209,14 @@
   <external-object source="libgcc.a"/>
  </executable>
 
+ <executable name="rtas-qemu.bin" target="target" condition="QEMU">
+  <rule>
+	$(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/$(ARCH)/qemu/rtas-ldscript -o $@ --whole-archive --pic-executable $^,"  LINK  $(TARGET_DIR)$@")</rule>
+  <object source="qemu/rtas.S"/>
+  <object source="qemu/rtas-tokens.c" flags="-std=c99 -fpic -DPIC"/>
+  <external-object source="libgcc.a"/>
+ </executable>
+
  <executable name="openbios-mol.elf" target="target" condition="MOL">
   <rule>
 	$(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^,"  LINK  $(TARGET_DIR)$@")
diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c
index 2b0b891..6d72386 100644
--- a/arch/ppc/qemu/init.c
+++ b/arch/ppc/qemu/init.c
@@ -579,6 +579,10 @@ static void kvm_of_init(void)
 	fword("finish-device");
 }
 
+#ifdef CONFIG_RTAS
+extern int rtas_size;
+#endif
+
 void
 arch_of_init( void )
 {
@@ -745,10 +749,11 @@ arch_of_init( void )
 		printk("Warning: No /rtas node\n");
 	else {
 		unsigned long size = 0x1000;
-		while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+		while ( size < rtas_size )
 			size *= 2;
 		set_property( ph, "rtas-size", (char*)&size, sizeof(size) );
 		set_int_property(ph, "rtas-version", 1);
+		set_int_property(ph, "display-character", 1);
 	}
 #endif
 
diff --git a/arch/ppc/qemu/kernel.h b/arch/ppc/qemu/kernel.h
index e8ae364..6ae928f 100644
--- a/arch/ppc/qemu/kernel.h
+++ b/arch/ppc/qemu/kernel.h
@@ -21,7 +21,6 @@ extern void		exit( int status );
 
 /* start.S */
 extern void 		flush_icache_range( char *start, char *stop );
-extern char		of_rtas_start[], of_rtas_end[];
 extern void             call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry );
 
 /* methods.c */
diff --git a/arch/ppc/qemu/methods.c b/arch/ppc/qemu/methods.c
index f27d532..00444a9 100644
--- a/arch/ppc/qemu/methods.c
+++ b/arch/ppc/qemu/methods.c
@@ -33,24 +33,27 @@
 #ifdef CONFIG_RTAS
 DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
 
+#include "qemu-rtas.h"
+#define RTAS_DATA_SIZE 0x1000
+const int rtas_size = RTAS_DATA_SIZE + sizeof(rtas_binary);
+
 /* ( physbase -- rtas_callback ) */
 static void
 rtas_instantiate( void )
 {
 	ucell physbase = POP();
-	ucell s=0x1000, size = (ucell)of_rtas_end - (ucell)of_rtas_start;
+	ucell s=0x1000, size = RTAS_DATA_SIZE + sizeof(rtas_binary);
 	unsigned long virt;
 
 	while( s < size )
 		s += 0x1000;
 	virt = ofmem_claim_virt( 0, s, 0x1000 );
 	ofmem_map( physbase, virt, s, -1 );
-	memcpy( (char*)virt, of_rtas_start, size );
+	memcpy( (char*)virt + RTAS_DATA_SIZE, rtas_binary, rtas_size - RTAS_DATA_SIZE );
 
-	printk("RTAS instantiated at %08x\n", physbase );
 	flush_icache_range( (char*)virt, (char*)virt + size );
 
-	PUSH( physbase );
+	PUSH( physbase + RTAS_DATA_SIZE );
 }
 
 NODE_METHODS( rtas ) = {
diff --git a/arch/ppc/qemu/rtas-ldscript b/arch/ppc/qemu/rtas-ldscript
new file mode 100644
index 0000000..f596eb7
--- /dev/null
+++ b/arch/ppc/qemu/rtas-ldscript
@@ -0,0 +1,47 @@
+OUTPUT_FORMAT(binary)
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+	_start = .;
+
+	/*. = 0x1000;*/
+	.rtasentry ALIGN(4096): { *(.rtasentry) }
+
+	/* Normal sections */
+	.text ALIGN(4096): {
+		*(.text)
+		*(.text.*)
+	}
+
+	.rodata ALIGN(4096): {
+		_rodata = .;
+		*(.rodata)
+		*(.rodata.*)
+		*(.note.ELFBoot)
+	}
+	.data ALIGN(4096): {
+		_data = .;
+		*(.data)
+		*(.data.*)
+		_edata = .;
+	}
+
+	.bss ALIGN(4096): {
+		_bss = .;
+		*(.sbss)
+		*(.sbss.*)
+		*(.bss)
+		*(.bss.*)
+		*(COMMON)
+		_ebss = .;
+	}
+
+	. = ALIGN(4096);
+	_end = .;
+
+	/* We discard .note sections other than .note.ELFBoot,
+	 * because some versions of GCC generate useless ones. */
+
+	/DISCARD/ : { *(.comment*) *(.note.*) }
+}
diff --git a/arch/ppc/qemu/rtas-tokens.c b/arch/ppc/qemu/rtas-tokens.c
new file mode 100644
index 0000000..f251716
--- /dev/null
+++ b/arch/ppc/qemu/rtas-tokens.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 Andreas Färber <andreas.faerber at web.de>
+ */
+
+#define RTAS_MAX_ARGS	10
+
+typedef struct rtas_args {
+	unsigned long	token;
+	long			nargs;
+	long			nret;
+	unsigned long	args[RTAS_MAX_ARGS];
+} rtas_args_t;
+
+void rtas_interface(rtas_args_t*, void*);
+
+/* drivers/escc.h */
+#define IO_ESCC_OFFSET  0x00013000
+/* drivers/escc.c */
+#define CTRL(addr) (*(volatile unsigned char *)(addr))
+#define DATA(addr) (*(volatile unsigned char *)(addr + 16))
+#define Tx_BUF_EMP      0x4     /* Tx Buffer empty */
+
+/*static void uart_putchar(int port, unsigned char c)
+{
+    while (!(CTRL(port) & Tx_BUF_EMP))
+        ;
+    DATA(port) = c;
+}*/
+
+/*void serial_putchar(char);*/
+
+static void serial_putchar(char c)
+{
+	unsigned long addr = 0x80800000;
+	volatile unsigned char *serial_dev = (unsigned char *)addr + IO_ESCC_OFFSET + 0x20;
+	//uart_putchar((int)serial_dev, c);
+	volatile unsigned char * port = serial_dev;
+    while (!(CTRL(port) & Tx_BUF_EMP))
+        ;
+    DATA(port) = c;
+}
+
+enum {
+	DISPLAY_CHARACTER = 1,
+};
+
+void rtas_interface(rtas_args_t* params, void* privateData)
+{
+	switch (params->token) {
+		case DISPLAY_CHARACTER: {
+			serial_putchar((char)params->args[0]);
+			serial_putchar('x');
+			params->args[params->nargs] = 0;
+			break;
+		}
+		default:
+			serial_putchar('.');
+			params->args[params->nargs] = -1;
+			break;
+	}
+	serial_putchar('\r');
+	serial_putchar('\n');
+}
diff --git a/arch/ppc/qemu/rtas.S b/arch/ppc/qemu/rtas.S
new file mode 100644
index 0000000..35037c4
--- /dev/null
+++ b/arch/ppc/qemu/rtas.S
@@ -0,0 +1,88 @@
+/*
+ * RTAS blob for QEMU
+ * Copyright (c) 2010 Andreas Färber <andreas.faerber at web.de>
+ */
+
+#include "asm/asmdefs.h"
+
+/*.data
+.space xxx, 0 */
+
+.section .rtasentry,"ax"
+	/* real mode! */
+GLOBL(_entry):
+	/*
+	 * r3 = arguments
+	 * r4 = private memory
+	 */
+	stw r1, 0(r4)
+	stw r2, 4(r4)
+
+	stwu r1, -12(r1)
+	stw r4, 8(r1)
+	mflr r0
+	stw r0, 4(r1)
+
+	stw r13,  8(r4)
+	stw r14, 12(r4)
+	stw r15, 16(r4)
+	stw r16, 20(r4)
+	stw r17, 24(r4)
+	stw r18, 28(r4)
+	stw r19, 32(r4)
+	stw r20, 36(r4)
+	stw r21, 40(r4)
+	stw r22, 44(r4)
+	stw r23, 48(r4)
+	stw r24, 52(r4)
+	stw r25, 56(r4)
+	stw r26, 60(r4)
+	stw r27, 64(r4)
+	stw r28, 68(r4)
+	stw r29, 72(r4)
+	stw r30, 76(r4)
+	stw r31, 80(r4)
+
+	mfcr r2
+	stw r2, 84(r4)
+
+	bl rtas_interface
+
+	lwz r0, 4(r1)
+	mtlr r0
+	lwz	r4, 8(r1)
+//	lwz	r1, 0(r1)
+
+	lwz r2, 84(r4)
+	mtcr r2
+
+	lwz r13,  8(r4)
+	lwz r14, 12(r4)
+	lwz r15, 16(r4)
+	lwz r16, 20(r4)
+	lwz r17, 24(r4)
+	lwz r18, 28(r4)
+	lwz r19, 32(r4)
+	lwz r20, 36(r4)
+	lwz r21, 40(r4)
+	lwz r22, 44(r4)
+	lwz r23, 48(r4)
+	lwz r24, 52(r4)
+	lwz r25, 56(r4)
+	lwz r26, 60(r4)
+	lwz r27, 64(r4)
+	lwz r28, 68(r4)
+	lwz r29, 72(r4)
+	lwz r30, 76(r4)
+	lwz r31, 80(r4)
+
+	lwz r2, 4(r4)
+	lwz r1, 0(r4)
+
+	blr
+
+/* libgcc.a */
+.globl	__divide_error
+__divide_error:
+1:	nop
+	b 1b
diff --git a/arch/ppc/qemu/start.S b/arch/ppc/qemu/start.S
index c995581..d9c61a7 100644
--- a/arch/ppc/qemu/start.S
+++ b/arch/ppc/qemu/start.S
@@ -522,13 +522,6 @@ GLOBL(of_client_callback):
 
 	blr
 
-	/* rtas glue (must be reloctable) */
-GLOBL(of_rtas_start):
-	/* r3 = argument buffer, r4 = of_rtas_start */
-	/* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
-	blr
-GLOBL(of_rtas_end):
-
 
 #define CACHE_LINE_SIZE         32
 #define LG_CACHE_LINE_SIZE      5
-- 
1.7.3




More information about the OpenBIOS mailing list