Index: arch/sparc64/include/console.h
===================================================================
--- arch/sparc64/include/console.h	(revision 80bff3426b0c5ce4e21f4e7f42a392db6cfc0d9a)
+++ arch/sparc64/include/console.h	(revision 65fb232f572bc21a808b3769b83436d82fe4a950)
@@ -30,4 +30,5 @@
 #define __sparc64_CONSOLE_H__
 
+extern void kofwinput(void *arg);
 extern void ofw_sparc64_console_init(void);
 
Index: arch/sparc64/src/console.c
===================================================================
--- arch/sparc64/src/console.c	(revision 80bff3426b0c5ce4e21f4e7f42a392db6cfc0d9a)
+++ arch/sparc64/src/console.c	(revision 65fb232f572bc21a808b3769b83436d82fe4a950)
@@ -33,10 +33,22 @@
 #include <arch/asm.h>
 #include <arch/register.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <proc/thread.h>
+#include <synch/mutex.h>
 
 static void ofw_sparc64_putchar(chardev_t *d, const char ch);
+static char ofw_sparc64_getchar(chardev_t *d);
+static void ofw_sparc64_suspend(chardev_t *d);
+static void ofw_sparc64_resume(chardev_t *d);
+
+mutex_t canwork;
 
 static chardev_t ofw_sparc64_console;
 static chardev_operations_t ofw_sparc64_console_ops = {
-	.write = ofw_sparc64_putchar
+	.write = ofw_sparc64_putchar,
+	.read = ofw_sparc64_getchar,
+	.resume = ofw_sparc64_resume,
+	.suspend = ofw_sparc64_suspend
 };
 
@@ -44,10 +56,13 @@
 {
 	chardev_initialize("ofw_sparc64_console", &ofw_sparc64_console, &ofw_sparc64_console_ops);
+	stdin = &ofw_sparc64_console;
 	stdout = &ofw_sparc64_console;
+	mutex_initialize(&canwork);
 }
 
-/** Print one character.
+/** Write one character.
  *
- * @param ch Character to be printed.
+ * @param d Character device (ignored).
+ * @param ch Character to be written.
  */
 void ofw_sparc64_putchar(chardev_t *d, const char ch)
@@ -69,2 +84,62 @@
 	pstate_write(pstate.value);
 }
+
+/** Read one character.
+ *
+ * The call is non-blocking.
+ *
+ * @param d Character device (ignored).
+ * @return Character read or zero if no character was read.
+ */
+char ofw_sparc64_getchar(chardev_t *d)
+{
+	char ch;
+	pstate_reg_t pstate;
+
+	/*
+	 * 32-bit OpenFirmware depends on PSTATE.AM bit set.
+	 */	
+	pstate.value = pstate_read();
+	pstate.am = true;
+	pstate_write(pstate.value);
+
+	ch = ofw_getchar();
+	
+	pstate.am = false;
+	pstate_write(pstate.value);
+	
+	return ch;
+}
+
+void ofw_sparc64_suspend(chardev_t *d)
+{
+	mutex_lock(&canwork);
+}
+
+void ofw_sparc64_resume(chardev_t *d)
+{
+	mutex_unlock(&canwork);
+}
+
+/** Kernel thread for pushing characters read from OFW to input buffer.
+ *
+ * @param arg Ignored.
+ */
+void kofwinput(void *arg)
+{
+
+	while (1) {
+		char ch = 0;
+		
+		mutex_lock(&canwork);
+		mutex_unlock(&canwork);
+		
+		ch = ofw_sparc64_getchar(NULL);
+		if (ch) {
+			if (ch == '\r')
+				ch = '\n';
+			chardev_push_character(&ofw_sparc64_console, ch);
+		}
+		thread_usleep(25000);
+	}
+}
Index: arch/sparc64/src/sparc64.c
===================================================================
--- arch/sparc64/src/sparc64.c	(revision 80bff3426b0c5ce4e21f4e7f42a392db6cfc0d9a)
+++ arch/sparc64/src/sparc64.c	(revision 65fb232f572bc21a808b3769b83436d82fe4a950)
@@ -28,8 +28,9 @@
 
 #include <arch.h>
-#include <print.h>
+#include <debug.h>
 #include <arch/trap/trap.h>
 #include <arch/console.h>
 #include <arch/drivers/tick.h>
+#include <proc/thread.h>
 
 void arch_pre_mm_init(void)
@@ -51,4 +52,13 @@
 void arch_post_smp_init(void)
 {
+	thread_t *t;
+	
+	/*
+	 * Create thread that reads characters from OFW's input.
+	 */
+	t = thread_create(kofwinput, NULL, TASK, 0);
+	if (!t)
+		panic("cannot create kofwinput\n");
+	thread_ready(t);
 }
 
Index: genarch/include/ofw/ofw.h
===================================================================
--- genarch/include/ofw/ofw.h	(revision 80bff3426b0c5ce4e21f4e7f42a392db6cfc0d9a)
+++ genarch/include/ofw/ofw.h	(revision 65fb232f572bc21a808b3769b83436d82fe4a950)
@@ -56,4 +56,5 @@
 extern __native ofw_call(const char *service, const int nargs, const int nret, ...);
 extern void ofw_putchar(const char ch);
+extern char ofw_getchar(void);
 extern phandle ofw_find_device(const char *name);
 extern int ofw_get_property(const phandle device, const char *name, void *buf, const int buflen);
Index: genarch/src/ofw/ofw.c
===================================================================
--- genarch/src/ofw/ofw.c	(revision 80bff3426b0c5ce4e21f4e7f42a392db6cfc0d9a)
+++ genarch/src/ofw/ofw.c	(revision 65fb232f572bc21a808b3769b83436d82fe4a950)
@@ -36,4 +36,5 @@
 
 phandle ofw_chosen;
+ihandle ofw_stdin;
 ihandle ofw_stdout;
 
@@ -44,6 +45,9 @@
 		ofw_done();
 	
+	if (ofw_get_property(ofw_chosen, "stdin",  &ofw_stdin, sizeof(ofw_stdin)) <= 0)
+		ofw_stdin = 0;
+		
 	if (ofw_get_property(ofw_chosen, "stdout",  &ofw_stdout, sizeof(ofw_stdout)) <= 0)
-		ofw_stdout = 0;
+		ofw_stdout = 0;	
 }
 
@@ -85,4 +89,23 @@
 }
 
+/** Read character from OFW's input.
+ *
+ * This call is non-blocking.
+ *
+ * @return 0 if no character was read, character read otherwise.
+ */
+char ofw_getchar(void)
+{
+	char ch;
+
+	if (ofw_stdin == 0)
+		return 0;
+	
+	if (ofw_call("read", 3, 1, ofw_stdin, &ch, 1) == 1)
+		return ch;
+	else
+		return 0;
+}
+
 phandle ofw_find_device(const char *name)
 {
Index: generic/include/console/chardev.h
===================================================================
--- generic/include/console/chardev.h	(revision 80bff3426b0c5ce4e21f4e7f42a392db6cfc0d9a)
+++ generic/include/console/chardev.h	(revision 65fb232f572bc21a808b3769b83436d82fe4a950)
@@ -64,5 +64,5 @@
 			       chardev_t *chardev, 
 			       chardev_operations_t *op);
-void chardev_push_character(chardev_t *chardev, __u8 ch);
+extern void chardev_push_character(chardev_t *chardev, __u8 ch);
 
 #endif /* __CHARDEV_H__ */
