Add just enough Open Firmware support for an output console.
authorDavid Given <dg@cowlark.com>
Sat, 12 Nov 2016 21:09:54 +0000 (22:09 +0100)
committerDavid Given <dg@cowlark.com>
Sat, 12 Nov 2016 21:09:54 +0000 (22:09 +0100)
plat/qemuppc/boot.s
plat/qemuppc/libsys/_sys_rawread.s [deleted file]
plat/qemuppc/libsys/_sys_rawwrite.s [deleted file]
plat/qemuppc/libsys/libsys.h
plat/qemuppc/libsys/openfirmware.c [new file with mode: 0644]

index dbd61ec..2dd9a4c 100644 (file)
@@ -30,6 +30,9 @@ begtext:
        ! sp+4            ptr to argv
        ! sp              ptr to env
 
+       li32 r3, __openfirmware_ptr
+       stw r5, 0(r3)
+
        li32 r3, envp
        stwu r3, -4(sp)
 
@@ -39,6 +42,7 @@ begtext:
        li32 r3, 1 ! argc
        stwu r3, -4(sp)
        
+       bl _openfirmware_init
        bl __m_a_i_n
        ! falls through
 
@@ -50,6 +54,15 @@ __exit:
 EXIT:
        b EXIT
 
+.define _openfirmware_call
+.extern _openfirmware_call
+_openfirmware_call:
+       lwz r3, 0(sp)
+       li32 r4, __openfirmware_ptr
+       lwz r4, 0(r4)
+       mtspr ctr, r4
+       bcctr 20, 0, 0
+
 ! Define symbols at the beginning of our various segments, so that we can find
 ! them. (Except .text, which has already been done.)
 
@@ -72,3 +85,4 @@ exename: .asciz 'qemuppc.img'
 .define .trppc, .ignmask
 .comm .trppc, 4              ! ptr to user trap handler
 .comm .ignmask, 4            ! user trap ignore mask 
+.comm __openfirmware_ptr, 4      ! OpenFirmware entry point
diff --git a/plat/qemuppc/libsys/_sys_rawread.s b/plat/qemuppc/libsys/_sys_rawread.s
deleted file mode 100644 (file)
index 1f2cd9d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-#include "powerpc.h"
-
-! Declare segments (the order is important).
-
-.sect .text
-.sect .rom
-.sect .data
-.sect .bss
-
-.sect .text
-
-! Reads a single byte.
-
-.define __sys_rawread
-__sys_rawread:
-       li32 r3, 0
-       bclr ALWAYS, 0, 0
-       
\ No newline at end of file
diff --git a/plat/qemuppc/libsys/_sys_rawwrite.s b/plat/qemuppc/libsys/_sys_rawwrite.s
deleted file mode 100644 (file)
index e9a1cc7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-#include "powerpc.h"
-
-! Declare segments (the order is important).
-
-.sect .text
-.sect .rom
-.sect .data
-.sect .bss
-
-.sect .text
-
-! Writes a single byte to the console.
-
-.define __sys_rawwrite
-.extern __sys_rawwrite
-
-__sys_rawwrite:
-       bclr ALWAYS, 0, 0
-       
\ No newline at end of file
index d4095ca..cf9878b 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef LIBSYS_H
 #define LIBSYS_H
 
+extern uint32_t openfirmware_call(void* array);
+
 extern void _sys_rawwrite(unsigned char b);
 extern unsigned char _sys_rawread(void);
 
diff --git a/plat/qemuppc/libsys/openfirmware.c b/plat/qemuppc/libsys/openfirmware.c
new file mode 100644 (file)
index 0000000..ad0c282
--- /dev/null
@@ -0,0 +1,80 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libsys.h"
+
+static void* stdout_handle;
+
+static void* of_finddevice(const char* name)
+{
+    struct
+    {
+        const char* method;
+        int ins, outs;
+        const char* name;
+        void* phandle;
+    } args;
+
+    args.method = "finddevice";
+    args.ins = 1;
+    args.outs = 1;
+    args.name = name;
+    openfirmware_call(&args);
+    return args.phandle;
+}
+
+static int of_getprop(void* phandle, const char* name, void* dest, int destlen)
+{
+    struct
+    {
+        const char* method;
+        int ins, outs;
+        void* phandle;
+        const char* name;
+        void* dest;
+        int destlen;
+        int flag;
+    } args;
+
+    args.method = "getprop";
+    args.ins = 4;
+    args.outs = 1;
+    args.phandle = phandle;
+    args.name = name;
+    args.dest = dest;
+    args.destlen = destlen;
+    openfirmware_call(&args);
+    return args.flag;
+}
+
+void openfirmware_init(void)
+{
+    void* chosen = of_finddevice("/chosen");
+    of_getprop(chosen, "stdout", &stdout_handle, sizeof(stdout_handle));
+}
+
+unsigned char _sys_rawread(void)
+{
+    return 0;
+}
+
+void _sys_rawwrite(unsigned char c)
+{
+    struct
+    {
+        const char* method;
+        int ins, outs;
+        void* ihandle;
+        void* address;
+        int len;
+        int actual;
+    } args;
+
+    args.method = "write";
+    args.ins = 3;
+    args.outs = 1;
+    args.ihandle = stdout_handle;
+    args.address = &c;
+    args.len = 1;
+    openfirmware_call(&args);
+}