[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