Index: .bzrignore
===================================================================
--- .bzrignore	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ .bzrignore	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -33,5 +33,5 @@
 uspace/app/kill/kill
 uspace/app/killall/killall
-uspace/app/klog/klog
+uspace/app/kio/kio
 uspace/app/loc/loc
 uspace/app/logset/logset
@@ -82,5 +82,5 @@
 uspace/dist/app/kill
 uspace/dist/app/killall
-uspace/dist/app/klog
+uspace/dist/app/kio
 uspace/dist/app/loc
 uspace/dist/app/logset
@@ -279,2 +279,10 @@
 uspace/app/viewer/viewer
 uspace/dist/app/viewer
+uspace/app/hdisk/hdisk
+uspace/dist/app/hdisk
+uspace/app/untar/untar
+uspace/dist/app/untar
+uspace/lib/posix/redefs-hide-libc-symbols.list
+uspace/lib/posix/redefs-show-posix-symbols.list
+uspace/srv/klog/klog
+uspace/dist/srv/klog
Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ HelenOS.config	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -71,4 +71,5 @@
 @ "beagleboardxm" BeagleBoard-xM
 @ "beaglebone" BeagleBone
+@ "raspberrypi" Raspberry Pi
 ! [PLATFORM=arm32] MACHINE (choice)
 
@@ -108,4 +109,7 @@
 ! [PLATFORM=arm32&MACHINE=integratorcp] PROCESSOR (choice)
 
+% CPU type
+@ "arm1176" ARM1176
+! [PLATFORM=arm32&MACHINE=raspberrypi] PROCESSOR (choice)
 
 # Add more ARMv4 CPUs
@@ -118,4 +122,9 @@
 @ "armv5" ARMv5
 ! [PLATFORM=arm32&(PROCESSOR=arm926ej_s)] PROCESSOR_ARCH (choice)
+
+# Add more ARMv6 CPUs
+% CPU arch
+@ "armv6" ARMv6
+! [PLATFORM=arm32&(PROCESSOR=arm1176)] PROCESSOR_ARCH (choice)
 
 # Add more ARMv7-A CPUs
@@ -467,5 +476,5 @@
 % Output device class
 @ "generic" Monitor or serial line
-! [PLATFORM=arm32&(MACHINE=gta02|MACHINE=integratorcp|MACHINE=beagleboardxm|MACHINE=beaglebone)] CONFIG_HID_OUT (choice)
+! [PLATFORM=arm32&(MACHINE=gta02|MACHINE=integratorcp|MACHINE=beagleboardxm|MACHINE=beaglebone|MACHINE=raspberrypi)] CONFIG_HID_OUT (choice)
 
 % Output device class
@@ -498,6 +507,6 @@
 ! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=serial)&PLATFORM=ia64&MACHINE=i460GX] CONFIG_NS16550 (y/n)
 
-% Support for ARM926 on-chip UART
-! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=integratorcp] CONFIG_ARM926_UART (y/n)
+% Support for PL011 UART
+! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&(MACHINE=integratorcp|MACHINE=raspberrypi)] CONFIG_PL011_UART (y/n)
 
 % Support for Samsung S3C24XX on-chip UART
@@ -519,4 +528,7 @@
 ! [PLATFORM=sparc32&MACHINE=leon3] CONFIG_GRLIB_IRQMP (y)
 
+% Support for BCM2835 mailbox
+! [PLATFORM=arm32&MACHINE=raspberrypi] CONFIG_BCM2835_MAILBOX (y/n)
+
 % Support for i8042 controller
 ! [CONFIG_PC_KBD=y] CONFIG_I8042 (y)
@@ -538,5 +550,5 @@
 
 % Serial line input module
-! [CONFIG_DSRLNIN=y|(PLATFORM=sparc32)|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=arm32&MACHINE=integratorcp&CONFIG_ARM926_UART=y)|(PLATFORM=arm32&MACHINE=beaglebone&CONFIG_OMAP_UART=y)|(PLATFORM=arm32&MACHINE=beagleboardxm&CONFIG_OMAP_UART=y)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)] CONFIG_SRLN (y)
+! [CONFIG_DSRLNIN=y|(PLATFORM=sparc32)|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=arm32&MACHINE=integratorcp&CONFIG_PL011_UART=y)|(PLATFORM=arm32&MACHINE=beaglebone&CONFIG_OMAP_UART=y)|(PLATFORM=arm32&MACHINE=beagleboardxm&CONFIG_OMAP_UART=y)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)|(PLATFORM=arm32&MACHINE=raspberrypi&CONFIG_PL011_UART=y)] CONFIG_SRLN (y)
 
 % EGA support
Index: abi/include/abi/ipc/event.h
===================================================================
--- abi/include/abi/ipc/event.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ abi/include/abi/ipc/event.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -38,10 +38,12 @@
 /** Global events */
 typedef enum event_type {
-	/** New data available in kernel log */
-	EVENT_KLOG = 0,
+	/** New data available in kernel character buffer */
+	EVENT_KIO = 0,
 	/** Returning from kernel console to uspace */
 	EVENT_KCONSOLE,
 	/** A task/thread has faulted and will be terminated */
 	EVENT_FAULT,
+	/** New data available in kernel log */
+	EVENT_KLOG,
 	EVENT_END
 } event_type_t;
Index: abi/include/abi/kio.h
===================================================================
--- abi/include/abi/kio.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ abi/include/abi/kio.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_KIO_H_
+#define ABI_KIO_H_
+
+enum {
+	KIO_UNKNOW,
+	KIO_WRITE,
+	KIO_UPDATE,
+	KIO_COMMAND
+};
+
+#endif
+
+/** @}
+ */
Index: abi/include/abi/klog.h
===================================================================
--- abi/include/abi/klog.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ abi/include/abi/klog.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jakub Jermar
+ * Copyright (c) 2014 Martin Sucha
  * All rights reserved.
  *
@@ -36,10 +36,8 @@
 #define ABI_KLOG_H_
 
-enum {
-	KLOG_UNKNOW,
+typedef enum {
 	KLOG_WRITE,
-	KLOG_UPDATE,
-	KLOG_COMMAND
-};
+	KLOG_READ
+} klog_operation_t;
 
 #endif
Index: abi/include/abi/log.h
===================================================================
--- abi/include/abi/log.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ abi/include/abi/log.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericlog
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_LOG_H_
+#define ABI_LOG_H_
+
+/** Log message level. */
+typedef enum {
+	/** Fatal error, program is not able to recover at all. */
+	LVL_FATAL,
+	/** Serious error but the program can recover from it. */
+	LVL_ERROR,
+	/** Easily recoverable problem. */
+	LVL_WARN,
+	/** Information message that ought to be printed by default. */
+	LVL_NOTE,
+	/** Debugging purpose message. */
+	LVL_DEBUG,
+	/** More detailed debugging message. */
+	LVL_DEBUG2,
+	
+	/** For checking range of values */
+	LVL_LIMIT
+} log_level_t;
+
+/* Who is the source of the message? */
+typedef enum {
+	LF_OTHER = 0,
+	LF_USPACE,
+	LF_ARCH
+} log_facility_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/abi/syscall.h
===================================================================
--- abi/include/abi/syscall.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ abi/include/abi/syscall.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -37,5 +37,5 @@
 
 typedef enum {
-	SYS_KLOG = 0,
+	SYS_KIO = 0,
 	SYS_TLS_SET = 1,  /* Hardcoded for AMD64, IA-32 (fibril.S in uspace) */
 	
@@ -99,4 +99,6 @@
 	SYS_DEBUG_ACTIVATE_CONSOLE,
 	
+	SYS_KLOG,
+	
 	SYSCALL_END
 } syscall_t;
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/Makefile.common	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -96,5 +96,6 @@
 	$(USPACE_PATH)/srv/devman/devman \
 	$(USPACE_PATH)/srv/fs/locfs/locfs \
-	$(USPACE_PATH)/srv/hid/compositor/compositor
+	$(USPACE_PATH)/srv/hid/compositor/compositor \
+	$(USPACE_PATH)/srv/klog/klog
 
 RD_SRVS_NON_ESSENTIAL = \
@@ -161,5 +162,5 @@
 	$(USPACE_PATH)/app/bdsh/bdsh \
 	$(USPACE_PATH)/app/getterm/getterm \
-	$(USPACE_PATH)/app/klog/klog \
+	$(USPACE_PATH)/app/kio/kio \
 	$(USPACE_PATH)/app/vlaunch/vlaunch \
 	$(USPACE_PATH)/app/vterm/vterm
Index: boot/arch/arm32/Makefile.inc
===================================================================
--- boot/arch/arm32/Makefile.inc	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/arch/arm32/Makefile.inc	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,4 +43,12 @@
 endif
 
+ifeq ($(MACHINE), raspberrypi)
+	BOOT_OUTPUT = image.boot
+	POST_OUTPUT = $(ROOT_PATH)/uImage.bin	
+	LADDR = 0x00008000
+	SADDR = 0x00008000
+	POSTBUILD = Makefile.uboot	     
+endif
+
 BFD_NAME = elf32-littlearm
 BFD_OUTPUT = $(BFD_NAME)
Index: boot/arch/arm32/include/arch.h
===================================================================
--- boot/arch/arm32/include/arch.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/arch/arm32/include/arch.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -46,4 +46,6 @@
 #elif defined MACHINE_beaglebone
 #define BOOT_BASE       0x80000000
+#elif defined MACHINE_raspberrypi
+#define BOOT_BASE	0x00008000
 #else
 #define BOOT_BASE	0x00000000
Index: boot/arch/arm32/include/main.h
===================================================================
--- boot/arch/arm32/include/main.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/arch/arm32/include/main.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -75,4 +75,24 @@
 #define ICP_SCONS_ADDR		0x16000000
 
+/** Raspberry PI serial console registers */
+#define BCM2835_UART0_BASE	0x20201000
+#define BCM2835_UART0_DR	(BCM2835_UART0_BASE + 0x00)
+#define BCM2835_UART0_FR	(BCM2835_UART0_BASE + 0x18)
+#define BCM2835_UART0_ILPR	(BCM2835_UART0_BASE + 0x20)
+#define BCM2835_UART0_IBRD	(BCM2835_UART0_BASE + 0x24)
+#define BCM2835_UART0_FBRD	(BCM2835_UART0_BASE + 0x28)
+#define BCM2835_UART0_LCRH	(BCM2835_UART0_BASE + 0x2C)
+#define BCM2835_UART0_CR	(BCM2835_UART0_BASE + 0x30)
+#define BCM2835_UART0_ICR	(BCM2835_UART0_BASE + 0x44)
+
+#define BCM2835_UART0_FR_TXFF	(1 << 5)
+#define BCM2835_UART0_LCRH_FEN	(1 << 4)
+#define BCM2835_UART0_LCRH_WL8	((1 << 5) | (1 << 6))
+#define BCM2835_UART0_CR_UARTEN	(1 << 0)
+#define BCM2835_UART0_CR_TXE	(1 << 8)
+#define BCM2835_UART0_CR_RXE	(1 << 9)
+
+
+
 extern void bootstrap(void);
 
Index: boot/arch/arm32/include/mm.h
===================================================================
--- boot/arch/arm32/include/mm.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/arch/arm32/include/mm.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -68,4 +68,8 @@
 #define AM335x_RAM_END     0xC0000000
 
+/** Start of ram memory on BCM2835 */
+#define BCM2835_RAM_START   0
+/** End of ram memory on BCM2835 */
+#define BCM2835_RAM_END     0x20000000
 
 /* Page table level 0 entry - "section" format is used
Index: boot/arch/arm32/src/mm.c
===================================================================
--- boot/arch/arm32/src/mm.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/arch/arm32/src/mm.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -116,4 +116,7 @@
 	if (address >= AM335x_RAM_START && address < AM335x_RAM_END)
 		return 1;
+#elif defined MACHINE_raspberrypi
+	if (address < BCM2835_RAM_END)
+		return 1;
 #endif
 	return address * 0;
Index: boot/arch/arm32/src/putchar.c
===================================================================
--- boot/arch/arm32/src/putchar.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ boot/arch/arm32/src/putchar.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -122,4 +122,46 @@
 #endif
 
+#ifdef MACHINE_raspberrypi
+
+static int raspi_init;
+
+static inline void write32(uint32_t addr, uint32_t data)
+{
+	*(volatile uint32_t *)(addr) = data;
+}
+
+static inline uint32_t read32(uint32_t addr)
+{
+	return *(volatile uint32_t *)(addr);
+}
+
+static void scons_init_raspi(void)
+{
+	write32(BCM2835_UART0_CR, 0x0);		/* Disable UART */
+	write32(BCM2835_UART0_ICR, 0x7f);	/* Clear interrupts */
+	write32(BCM2835_UART0_IBRD, 1);		/* Set integer baud rate */
+	write32(BCM2835_UART0_FBRD, 40);	/* Set fractional baud rate */
+	write32(BCM2835_UART0_LCRH,
+		BCM2835_UART0_LCRH_FEN |	/* Enable FIFOs */
+		BCM2835_UART0_LCRH_WL8);	/* Word length: 8 */
+	write32(BCM2835_UART0_CR,
+		BCM2835_UART0_CR_UARTEN |	/* Enable UART */
+		BCM2835_UART0_CR_TXE |		/* Enable TX */
+		BCM2835_UART0_CR_RXE);		/* Enable RX */
+}
+
+static void scons_sendb_raspi(uint8_t byte)
+{
+	if (!raspi_init) {
+		scons_init_raspi();
+		raspi_init = 1;
+	}
+
+	while (read32(BCM2835_UART0_FR) & BCM2835_UART0_FR_TXFF);
+
+	write32(BCM2835_UART0_DR, byte);
+}
+#endif
+
 /** Send a byte to the serial console.
  *
@@ -139,4 +181,7 @@
 #ifdef MACHINE_integratorcp
 	scons_sendb_icp(byte);
+#endif
+#ifdef MACHINE_raspberrypi
+	scons_sendb_raspi(byte);
 #endif
 }
Index: contrib/arch/HelenOS.adl
===================================================================
--- contrib/arch/HelenOS.adl	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/HelenOS.adl	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -22,5 +22,5 @@
 	
 	/* Kernel log */
-	inst klog klog;
+	inst kio kio;
 	
 	[/uspace/lib/libc/bind%ns]
@@ -30,5 +30,5 @@
 	[/uspace/lib/libc/bind%vfs]
 	[/uspace/lib/libc/bind%console]
-	[/uspace/lib/libc/bind%klog]
+	[/uspace/lib/libc/bind%kio]
 	
 	bind ns:kbd to console:kbd;
@@ -58,4 +58,4 @@
 	bind console:sys_console to kernel:sys_console;
 	
-	bind klog:ns to ns:ns;
+	bind kio:ns to ns:ns;
 };
Index: contrib/arch/kernel/kernel.adl
===================================================================
--- contrib/arch/kernel/kernel.adl	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/kernel/kernel.adl	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -3,9 +3,9 @@
  *****************************/
 
-interface sys_klog {
+interface sys_kio {
 		/* Print using kernel facility */
-		sysarg_t sys_klog(int fd, const void *buf, size_t size);
-	protocol:
-		?sys_klog*
+		sysarg_t sys_kio(int fd, const void *buf, size_t size);
+	protocol:
+		?sys_kio*
 };
 
@@ -251,5 +251,5 @@
 frame sys_console {
 	provides:
-		sys_klog sys_klog;
+		sys_kio sys_kio;
 		sys_console sys_console;
 };
@@ -316,5 +316,5 @@
 	inst sys_debug sys_debug;
 	
-	delegate sys_klog to sys_console:sys_klog;
+	delegate sys_kio to sys_console:sys_kio;
 	delegate sys_console to sys_console:sys_console;
 	delegate sys_tls to sys_proc:sys_tls;
Index: contrib/arch/uspace/app/kio/kio.adl
===================================================================
--- contrib/arch/uspace/app/kio/kio.adl	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ contrib/arch/uspace/app/kio/kio.adl	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,9 @@
+frame kio {
+	requires:
+		naming_service ns;
+		[/uspace/lib/libc/requires]
+	initialization:
+		!ns.ipc_m_share_in /* SERVICE_MEM_KIO */
+	protocol:
+		[/uspace/lib/libc/protocol]
+};
Index: ntrib/arch/uspace/app/klog/klog.adl
===================================================================
--- contrib/arch/uspace/app/klog/klog.adl	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ 	(revision )
@@ -1,9 +1,0 @@
-frame klog {
-	requires:
-		naming_service ns;
-		[/uspace/lib/libc/requires]
-	initialization:
-		!ns.ipc_m_share_in /* SERVICE_MEM_KLOG */
-	protocol:
-		[/uspace/lib/libc/protocol]
-};
Index: contrib/arch/uspace/lib/libc/bind
===================================================================
--- contrib/arch/uspace/lib/libc/bind	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/uspace/lib/libc/bind	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,4 +1,4 @@
 /* Bind %% to kernel interfaces */
-bind %%:sys_klog to kernel:sys_klog;
+bind %%:sys_kio to kernel:sys_kio;
 bind %%:sys_tls to kernel:sys_tls;
 bind %%:sys_thread to kernel:sys_thread;
Index: contrib/arch/uspace/lib/libc/protocol
===================================================================
--- contrib/arch/uspace/lib/libc/protocol	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/uspace/lib/libc/protocol	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,5 +1,5 @@
 /* Protocol according to which libc uses kernel syscalls */
 (
-	!sys_klog.sys_klog +
+	!sys_kio.sys_kio +
 	!sys_tls.sys_tls_set +
 	!sys_thread.sys_thread_create +
Index: contrib/arch/uspace/lib/libc/requires
===================================================================
--- contrib/arch/uspace/lib/libc/requires	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/uspace/lib/libc/requires	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,4 +1,4 @@
 /* Kernel interfaces required by libc */
-sys_klog sys_klog;
+sys_kio sys_kio;
 sys_tls sys_tls;
 sys_thread sys_thread;
Index: contrib/arch/uspace/lib/libc/subsume
===================================================================
--- contrib/arch/uspace/lib/libc/subsume	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/uspace/lib/libc/subsume	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,4 +1,4 @@
 /* Subsume %% to kernel interfaces */
-subsume %%:sys_klog to sys_klog;
+subsume %%:sys_kio to sys_kio;
 subsume %%:sys_tls to sys_tls;
 subsume %%:sys_thread to sys_thread;
Index: contrib/arch/uspace/srv/ns/ns.adl
===================================================================
--- contrib/arch/uspace/srv/ns/ns.adl	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ contrib/arch/uspace/srv/ns/ns.adl	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -6,5 +6,5 @@
 		sysarg_t ipc_m_connect_me_to(in sysarg_t service, in sysarg_t arg2, in sysarg_t arg3, in sysarg_t flags);
 		
-		/* Share real-time clock page or klog page */
+		/* Share real-time clock page or kio page */
 		sysarg_t ipc_m_share_in(in sysarg_t as_area_base, in sysarg_t as_area_size, in sysarg_t service);
 		
Index: defaults/arm32/raspberrypi/Makefile.config
===================================================================
--- defaults/arm32/raspberrypi/Makefile.config	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ defaults/arm32/raspberrypi/Makefile.config	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,8 @@
+# Machine type
+MACHINE = raspberrypi
+
+# RAM disk format
+RDFMT = fat
+
+#framebuffer
+CONFIG_FB = n
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -212,4 +212,5 @@
 	generic/src/debug/debug.c \
 	generic/src/interrupt/interrupt.c \
+	generic/src/log/log.c \
 	generic/src/main/main.c \
 	generic/src/main/kinit.c \
Index: kernel/arch/amd64/src/interrupt.c
===================================================================
--- kernel/arch/amd64/src/interrupt.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/amd64/src/interrupt.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -35,4 +35,5 @@
 #include <arch/interrupt.h>
 #include <print.h>
+#include <log.h>
 #include <debug.h>
 #include <panic.h>
@@ -66,16 +67,16 @@
 void istate_decode(istate_t *istate)
 {
-	printf("cs =%0#18" PRIx64 "\trip=%0#18" PRIx64 "\t"
+	log_printf("cs =%0#18" PRIx64 "\trip=%0#18" PRIx64 "\t"
 	    "rfl=%0#18" PRIx64 "\terr=%0#18" PRIx64 "\n",
 	    istate->cs, istate->rip, istate->rflags, istate->error_word);
 	
 	if (istate_from_uspace(istate))
-		printf("ss =%0#18" PRIx64 "\n", istate->ss);
-	
-	printf("rax=%0#18" PRIx64 "\trbx=%0#18" PRIx64 "\t"
+		log_printf("ss =%0#18" PRIx64 "\n", istate->ss);
+	
+	log_printf("rax=%0#18" PRIx64 "\trbx=%0#18" PRIx64 "\t"
 	    "rcx=%0#18" PRIx64 "\trdx=%0#18" PRIx64 "\n",
 	    istate->rax, istate->rbx, istate->rcx, istate->rdx);
 	
-	printf("rsi=%0#18" PRIx64 "\trdi=%0#18" PRIx64 "\t"
+	log_printf("rsi=%0#18" PRIx64 "\trdi=%0#18" PRIx64 "\t"
 	    "rbp=%0#18" PRIx64 "\trsp=%0#18" PRIx64 "\n",
 	    istate->rsi, istate->rdi, istate->rbp,
@@ -83,9 +84,9 @@
 	    (uintptr_t) &istate->rsp);
 	
-	printf("r8 =%0#18" PRIx64 "\tr9 =%0#18" PRIx64 "\t"
+	log_printf("r8 =%0#18" PRIx64 "\tr9 =%0#18" PRIx64 "\t"
 	    "r10=%0#18" PRIx64 "\tr11=%0#18" PRIx64 "\n",
 	    istate->r8, istate->r9, istate->r10, istate->r11);
 	
-	printf("r12=%0#18" PRIx64 "\tr13=%0#18" PRIx64 "\t"
+	log_printf("r12=%0#18" PRIx64 "\tr13=%0#18" PRIx64 "\t"
 	    "r14=%0#18" PRIx64 "\tr15=%0#18" PRIx64 "\n",
 	    istate->r12, istate->r13, istate->r14, istate->r15);
@@ -193,5 +194,6 @@
 		 */
 #ifdef CONFIG_DEBUG
-		printf("cpu%u: spurious interrupt (inum=%u)\n", CPU->id, inum);
+		log(LF_ARCH, LVL_DEBUG, "cpu%u: spurious interrupt (inum=%u)",
+		    CPU->id, inum);
 #endif
 	}
Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/Makefile.inc	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -89,4 +89,8 @@
 endif
 
+ifeq ($(MACHINE),raspberrypi)
+	ARCH_SOURCES += arch/$(KARCH)/src/mach/raspberrypi/raspberrypi.c
+endif
+
 ifeq ($(CONFIG_PL050),y)
 	ARCH_SOURCES += genarch/src/drivers/pl050/pl050.c
Index: kernel/arch/arm32/_link.ld.in
===================================================================
--- kernel/arch/arm32/_link.ld.in	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/_link.ld.in	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -13,4 +13,6 @@
 #elif defined MACHINE_beaglebone
 #define KERNEL_LOAD_ADDRESS 0x80a00000
+#elif defined MACHINE_raspberrypi
+#define KERNEL_LOAD_ADDRESS 0x80a08000
 #else
 #define KERNEL_LOAD_ADDRESS 0x80a00000
Index: kernel/arch/arm32/include/arch/cp15.h
===================================================================
--- kernel/arch/arm32/include/arch/cp15.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/include/arch/cp15.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -231,4 +231,5 @@
 	SCTLR_FAST_IRQ_EN_FLAG       = 1 << 21, /* Disable impl. specific feat*/
 	SCTLR_UNALIGNED_EN_FLAG      = 1 << 22, /* Must be 1 on armv7 */
+	SCTLR_EXTENDED_PT_EN_FLAG    = 1 << 23,
 	SCTLR_IRQ_VECTORS_EN_FLAG    = 1 << 24,
 	SCTLR_BIG_ENDIAN_EXC_FLAG    = 1 << 25,
Index: kernel/arch/arm32/include/arch/mach/integratorcp/integratorcp.h
===================================================================
--- kernel/arch/arm32/include/arch/mach/integratorcp/integratorcp.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/include/arch/mach/integratorcp/integratorcp.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -46,5 +46,6 @@
 #define ICP_IRQC_MAX_IRQ  8
 #define ICP_KBD_IRQ       3
-#define ICP_TIMER_IRQ    6
+#define ICP_TIMER_IRQ     6
+#define ICP_UART0_IRQ     1
 
 /** Timer frequency */
Index: kernel/arch/arm32/include/arch/mach/raspberrypi/raspberrypi.h
===================================================================
--- kernel/arch/arm32/include/arch/mach/raspberrypi/raspberrypi.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/arch/arm32/include/arch/mach/raspberrypi/raspberrypi.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup arm32raspberrypi raspberrypi
+ *  @brief Raspberry Pi platform.
+ *  @ingroup arm32
+ * @{
+ */
+/** @file
+ *  @brief Raspberry Pi platform driver.
+ */
+
+#ifndef KERN_arm32_raspberrypi_H_
+#define KERN_arm32_raspberrypi_H_
+
+#include <arch/machine_func.h>
+
+extern struct arm_machine_ops raspberrypi_machine_ops;
+
+#define BCM2835_UART0_BASE_ADDRESS   0x20201000
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/arm32/include/arch/mm/frame.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/frame.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/include/arch/mm/frame.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -63,4 +63,9 @@
 #define BOOT_PAGE_TABLE_ADDRESS  0x80008000
 
+#elif defined MACHINE_raspberrypi
+
+#define PHYSMEM_START_ADDR       0x00000000
+#define BOOT_PAGE_TABLE_ADDRESS  0x00010000
+
 #else
 
Index: kernel/arch/arm32/include/arch/mm/page_armv6.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page_armv6.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/include/arch/mm/page_armv6.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -278,7 +278,12 @@
 	}
 	
+#if defined(PROCESSOR_ARCH_armv6)
+	/* FIXME: this disables caches */
+	p->shareable = 1;
+#else
 	/* Shareable is ignored for devices (non-cacheable),
 	 * turn it off for normal memory. */
 	p->shareable = 0;
+#endif
 	
 	p->non_global = !(flags & PAGE_GLOBAL);
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -49,4 +49,5 @@
 #include <ddi/ddi.h>
 #include <ddi/device.h>
+#include <log.h>
 
 #define GTA02_MEMORY_START	0x30000000	/* physical */
@@ -149,5 +150,5 @@
 	} else {
 		/* Spurious interrupt.*/
-		printf("cpu%d: spurious interrupt (inum=%d)\n",
+		log(LF_ARCH, LVL_DEBUG, "cpu%d: spurious interrupt (inum=%d)",
 		    CPU->id, inum);
 	}
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -37,11 +37,10 @@
 #include <ipc/irq.h>
 #include <console/chardev.h>
+#include <genarch/drivers/pl011/pl011.h>
 #include <genarch/drivers/pl050/pl050.h>
-#include <genarch/drivers/arm926_uart/arm926_uart.h>
 #include <genarch/kbrd/kbrd.h>
 #include <genarch/srln/srln.h>
 #include <console/console.h>
 #include <sysinfo/sysinfo.h>
-#include <print.h>
 #include <ddi/device.h>
 #include <mm/page.h>
@@ -53,5 +52,6 @@
 #include <abi/fb/visuals.h>
 #include <ddi/ddi.h>
-#include <print.h>
+#include <log.h>
+
 
 
@@ -61,5 +61,5 @@
 	icp_hw_map_t hw_map;
 	irq_t timer_irq;
-	arm926_uart_t uart;
+	pl011_uart_t uart;
 } icp;
 
@@ -275,5 +275,6 @@
 			} else {
 				/* Spurious interrupt.*/
-				printf("cpu%d: spurious interrupt (inum=%d)\n",
+				log(LF_ARCH, LVL_DEBUG,
+				    "cpu%d: spurious interrupt (inum=%d)",
 				    CPU->id, i);
 			}
@@ -314,7 +315,6 @@
 		stdout_wire(fbdev);
 #endif
-#ifdef CONFIG_ARM926_UART
-	if (arm926_uart_init(&icp.uart, ARM926_UART0_IRQ,
-	    ARM926_UART0_BASE_ADDRESS, sizeof(arm926_uart_regs_t)))
+#ifdef CONFIG_PL011_UART
+	if (pl011_uart_init(&icp.uart, ICP_UART0_IRQ, ICP_UART))
 		stdout_wire(&icp.uart.outdev);
 #endif
@@ -350,11 +350,11 @@
 	    ICP_KBD);
 
-#ifdef CONFIG_ARM926_UART
+#ifdef CONFIG_PL011_UART
         srln_instance_t *srln_instance = srln_init();
         if (srln_instance) {
                 indev_t *sink = stdin_wire();
                 indev_t *srln = srln_wire(srln_instance, sink);
-                arm926_uart_input_wire(&icp.uart, srln);
-		icp_irqc_unmask(ARM926_UART0_IRQ);
+                pl011_uart_input_wire(&icp.uart, srln);
+                icp_irqc_unmask(ICP_UART0_IRQ);
         }
 #endif
Index: kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c
===================================================================
--- kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup arm32raspberrypi
+ * @{
+ */
+/** @file
+ *  @brief Raspberry PI platform driver.
+ */
+
+#include <arch/exception.h>
+#include <arch/mach/raspberrypi/raspberrypi.h>
+#include <genarch/drivers/pl011/pl011.h>
+#include <genarch/drivers/bcm2835/irc.h>
+#include <genarch/drivers/bcm2835/timer.h>
+#include <genarch/drivers/bcm2835/mbox.h>
+#include <arch/mm/page.h>
+#include <mm/page.h>
+#include <mm/km.h>
+#include <genarch/fb/fb.h>
+#include <abi/fb/visuals.h>
+#include <genarch/srln/srln.h>
+#include <sysinfo/sysinfo.h>
+#include <interrupt.h>
+#include <ddi/ddi.h>
+#include <ddi/device.h>
+
+#define RPI_DEFAULT_MEMORY_START	0
+#define RPI_DEFAULT_MEMORY_SIZE		0x08000000
+#define RPI_MEMORY_SKIP			0x8000
+
+static void raspberrypi_init(void);
+static void raspberrypi_timer_irq_start(void);
+static void raspberrypi_cpu_halt(void);
+static void raspberrypi_get_memory_extents(uintptr_t *start, size_t *size);
+static void raspberrypi_irq_exception(unsigned int exc_no, istate_t *istate);
+static void raspberrypi_frame_init(void);
+static void raspberrypi_output_init(void);
+static void raspberrypi_input_init(void);
+static size_t raspberrypi_get_irq_count(void);
+static const char *raspberrypi_get_platform_name(void);
+
+static struct {
+	pl011_uart_t	uart;
+	bcm2835_irc_t	*irc;
+	bcm2835_timer_t	*timer;
+} raspi;
+
+struct arm_machine_ops raspberrypi_machine_ops = {
+	raspberrypi_init,
+	raspberrypi_timer_irq_start,
+	raspberrypi_cpu_halt,
+	raspberrypi_get_memory_extents,
+	raspberrypi_irq_exception,
+	raspberrypi_frame_init,
+	raspberrypi_output_init,
+	raspberrypi_input_init,
+	raspberrypi_get_irq_count,
+	raspberrypi_get_platform_name
+};
+
+static irq_ownership_t raspberrypi_timer_irq_claim(irq_t *irq)
+{
+	return IRQ_ACCEPT;
+}
+
+static void raspberrypi_timer_irq_handler(irq_t *irq)
+{
+	bcm2835_timer_irq_ack(raspi.timer);
+	spinlock_unlock(&irq->lock);
+	clock();
+	spinlock_lock(&irq->lock);
+}
+
+static void raspberrypi_init(void)
+{
+	/* Initialize interrupt controller */
+	raspi.irc = (void *) km_map(BCM2835_IRC_ADDR, sizeof(bcm2835_irc_t),
+				    PAGE_NOT_CACHEABLE);
+	ASSERT(raspi.irc);
+	bcm2835_irc_init(raspi.irc);
+
+	/* Initialize system timer */
+	raspi.timer = (void *) km_map(BCM2835_TIMER_ADDR,
+				      sizeof(bcm2835_timer_t),
+				      PAGE_NOT_CACHEABLE);
+}
+
+static void raspberrypi_timer_irq_start(void)
+{
+	/* Initialize timer IRQ */
+	static irq_t timer_irq;
+	irq_initialize(&timer_irq);
+	timer_irq.devno = device_assign_devno();
+	timer_irq.inr = BCM2835_TIMER1_IRQ;
+	timer_irq.claim = raspberrypi_timer_irq_claim;
+	timer_irq.handler = raspberrypi_timer_irq_handler;
+	irq_register(&timer_irq);
+
+	bcm2835_irc_enable(raspi.irc, BCM2835_TIMER1_IRQ);
+	bcm2835_timer_start(raspi.timer);
+}
+
+static void raspberrypi_cpu_halt(void)
+{
+	while (1) ;
+}
+
+/** Get extents of available memory.
+ *
+ * @param start		Place to store memory start address (physical).
+ * @param size		Place to store memory size.
+ */
+static void raspberrypi_get_memory_extents(uintptr_t *start, size_t *size)
+{
+	uint32_t mbase, msize;
+
+	if (bcm2835_prop_get_memory(&mbase, &msize)) {
+		*start = mbase + RPI_MEMORY_SKIP;
+		*size  = msize - RPI_MEMORY_SKIP;
+	} else {
+		/* Stick to safe default values */
+		*start = RPI_DEFAULT_MEMORY_START + RPI_MEMORY_SKIP;
+		*size  = RPI_DEFAULT_MEMORY_SIZE - RPI_MEMORY_SKIP;
+	}
+}
+
+static void raspberrypi_irq_exception(unsigned int exc_no, istate_t *istate)
+{
+	const unsigned inum = bcm2835_irc_inum_get(raspi.irc);
+
+	irq_t *irq = irq_dispatch_and_lock(inum);
+	if (irq) {
+		/* The IRQ handler was found. */
+		irq->handler(irq);
+		spinlock_unlock(&irq->lock);
+	} else {
+		/* Spurious interrupt.*/
+		printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum);
+		bcm2835_irc_disable(raspi.irc, inum);
+	}
+}
+
+static void raspberrypi_frame_init(void)
+{
+}
+
+static void raspberrypi_output_init(void)
+{
+#ifdef CONFIG_FB
+	fb_properties_t prop;
+	if (bcm2835_fb_init(&prop)) {
+		outdev_t *fb_dev = fb_init(&prop);
+		if (fb_dev)
+			stdout_wire(fb_dev);
+	}
+#endif
+
+#ifdef CONFIG_PL011_UART
+	if (pl011_uart_init(&raspi.uart, BCM2835_UART_IRQ,
+			    BCM2835_UART0_BASE_ADDRESS))
+		stdout_wire(&raspi.uart.outdev);
+#endif
+}
+
+static void raspberrypi_input_init(void)
+{
+	srln_instance_t *srln_instance = srln_init();
+	if (srln_instance) {
+		indev_t *sink = stdin_wire();
+		indev_t *srln = srln_wire(srln_instance, sink);
+
+		pl011_uart_input_wire(&raspi.uart, srln);
+		bcm2835_irc_enable(raspi.irc, BCM2835_UART_IRQ);
+	}
+}
+
+size_t raspberrypi_get_irq_count(void)
+{
+	return BCM2835_IRQ_COUNT;
+}
+
+const char *raspberrypi_get_platform_name(void)
+{
+	return "raspberrypi";
+}
+
+/** @}
+ */
Index: kernel/arch/arm32/src/machine_func.c
===================================================================
--- kernel/arch/arm32/src/machine_func.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/arm32/src/machine_func.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,4 +43,5 @@
 #include <arch/mach/beagleboardxm/beagleboardxm.h>
 #include <arch/mach/beaglebone/beaglebone.h>
+#include <arch/mach/raspberrypi/raspberrypi.h>
 
 /** Pointer to machine_ops structure being used. */
@@ -58,4 +59,6 @@
 #elif defined(MACHINE_beaglebone)
 	machine_ops = &bbone_machine_ops;
+#elif defined(MACHINE_raspberrypi)
+	machine_ops = &raspberrypi_machine_ops;
 #else
 #error Machine type not defined.
Index: kernel/arch/ia32/src/drivers/i8259.c
===================================================================
--- kernel/arch/ia32/src/drivers/i8259.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/ia32/src/drivers/i8259.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -42,5 +42,5 @@
 #include <arch/asm.h>
 #include <arch.h>
-#include <print.h>
+#include <log.h>
 #include <interrupt.h>
 
@@ -129,5 +129,5 @@
 {
 #ifdef CONFIG_DEBUG
-	printf("cpu%u: PIC spurious interrupt\n", CPU->id);
+	log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt", CPU->id);
 #endif
 }
Index: kernel/arch/ia32/src/smp/apic.c
===================================================================
--- kernel/arch/ia32/src/smp/apic.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/ia32/src/smp/apic.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -42,5 +42,5 @@
 #include <interrupt.h>
 #include <arch/interrupt.h>
-#include <print.h>
+#include <log.h>
 #include <arch/asm.h>
 #include <arch.h>
@@ -135,5 +135,5 @@
 {
 #ifdef CONFIG_DEBUG
-	printf("cpu%u: APIC spurious interrupt\n", CPU->id);
+	log(LF_ARCH, LVL_DEBUG, "cpu%u: APIC spurious interrupt", CPU->id);
 #endif
 }
@@ -241,18 +241,23 @@
 	esr.value = l_apic[ESR];
 	
-	if (esr.send_checksum_error)
-		printf("Send Checksum Error\n");
-	if (esr.receive_checksum_error)
-		printf("Receive Checksum Error\n");
-	if (esr.send_accept_error)
-		printf("Send Accept Error\n");
-	if (esr.receive_accept_error)
-		printf("Receive Accept Error\n");
-	if (esr.send_illegal_vector)
-		printf("Send Illegal Vector\n");
-	if (esr.received_illegal_vector)
-		printf("Received Illegal Vector\n");
-	if (esr.illegal_register_address)
-		printf("Illegal Register Address\n");
+	if (esr.err_bitmap) {
+		log_begin(LF_ARCH, LVL_ERROR);
+		log_printf("APIC errors detected:");
+		if (esr.send_checksum_error)
+			log_printf("\nSend Checksum Error");
+		if (esr.receive_checksum_error)
+			log_printf("\nReceive Checksum Error");
+		if (esr.send_accept_error)
+			log_printf("\nSend Accept Error");
+		if (esr.receive_accept_error)
+			log_printf("\nReceive Accept Error");
+		if (esr.send_illegal_vector)
+			log_printf("\nSend Illegal Vector");
+		if (esr.received_illegal_vector)
+			log_printf("\nReceived Illegal Vector");
+		if (esr.illegal_register_address)
+			log_printf("\nIllegal Register Address");
+		log_end();
+	}
 	
 	return !esr.err_bitmap;
@@ -270,5 +275,5 @@
 			retries = 0;
 #ifdef CONFIG_DEBUG
-			printf("IPI is pending.\n");
+			log(LF_ARCH, LVL_DEBUG, "IPI is pending.");
 #endif
 			delay(20);
@@ -489,10 +494,11 @@
 {
 #ifdef LAPIC_VERBOSE
-	printf("LVT on cpu%u, LAPIC ID: %" PRIu8 "\n",
+	log_begin(LF_ARCH, LVL_DEBUG);
+	log_printf("LVT on cpu%u, LAPIC ID: %" PRIu8 "\n",
 	    CPU->id, l_apic_id());
 	
 	lvt_tm_t tm;
 	tm.value = l_apic[LVT_Tm];
-	printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n",
+	log_printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n",
 	    tm.vector, delivs_str[tm.delivs], mask_str[tm.masked],
 	    tm_mode_str[tm.mode]);
@@ -500,5 +506,5 @@
 	lvt_lint_t lint;
 	lint.value = l_apic[LVT_LINT0];
-	printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
+	log_printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
 	    tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs],
 	    intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode],
@@ -506,5 +512,5 @@
 	
 	lint.value = l_apic[LVT_LINT1];
-	printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
+	log_printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n",
 	    tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs],
 	    intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode],
@@ -513,6 +519,7 @@
 	lvt_error_t error;
 	error.value = l_apic[LVT_Err];
-	printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector,
+	log_printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector,
 	    delivs_str[error.delivs], mask_str[error.masked]);
+	log_end();
 #endif
 }
Index: kernel/arch/ia32/src/smp/mps.c
===================================================================
--- kernel/arch/ia32/src/smp/mps.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/ia32/src/smp/mps.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -36,5 +36,5 @@
 
 #include <config.h>
-#include <print.h>
+#include <log.h>
 #include <debug.h>
 #include <arch/smp/mps.h>
@@ -181,5 +181,5 @@
 	buf[6] = 0;
 	
-	printf("MPS: bus=%" PRIu8 " (%s)\n", bus->bus_id, buf);
+	log(LF_ARCH, LVL_DEBUG, "MPS: bus=%" PRIu8 " (%s)", bus->bus_id, buf);
 #endif
 }
@@ -205,58 +205,60 @@
 {
 #ifdef MPSCT_VERBOSE
-	printf("MPS: ");
+	log_begin(LF_ARCH, LVL_DEBUG);
+	log_printf("MPS: ");
 	
 	switch (iointr->intr_type) {
 	case 0:
-		printf("INT");
-		break;
-	case 1:
-		printf("NMI");
-		break;
-	case 2:
-		printf("SMI");
-		break;
-	case 3:
-		printf("ExtINT");
-		break;
-	}
-	
-	printf(", ");
+		log_printf("INT");
+		break;
+	case 1:
+		log_printf("NMI");
+		break;
+	case 2:
+		log_printf("SMI");
+		break;
+	case 3:
+		log_printf("ExtINT");
+		break;
+	}
+	
+	log_printf(", ");
 	
 	switch (iointr->poel & 3) {
 	case 0:
-		printf("bus-like");
-		break;
-	case 1:
-		printf("active high");
-		break;
-	case 2:
-		printf("reserved");
-		break;
-	case 3:
-		printf("active low");
-		break;
-	}
-	
-	printf(", ");
+		log_printf("bus-like");
+		break;
+	case 1:
+		log_printf("active high");
+		break;
+	case 2:
+		log_printf("reserved");
+		break;
+	case 3:
+		log_printf("active low");
+		break;
+	}
+	
+	log_printf(", ");
 	
 	switch ((iointr->poel >> 2) & 3) {
 	case 0:
-		printf("bus-like");
-		break;
-	case 1:
-		printf("edge-triggered");
-		break;
-	case 2:
-		printf("reserved");
-		break;
-	case 3:
-		printf("level-triggered");
-		break;
-	}
-	
-	printf(", bus=%" PRIu8 " irq=%" PRIu8 " io_apic=%" PRIu8" pin=%"
-	    PRIu8 "\n", iointr->src_bus_id, iointr->src_bus_irq,
+		log_printf("bus-like");
+		break;
+	case 1:
+		log_printf("edge-triggered");
+		break;
+	case 2:
+		log_printf("reserved");
+		break;
+	case 3:
+		log_printf("level-triggered");
+		break;
+	}
+	
+	log_printf(", bus=%" PRIu8 " irq=%" PRIu8 " io_apic=%" PRIu8" pin=%"
+	    PRIu8, iointr->src_bus_id, iointr->src_bus_irq,
 	    iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
+	log_end();
 #endif
 }
@@ -266,58 +268,60 @@
 {
 #ifdef MPSCT_VERBOSE
-	printf("MPS: ");
+	log_begin(LF_ARCH, LVL_DEBUG);
+	log_printf("MPS: ");
 	
 	switch (lintr->intr_type) {
 	case 0:
-		printf("INT");
-		break;
-	case 1:
-		printf("NMI");
-		break;
-	case 2:
-		printf("SMI");
-		break;
-	case 3:
-		printf("ExtINT");
-		break;
-	}
-	
-	printf(", ");
+		log_printf("INT");
+		break;
+	case 1:
+		log_printf("NMI");
+		break;
+	case 2:
+		log_printf("SMI");
+		break;
+	case 3:
+		log_printf("ExtINT");
+		break;
+	}
+	
+	log_printf(", ");
 	
 	switch (lintr->poel & 3) {
 	case 0:
-		printf("bus-like");
-		break;
-	case 1:
-		printf("active high");
-		break;
-	case 2:
-		printf("reserved");
-		break;
-	case 3:
-		printf("active low");
-		break;
-	}
-	
-	printf(", ");
+		log_printf("bus-like");
+		break;
+	case 1:
+		log_printf("active high");
+		break;
+	case 2:
+		log_printf("reserved");
+		break;
+	case 3:
+		log_printf("active low");
+		break;
+	}
+	
+	log_printf(", ");
 	
 	switch ((lintr->poel >> 2) & 3) {
 	case 0:
-		printf("bus-like");
-		break;
-	case 1:
-		printf("edge-triggered");
-		break;
-	case 2:
-		printf("reserved");
-		break;
-	case 3:
-		printf("level-triggered");
-		break;
-	}
-	
-	printf(", bus=%" PRIu8 " irq=%" PRIu8 " l_apic=%" PRIu8" pin=%"
-	    PRIu8 "\n", lintr->src_bus_id, lintr->src_bus_irq,
+		log_printf("bus-like");
+		break;
+	case 1:
+		log_printf("edge-triggered");
+		break;
+	case 2:
+		log_printf("reserved");
+		break;
+	case 3:
+		log_printf("level-triggered");
+		break;
+	}
+	
+	log_printf(", bus=%" PRIu8 " irq=%" PRIu8 " l_apic=%" PRIu8" pin=%"
+	    PRIu8, lintr->src_bus_id, lintr->src_bus_irq,
 	    lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
+	log_end();
 #endif
 }
@@ -332,6 +336,7 @@
 		switch (cur[CT_EXT_ENTRY_TYPE]) {
 		default:
-			printf("MPS: Skipping MP Configuration Table extended "
-			    "entry type %" PRIu8 "\n", cur[CT_EXT_ENTRY_TYPE]);
+			log(LF_ARCH, LVL_NOTE, "MPS: Skipping MP Configuration"
+			    " Table extended entry type %" PRIu8,
+			    cur[CT_EXT_ENTRY_TYPE]);
 		}
 	}
@@ -341,15 +346,15 @@
 {
 	if (ct->signature != CT_SIGNATURE) {
-		printf("MPS: Wrong ct->signature\n");
+		log(LF_ARCH, LVL_WARN, "MPS: Wrong ct->signature");
 		return;
 	}
 	
 	if (!mps_ct_check()) {
-		printf("MPS: Wrong ct checksum\n");
+		log(LF_ARCH, LVL_WARN, "MPS: Wrong ct checksum");
 		return;
 	}
 	
 	if (ct->oem_table) {
-		printf("MPS: ct->oem_table not supported\n");
+		log(LF_ARCH, LVL_WARN, "MPS: ct->oem_table not supported");
 		return;
 	}
@@ -402,5 +407,5 @@
 			 * Something is wrong. Fallback to UP mode.
 			 */
-			printf("MPS: ct badness %" PRIu8 "\n", *cur);
+			log(LF_ARCH, LVL_WARN, "MPS: ct badness %" PRIu8, *cur);
 			return;
 		}
@@ -418,5 +423,5 @@
 	 * Not yet implemented.
 	 */
-	printf("MPS: Default configuration not supported\n");
+	log(LF_ARCH, LVL_WARN, "MPS: Default configuration not supported");
 }
 
@@ -449,9 +454,9 @@
 	
 fs_found:
-	printf("%p: MPS Floating Pointer Structure\n", fs);
+	log(LF_ARCH, LVL_NOTE, "%p: MPS Floating Pointer Structure", fs);
 	
 	if ((fs->config_type == 0) && (fs->configuration_table)) {
 		if (fs->mpfib2 >> 7) {
-			printf("MPS: PIC mode not supported\n");
+			log(LF_ARCH, LVL_WARN, "MPS: PIC mode not supported\n");
 			return;
 		}
Index: kernel/arch/ia32/src/smp/smp.c
===================================================================
--- kernel/arch/ia32/src/smp/smp.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/ia32/src/smp/smp.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -52,5 +52,5 @@
 #include <mm/slab.h>
 #include <mm/as.h>
-#include <print.h>
+#include <log.h>
 #include <memstr.h>
 #include <arch/drivers/i8259.h>
@@ -129,6 +129,6 @@
 		
 		if (ops->cpu_apic_id(i) == bsp_l_apic) {
-			printf("kmp: bad processor entry #%u, will not send IPI "
-			    "to myself\n", i);
+			log(LF_ARCH, LVL_ERROR, "kmp: bad processor entry #%u, "
+			    "will not send IPI to myself", i);
 			continue;
 		}
@@ -162,10 +162,10 @@
 			if (waitq_sleep_timeout(&ap_completion_wq, 1000000,
 			    SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT) {
-				printf("%s: waiting for cpu%u (APIC ID = %d) "
-				    "timed out\n", __FUNCTION__, i,
-				    ops->cpu_apic_id(i));
+				log(LF_ARCH, LVL_NOTE, "%s: waiting for cpu%u "
+				    "(APIC ID = %d) timed out", __FUNCTION__,
+				    i, ops->cpu_apic_id(i));
 			}
 		} else
-			printf("INIT IPI for l_apic%d failed\n",
+			log(LF_ARCH, LVL_ERROR, "INIT IPI for l_apic%d failed",
 			    ops->cpu_apic_id(i));
 	}
Index: kernel/arch/mips32/src/debugger.c
===================================================================
--- kernel/arch/mips32/src/debugger.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/mips32/src/debugger.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -39,4 +39,5 @@
 #include <console/cmd.h>
 #include <print.h>
+#include <log.h>
 #include <panic.h>
 #include <arch.h>
@@ -294,17 +295,21 @@
 	cmd_initialize(&bkpts_info);
 	if (!cmd_register(&bkpts_info))
-		printf("Cannot register command %s\n", bkpts_info.name);
+		log(LF_OTHER, LVL_WARN, "Cannot register command %s",
+		    bkpts_info.name);
 	
 	cmd_initialize(&delbkpt_info);
 	if (!cmd_register(&delbkpt_info))
-		printf("Cannot register command %s\n", delbkpt_info.name);
+		log(LF_OTHER, LVL_WARN, "Cannot register command %s",
+		    delbkpt_info.name);
 	
 	cmd_initialize(&addbkpt_info);
 	if (!cmd_register(&addbkpt_info))
-		printf("Cannot register command %s\n", addbkpt_info.name);
+		log(LF_OTHER, LVL_WARN, "Cannot register command %s",
+		    addbkpt_info.name);
 	
 	cmd_initialize(&addbkpte_info);
 	if (!cmd_register(&addbkpte_info))
-		printf("Cannot register command %s\n", addbkpte_info.name);
+		log(LF_OTHER, LVL_WARN, "Cannot register command %s",
+		    addbkpte_info.name);
 #endif /* CONFIG_KCONSOLE */
 }
Index: kernel/arch/mips32/src/exception.c
===================================================================
--- kernel/arch/mips32/src/exception.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/mips32/src/exception.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -48,4 +48,5 @@
 #include <arch/debugger.h>
 #include <symtab.h>
+#include <log.h>
 
 static const char *exctable[] = {
@@ -74,37 +75,37 @@
 void istate_decode(istate_t *istate)
 {
-	printf("epc=%#010" PRIx32 "\tsta=%#010" PRIx32 "\t"
+	log_printf("epc=%#010" PRIx32 "\tsta=%#010" PRIx32 "\t"
 	    "lo =%#010" PRIx32 "\thi =%#010" PRIx32 "\n",
 	    istate->epc, istate->status, istate->lo, istate->hi);
 	
-	printf("a0 =%#010" PRIx32 "\ta1 =%#010" PRIx32 "\t"
+	log_printf("a0 =%#010" PRIx32 "\ta1 =%#010" PRIx32 "\t"
 	    "a2 =%#010" PRIx32 "\ta3 =%#010" PRIx32 "\n",
 	    istate->a0, istate->a1, istate->a2, istate->a3);
 	
-	printf("t0 =%#010" PRIx32 "\tt1 =%#010" PRIx32 "\t"
+	log_printf("t0 =%#010" PRIx32 "\tt1 =%#010" PRIx32 "\t"
 	    "t2 =%#010" PRIx32 "\tt3 =%#010" PRIx32 "\n",
 	    istate->t0, istate->t1, istate->t2, istate->t3);
 	
-	printf("t4 =%#010" PRIx32 "\tt5 =%#010" PRIx32 "\t"
+	log_printf("t4 =%#010" PRIx32 "\tt5 =%#010" PRIx32 "\t"
 	    "t6 =%#010" PRIx32 "\tt7 =%#010" PRIx32 "\n",
 	    istate->t4, istate->t5, istate->t6, istate->t7);
 	
-	printf("t8 =%#010" PRIx32 "\tt9 =%#010" PRIx32 "\t"
+	log_printf("t8 =%#010" PRIx32 "\tt9 =%#010" PRIx32 "\t"
 	    "v0 =%#010" PRIx32 "\tv1 =%#010" PRIx32 "\n",
 	    istate->t8, istate->t9, istate->v0, istate->v1);
 	
-	printf("s0 =%#010" PRIx32 "\ts1 =%#010" PRIx32 "\t"
+	log_printf("s0 =%#010" PRIx32 "\ts1 =%#010" PRIx32 "\t"
 	    "s2 =%#010" PRIx32 "\ts3 =%#010" PRIx32 "\n",
 	    istate->s0, istate->s1, istate->s2, istate->s3);
 	
-	printf("s4 =%#010" PRIx32 "\ts5 =%#010" PRIx32 "\t"
+	log_printf("s4 =%#010" PRIx32 "\ts5 =%#010" PRIx32 "\t"
 	    "s6 =%#010" PRIx32 "\ts7 =%#010" PRIx32 "\n",
 	    istate->s4, istate->s5, istate->s6, istate->s7);
 	
-	printf("s8 =%#010" PRIx32 "\tat =%#010" PRIx32 "\t"
+	log_printf("s8 =%#010" PRIx32 "\tat =%#010" PRIx32 "\t"
 	    "kt0=%#010" PRIx32 "\tkt1=%#010" PRIx32 "\n",
 	    istate->s8, istate->at, istate->kt0, istate->kt1);
 	
-	printf("sp =%#010" PRIx32 "\tra =%#010" PRIx32 "\t"
+	log_printf("sp =%#010" PRIx32 "\tra =%#010" PRIx32 "\t"
 	    "gp =%#010" PRIx32 "\n",
 	    istate->sp, istate->ra, istate->gp);
@@ -194,5 +195,6 @@
 				 */
 #ifdef CONFIG_DEBUG
-				printf("cpu%u: spurious interrupt (inum=%u)\n",
+				log(LF_ARCH, LVL_DEBUG,
+				    "cpu%u: spurious interrupt (inum=%u)",
 				    CPU->id, i);
 #endif
Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,4 +43,5 @@
 #include <synch/mutex.h>
 #include <print.h>
+#include <log.h>
 #include <debug.h>
 #include <align.h>
@@ -217,5 +218,5 @@
 	 */
 	if (index.p) {
-		printf("%s: TLBP failed in exception handler (badvaddr=%#"
+		log(LF_ARCH, LVL_WARN, "%s: TLBP failed in exception handler (badvaddr=%#"
 		    PRIxn ", ASID=%d).\n", __func__, badvaddr,
 		    AS ? AS->asid : -1);
Index: kernel/arch/ppc32/src/interrupt.c
===================================================================
--- kernel/arch/ppc32/src/interrupt.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/ppc32/src/interrupt.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -44,4 +44,5 @@
 #include <arch/mm/pht.h>
 #include <print.h>
+#include <log.h>
 
 void start_decrementer(void)
@@ -55,44 +56,44 @@
 void istate_decode(istate_t *istate)
 {
-	printf("r0 =%0#10" PRIx32 "\tr1 =%0#10" PRIx32 "\t"
+	log_printf("r0 =%0#10" PRIx32 "\tr1 =%0#10" PRIx32 "\t"
 	    "r2 =%0#10" PRIx32 "\n", istate->r0, istate->sp, istate->r2);
 	
-	printf("r3 =%0#10" PRIx32 "\tr4 =%0#10" PRIx32 "\t"
+	log_printf("r3 =%0#10" PRIx32 "\tr4 =%0#10" PRIx32 "\t"
 	    "r5 =%0#10" PRIx32 "\n", istate->r3, istate->r4, istate->r5);
 	
-	printf("r6 =%0#10" PRIx32 "\tr7 =%0#10" PRIx32 "\t"
+	log_printf("r6 =%0#10" PRIx32 "\tr7 =%0#10" PRIx32 "\t"
 	    "r8 =%0#10" PRIx32 "\n", istate->r6, istate->r7, istate->r8);
 	
-	printf("r9 =%0#10" PRIx32 "\tr10=%0#10" PRIx32 "\t"
+	log_printf("r9 =%0#10" PRIx32 "\tr10=%0#10" PRIx32 "\t"
 	    "r11=%0#10" PRIx32 "\n", istate->r9, istate->r10, istate->r11);
 	
-	printf("r12=%0#10" PRIx32 "\tr13=%0#10" PRIx32 "\t"
+	log_printf("r12=%0#10" PRIx32 "\tr13=%0#10" PRIx32 "\t"
 	    "r14=%0#10" PRIx32 "\n", istate->r12, istate->r13, istate->r14);
 	
-	printf("r15=%0#10" PRIx32 "\tr16=%0#10" PRIx32 "\t"
+	log_printf("r15=%0#10" PRIx32 "\tr16=%0#10" PRIx32 "\t"
 	    "r17=%0#10" PRIx32 "\n", istate->r15, istate->r16, istate->r17);
 	
-	printf("r18=%0#10" PRIx32 "\tr19=%0#10" PRIx32 "\t"
+	log_printf("r18=%0#10" PRIx32 "\tr19=%0#10" PRIx32 "\t"
 	    "r20=%0#10" PRIx32 "\n", istate->r18, istate->r19, istate->r20);
 	
-	printf("r21=%0#10" PRIx32 "\tr22=%0#10" PRIx32 "\t"
+	log_printf("r21=%0#10" PRIx32 "\tr22=%0#10" PRIx32 "\t"
 	    "r23=%0#10" PRIx32 "\n", istate->r21, istate->r22, istate->r23);
 	
-	printf("r24=%0#10" PRIx32 "\tr25=%0#10" PRIx32 "\t"
+	log_printf("r24=%0#10" PRIx32 "\tr25=%0#10" PRIx32 "\t"
 	    "r26=%0#10" PRIx32 "\n", istate->r24, istate->r25, istate->r26);
 	
-	printf("r27=%0#10" PRIx32 "\tr28=%0#10" PRIx32 "\t"
+	log_printf("r27=%0#10" PRIx32 "\tr28=%0#10" PRIx32 "\t"
 	    "r29=%0#10" PRIx32 "\n", istate->r27, istate->r28, istate->r29);
 	
-	printf("r30=%0#10" PRIx32 "\tr31=%0#10" PRIx32 "\n",
+	log_printf("r30=%0#10" PRIx32 "\tr31=%0#10" PRIx32 "\n",
 	    istate->r30, istate->r31);
 	
-	printf("cr =%0#10" PRIx32 "\tpc =%0#10" PRIx32 "\t"
+	log_printf("cr =%0#10" PRIx32 "\tpc =%0#10" PRIx32 "\t"
 	    "lr =%0#10" PRIx32 "\n", istate->cr, istate->pc, istate->lr);
 	
-	printf("ctr=%0#10" PRIx32 "\txer=%0#10" PRIx32 "\t"
+	log_printf("ctr=%0#10" PRIx32 "\txer=%0#10" PRIx32 "\t"
 	    "dar=%0#10" PRIx32 "\n", istate->ctr, istate->xer, istate->dar);
 	
-	printf("srr1=%0#10" PRIx32 "\n", istate->srr1);
+	log_printf("srr1=%0#10" PRIx32 "\n", istate->srr1);
 }
 
@@ -130,6 +131,6 @@
 			 */
 #ifdef CONFIG_DEBUG
-			printf("cpu%u: spurious interrupt (inum=%" PRIu8 ")\n",
-			    CPU->id, inum);
+			log(LF_ARCH, LVL_DEBUG, "cpu%u: spurious interrupt"
+			    " (inum=%" PRIu8 ")", CPU->id, inum);
 #endif
 		}
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -44,5 +44,5 @@
 #include <align.h>
 #include <str.h>
-#include <print.h>
+#include <log.h>
 #include <sysinfo/sysinfo.h>
 
@@ -71,5 +71,6 @@
 	ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
 	if ((!prop) || (!prop->value)) {
-		printf("ns16550: Unable to find interrupts property\n");
+		log(LF_ARCH, LVL_ERROR,
+		    "ns16550: Unable to find interrupts property");
 		return false;
 	}
@@ -82,5 +83,6 @@
 	prop = ofw_tree_getprop(node, "reg");
 	if ((!prop) || (!prop->value)) {
-		printf("ns16550: Unable to find reg property\n");
+		log(LF_ARCH, LVL_ERROR,
+		    "ns16550: Unable to find reg property");
 		return false;
 	}
@@ -91,5 +93,6 @@
 	if (!ofw_ebus_apply_ranges(node->parent,
 	    ((ofw_ebus_reg_t *) prop->value), &pa)) {
-		printf("ns16550: Failed to determine address\n");
+		log(LF_ARCH, LVL_ERROR,
+		    "ns16550: Failed to determine address");
 		return false;
 	}
@@ -101,5 +104,6 @@
 	    ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
 	    &cir_arg)) {
-		printf("ns16550: Failed to determine interrupt\n");
+		log(LF_ARCH, LVL_ERROR,
+		    "ns16550: Failed to determine interrupt");
 		return false;
 	}
@@ -117,5 +121,6 @@
 	    PAGE_WRITE | PAGE_NOT_CACHEABLE) + offset);
 	
-	ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg);
+	ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir,
+	    cir_arg);
 	if (ns16550_instance) {
 		kbrd_instance_t *kbrd_instance = kbrd_init();
Index: kernel/arch/sparc64/src/drivers/pci.c
===================================================================
--- kernel/arch/sparc64/src/drivers/pci.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/drivers/pci.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,5 +43,5 @@
 #include <typedefs.h>
 #include <debug.h>
-#include <print.h>
+#include <log.h>
 #include <str.h>
 #include <arch/asm.h>
@@ -213,5 +213,5 @@
 		 * Unsupported model.
 		 */
-		printf("Unsupported PCI controller model (%s).\n",
+		log(LF_ARCH, LVL_WARN, "Unsupported PCI controller model (%s).",
 		    (char *) prop->value);
 	}
Index: kernel/arch/sparc64/src/drivers/scr.c
===================================================================
--- kernel/arch/sparc64/src/drivers/scr.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/drivers/scr.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -81,5 +81,5 @@
 	
 	if (scr_type == SCR_UNKNOWN) {
-		printf("Unknown screen device.\n");
+		log(LF_ARCH, LVL_ERROR, "Unknown screen device.");
 		return;
 	}
@@ -117,5 +117,5 @@
 	case SCR_ATYFB:
 		if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
-			printf("Too few screen registers.\n");
+			log(LF_ARCH, LVL_ERROR, "Too few screen registers.");
 			return;
 		}
@@ -124,5 +124,6 @@
 		
 		if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
-			printf("Failed to absolutize fb register.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to absolutize fb register.");
 			return;
 		}
@@ -130,5 +131,6 @@
 		if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
 		    &fb_addr)) {
-			printf("Failed to determine screen address.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to determine screen address.");
 			return;
 		}
@@ -152,5 +154,6 @@
 			break;
 		default:
-			printf("Unsupported bits per pixel.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Unsupported bits per pixel.");
 			return;
 		}
@@ -159,5 +162,6 @@
 	case SCR_XVR:
 		if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
-			printf("Too few screen registers.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Too few screen registers.");
 			return;
 		}
@@ -166,5 +170,6 @@
 		
 		if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
-			printf("Failed to absolutize fb register.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to absolutize fb register.");
 			return;
 		}
@@ -172,5 +177,6 @@
 		if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
 		    &fb_addr)) {
-			printf("Failed to determine screen address.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to determine screen address.");
 			return;
 		}
@@ -196,5 +202,6 @@
 			break;
 		default:
-			printf("Unsupported bits per pixel.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Unsupported bits per pixel.");
 			return;
 		}
@@ -207,5 +214,6 @@
 		upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
 		if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) {
-			printf("Failed to determine screen address.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to determine screen address.");
 			return;
 		}
@@ -219,5 +227,5 @@
 			break;
 		default:
-			printf("Not implemented.\n");
+			log(LF_ARCH, LVL_WARN, "Not implemented.");
 			return;
 		}
@@ -225,5 +233,6 @@
 		sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0];
 		if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) {
-			printf("Failed to determine screen address.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to determine screen address.");
 			return;
 		}
@@ -233,5 +242,5 @@
 	case SCR_QEMU_VGA:
 		if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
-			printf("Too few screen registers.\n");
+			log(LF_ARCH, LVL_ERROR, "Too few screen registers.");
 			return;
 		}
@@ -240,5 +249,6 @@
 
 		if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
-			printf("Failed to absolutize fb register.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to absolutize fb register.");
 			return;
 		}
@@ -246,5 +256,6 @@
 		if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
 		    &fb_addr)) {
-			printf("Failed to determine screen address.\n");
+			log(LF_ARCH, LVL_ERROR,
+			    "Failed to determine screen address.");
 			return;
 		}
@@ -268,5 +279,5 @@
 			break;
 		default:
-			printf("Unsupported bits per pixel.\n");
+			log(LF_ARCH, LVL_ERROR, "Unsupported bits per pixel.");
 			return;
 		}
Index: kernel/arch/sparc64/src/mm/sun4v/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/tlb.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/mm/sun4v/tlb.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -46,4 +46,5 @@
 #include <arch.h>
 #include <print.h>
+#include <log.h>
 #include <typedefs.h>
 #include <config.h>
@@ -335,5 +336,5 @@
 void tlb_print(void)
 {
-	printf("Operation not possible on Niagara.\n");
+	log(LF_ARCH, LVL_WARN, "Operation not possible on Niagara.");
 }
 
Index: kernel/arch/sparc64/src/smp/sun4u/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,5 +43,5 @@
 #include <typedefs.h>
 #include <synch/waitq.h>
-#include <print.h>
+#include <log.h>
 #include <arch/cpu_node.h>
 
@@ -108,6 +108,6 @@
 	if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) ==
 	    ESYNCH_TIMEOUT)
-		printf("%s: waiting for processor (mid = %" PRIu32
-		    ") timed out\n", __func__, mid);
+		log(LF_ARCH, LVL_NOTE, "%s: waiting for processor (mid = %" PRIu32
+		    ") timed out", __func__, mid);
 }
 
Index: kernel/arch/sparc64/src/sun4v/md.c
===================================================================
--- kernel/arch/sparc64/src/sun4v/md.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/sun4v/md.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -36,5 +36,5 @@
 #include <panic.h>
 #include <func.h>
-#include <print.h>
+#include <log.h>
 #include <str.h>
 #include <arch/sun4v/md.h>
@@ -310,6 +310,6 @@
 	retval = retval;
 	if (retval != HV_EOK) {
-		printf("Could not retrieve machine description, "
-		    "error=%" PRIu64 ".\n", retval);
+		log(LF_ARCH, LVL_ERROR, "Could not retrieve machine "
+		    "description, error=%" PRIu64 ".", retval);
 	}
 }
Index: kernel/arch/sparc64/src/trap/sun4u/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/sun4u/interrupt.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/trap/sun4u/interrupt.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -42,5 +42,5 @@
 #include <arch/asm.h>
 #include <arch/barrier.h>
-#include <print.h>
+#include <log.h>
 #include <arch.h>
 #include <mm/tlb.h>
@@ -96,6 +96,7 @@
 		 */
 #ifdef CONFIG_DEBUG
-		printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
-		    ", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
+		log(LF_ARCH, LVL_DEBUG,
+		    "cpu%u: spurious interrupt (intrcv=%#" PRIx64 ", data0=%#"
+		    PRIx64 ")", CPU->id, intrcv, data0);
 #else
 		(void) intrcv;
Index: kernel/arch/sparc64/src/trap/sun4v/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/sun4v/interrupt.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/arch/sparc64/src/trap/sun4v/interrupt.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -42,5 +42,5 @@
 #include <arch/asm.h>
 #include <arch/barrier.h>
-#include <print.h>
+#include <log.h>
 #include <arch.h>
 #include <mm/tlb.h>
@@ -111,6 +111,6 @@
 			((void (*)(void)) data1)();
 		} else {
-			printf("Spurious interrupt on %" PRIu64 ", data = %" PRIx64 ".\n",
-			    CPU->arch.id, data1);
+			log(LF_ARCH, LVL_DEBUG, "Spurious interrupt on %" PRIu64
+			    ", data = %" PRIx64 ".", CPU->arch.id, data1);
 		}
 	}
Index: kernel/doc/doxygroups.h
===================================================================
--- kernel/doc/doxygroups.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/doc/doxygroups.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -167,6 +167,6 @@
  */
  
-/** @defgroup genericklog KLog
- * @brief Kernel logging facility
+/** @defgroup generickio KIO
+ * @brief Kernel character input/output facility
  * @ingroup genericconsole
  */
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/genarch/Makefile.inc	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -90,7 +90,7 @@
 endif
 
-ifeq ($(CONFIG_ARM926_UART),y)
+ifeq ($(CONFIG_PL011_UART),y)
 	GENARCH_SOURCES += \
-		genarch/src/drivers/arm926_uart/arm926_uart.c
+		genarch/src/drivers/pl011/pl011.c
 endif
 
@@ -123,4 +123,9 @@
 	GENARCH_SOURCES += \
 		genarch/src/drivers/am335x/timer.c
+endif
+
+ifeq ($(CONFIG_BCM2835_MAILBOX),y)
+	GENARCH_SOURCES += \
+		genarch/src/drivers/bcm2835/mbox.c
 endif
 
Index: rnel/genarch/include/genarch/drivers/arm926_uart/arm926_uart.h
===================================================================
--- kernel/genarch/include/genarch/drivers/arm926_uart/arm926_uart.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ 	(revision )
@@ -1,169 +1,0 @@
-/*
- * Copyright (c) 2012 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup genarch
- * @{
- */
-/**
- * @file
- * @brief ARM926 on-chip UART (PrimeCell UART, PL011) driver.
- */
-
-#ifndef KERN_ARM926_UART_H_
-#define KERN_ARM926_UART_H_
-
-#include <ddi/irq.h>
-#include <console/chardev.h>
-#include <typedefs.h>
-
-
-/** ARM926 User Guide ch. 4.8.5 (p. 106 in the pdf) */
-#define ARM926_UART0_BASE_ADDRESS   0x16000000
-#define ARM926_UART1_BASE_ADDRESS   0x16000000
-
-/** ARM926 User Guide ch. A.1 (p. 124 in the pdf) */
-#define ARM926_UART0_IRQ   1
-#define ARM926_UART1_IRQ   2
-
-/** PrimeCell UART TRM ch. 3.3 (p. 49 in the pdf) */
-typedef struct {
-	/** UART data register */
-	ioport32_t data;
-#define ARM926_UART_DATA_DATA_MASK   0xff
-#define ARM926_UART_DATA_FE_FLAG   (1 <<  7)
-#define ARM926_UART_DATA_PE_FLAG   (1 <<  9)
-#define ARM926_UART_DATA_BE_FLAG   (1 << 10)
-#define ARM926_UART_DATA_OE_FLAG   (1 << 11)
-
-	union {
-		/* Same values that are in upper bits of data register*/
-		const ioport32_t status;
-#define ARM926_UART_STATUS_FE_FLAG   (1 << 0)
-#define ARM926_UART_STATUS_PE_FLAG   (1 << 1)
-#define ARM926_UART_STATUS_BE_FLAG   (1 << 2)
-#define ARM926_UART_STATUS_OE_FLAG   (1 << 3)
-		/* Writing anything clears all errors */
-		ioport32_t error_clear;
-	};
-	uint32_t padd0_[4];
-
-	const ioport32_t flag;
-#define ARM926_UART_FLAG_CTS_FLAG    (1 << 0)
-#define ARM926_UART_FLAG_DSR_FLAG    (1 << 1)
-#define ARM926_UART_FLAG_DCD_FLAG    (1 << 2)
-#define ARM926_UART_FLAG_BUSY_FLAG   (1 << 3)
-#define ARM926_UART_FLAG_RXFE_FLAG   (1 << 4)
-#define ARM926_UART_FLAG_TXFF_FLAG   (1 << 5)
-#define ARM926_UART_FLAG_RXFF_FLAG   (1 << 6)
-#define ARM926_UART_FLAG_TXFE_FLAG   (1 << 7)
-#define ARM926_UART_FLAG_RI_FLAG     (1 << 8)
-	uint32_t padd1_;
-
-	ioport32_t irda_low_power;
-#define ARM926_UART_IRDA_LOW_POWER_MASK   0xff
-
-	ioport32_t int_baud_divisor;
-#define ARM926_UART_INT_BAUD_DIVISOR_MASK   0xffff
-
-	ioport32_t fract_baud_divisor;
-#define ARM926_UART_FRACT_BAUD_DIVISOR_MASK   0x1f
-
-	ioport32_t line_control_high;
-#define ARM926_UART_CONTROLHI_BRK_FLAG    (1 << 0)
-#define ARM926_UART_CONTROLHI_PEN_FLAG    (1 << 1)
-#define ARM926_UART_CONTROLHI_EPS_FLAG    (1 << 2)
-#define ARM926_UART_CONTROLHI_STP2_FLAG   (1 << 3)
-#define ARM926_UART_CONTROLHI_FEN_FLAG    (1 << 4)
-#define ARM926_UART_CONTROLHI_WLEN_MASK   0x3
-#define ARM926_UART_CONTROLHI_WLEN_SHIFT    5
-#define ARM926_UART_CONTROLHI_SPS_FLAG    (1 << 5)
-
-	ioport32_t control;
-#define ARM926_UART_CONTROL_UARTEN_FLAG   (1 << 0)
-#define ARM926_UART_CONTROL_SIREN_FLAG    (1 << 1)
-#define ARM926_UART_CONTROL_SIRLP_FLAG    (1 << 2)
-#define ARM926_UART_CONTROL_LBE_FLAG      (1 << 7)
-#define ARM926_UART_CONTROL_TXE_FLAG      (1 << 8)
-#define ARM926_UART_CONTROL_RXE_FLAG      (1 << 9)
-#define ARM926_UART_CONTROL_DTR_FLAG     (1 << 10)
-#define ARM926_UART_CONTROL_RTS_FLAG     (1 << 11)
-#define ARM926_UART_CONTROL_OUT1_FLAG    (1 << 12)
-#define ARM926_UART_CONTROL_OUT2_FLAG    (1 << 13)
-#define ARM926_UART_CONTROL_RTSE_FLAG    (1 << 14)
-#define ARM926_UART_CONTROL_CTSE_FLAG    (1 << 15)
-
-	ioport32_t interrupt_fifo;
-#define ARM926_UART_INTERRUPTFIFO_TX_MASK   0x7
-#define ARM926_UART_INTERRUPTFIFO_TX_SHIFT    0
-#define ARM926_UART_INTERRUPTFIFO_RX_MASK   0x7
-#define ARM926_UART_INTERRUPTFIFO_RX_SHIFT    3
-
-	/** Interrupt mask register */
-	ioport32_t interrupt_mask;
-	/** Pending interrupts before applying the mask */
-	const ioport32_t raw_interrupt_status;
-	/** Pending interrupts after applying the mask */
-	const ioport32_t masked_interrupt_status;
-	/** Write 1s to clear pending interrupts */
-	ioport32_t interrupt_clear;
-#define ARM926_UART_INTERRUPT_RIM_FLAG    (1 << 0)
-#define ARM926_UART_INTERRUPT_CTSM_FLAG   (1 << 1)
-#define ARM926_UART_INTERRUPT_DCDM_FLAG   (1 << 2)
-#define ARM926_UART_INTERRUPT_DSRM_FLAG   (1 << 3)
-#define ARM926_UART_INTERRUPT_RX_FLAG     (1 << 4)
-#define ARM926_UART_INTERRUPT_TX_FLAG     (1 << 5)
-#define ARM926_UART_INTERRUPT_RT_FLAG     (1 << 6)
-#define ARM926_UART_INTERRUPT_FE_FLAG     (1 << 7)
-#define ARM926_UART_INTERRUPT_PE_FLAG     (1 << 8)
-#define ARM926_UART_INTERRUPT_BE_FLAG     (1 << 9)
-#define ARM926_UART_INTERRUPT_OE_FLAG    (1 << 10)
-#define ARM926_UART_INTERRUPT_ALL           0x3ff
-
-	ioport32_t dma_control;
-#define ARM926_UART_DMACONTROL_RXDMAEN_FLAG    (1 << 0)
-#define ARM926_UART_DMACONTROL_TXDMAEN_FLAG    (1 << 1)
-#define ARM926_UART_DMACONTROL_DMAONERR_FLAG   (1 << 2)
-
-	// TODO There is some reserved space here followed by
-	// peripheral identification registers.
-} arm926_uart_regs_t;
-
-typedef struct {
-	arm926_uart_regs_t *regs;
-	indev_t *indev;
-	outdev_t outdev;
-	irq_t irq;
-} arm926_uart_t;
-
-bool arm926_uart_init(arm926_uart_t *, inr_t, uintptr_t, size_t);
-void arm926_uart_input_wire(arm926_uart_t *, indev_t *);
-
-#endif
-/**
- * @}
- */
Index: kernel/genarch/include/genarch/drivers/bcm2835/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/bcm2835/irc.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/genarch/include/genarch/drivers/bcm2835/irc.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2012 Jan Vesely
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief Broadcom BCM2835 on-chip interrupt controller driver.
+ */
+
+#ifndef KERN_BCM2835_IRQC_H_
+#define KERN_BCM2835_IRQC_H_
+
+#include <typedefs.h>
+
+#define BANK_GPU0	0
+#define BANK_GPU1	1
+#define BANK_ARM	2
+
+#define IRQ_TO_BANK(x)	((x) >> 5)
+#define IRQ_TO_NUM(x)	((x) & 0x1f)
+
+#define MAKE_IRQ(b,n)	(((b) << 5) | ((n) & 0x1f))
+
+#define BCM2835_UART_IRQ	MAKE_IRQ(BANK_GPU1, 25)
+#define BCM2835_TIMER1_IRQ	MAKE_IRQ(BANK_GPU0,  1)
+
+#define IRQ_PEND_ARM_M		0xFF
+#define IRQ_PEND_GPU0_M		(1 << 8)
+#define IRQ_PEND_GPU1_M		(1 << 9)
+#define IRQ_PEND_SHORT_M	0x1FFC00
+#define IRQ_PEND_SHORT_S	10
+
+unsigned shortcut_inums[] = {7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62};
+
+typedef struct {
+	ioport32_t	irq_basic_pending;
+	ioport32_t	irq_pending1;
+	ioport32_t	irq_pending2;
+
+	ioport32_t	fiq_control;
+
+	ioport32_t	irq_enable[3];
+	ioport32_t	irq_disable[3];
+} bcm2835_irc_t;
+
+#define BCM2835_IRC_ADDR 0x2000b200
+#define BCM2835_IRQ_COUNT 96
+
+static inline void bcm2835_irc_dump(bcm2835_irc_t *regs)
+{
+#define DUMP_REG(name) \
+	printf("%s : %08x\n", #name, regs->name);
+
+	DUMP_REG(irq_basic_pending);
+	DUMP_REG(irq_pending1);
+	DUMP_REG(irq_pending2);
+	DUMP_REG(fiq_control);
+
+	for (int i = 0; i < 3; ++i) {
+		DUMP_REG(irq_enable[i]);
+		DUMP_REG(irq_disable[i]);
+	}
+#undef DUMP_REG
+}
+
+static inline void bcm2835_irc_init(bcm2835_irc_t *regs)
+{
+	/* Disable all interrupts */
+	regs->irq_disable[BANK_GPU0] = 0xffffffff;
+	regs->irq_disable[BANK_GPU1] = 0xffffffff;
+	regs->irq_disable[BANK_ARM]  = 0xffffffff;
+
+	/* Disable FIQ generation */
+	regs->fiq_control = 0;
+}
+
+static inline int ffs(unsigned int x)
+{
+	int ret;
+
+	asm volatile (
+		"clz r0, %[x]\n"
+		"rsb %[ret], r0, #32\n"
+		: [ret] "=r" (ret)
+		: [x] "r" (x)
+		: "r0" );
+
+	return ret;
+}
+
+static inline unsigned bcm2835_irc_inum_get(bcm2835_irc_t *regs)
+{
+	uint32_t pending;
+	int inum = -1;
+
+	pending = regs->irq_basic_pending;
+
+	/*
+	 * The basic pending register shows interrupts pending from ARM
+	 * peripherals and it also contains, in order to speed up processing,
+	 * additional information about pending GPU interrupts:
+	 *
+	 *  - bits 0-7 are associated to ARM peripherals
+	 *  - bit 8 is 1 when at least one bit is set in pending register 1
+	 *  - bit 9 is 1 when at least one bit is set in pending register 2
+	 *  - bits 10-20 indicate pending status of selected GPU peripherals
+	 *
+	 *  Reference: BCM2835 ARM Peripherals, p.113
+	 */
+
+	if (pending & IRQ_PEND_ARM_M) {
+		inum = MAKE_IRQ(BANK_ARM, ffs(pending & IRQ_PEND_ARM_M) - 1);
+	} else if (pending & IRQ_PEND_SHORT_M) {
+		int pos = (pending & IRQ_PEND_SHORT_M) >> IRQ_PEND_SHORT_S;
+		inum = shortcut_inums[ffs(pos) - 1];
+	} else if (pending & IRQ_PEND_GPU0_M) {
+		inum = MAKE_IRQ(BANK_GPU0, ffs(regs->irq_pending1) - 1);
+	} else if (pending & IRQ_PEND_GPU1_M) {
+		inum = MAKE_IRQ(BANK_GPU1, ffs(regs->irq_pending2) - 1);
+	}
+
+	if (inum < 0) {
+		printf("Spurious interrupt!\n");
+		bcm2835_irc_dump(regs);
+		inum = 0;
+	}
+
+	return inum;
+}
+
+static inline void bcm2835_irc_enable(bcm2835_irc_t *regs, unsigned inum)
+{
+	ASSERT(inum < BCM2835_IRQ_COUNT);
+	regs->irq_enable[IRQ_TO_BANK(inum)] |= (1 << IRQ_TO_NUM(inum));
+}
+
+static inline void bcm2835_irc_disable(bcm2835_irc_t *regs, unsigned inum)
+{
+	ASSERT(inum < BCM2835_IRQ_COUNT);
+	regs->irq_disable[IRQ_TO_BANK(inum)] |= (1 << IRQ_TO_NUM(inum));
+}
+
+#endif /* KERN_BCM2835_IRQC_H_ */
+
+/**
+ * @}
+ */
Index: kernel/genarch/include/genarch/drivers/bcm2835/mbox.h
===================================================================
--- kernel/genarch/include/genarch/drivers/bcm2835/mbox.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/genarch/include/genarch/drivers/bcm2835/mbox.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief BCM2835 mailbox communication routines
+ */
+
+#ifndef _BCM2835_MBOX_H_
+#define _BCM2835_MBOX_H_
+
+#include <genarch/fb/fb.h>
+#include <arch/mm/page.h>
+#include <align.h>
+
+#define BCM2835_MBOX0_ADDR	0x2000B880
+
+enum {
+	MBOX_CHAN_PM		= 0,
+	MBOX_CHAN_FB		= 1,
+	MBOX_CHAN_UART		= 2,
+	MBOX_CHAN_VCHIQ		= 3,
+	MBOX_CHAN_LED		= 4,
+	MBOX_CHAN_BTN		= 5,
+	MBOX_CHAN_TS		= 6,
+	MBOX_CHAN_PROP_A2V	= 8,
+	MBOX_CHAN_PROP_V2A	= 9
+};
+
+enum {
+	TAG_GET_FW_REV		= 0x00000001,
+	TAG_GET_BOARD_MODEL	= 0x00010001,
+	TAG_GET_BOARD_REV	= 0x00010002,
+	TAG_GET_BOARD_MAC	= 0x00010003,
+	TAG_GET_BOARD_SERIAL	= 0x00010004,
+	TAG_GET_ARM_MEMORY	= 0x00010005,
+	TAG_GET_VC_MEMORY	= 0x00010006,
+	TAG_GET_CLOCKS		= 0x00010007,
+	TAG_GET_CMD_LINE	= 0x00050001,
+};
+
+enum {
+	MBOX_PROP_CODE_REQ	= 0x00000000,
+	MBOX_PROP_CODE_RESP_OK	= 0x80000000,
+	MBOX_PROP_CODE_RESP_ERR	= 0x80000001
+};
+
+#define MBOX_STATUS_FULL	(1 << 31)
+#define MBOX_STATUS_EMPTY	(1 << 30)
+
+#define MBOX_COMPOSE(chan, value) (((chan) & 0xf) | ((value) & ~0xf))
+#define MBOX_MSG_CHAN(msg)	((msg) & 0xf)
+#define MBOX_MSG_VALUE(msg)	((msg) & ~0xf)
+
+#define KA2VCA(addr)		(KA2PA(addr) + 0x40000000)
+
+#define MBOX_ADDR_ALIGN		16
+
+#define MBOX_BUFF_ALLOC(name, type)					\
+	char tmp_ ## name[sizeof(type) + MBOX_ADDR_ALIGN] = { 0 };      \
+	type *name = (type *)ALIGN_UP((uintptr_t)tmp_ ## name, MBOX_ADDR_ALIGN);
+
+typedef struct {
+	ioport32_t read;
+	ioport32_t unused[3];
+	ioport32_t peek;
+	ioport32_t sender;
+	ioport32_t status;
+	ioport32_t config;
+	ioport32_t write;
+} bcm2835_mbox_t;
+
+typedef struct {
+	ioport32_t size;
+	ioport32_t code;
+} mbox_prop_buf_hdr_t;
+
+typedef struct {
+	ioport32_t tag_id;
+	ioport32_t buf_size;
+	ioport32_t val_len;
+} mbox_tag_hdr_t;
+
+typedef struct {
+	ioport32_t base;
+	ioport32_t size;
+} mbox_tag_getmem_resp_t;
+
+typedef struct {
+	mbox_prop_buf_hdr_t	buf_hdr;
+	mbox_tag_hdr_t		tag_hdr;
+	mbox_tag_getmem_resp_t	data;
+	uint32_t		zero;
+} mbox_getmem_buf_t;
+
+typedef struct {
+	ioport32_t width;
+	ioport32_t height;
+	ioport32_t virt_width;
+	ioport32_t virt_height;
+	ioport32_t pitch;
+	ioport32_t bpp;
+	ioport32_t x_offset;
+	ioport32_t y_offset;
+	ioport32_t addr;
+	ioport32_t size;
+} bcm2835_fb_desc_t;
+
+bool bcm2835_prop_get_memory(uint32_t *base, uint32_t *size);
+bool bcm2835_fb_init(fb_properties_t *prop);
+
+#endif
+/**
+ * @}
+ */
Index: kernel/genarch/include/genarch/drivers/bcm2835/timer.h
===================================================================
--- kernel/genarch/include/genarch/drivers/bcm2835/timer.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/genarch/include/genarch/drivers/bcm2835/timer.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief Broadcom BCM2835 system timer driver.
+ */
+
+#ifndef KERN_BCM2835_TIMER_H_
+
+#include <typedefs.h>
+#include <mm/km.h>
+
+#define BCM2835_TIMER_ADDR 0x20003000
+#define BCM2835_CLOCK_FREQ 1000000
+
+typedef struct {
+	/** System Timer Control/Status */
+	ioport32_t cs;
+#define BCM2835_TIMER_CS_M0 (1 << 0)
+#define BCM2835_TIMER_CS_M1 (1 << 1)
+#define BCM2835_TIMER_CS_M2 (1 << 2)
+#define BCM2835_TIMER_CS_M3 (1 << 3)
+	/** System Timer Counter Lower 32 bits */
+	ioport32_t clo;
+	/** System Timer Counter Higher 32 bits */
+	ioport32_t chi;
+	/** System Timer Compare 0 */
+	ioport32_t c0;
+	/** System Timer Compare 1 */
+	ioport32_t c1;
+	/** System Timer Compare 2 */
+	ioport32_t c2;
+	/** System Timer Compare 3 */
+	ioport32_t c3;
+} bcm2835_timer_t;
+
+
+static inline void bcm2835_timer_start(bcm2835_timer_t* timer)
+{
+	ASSERT(timer);
+	/* Clear pending interrupt on channel 1 */
+	timer->cs |= BCM2835_TIMER_CS_M1;
+	/* Initialize compare value for match channel 1 */
+	timer->c1 = timer->clo + (BCM2835_CLOCK_FREQ / HZ);
+}
+
+static inline void bcm2835_timer_irq_ack(bcm2835_timer_t* timer)
+{
+	ASSERT(timer);
+	/* Clear pending interrupt on channel 1 */
+	timer->cs |= BCM2835_TIMER_CS_M1;
+	/* Reprogram compare value for match channel 1 */
+	timer->c1 = timer->clo + (BCM2835_CLOCK_FREQ / HZ);
+}
+
+#endif /* KERN_BCM2835_TIMER_H_ */
Index: kernel/genarch/include/genarch/drivers/pl011/pl011.h
===================================================================
--- kernel/genarch/include/genarch/drivers/pl011/pl011.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/genarch/include/genarch/drivers/pl011/pl011.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief ARM PrimeCell PL011 UART driver.
+ */
+
+#ifndef KERN_PL011_H_
+#define KERN_PL011_H_
+
+#include <ddi/irq.h>
+#include <console/chardev.h>
+#include <typedefs.h>
+
+/** PrimeCell UART TRM ch. 3.3 (p. 49 in the pdf) */
+typedef struct {
+	/** UART data register */
+	ioport32_t data;
+#define PL011_UART_DATA_DATA_MASK   0xff
+#define PL011_UART_DATA_FE_FLAG   (1 <<  7)
+#define PL011_UART_DATA_PE_FLAG   (1 <<  9)
+#define PL011_UART_DATA_BE_FLAG   (1 << 10)
+#define PL011_UART_DATA_OE_FLAG   (1 << 11)
+
+	union {
+		/* Same values that are in upper bits of data register*/
+		const ioport32_t status;
+#define PL011_UART_STATUS_FE_FLAG   (1 << 0)
+#define PL011_UART_STATUS_PE_FLAG   (1 << 1)
+#define PL011_UART_STATUS_BE_FLAG   (1 << 2)
+#define PL011_UART_STATUS_OE_FLAG   (1 << 3)
+		/* Writing anything clears all errors */
+		ioport32_t error_clear;
+	};
+	uint32_t padd0_[4];
+
+	const ioport32_t flag;
+#define PL011_UART_FLAG_CTS_FLAG    (1 << 0)
+#define PL011_UART_FLAG_DSR_FLAG    (1 << 1)
+#define PL011_UART_FLAG_DCD_FLAG    (1 << 2)
+#define PL011_UART_FLAG_BUSY_FLAG   (1 << 3)
+#define PL011_UART_FLAG_RXFE_FLAG   (1 << 4)
+#define PL011_UART_FLAG_TXFF_FLAG   (1 << 5)
+#define PL011_UART_FLAG_RXFF_FLAG   (1 << 6)
+#define PL011_UART_FLAG_TXFE_FLAG   (1 << 7)
+#define PL011_UART_FLAG_RI_FLAG     (1 << 8)
+	uint32_t padd1_;
+
+	ioport32_t irda_low_power;
+#define PL011_UART_IRDA_LOW_POWER_MASK   0xff
+
+	ioport32_t int_baud_divisor;
+#define PL011_UART_INT_BAUD_DIVISOR_MASK   0xffff
+
+	ioport32_t fract_baud_divisor;
+#define PL011_UART_FRACT_BAUD_DIVISOR_MASK   0x1f
+
+	ioport32_t line_control_high;
+#define PL011_UART_CONTROLHI_BRK_FLAG    (1 << 0)
+#define PL011_UART_CONTROLHI_PEN_FLAG    (1 << 1)
+#define PL011_UART_CONTROLHI_EPS_FLAG    (1 << 2)
+#define PL011_UART_CONTROLHI_STP2_FLAG   (1 << 3)
+#define PL011_UART_CONTROLHI_FEN_FLAG    (1 << 4)
+#define PL011_UART_CONTROLHI_WLEN_MASK   0x3
+#define PL011_UART_CONTROLHI_WLEN_SHIFT    5
+#define PL011_UART_CONTROLHI_SPS_FLAG    (1 << 5)
+
+	ioport32_t control;
+#define PL011_UART_CONTROL_UARTEN_FLAG   (1 << 0)
+#define PL011_UART_CONTROL_SIREN_FLAG    (1 << 1)
+#define PL011_UART_CONTROL_SIRLP_FLAG    (1 << 2)
+#define PL011_UART_CONTROL_LBE_FLAG      (1 << 7)
+#define PL011_UART_CONTROL_TXE_FLAG      (1 << 8)
+#define PL011_UART_CONTROL_RXE_FLAG      (1 << 9)
+#define PL011_UART_CONTROL_DTR_FLAG     (1 << 10)
+#define PL011_UART_CONTROL_RTS_FLAG     (1 << 11)
+#define PL011_UART_CONTROL_OUT1_FLAG    (1 << 12)
+#define PL011_UART_CONTROL_OUT2_FLAG    (1 << 13)
+#define PL011_UART_CONTROL_RTSE_FLAG    (1 << 14)
+#define PL011_UART_CONTROL_CTSE_FLAG    (1 << 15)
+
+	ioport32_t interrupt_fifo;
+#define PL011_UART_INTERRUPTFIFO_TX_MASK   0x7
+#define PL011_UART_INTERRUPTFIFO_TX_SHIFT    0
+#define PL011_UART_INTERRUPTFIFO_RX_MASK   0x7
+#define PL011_UART_INTERRUPTFIFO_RX_SHIFT    3
+
+	/** Interrupt mask register */
+	ioport32_t interrupt_mask;
+	/** Pending interrupts before applying the mask */
+	const ioport32_t raw_interrupt_status;
+	/** Pending interrupts after applying the mask */
+	const ioport32_t masked_interrupt_status;
+	/** Write 1s to clear pending interrupts */
+	ioport32_t interrupt_clear;
+#define PL011_UART_INTERRUPT_RIM_FLAG    (1 << 0)
+#define PL011_UART_INTERRUPT_CTSM_FLAG   (1 << 1)
+#define PL011_UART_INTERRUPT_DCDM_FLAG   (1 << 2)
+#define PL011_UART_INTERRUPT_DSRM_FLAG   (1 << 3)
+#define PL011_UART_INTERRUPT_RX_FLAG     (1 << 4)
+#define PL011_UART_INTERRUPT_TX_FLAG     (1 << 5)
+#define PL011_UART_INTERRUPT_RT_FLAG     (1 << 6)
+#define PL011_UART_INTERRUPT_FE_FLAG     (1 << 7)
+#define PL011_UART_INTERRUPT_PE_FLAG     (1 << 8)
+#define PL011_UART_INTERRUPT_BE_FLAG     (1 << 9)
+#define PL011_UART_INTERRUPT_OE_FLAG    (1 << 10)
+#define PL011_UART_INTERRUPT_ALL           0x3ff
+
+	ioport32_t dma_control;
+#define PL011_UART_DMACONTROL_RXDMAEN_FLAG    (1 << 0)
+#define PL011_UART_DMACONTROL_TXDMAEN_FLAG    (1 << 1)
+#define PL011_UART_DMACONTROL_DMAONERR_FLAG   (1 << 2)
+
+	// TODO There is some reserved space here followed by
+	// peripheral identification registers.
+} pl011_uart_regs_t;
+
+typedef struct {
+	pl011_uart_regs_t *regs;
+	indev_t *indev;
+	outdev_t outdev;
+	irq_t irq;
+} pl011_uart_t;
+
+bool pl011_uart_init(pl011_uart_t *, inr_t, uintptr_t);
+void pl011_uart_input_wire(pl011_uart_t *, indev_t *);
+
+#endif
+/**
+ * @}
+ */
Index: kernel/genarch/src/acpi/acpi.c
===================================================================
--- kernel/genarch/src/acpi/acpi.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/genarch/src/acpi/acpi.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -41,5 +41,5 @@
 #include <mm/page.h>
 #include <mm/km.h>
-#include <print.h>
+#include <log.h>
 
 #define RSDP_SIGNATURE      "RSD PTR "
@@ -211,10 +211,10 @@
 	
 	if ((acpi_rsdt) && (!acpi_sdt_check((uint8_t *) acpi_rsdt))) {
-		printf("RSDT: bad checksum\n");
+		log(LF_ARCH, LVL_ERROR, "RSDT: bad checksum");
 		return;
 	}
 	
 	if ((acpi_xsdt) && (!acpi_sdt_check((uint8_t *) acpi_xsdt))) {
-		printf("XSDT: bad checksum\n");
+		log(LF_ARCH, LVL_ERROR, "XSDT: bad checksum");
 		return;
 	}
Index: kernel/genarch/src/acpi/madt.c
===================================================================
--- kernel/genarch/src/acpi/madt.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/genarch/src/acpi/madt.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,5 +43,5 @@
 #include <debug.h>
 #include <config.h>
-#include <print.h>
+#include <log.h>
 #include <mm/slab.h>
 #include <memstr.h>
@@ -236,5 +236,6 @@
 		case MADT_L_SAPIC:
 		case MADT_PLATFORM_INTR_SRC:
-			printf("MADT: Skipping %s entry (type=%" PRIu8 ")\n",
+			log(LF_ARCH, LVL_WARN,
+			    "MADT: Skipping %s entry (type=%" PRIu8 ")",
 			    entry[hdr->type], hdr->type);
 			break;
@@ -242,9 +243,11 @@
 			if ((hdr->type >= MADT_RESERVED_SKIP_BEGIN)
 			    && (hdr->type <= MADT_RESERVED_SKIP_END))
-				printf("MADT: Skipping reserved entry (type=%" PRIu8 ")\n",
+				log(LF_ARCH, LVL_NOTE,
+				    "MADT: Skipping reserved entry (type=%" PRIu8 ")",
 				    hdr->type);
 				
 			if (hdr->type >= MADT_RESERVED_OEM_BEGIN)
-				printf("MADT: Skipping OEM entry (type=%" PRIu8 ")\n",
+				log(LF_ARCH, LVL_NOTE,
+				    "MADT: Skipping OEM entry (type=%" PRIu8 ")",
 				    hdr->type);
 			
Index: rnel/genarch/src/drivers/arm926_uart/arm926_uart.c
===================================================================
--- kernel/genarch/src/drivers/arm926_uart/arm926_uart.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ 	(revision )
@@ -1,140 +1,0 @@
-/*
- * Copyright (c) 2012 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup genarch
- * @{
- */
-/**
- * @file
- * @brief ARM926 on-chip UART (PrimeCell UART, PL011) driver.
- */
-
-#include <genarch/drivers/arm926_uart/arm926_uart.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <ddi/device.h>
-#include <arch/asm.h>
-#include <mm/slab.h>
-#include <mm/page.h>
-#include <mm/km.h>
-#include <sysinfo/sysinfo.h>
-#include <str.h>
-
-static void arm926_uart_sendb(arm926_uart_t *uart, uint8_t byte)
-{
-	/* Wait for space becoming available in Tx FIFO. */
-	// TODO make pio_read accept consts pointers and remove the cast
-	while ((pio_read_32((ioport32_t*)&uart->regs->flag) & ARM926_UART_FLAG_TXFF_FLAG) != 0)
-		;
-
-	pio_write_32(&uart->regs->data, byte);
-}
-
-static void arm926_uart_putchar(outdev_t *dev, wchar_t ch)
-{
-	arm926_uart_t *uart = dev->data;
-
-	if (!ascii_check(ch)) {
-		arm926_uart_sendb(uart, U_SPECIAL);
-	} else {
-		if (ch == '\n')
-			arm926_uart_sendb(uart, (uint8_t) '\r');
-		arm926_uart_sendb(uart, (uint8_t) ch);
-	}
-}
-
-static outdev_operations_t arm926_uart_ops = {
-	.write = arm926_uart_putchar,
-	.redraw = NULL,
-};
-
-static irq_ownership_t arm926_uart_claim(irq_t *irq)
-{
-	return IRQ_ACCEPT;
-}
-
-static void arm926_uart_irq_handler(irq_t *irq)
-{
-	arm926_uart_t *uart = irq->instance;
-
-	// TODO make pio_read accept const pointers and remove the cast
-	while ((pio_read_32((ioport32_t*)&uart->regs->flag) & ARM926_UART_FLAG_RXFE_FLAG) == 0) {
-		/* We ignore all error flags here */
-		const uint8_t data = pio_read_32(&uart->regs->data);
-		if (uart->indev)
-			indev_push_character(uart->indev, data);
-	}
-	/* Ack interrupts */
-	pio_write_32(&uart->regs->interrupt_clear, ARM926_UART_INTERRUPT_ALL);
-}
-
-bool arm926_uart_init(
-    arm926_uart_t *uart, inr_t interrupt, uintptr_t addr, size_t size)
-{
-	ASSERT(uart);
-	uart->regs = (void*)km_map(addr, size, PAGE_NOT_CACHEABLE);
-
-	ASSERT(uart->regs);
-
-	/* Enable hw flow control */
-	uart->regs->control = 0 |
-	    ARM926_UART_CONTROL_UARTEN_FLAG |
-	    ARM926_UART_CONTROL_RTSE_FLAG |
-	    ARM926_UART_CONTROL_CTSE_FLAG;
-
-	/* Mask all interrupts */
-	uart->regs->interrupt_mask = 0;
-
-	outdev_initialize("arm926_uart_dev", &uart->outdev, &arm926_uart_ops);
-	uart->outdev.data = uart;
-
-	/* Initialize IRQ */
-	irq_initialize(&uart->irq);
-        uart->irq.devno = device_assign_devno();
-        uart->irq.inr = interrupt;
-        uart->irq.claim = arm926_uart_claim;
-        uart->irq.handler = arm926_uart_irq_handler;
-        uart->irq.instance = uart;
-
-	return true;
-}
-
-void arm926_uart_input_wire(arm926_uart_t *uart, indev_t *indev)
-{
-	ASSERT(uart);
-	ASSERT(indev);
-
-	uart->indev = indev;
-	irq_register(&uart->irq);
-	/* Enable receive interrupt */
-	uart->regs->interrupt_mask |= ARM926_UART_INTERRUPT_RX_FLAG;
-}
-
-/** @}
- */
-
Index: kernel/genarch/src/drivers/bcm2835/mbox.c
===================================================================
--- kernel/genarch/src/drivers/bcm2835/mbox.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/genarch/src/drivers/bcm2835/mbox.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief BCM2835 mailbox communication routines
+ */
+
+#include <mm/km.h>
+#include <typedefs.h>
+#include <genarch/drivers/bcm2835/mbox.h>
+
+static void mbox_write(bcm2835_mbox_t *mbox, uint8_t chan, uint32_t value)
+{
+	while (mbox->status & MBOX_STATUS_FULL) ;
+	mbox->write = MBOX_COMPOSE(chan, value);
+}
+
+static uint32_t mbox_read(bcm2835_mbox_t *mbox, uint8_t chan)
+{
+	uint32_t msg;
+
+	do {
+		while (mbox->status & MBOX_STATUS_EMPTY) ;
+		msg = mbox->read;
+	} while (MBOX_MSG_CHAN(msg) != chan);
+
+	return MBOX_MSG_VALUE(msg);
+}
+
+bool bcm2835_prop_get_memory(uint32_t *base, uint32_t *size)
+{
+	bool ret;
+	MBOX_BUFF_ALLOC(req, mbox_getmem_buf_t);
+
+	req->buf_hdr.size = sizeof(mbox_getmem_buf_t);
+	req->buf_hdr.code = MBOX_PROP_CODE_REQ;
+	req->tag_hdr.tag_id = TAG_GET_ARM_MEMORY;
+	req->tag_hdr.buf_size = sizeof(mbox_tag_getmem_resp_t);
+	req->tag_hdr.val_len = 0;
+	req->zero = 0;
+
+	mbox_write((bcm2835_mbox_t *)BCM2835_MBOX0_ADDR,
+		   MBOX_CHAN_PROP_A2V, KA2VCA((uint32_t)req));
+	mbox_read((bcm2835_mbox_t *)BCM2835_MBOX0_ADDR,
+		  MBOX_CHAN_PROP_A2V);
+
+	if (req->buf_hdr.code == MBOX_PROP_CODE_RESP_OK) {
+		*base = req->data.base;
+		*size = req->data.size;
+		ret = true;
+	} else {
+		ret = false;
+	}
+
+	return ret;
+}
+
+bool bcm2835_fb_init(fb_properties_t *prop)
+{
+	bcm2835_mbox_t *fb_mbox;
+	bool ret = false;
+        MBOX_BUFF_ALLOC(fb_desc, bcm2835_fb_desc_t);
+
+	fb_mbox = (void *) km_map(BCM2835_MBOX0_ADDR, sizeof(bcm2835_mbox_t),
+				  PAGE_NOT_CACHEABLE);
+
+	fb_desc->width = 640;
+	fb_desc->height = 480;
+	fb_desc->virt_width = fb_desc->width;
+	fb_desc->virt_height = fb_desc->height;
+	fb_desc->pitch = 0;			/* Set by VC */
+	fb_desc->bpp = 16;
+	fb_desc->x_offset = 0;
+	fb_desc->y_offset = 0;
+	fb_desc->addr = 0;			/* Set by VC */
+	fb_desc->size = 0;			/* Set by VC */
+
+	mbox_write(fb_mbox, MBOX_CHAN_FB, KA2VCA(fb_desc));
+
+	if (mbox_read(fb_mbox, MBOX_CHAN_FB)) {
+		printf("BCM2835 framebuffer initialization failed\n");
+		goto out;
+	}
+
+	prop->addr = fb_desc->addr;
+	prop->offset = 0;
+	prop->x = fb_desc->width;
+	prop->y = fb_desc->height;
+	prop->scan = fb_desc->pitch;
+	prop->visual = VISUAL_RGB_5_6_5_LE;
+
+	printf("BCM2835 framebuffer at 0x%08x (%dx%d)\n", prop->addr,
+	       prop->x, prop->y);
+	ret = true;
+out:
+	km_unmap((uintptr_t)fb_mbox, sizeof(bcm2835_mbox_t));
+	return ret;
+}
+
+/**
+ * @}
+ */
Index: kernel/genarch/src/drivers/pl011/pl011.c
===================================================================
--- kernel/genarch/src/drivers/pl011/pl011.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/genarch/src/drivers/pl011/pl011.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief ARM PrimeCell PL011 UART driver.
+ */
+
+#include <genarch/drivers/pl011/pl011.h>
+#include <console/chardev.h>
+#include <console/console.h>
+#include <ddi/device.h>
+#include <arch/asm.h>
+#include <mm/slab.h>
+#include <mm/page.h>
+#include <mm/km.h>
+#include <sysinfo/sysinfo.h>
+#include <str.h>
+
+static void pl011_uart_sendb(pl011_uart_t *uart, uint8_t byte)
+{
+	/* Wait for space becoming available in Tx FIFO. */
+	// TODO make pio_read accept consts pointers and remove the cast
+	while ((pio_read_32((ioport32_t*)&uart->regs->flag) & PL011_UART_FLAG_TXFF_FLAG) != 0)
+		;
+
+	pio_write_32(&uart->regs->data, byte);
+}
+
+static void pl011_uart_putchar(outdev_t *dev, wchar_t ch)
+{
+	pl011_uart_t *uart = dev->data;
+
+	if (!ascii_check(ch)) {
+		pl011_uart_sendb(uart, U_SPECIAL);
+	} else {
+		if (ch == '\n')
+			pl011_uart_sendb(uart, (uint8_t) '\r');
+		pl011_uart_sendb(uart, (uint8_t) ch);
+	}
+}
+
+static outdev_operations_t pl011_uart_ops = {
+	.write = pl011_uart_putchar,
+	.redraw = NULL,
+};
+
+static irq_ownership_t pl011_uart_claim(irq_t *irq)
+{
+	return IRQ_ACCEPT;
+}
+
+static void pl011_uart_irq_handler(irq_t *irq)
+{
+	pl011_uart_t *uart = irq->instance;
+
+	// TODO make pio_read accept const pointers and remove the cast
+	while ((pio_read_32((ioport32_t*)&uart->regs->flag) & PL011_UART_FLAG_RXFE_FLAG) == 0) {
+		/* We ignore all error flags here */
+		const uint8_t data = pio_read_32(&uart->regs->data);
+		if (uart->indev)
+			indev_push_character(uart->indev, data);
+	}
+	/* Ack interrupts */
+	pio_write_32(&uart->regs->interrupt_clear, PL011_UART_INTERRUPT_ALL);
+}
+
+bool pl011_uart_init(pl011_uart_t *uart, inr_t interrupt, uintptr_t addr)
+{
+	ASSERT(uart);
+	uart->regs = (void*)km_map(addr, sizeof(pl011_uart_regs_t),
+				   PAGE_NOT_CACHEABLE);
+	ASSERT(uart->regs);
+
+	/* Disable UART */
+	uart->regs->control &= ~ PL011_UART_CONTROL_UARTEN_FLAG;
+
+	/* Enable hw flow control */
+	uart->regs->control |=
+		PL011_UART_CONTROL_RTSE_FLAG |
+		PL011_UART_CONTROL_CTSE_FLAG;
+
+	/* Mask all interrupts */
+	uart->regs->interrupt_mask = 0;
+	/* Clear interrupts */
+	uart->regs->interrupt_clear = PL011_UART_INTERRUPT_ALL;
+	/* Enable UART, TX and RX */
+	uart->regs->control |=
+		PL011_UART_CONTROL_UARTEN_FLAG |
+		PL011_UART_CONTROL_TXE_FLAG |
+		PL011_UART_CONTROL_RXE_FLAG;
+
+	outdev_initialize("pl011_uart_dev", &uart->outdev, &pl011_uart_ops);
+	uart->outdev.data = uart;
+
+	/* Initialize IRQ */
+	irq_initialize(&uart->irq);
+	uart->irq.devno = device_assign_devno();
+	uart->irq.inr = interrupt;
+	uart->irq.claim = pl011_uart_claim;
+	uart->irq.handler = pl011_uart_irq_handler;
+	uart->irq.instance = uart;
+
+	return true;
+}
+
+void pl011_uart_input_wire(pl011_uart_t *uart, indev_t *indev)
+{
+	ASSERT(uart);
+	ASSERT(indev);
+
+	uart->indev = indev;
+	irq_register(&uart->irq);
+	/* Enable receive interrupts */
+	uart->regs->interrupt_mask |=
+		PL011_UART_INTERRUPT_RX_FLAG |
+		PL011_UART_INTERRUPT_RT_FLAG;
+}
+
+/** @}
+ */
+
Index: kernel/genarch/src/drivers/via-cuda/cuda.c
===================================================================
--- kernel/genarch/src/drivers/via-cuda/cuda.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/genarch/src/drivers/via-cuda/cuda.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -118,5 +118,5 @@
 }
 
-#include <print.h>
+#include <log.h>
 void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin)
 {
@@ -197,5 +197,5 @@
 
 	if ((b & TREQ) != 0) {
-		printf("cuda_irq_listen: no TREQ?!\n");
+		log(LF_OTHER, LVL_ERROR, "cuda_irq_listen: no TREQ?!");
 		return;
 	}
Index: kernel/generic/include/console/console.h
===================================================================
--- kernel/generic/include/console/console.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/include/console/console.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -39,4 +39,5 @@
 #include <print.h>
 #include <console/chardev.h>
+#include <synch/spinlock.h>
 
 #define PAGING(counter, increment, before, after) \
@@ -62,10 +63,13 @@
 extern void console_init(void);
 
-extern void klog_init(void);
-extern void klog_update(void *);
+extern void kio_init(void);
+extern void kio_update(void *);
+extern void kio_flush(void);
+extern void kio_push_char(const wchar_t);
+SPINLOCK_EXTERN(kio_lock);
 
 extern wchar_t getc(indev_t *indev);
 extern size_t gets(indev_t *indev, char *buf, size_t buflen);
-extern sysarg_t sys_klog(int cmd, const void *buf, size_t size);
+extern sysarg_t sys_kio(int cmd, const void *buf, size_t size);
 
 extern void grab_console(void);
Index: kernel/generic/include/debug.h
===================================================================
--- kernel/generic/include/debug.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/include/debug.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -107,5 +107,6 @@
 #define LOG(format, ...) \
 	do { \
-		printf("%s() from %s at %s:%u: " format "\n", __func__, \
+		log(LF_OTHER, LVL_DEBUG, \
+		    "%s() from %s at %s:%u: " format,__func__, \
 		    symtab_fmt_name_lookup(CALLER), __FILE__, __LINE__, \
 		    ##__VA_ARGS__); \
Index: kernel/generic/include/log.h
===================================================================
--- kernel/generic/include/log.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/generic/include/log.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericlog
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_LOG_H_
+#define KERN_LOG_H_
+
+#include <typedefs.h>
+#include <stdarg.h>
+#include <printf/verify.h>
+#include <abi/log.h>
+#include <abi/klog.h>
+
+extern void log_init(void);
+extern void log_begin(log_facility_t, log_level_t);
+extern void log_end(void);
+extern int log_vprintf(const char *, va_list);
+extern int log_printf(const char *, ...)
+    PRINTF_ATTRIBUTE(1, 2);
+extern int log(log_facility_t, log_level_t, const char *, ...)
+    PRINTF_ATTRIBUTE(3, 4);
+
+extern sysarg_t sys_klog(sysarg_t, void *buf, size_t size,
+    sysarg_t level);
+
+#endif /* KERN_LOG_H_ */
+
+/** @}
+ */
Index: kernel/generic/include/synch/spinlock.h
===================================================================
--- kernel/generic/include/synch/spinlock.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/include/synch/spinlock.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -137,5 +137,5 @@
 #ifdef CONFIG_DEBUG_SPINLOCK
 
-#include <print.h>
+#include <log.h>
 
 #define DEADLOCK_THRESHOLD  100000000
@@ -146,5 +146,6 @@
 	if ((pname)++ > (value)) { \
 		(pname) = 0; \
-		printf("Deadlock probe %s: exceeded threshold %u\n" \
+		log(LF_OTHER, LVL_WARN, \
+		    "Deadlock probe %s: exceeded threshold %u\n" \
 		    "cpu%u: function=%s, line=%u\n", \
 		    #pname, (value), CPU->id, __func__, __LINE__); \
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/console/cmd.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -45,4 +45,5 @@
 #include <console/kconsole.h>
 #include <print.h>
+#include <log.h>
 #include <panic.h>
 #include <typedefs.h>
@@ -639,5 +640,6 @@
 	for (i = 0; basic_commands[i]; i++) {
 		if (!cmd_register(basic_commands[i])) {
-			printf("Cannot register command %s\n",
+			log(LF_OTHER, LVL_ERROR,
+			    "Cannot register command %s",
 			    basic_commands[i]->name);
 		}
@@ -665,5 +667,5 @@
 	unsigned int _len = (unsigned int) len;
 	if ((_len != len) || (((int) _len) < 0)) {
-		printf("Command length overflow\n");
+		log(LF_OTHER, LVL_ERROR, "Command length overflow");
 		return 1;
 	}
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/console/console.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -52,32 +52,32 @@
 #include <errno.h>
 #include <str.h>
-#include <abi/klog.h>
-
-#define KLOG_PAGES    8
-#define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
+#include <abi/kio.h>
+
+#define KIO_PAGES    8
+#define KIO_LENGTH   (KIO_PAGES * PAGE_SIZE / sizeof(wchar_t))
 
 /** Kernel log cyclic buffer */
-wchar_t klog[KLOG_LENGTH] __attribute__((aligned(PAGE_SIZE)));
+wchar_t kio[KIO_LENGTH] __attribute__((aligned(PAGE_SIZE)));
 
 /** Kernel log initialized */
-static atomic_t klog_inited = {false};
+static atomic_t kio_inited = {false};
 
 /** First kernel log characters */
-static size_t klog_start = 0;
+static size_t kio_start = 0;
 
 /** Number of valid kernel log characters */
-static size_t klog_len = 0;
+static size_t kio_len = 0;
 
 /** Number of stored (not printed) kernel log characters */
-static size_t klog_stored = 0;
+static size_t kio_stored = 0;
 
 /** Number of stored kernel log characters for uspace */
-static size_t klog_uspace = 0;
+static size_t kio_uspace = 0;
 
 /** Kernel log spinlock */
-SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "klog_lock");
-
-/** Physical memory area used for klog buffer */
-static parea_t klog_parea;
+SPINLOCK_INITIALIZE_NAME(kio_lock, "kio_lock");
+
+/** Physical memory area used for kio buffer */
+static parea_t kio_parea;
 
 static indev_t stdin_sink;
@@ -146,21 +146,21 @@
  *
  */
-void klog_init(void)
-{
-	void *faddr = (void *) KA2PA(klog);
+void kio_init(void)
+{
+	void *faddr = (void *) KA2PA(kio);
 	
 	ASSERT((uintptr_t) faddr % FRAME_SIZE == 0);
 	
-	klog_parea.pbase = (uintptr_t) faddr;
-	klog_parea.frames = SIZE2FRAMES(sizeof(klog));
-	klog_parea.unpriv = false;
-	klog_parea.mapped = false;
-	ddi_parea_register(&klog_parea);
-	
-	sysinfo_set_item_val("klog.faddr", NULL, (sysarg_t) faddr);
-	sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES);
-	
-	event_set_unmask_callback(EVENT_KLOG, klog_update);
-	atomic_set(&klog_inited, true);
+	kio_parea.pbase = (uintptr_t) faddr;
+	kio_parea.frames = SIZE2FRAMES(sizeof(kio));
+	kio_parea.unpriv = false;
+	kio_parea.mapped = false;
+	ddi_parea_register(&kio_parea);
+	
+	sysinfo_set_item_val("kio.faddr", NULL, (sysarg_t) faddr);
+	sysinfo_set_item_val("kio.pages", NULL, KIO_PAGES);
+	
+	event_set_unmask_callback(EVENT_KIO, kio_update);
+	atomic_set(&kio_inited, true);
 }
 
@@ -247,18 +247,68 @@
 }
 
-void klog_update(void *event)
-{
-	if (!atomic_get(&klog_inited))
+void kio_update(void *event)
+{
+	if (!atomic_get(&kio_inited))
 		return;
 	
-	spinlock_lock(&klog_lock);
-	
-	if (klog_uspace > 0) {
-		if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
-		    klog_uspace) == EOK)
-			klog_uspace = 0;
-	}
-	
-	spinlock_unlock(&klog_lock);
+	spinlock_lock(&kio_lock);
+	
+	if (kio_uspace > 0) {
+		if (event_notify_3(EVENT_KIO, true, kio_start, kio_len,
+		    kio_uspace) == EOK)
+			kio_uspace = 0;
+	}
+	
+	spinlock_unlock(&kio_lock);
+}
+
+/** Flush characters that are stored in the output buffer
+ * 
+ */
+void kio_flush(void)
+{
+	bool ordy = ((stdout) && (stdout->op->write));
+	
+	if (!ordy)
+		return;
+
+	spinlock_lock(&kio_lock);
+
+	/* Print characters that weren't printed earlier */
+	while (kio_stored > 0) {
+		wchar_t tmp = kio[(kio_start + kio_len - kio_stored) % KIO_LENGTH];
+		kio_stored--;
+
+		/*
+		 * We need to give up the spinlock for
+		 * the physical operation of writing out
+		 * the character.
+		 */
+		spinlock_unlock(&kio_lock);
+		stdout->op->write(stdout, tmp);
+		spinlock_lock(&kio_lock);
+	}
+
+	spinlock_unlock(&kio_lock);
+}
+
+/** Put a character into the output buffer.
+ * 
+ * The caller is required to hold kio_lock
+ */
+void kio_push_char(const wchar_t ch)
+{
+	kio[(kio_start + kio_len) % KIO_LENGTH] = ch;
+	if (kio_len < KIO_LENGTH)
+		kio_len++;
+	else
+		kio_start = (kio_start + 1) % KIO_LENGTH;
+	
+	if (kio_stored < kio_len)
+		kio_stored++;
+	
+	/* The character is stored for uspace */
+	if (kio_uspace < kio_len)
+		kio_uspace++;
 }
 
@@ -267,48 +317,12 @@
 	bool ordy = ((stdout) && (stdout->op->write));
 	
-	spinlock_lock(&klog_lock);
-	
-	/* Print charaters stored in kernel log */
-	if (ordy) {
-		while (klog_stored > 0) {
-			wchar_t tmp = klog[(klog_start + klog_len - klog_stored) % KLOG_LENGTH];
-			klog_stored--;
-			
-			/*
-			 * We need to give up the spinlock for
-			 * the physical operation of writting out
-			 * the character.
-			 */
-			spinlock_unlock(&klog_lock);
-			stdout->op->write(stdout, tmp);
-			spinlock_lock(&klog_lock);
-		}
-	}
-	
-	/* Store character in the cyclic kernel log */
-	klog[(klog_start + klog_len) % KLOG_LENGTH] = ch;
-	if (klog_len < KLOG_LENGTH)
-		klog_len++;
-	else
-		klog_start = (klog_start + 1) % KLOG_LENGTH;
+	spinlock_lock(&kio_lock);
+	kio_push_char(ch);
+	spinlock_unlock(&kio_lock);
+	
+	/* Output stored characters */
+	kio_flush();
 	
 	if (!ordy) {
-		if (klog_stored < klog_len)
-			klog_stored++;
-	}
-	
-	/* The character is stored for uspace */
-	if (klog_uspace < klog_len)
-		klog_uspace++;
-	
-	spinlock_unlock(&klog_lock);
-	
-	if (ordy) {
-		/*
-		 * Output the character. In this case
-		 * it should be no longer buffered.
-		 */
-		stdout->op->write(stdout, ch);
-	} else {
 		/*
 		 * No standard output routine defined yet.
@@ -326,5 +340,5 @@
 	/* Force notification on newline */
 	if (ch == '\n')
-		klog_update(NULL);
+		kio_update(NULL);
 }
 
@@ -334,5 +348,5 @@
  *
  */
-sysarg_t sys_klog(int cmd, const void *buf, size_t size)
+sysarg_t sys_kio(int cmd, const void *buf, size_t size)
 {
 	char *data;
@@ -340,9 +354,9 @@
 
 	switch (cmd) {
-	case KLOG_UPDATE:
-		klog_update(NULL);
+	case KIO_UPDATE:
+		kio_update(NULL);
 		return EOK;
-	case KLOG_WRITE:
-	case KLOG_COMMAND:
+	case KIO_WRITE:
+	case KIO_COMMAND:
 		break;
 	default:
@@ -366,8 +380,8 @@
 		
 		switch (cmd) {
-		case KLOG_WRITE:
+		case KIO_WRITE:
 			printf("%s", data);
 			break;
-		case KLOG_COMMAND:
+		case KIO_COMMAND:
 			if (!stdin)
 				break;
Index: kernel/generic/src/lib/func.c
===================================================================
--- kernel/generic/src/lib/func.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/lib/func.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -37,5 +37,5 @@
 
 #include <func.h>
-#include <print.h>
+#include <log.h>
 #include <cpu.h>
 #include <arch/asm.h>
@@ -72,7 +72,7 @@
 	
 	if (CPU)
-		printf("cpu%u: halted\n", CPU->id);
+		log(LF_OTHER, LVL_NOTE, "cpu%u: halted", CPU->id);
 	else
-		printf("cpu: halted\n");
+		log(LF_OTHER, LVL_NOTE, "cpu: halted");
 	
 	cpu_halt();
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/lib/rd.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -38,5 +38,5 @@
  */
 
-#include <print.h>
+#include <log.h>
 #include <lib/rd.h>
 #include <mm/frame.h>
@@ -68,5 +68,6 @@
 	sysinfo_set_item_val("rd.address.physical", NULL, (sysarg_t) base);
 	
-	printf("RAM disk at %p (size %zu bytes)\n", (void *) base, size);
+	log(LF_OTHER, LVL_NOTE, "RAM disk at %p (size %zu bytes)", (void *) base,
+	    size);
 }
 
Index: kernel/generic/src/log/log.c
===================================================================
--- kernel/generic/src/log/log.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ kernel/generic/src/log/log.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericlog
+ * @{
+ */
+/** @file
+ */
+
+#include <sysinfo/sysinfo.h>
+#include <synch/spinlock.h>
+#include <typedefs.h>
+#include <ddi/irq.h>
+#include <ddi/ddi.h>
+#include <ipc/event.h>
+#include <ipc/irq.h>
+#include <arch.h>
+#include <panic.h>
+#include <putchar.h>
+#include <atomic.h>
+#include <syscall/copy.h>
+#include <errno.h>
+#include <str.h>
+#include <print.h>
+#include <printf/printf_core.h>
+#include <stdarg.h>
+#include <log.h>
+#include <console/console.h>
+#include <abi/log.h>
+
+#define LOG_PAGES    8
+#define LOG_LENGTH   (LOG_PAGES * PAGE_SIZE)
+#define LOG_ENTRY_HEADER_LENGTH (sizeof(size_t) + sizeof(uint32_t))
+
+/** Cyclic buffer holding the data for kernel log */
+uint8_t log_buffer[LOG_LENGTH] __attribute__((aligned(PAGE_SIZE)));
+
+/** Kernel log initialized */
+static atomic_t log_inited = {false};
+
+/** Position in the cyclic buffer where the first log entry starts */
+size_t log_start = 0;
+
+/** Sum of length of all log entries currently stored in the cyclic buffer */
+size_t log_used = 0;
+
+/** Log spinlock */
+SPINLOCK_STATIC_INITIALIZE_NAME(log_lock, "log_lock");
+
+/** Overall count of logged messages, which may overflow as needed */
+static uint32_t log_counter = 0;
+
+/** Starting position of the entry currently being written to the log */
+static size_t log_current_start = 0;
+
+/** Length (including header) of the entry currently being written to the log */
+static size_t log_current_len = 0;
+
+/** Start of the next entry to be handed to uspace starting from log_start */
+static size_t next_for_uspace = 0;
+
+static void log_update(void *);
+
+/** Initialize kernel logging facility
+ *
+ */
+void log_init(void)
+{	
+	event_set_unmask_callback(EVENT_KLOG, log_update);
+	atomic_set(&log_inited, true);
+}
+
+static size_t log_copy_from(uint8_t *data, size_t pos, size_t len) {
+	for (size_t i = 0; i < len; i++, pos = (pos + 1) % LOG_LENGTH) {
+		data[i] = log_buffer[pos];
+	}
+	return pos;
+}
+
+static size_t log_copy_to(const uint8_t *data, size_t pos, size_t len) {
+	for (size_t i = 0; i < len; i++, pos = (pos + 1) % LOG_LENGTH) {
+		log_buffer[pos] = data[i];
+	}
+	return pos;
+}
+
+/** Append data to the currently open log entry.
+ * 
+ * This function requires that the log_lock is acquired by the caller.
+ */
+static void log_append(const uint8_t *data, size_t len)
+{
+	/* Cap the length so that the entry entirely fits into the buffer */
+	if (len > LOG_LENGTH - log_current_len) {
+		len = LOG_LENGTH - log_current_len;
+	}
+	
+	if (len == 0)
+		return;
+	
+	size_t log_free = LOG_LENGTH - log_used - log_current_len;
+	
+	/* Discard older entries to make space, if necessary */
+	while (len > log_free) {
+		size_t entry_len;
+		log_copy_from((uint8_t *) &entry_len, log_start, sizeof(size_t));
+		log_start = (log_start + entry_len) % LOG_LENGTH;
+		log_used -= entry_len;
+		log_free += entry_len;
+		next_for_uspace -= entry_len;
+	}
+	
+	size_t pos = (log_current_start + log_current_len) % LOG_LENGTH;
+	log_copy_to(data, pos, len);
+	log_current_len += len;
+}
+
+/** Begin writing an entry to the log.
+ * 
+ * This acquires the log and output buffer locks, so only calls to log_* functions should
+ * be used until calling log_end.
+ */
+void log_begin(log_facility_t fac, log_level_t level)
+{
+	spinlock_lock(&log_lock);
+	spinlock_lock(&kio_lock);
+	
+	log_current_start = (log_start + log_used) % LOG_LENGTH;
+	log_current_len = 0;
+	
+	/* Write header of the log entry, the length will be written in log_end() */
+	log_append((uint8_t *) &log_current_len, sizeof(size_t));
+	log_append((uint8_t *) &log_counter, sizeof(uint32_t));
+	uint32_t fac32 = fac;
+	uint32_t lvl32 = level;
+	log_append((uint8_t *) &fac32, sizeof(uint32_t));
+	log_append((uint8_t *) &lvl32, sizeof(uint32_t));
+	
+	log_counter++;
+}
+
+/** Finish writing an entry to the log.
+ * 
+ * This releases the log and output buffer locks.
+ */
+void log_end(void) {
+	/* Set the length in the header to correct value */
+	log_copy_to((uint8_t *) &log_current_len, log_current_start, sizeof(size_t));
+	log_used += log_current_len;
+	
+	kio_push_char('\n');
+	spinlock_unlock(&kio_lock);
+	spinlock_unlock(&log_lock);
+	
+	/* This has to be called after we released the locks above */
+	kio_flush();
+	kio_update(NULL);
+	log_update(NULL);
+}
+
+static void log_update(void *event)
+{
+	if (!atomic_get(&log_inited))
+		return;
+	
+	spinlock_lock(&log_lock);
+	if (next_for_uspace < log_used)
+		event_notify_0(EVENT_KLOG, true);
+	spinlock_unlock(&log_lock);
+}
+
+static int log_printf_str_write(const char *str, size_t size, void *data)
+{
+	size_t offset = 0;
+	size_t chars = 0;
+	
+	while (offset < size) {
+		kio_push_char(str_decode(str, &offset, size));
+		chars++;
+	}
+	
+	log_append((const uint8_t *)str, size);
+	
+	return chars;
+}
+
+static int log_printf_wstr_write(const wchar_t *wstr, size_t size, void *data)
+{
+	char buffer[16];
+	size_t offset = 0;
+	size_t chars = 0;
+	
+	for (offset = 0; offset < size; offset += sizeof(wchar_t), chars++) {
+		kio_push_char(wstr[chars]);
+		
+		size_t buffer_offset = 0;
+		int rc = chr_encode(wstr[chars], buffer, &buffer_offset, 16);
+		if (rc != EOK) {
+			return rc;
+		}
+		
+		log_append((const uint8_t *)buffer, buffer_offset);
+	}
+	
+	return chars;
+}
+
+/** Append a message to the currently being written entry.
+ * 
+ * Requires that an entry has been started using log_begin()
+ */
+int log_vprintf(const char *fmt, va_list args)
+{
+	int ret;
+	
+	printf_spec_t ps = {
+		log_printf_str_write,
+		log_printf_wstr_write,
+		NULL
+	};
+	
+	
+	ret = printf_core(fmt, &ps, args);
+	
+	return ret;
+}
+
+/** Append a message to the currently being written entry.
+ * 
+ * Requires that an entry has been started using log_begin()
+ */
+int log_printf(const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+	
+	va_start(args, fmt);
+	ret = log_vprintf(fmt, args);
+	va_end(args);
+	
+	return ret;
+}
+
+/** Log a message to the kernel log.
+ * 
+ * This atomically appends a log entry.
+ * The resulting message should not contain a trailing newline, as the log
+ * entries are explicitly delimited when stored in the log.
+ */
+int log(log_facility_t fac, log_level_t level, const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+	
+	log_begin(fac, level);
+	
+	va_start(args, fmt);
+	ret = log_vprintf(fmt, args);
+	va_end(args);
+	
+	log_end();
+	
+	return ret;
+}
+
+/** Control of the log from uspace
+ *
+ */
+sysarg_t sys_klog(sysarg_t operation, void *buf, size_t size,
+    sysarg_t level)
+{
+	char *data;
+	int rc;
+	
+	if (size > PAGE_SIZE)
+		return (sysarg_t) ELIMIT;
+	
+	switch (operation) {
+		case KLOG_WRITE:
+			data = (char *) malloc(size + 1, 0);
+			if (!data)
+				return (sysarg_t) ENOMEM;
+			
+			rc = copy_from_uspace(data, buf, size);
+			if (rc) {
+				free(data);
+				return (sysarg_t) rc;
+			}
+			data[size] = 0;
+			
+			if (level >= LVL_LIMIT)
+				level = LVL_NOTE;
+			
+			log(LF_USPACE, level, "%s", data);
+			
+			free(data);
+			return EOK;
+		case KLOG_READ:
+			data = (char *) malloc(size, 0);
+			if (!data)
+				return (sysarg_t) ENOMEM;
+			
+			size_t entry_len = 0;
+			size_t copied = 0;
+			
+			rc = EOK;
+	
+			spinlock_lock(&log_lock);
+			
+			while (next_for_uspace < log_used) {
+				size_t pos = (log_start + next_for_uspace) % LOG_LENGTH;
+				log_copy_from((uint8_t *) &entry_len, pos, sizeof(size_t));
+				
+				if (entry_len > PAGE_SIZE) {
+					/* 
+					 * Since we limit data transfer
+					 * to uspace to a maximum of PAGE_SIZE
+					 * bytes, skip any entries larger
+					 * than this limit to prevent
+					 * userspace being stuck trying to
+					 * read them.
+					 */
+					next_for_uspace += entry_len;
+					continue;
+				}
+				
+				if (size < copied + entry_len) {
+					if (copied == 0)
+						rc = EOVERFLOW;
+					break;
+				}
+				
+				log_copy_from((uint8_t *) (data + copied), pos, entry_len);
+				copied += entry_len;
+				next_for_uspace += entry_len;
+			}
+			
+			spinlock_unlock(&log_lock);
+			
+			if (rc != EOK) {
+				free(data);
+				return (sysarg_t) rc;
+			}
+			
+			rc = copy_to_uspace(buf, data, size);
+			
+			free(data);
+			
+			if (rc != EOK)
+				return (sysarg_t) rc;
+			
+			return copied;
+		default:
+			return (sysarg_t) ENOTSUP;
+	}
+}
+
+
+/** @}
+ */
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/main/kinit.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -59,4 +59,5 @@
 #include <mm/km.h>
 #include <print.h>
+#include <log.h>
 #include <memstr.h>
 #include <console/console.h>
@@ -140,5 +141,6 @@
 				thread_ready(thread);
 			} else
-				printf("Unable to create kcpulb thread for cpu%u\n", i);
+				log(LF_OTHER, LVL_ERROR,
+				    "Unable to create kcpulb thread for cpu%u", i);
 		}
 	}
@@ -156,5 +158,5 @@
 		thread_ready(thread);
 	else
-		printf("Unable to create kload thread\n");
+		log(LF_OTHER, LVL_ERROR, "Unable to create kload thread");
 	
 #ifdef CONFIG_KCONSOLE
@@ -168,5 +170,6 @@
 			thread_ready(thread);
 		else
-			printf("Unable to create kconsole thread\n");
+			log(LF_OTHER, LVL_ERROR,
+			    "Unable to create kconsole thread");
 	}
 #endif /* CONFIG_KCONSOLE */
@@ -210,5 +213,6 @@
 	for (i = 0; i < init.cnt; i++) {
 		if (init.tasks[i].paddr % FRAME_SIZE) {
-			printf("init[%zu]: Address is not frame aligned\n", i);
+			log(LF_OTHER, LVL_ERROR,
+			    "init[%zu]: Address is not frame aligned", i);
 			programs[i].task = NULL;
 			continue;
@@ -273,6 +277,7 @@
 			init_rd((void *) init.tasks[i].paddr, init.tasks[i].size);
 		} else
-			printf("init[%zu]: Init binary load failed "
-			    "(error %d, loader status %u)\n", i, rc,
+			log(LF_OTHER, LVL_ERROR,
+			    "init[%zu]: Init binary load failed "
+			    "(error %d, loader status %u)", i, rc,
 			    programs[i].loader_status);
 	}
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/main/main.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -62,4 +62,5 @@
 #include <console/kconsole.h>
 #include <console/console.h>
+#include <log.h>
 #include <cpu.h>
 #include <align.h>
@@ -281,5 +282,6 @@
 	ipc_init();
 	event_init();
-	klog_init();
+	kio_init();
+	log_init();
 	stats_init();
 	
Index: kernel/generic/src/main/shutdown.c
===================================================================
--- kernel/generic/src/main/shutdown.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/main/shutdown.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -39,4 +39,5 @@
 #include <func.h>
 #include <print.h>
+#include <log.h>
 
 void reboot(void)
@@ -45,5 +46,5 @@
 	
 #ifdef CONFIG_DEBUG
-	printf("Rebooting the system\n");
+	log(LF_OTHER, LVL_DEBUG, "Rebooting the system");
 #endif
 	
Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/mm/frame.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -54,4 +54,5 @@
 #include <arch.h>
 #include <print.h>
+#include <log.h>
 #include <align.h>
 #include <mm/slab.h>
@@ -121,5 +122,6 @@
 {
 	if (zones.count + 1 == ZONES_MAX) {
-		printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
+		log(LF_OTHER, LVL_ERROR, "Maximum zone count %u exceeded!",
+		    ZONES_MAX);
 		return (size_t) -1;
 	}
@@ -141,6 +143,7 @@
 			    (!iswithin(zones.info[i].base, zones.info[i].count,
 			    base, count))) {
-				printf("Zone (%p, %p) overlaps "
-				    "with previous zone (%p %p)!\n",
+				log(LF_OTHER, LVL_WARN,
+				    "Zone (%p, %p) overlaps "
+				    "with previous zone (%p %p)!",
 				    (void *) PFN2ADDR(base), (void *) PFN2ADDR(count),
 				    (void *) PFN2ADDR(zones.info[i].base),
@@ -913,6 +916,7 @@
 		
 #ifdef CONFIG_DEBUG
-		printf("Thread %" PRIu64 " waiting for %zu frames "
-		    "(%zu available).\n", THREAD->tid, count, avail);
+		log(LF_OTHER, LVL_DEBUG,
+		    "Thread %" PRIu64 " waiting for %zu frames "
+		    "%zu available.", THREAD->tid, count, avail);
 #endif
 		
@@ -938,5 +942,6 @@
 		
 #ifdef CONFIG_DEBUG
-		printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
+		log(LF_OTHER, LVL_DEBUG, "Thread %" PRIu64 " woken up.",
+		    THREAD->tid);
 #endif
 		
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/proc/program.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -49,5 +49,5 @@
 #include <lib/elf_load.h>
 #include <errno.h>
-#include <print.h>
+#include <log.h>
 #include <syscall/copy.h>
 #include <proc/program.h>
@@ -155,5 +155,5 @@
 		
 		program_loader = image_addr;
-		printf("Program loader at %p\n", (void *) image_addr);
+		log(LF_OTHER, LVL_NOTE, "Program loader at %p", (void *) image_addr);
 		
 		return EOK;
@@ -181,5 +181,6 @@
 	if (!loader) {
 		as_destroy(as);
-		printf("Cannot spawn loader as none was registered\n");
+		log(LF_OTHER, LVL_ERROR,
+		    "Cannot spawn loader as none was registered");
 		return ENOENT;
 	}
@@ -189,5 +190,5 @@
 	if (prg->loader_status != EE_OK) {
 		as_destroy(as);
-		printf("Cannot spawn loader (%s)\n",
+		log(LF_OTHER, LVL_ERROR, "Cannot spawn loader (%s)",
 		    elf_error(prg->loader_status));
 		return ENOENT;
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/proc/scheduler.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -61,4 +61,5 @@
 #include <cpu.h>
 #include <print.h>
+#include <log.h>
 #include <debug.h>
 #include <stacktrace.h>
@@ -517,6 +518,7 @@
 	
 #ifdef SCHEDULER_VERBOSE
-	printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
-	    ", nrdy=%" PRIua ")\n", CPU->id, THREAD->tid, THREAD->priority,
+	log(LF_OTHER, LVL_DEBUG,
+	    "cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
+	    ", nrdy=%" PRIua ")", CPU->id, THREAD->tid, THREAD->priority,
 	    THREAD->ticks, atomic_get(&CPU->nrdy));
 #endif
@@ -663,6 +665,7 @@
 				
 #ifdef KCPULB_VERBOSE
-				printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, "
-				    "nrdy=%ld, avg=%ld\n", CPU->id, t->tid,
+				log(LF_OTHER, LVL_DEBUG,
+				    "kcpulb%u: TID %" PRIu64 " -> cpu%u, "
+				    "nrdy=%ld, avg=%ld", CPU->id, t->tid,
 				    CPU->id, atomic_get(&CPU->nrdy),
 				    atomic_get(&nrdy) / config.cpu_active);
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ kernel/generic/src/syscall/syscall.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -56,4 +56,5 @@
 #include <console/console.h>
 #include <udebug/udebug.h>
+#include <log.h>
 
 /** Dispatch system call */
@@ -86,5 +87,6 @@
 		rc = syscall_table[id](a1, a2, a3, a4, a5, a6);
 	} else {
-		printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id);
+		log(LF_OTHER, LVL_ERROR,
+		    "Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id);
 		task_kill_self(true);
 	}
@@ -120,5 +122,5 @@
 syshandler_t syscall_table[SYSCALL_END] = {
 	/* System management syscalls. */
-	(syshandler_t) sys_klog,
+	(syshandler_t) sys_kio,
 	(syshandler_t) sys_tls_set,
 	
@@ -190,5 +192,7 @@
 	
 	/* Kernel console syscalls. */
-	(syshandler_t) sys_debug_activate_console
+	(syshandler_t) sys_debug_activate_console,
+	
+	(syshandler_t) sys_klog,
 };
 
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -50,5 +50,5 @@
 	app/kill \
 	app/killall \
-	app/klog \
+	app/kio \
 	app/loc \
 	app/logset \
@@ -92,4 +92,5 @@
 	srv/locsrv \
 	srv/logger \
+	srv/klog \
 	srv/devman \
 	srv/loader \
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/app/init/init.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -336,4 +336,5 @@
 		srv_start("/srv/tmpfs");
 	
+	srv_start("/srv/klog");
 	srv_start("/srv/locfs");
 	srv_start("/srv/taskmon");
Index: uspace/app/kio/Makefile
===================================================================
--- uspace/app/kio/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/app/kio/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBCLUI_PREFIX)/libclui.a
+EXTRA_CFLAGS = -I$(LIBCLUI_PREFIX)
+BINARY = kio
+
+SOURCES = \
+	kio.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/kio/kio.c
===================================================================
--- uspace/app/kio/kio.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/app/kio/kio.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kio KIO
+ * @brief HelenOS KIO
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <async.h>
+#include <as.h>
+#include <ddi.h>
+#include <event.h>
+#include <errno.h>
+#include <str_error.h>
+#include <io/kio.h>
+#include <sysinfo.h>
+#include <malloc.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <adt/prodcons.h>
+#include <tinput.h>
+
+#define NAME       "kio"
+#define LOG_FNAME  "/log/kio"
+
+/* Producer/consumer buffers */
+typedef struct {
+	link_t link;
+	size_t length;
+	wchar_t *data;
+} item_t;
+
+static prodcons_t pc;
+
+/* Pointer to kio area */
+static wchar_t *kio;
+static size_t kio_length;
+
+/* Notification mutex */
+static FIBRIL_MUTEX_INITIALIZE(mtx);
+
+/** Klog producer
+ *
+ * Copies the contents of a character buffer to local
+ * producer/consumer queue.
+ *
+ * @param length Number of characters to copy.
+ * @param data   Pointer to the kernel kio buffer.
+ *
+ */
+static void producer(size_t length, wchar_t *data)
+{
+	item_t *item = (item_t *) malloc(sizeof(item_t));
+	if (item == NULL)
+		return;
+	
+	size_t sz = sizeof(wchar_t) * length;
+	wchar_t *buf = (wchar_t *) malloc(sz);
+	if (data == NULL) {
+		free(item);
+		return;
+	}
+	
+	memcpy(buf, data, sz);
+	
+	link_initialize(&item->link);
+	item->length = length;
+	item->data = buf;
+	prodcons_produce(&pc, &item->link);
+}
+
+/** Klog consumer
+ *
+ * Waits in an infinite loop for the character data created by
+ * the producer and outputs them to stdout and optionally into
+ * a file.
+ *
+ * @param data Unused.
+ *
+ * @return Always EOK (unreachable).
+ *
+ */
+static int consumer(void *data)
+{
+	FILE *log = fopen(LOG_FNAME, "a");
+	if (log == NULL)
+		printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
+		    str_error(errno));
+	
+	while (true) {
+		link_t *link = prodcons_consume(&pc);
+		item_t *item = list_get_instance(link, item_t, link);
+		
+		for (size_t i = 0; i < item->length; i++)
+			putchar(item->data[i]);
+		
+		if (log != NULL) {
+			for (size_t i = 0; i < item->length; i++)
+				fputc(item->data[i], log);
+			
+			fflush(log);
+			fsync(fileno(log));
+		}
+		
+		free(item->data);
+		free(item);
+	}
+	
+	fclose(log);
+	return EOK;
+}
+
+/** Kernel notification handler
+ *
+ * Receives kernel kio notifications.
+ *
+ * @param callid IPC call ID
+ * @param call   IPC call structure
+ * @param arg    Local argument
+ *
+ */
+static void notification_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	/*
+	 * Make sure we process only a single notification
+	 * at any time to limit the chance of the consumer
+	 * starving.
+	 *
+	 * Note: Usually the automatic masking of the kio
+	 * notifications on the kernel side does the trick
+	 * of limiting the chance of accidentally copying
+	 * the same data multiple times. However, due to
+	 * the non-blocking architecture of kio notifications,
+	 * this possibility cannot be generally avoided.
+	 */
+	
+	fibril_mutex_lock(&mtx);
+	
+	size_t kio_start = (size_t) IPC_GET_ARG1(*call);
+	size_t kio_len = (size_t) IPC_GET_ARG2(*call);
+	size_t kio_stored = (size_t) IPC_GET_ARG3(*call);
+	
+	size_t offset = (kio_start + kio_len - kio_stored) % kio_length;
+	
+	/* Copy data from the ring buffer */
+	if (offset + kio_stored >= kio_length) {
+		size_t split = kio_length - offset;
+		
+		producer(split, kio + offset);
+		producer(kio_stored - split, kio);
+	} else
+		producer(kio_stored, kio + offset);
+	
+	event_unmask(EVENT_KIO);
+	fibril_mutex_unlock(&mtx);
+}
+
+int main(int argc, char *argv[])
+{
+	size_t pages;
+	int rc = sysinfo_get_value("kio.pages", &pages);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to get number of kio pages\n",
+		    NAME);
+		return rc;
+	}
+	
+	uintptr_t faddr;
+	rc = sysinfo_get_value("kio.faddr", &faddr);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to get kio physical address\n",
+		    NAME);
+		return rc;
+	}
+	
+	size_t size = pages * PAGE_SIZE;
+	kio_length = size / sizeof(wchar_t);
+	
+	rc = physmem_map(faddr, pages, AS_AREA_READ | AS_AREA_CACHEABLE,
+	    (void *) &kio);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to map kio\n", NAME);
+		return rc;
+	}
+	
+	prodcons_initialize(&pc);
+	async_set_interrupt_received(notification_received);
+	rc = event_subscribe(EVENT_KIO, 0);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to register kio notifications\n",
+		    NAME);
+		return rc;
+	}
+	
+	fid_t fid = fibril_create(consumer, NULL);
+	if (!fid) {
+		fprintf(stderr, "%s: Unable to create consumer fibril\n",
+		    NAME);
+		return ENOMEM;
+	}
+	
+	tinput_t *input = tinput_new();
+	if (!input) {
+		fprintf(stderr, "%s: Could not create input\n", NAME);
+		return ENOMEM;
+	}	
+
+	fibril_add_ready(fid);
+	event_unmask(EVENT_KIO);
+	kio_update();
+	
+	tinput_set_prompt(input, "kio> ");
+
+	char *str;
+	while ((rc = tinput_read(input, &str)) == EOK) {
+		if (str_cmp(str, "") == 0) {
+			free(str);
+			continue;
+		}
+
+		kio_command(str, str_size(str));
+		free(str);
+	}
+ 
+	if (rc == ENOENT)
+		rc = EOK;	
+
+	return EOK;
+}
+
+/** @}
+ */
Index: pace/app/klog/Makefile
===================================================================
--- uspace/app/klog/Makefile	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBCLUI_PREFIX)/libclui.a
-EXTRA_CFLAGS = -I$(LIBCLUI_PREFIX)
-BINARY = klog
-
-SOURCES = \
-	klog.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ 	(revision )
@@ -1,261 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup klog KLog
- * @brief HelenOS KLog
- * @{
- */
-/**
- * @file
- */
-
-#include <stdio.h>
-#include <async.h>
-#include <as.h>
-#include <ddi.h>
-#include <event.h>
-#include <errno.h>
-#include <str_error.h>
-#include <io/klog.h>
-#include <sysinfo.h>
-#include <malloc.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <adt/prodcons.h>
-#include <tinput.h>
-
-#define NAME       "klog"
-#define LOG_FNAME  "/log/klog"
-
-/* Producer/consumer buffers */
-typedef struct {
-	link_t link;
-	size_t length;
-	wchar_t *data;
-} item_t;
-
-static prodcons_t pc;
-
-/* Pointer to klog area */
-static wchar_t *klog;
-static size_t klog_length;
-
-/* Notification mutex */
-static FIBRIL_MUTEX_INITIALIZE(mtx);
-
-/** Klog producer
- *
- * Copies the contents of a character buffer to local
- * producer/consumer queue.
- *
- * @param length Number of characters to copy.
- * @param data   Pointer to the kernel klog buffer.
- *
- */
-static void producer(size_t length, wchar_t *data)
-{
-	item_t *item = (item_t *) malloc(sizeof(item_t));
-	if (item == NULL)
-		return;
-	
-	size_t sz = sizeof(wchar_t) * length;
-	wchar_t *buf = (wchar_t *) malloc(sz);
-	if (data == NULL) {
-		free(item);
-		return;
-	}
-	
-	memcpy(buf, data, sz);
-	
-	link_initialize(&item->link);
-	item->length = length;
-	item->data = buf;
-	prodcons_produce(&pc, &item->link);
-}
-
-/** Klog consumer
- *
- * Waits in an infinite loop for the character data created by
- * the producer and outputs them to stdout and optionally into
- * a file.
- *
- * @param data Unused.
- *
- * @return Always EOK (unreachable).
- *
- */
-static int consumer(void *data)
-{
-	FILE *log = fopen(LOG_FNAME, "a");
-	if (log == NULL)
-		printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
-		    str_error(errno));
-	
-	while (true) {
-		link_t *link = prodcons_consume(&pc);
-		item_t *item = list_get_instance(link, item_t, link);
-		
-		for (size_t i = 0; i < item->length; i++)
-			putchar(item->data[i]);
-		
-		if (log != NULL) {
-			for (size_t i = 0; i < item->length; i++)
-				fputc(item->data[i], log);
-			
-			fflush(log);
-			fsync(fileno(log));
-		}
-		
-		free(item->data);
-		free(item);
-	}
-	
-	fclose(log);
-	return EOK;
-}
-
-/** Kernel notification handler
- *
- * Receives kernel klog notifications.
- *
- * @param callid IPC call ID
- * @param call   IPC call structure
- * @param arg    Local argument
- *
- */
-static void notification_received(ipc_callid_t callid, ipc_call_t *call)
-{
-	/*
-	 * Make sure we process only a single notification
-	 * at any time to limit the chance of the consumer
-	 * starving.
-	 *
-	 * Note: Usually the automatic masking of the klog
-	 * notifications on the kernel side does the trick
-	 * of limiting the chance of accidentally copying
-	 * the same data multiple times. However, due to
-	 * the non-blocking architecture of klog notifications,
-	 * this possibility cannot be generally avoided.
-	 */
-	
-	fibril_mutex_lock(&mtx);
-	
-	size_t klog_start = (size_t) IPC_GET_ARG1(*call);
-	size_t klog_len = (size_t) IPC_GET_ARG2(*call);
-	size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
-	
-	size_t offset = (klog_start + klog_len - klog_stored) % klog_length;
-	
-	/* Copy data from the ring buffer */
-	if (offset + klog_stored >= klog_length) {
-		size_t split = klog_length - offset;
-		
-		producer(split, klog + offset);
-		producer(klog_stored - split, klog);
-	} else
-		producer(klog_stored, klog + offset);
-	
-	event_unmask(EVENT_KLOG);
-	fibril_mutex_unlock(&mtx);
-}
-
-int main(int argc, char *argv[])
-{
-	size_t pages;
-	int rc = sysinfo_get_value("klog.pages", &pages);
-	if (rc != EOK) {
-		fprintf(stderr, "%s: Unable to get number of klog pages\n",
-		    NAME);
-		return rc;
-	}
-	
-	uintptr_t faddr;
-	rc = sysinfo_get_value("klog.faddr", &faddr);
-	if (rc != EOK) {
-		fprintf(stderr, "%s: Unable to get klog physical address\n",
-		    NAME);
-		return rc;
-	}
-	
-	size_t size = pages * PAGE_SIZE;
-	klog_length = size / sizeof(wchar_t);
-	
-	rc = physmem_map(faddr, pages, AS_AREA_READ | AS_AREA_CACHEABLE,
-	    (void *) &klog);
-	if (rc != EOK) {
-		fprintf(stderr, "%s: Unable to map klog\n", NAME);
-		return rc;
-	}
-	
-	prodcons_initialize(&pc);
-	async_set_interrupt_received(notification_received);
-	rc = event_subscribe(EVENT_KLOG, 0);
-	if (rc != EOK) {
-		fprintf(stderr, "%s: Unable to register klog notifications\n",
-		    NAME);
-		return rc;
-	}
-	
-	fid_t fid = fibril_create(consumer, NULL);
-	if (!fid) {
-		fprintf(stderr, "%s: Unable to create consumer fibril\n",
-		    NAME);
-		return ENOMEM;
-	}
-	
-	tinput_t *input = tinput_new();
-	if (!input) {
-		fprintf(stderr, "%s: Could not create input\n", NAME);
-		return ENOMEM;
-	}	
-
-	fibril_add_ready(fid);
-	event_unmask(EVENT_KLOG);
-	klog_update();
-	
-	tinput_set_prompt(input, "klog> ");
-
-	char *str;
-	while ((rc = tinput_read(input, &str)) == EOK) {
-		if (str_cmp(str, "") == 0) {
-			free(str);
-			continue;
-		}
-
-		klog_command(str, str_size(str));
-		free(str);
-	}
- 
-	if (rc == ENOENT)
-		rc = EOK;	
-
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/app/trace/syscalls.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -38,5 +38,5 @@
 
 const sc_desc_t syscall_desc[] = {
-    [SYS_KLOG] ={ "klog",				3,	V_INT_ERRNO },
+    [SYS_KIO] ={ "kio",					3,	V_INT_ERRNO },
     [SYS_TLS_SET] = { "tls_set",			1,	V_ERRNO },
 
Index: uspace/app/vdemo/vdemo.c
===================================================================
--- uspace/app/vdemo/vdemo.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/app/vdemo/vdemo.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -110,5 +110,5 @@
 {
 	if (argc >= 2) {
-		window_t *main_window = window_open(argv[1], true, true, "vdemo", 0, 0);
+		window_t *main_window = window_open(argv[1], true, true, "vdemo");
 		if (!main_window) {
 			printf("Cannot open main window.\n");
@@ -117,12 +117,18 @@
 
 		pixel_t grd_bg = PIXEL(255, 240, 240, 240);
-		pixel_t btn_bg = PIXEL(255, 0, 0, 0);
-		pixel_t btn_fg = PIXEL(255, 240, 240, 240);
+		
+		pixel_t btn_bg = PIXEL(255, 240, 240, 240);
+		pixel_t btn_fg = PIXEL(255, 186, 186, 186);
+		pixel_t btn_text = PIXEL(255, 0, 0, 0);
+		
 		pixel_t lbl_bg = PIXEL(255, 240, 240, 240);
-		pixel_t lbl_fg = PIXEL(255, 0, 0, 0);
+		pixel_t lbl_text = PIXEL(255, 0, 0, 0);
 
-		my_label_t *lbl_action = create_my_label(NULL, "Hello there!", 16, lbl_bg, lbl_fg);
-		button_t *btn_confirm = create_button(NULL, "Confirm", 16, btn_bg, btn_fg);
-		button_t *btn_cancel = create_button(NULL, "Cancel", 16, btn_bg, btn_fg);
+		my_label_t *lbl_action = create_my_label(NULL, "Hello there!", 16,
+		    lbl_bg, lbl_text);
+		button_t *btn_confirm = create_button(NULL, "Confirm", 16, btn_bg,
+		    btn_fg, btn_text);
+		button_t *btn_cancel = create_button(NULL, "Cancel", 16, btn_bg,
+		    btn_fg, btn_text);
 		grid_t *grid = create_grid(window_root(main_window), 2, 2, grd_bg);
 		if (!lbl_action || !btn_confirm || !btn_cancel || !grid) {
@@ -144,5 +150,6 @@
 		grid->add(grid, &btn_confirm->widget, 0, 1, 1, 1);
 		grid->add(grid, &btn_cancel->widget, 1, 1, 1, 1);
-		window_resize(main_window, 200, 76);
+		window_resize(main_window, 0, 0, 200, 76,
+		    WINDOW_PLACEMENT_CENTER);
 
 		window_exec(main_window);
Index: uspace/app/viewer/viewer.c
===================================================================
--- uspace/app/viewer/viewer.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/app/viewer/viewer.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -166,5 +166,5 @@
 	}
 	
-	main_window = window_open(argv[1], true, false, "viewer", 0, 0);
+	main_window = window_open(argv[1], true, false, "viewer");
 	if (!main_window) {
 		printf("Cannot open main window.\n");
@@ -192,5 +192,6 @@
 	}
 	
-	window_resize(main_window, WINDOW_WIDTH, WINDOW_HEIGHT);
+	window_resize(main_window, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
+	    WINDOW_PLACEMENT_ABSOLUTE);
 	window_exec(main_window);
 	
Index: uspace/app/vlaunch/vlaunch.c
===================================================================
--- uspace/app/vlaunch/vlaunch.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/app/vlaunch/vlaunch.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -115,5 +115,5 @@
 	
 	winreg = argv[1];
-	window_t *main_window = window_open(argv[1], true, true, "vlaunch", 0, 0);
+	window_t *main_window = window_open(argv[1], true, true, "vlaunch");
 	if (!main_window) {
 		printf("Cannot open main window.\n");
@@ -122,19 +122,22 @@
 	
 	pixel_t grd_bg = PIXEL(255, 255, 255, 255);
-	pixel_t btn_bg = PIXEL(255, 0, 0, 0);
-	pixel_t btn_fg = PIXEL(255, 240, 240, 240);
+	
+	pixel_t btn_bg = PIXEL(255, 255, 255, 255);
+	pixel_t btn_fg = PIXEL(255, 186, 186, 186);
+	pixel_t btn_text = PIXEL(255, 0, 0, 0);
+	
 	pixel_t lbl_bg = PIXEL(255, 255, 255, 255);
-	pixel_t lbl_fg = PIXEL(255, 0, 0, 0);
+	pixel_t lbl_text = PIXEL(255, 0, 0, 0);
 	
 	canvas_t *logo_canvas = create_canvas(NULL, LOGO_WIDTH, LOGO_HEIGHT,
 	    logo);
 	label_t *lbl_caption = create_label(NULL, "Launch application:", 16,
-	    lbl_bg, lbl_fg);
+	    lbl_bg, lbl_text);
 	button_t *btn_vterm = create_button(NULL, "vterm", 16, btn_bg,
-	    btn_fg);
+	    btn_fg, btn_text);
 	button_t *btn_vdemo = create_button(NULL, "vdemo", 16, btn_bg,
-	    btn_fg);
+	    btn_fg, btn_text);
 	button_t *btn_vlaunch = create_button(NULL, "vlaunch", 16, btn_bg,
-	    btn_fg);
+	    btn_fg, btn_text);
 	grid_t *grid = create_grid(window_root(main_window), 1, 5, grd_bg);
 	
@@ -156,5 +159,6 @@
 	grid->add(grid, &btn_vlaunch->widget, 0, 4, 1, 1);
 	
-	window_resize(main_window, 210, 130 + LOGO_HEIGHT);
+	window_resize(main_window, 0, 0, 210, 130 + LOGO_HEIGHT,
+	    WINDOW_PLACEMENT_RIGHT | WINDOW_PLACEMENT_TOP);
 	window_exec(main_window);
 	
Index: uspace/app/vterm/vterm.c
===================================================================
--- uspace/app/vterm/vterm.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/app/vterm/vterm.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -49,5 +49,5 @@
 	}
 	
-	window_t *main_window = window_open(argv[1], true, true, "vterm", 0, 0);
+	window_t *main_window = window_open(argv[1], true, true, "vterm");
 	if (!main_window) {
 		printf("%s: Cannot open main window.\n", NAME);
@@ -55,5 +55,5 @@
 	}
 	
-	window_resize(main_window, 650, 510);
+	window_resize(main_window, 0, 0, 648, 508, WINDOW_PLACEMENT_ANY);
 	terminal_t *terminal_widget =
 	    create_terminal(window_root(main_window), 640, 480);
Index: uspace/drv/infrastructure/rootmalta/rootmalta.c
===================================================================
--- uspace/drv/infrastructure/rootmalta/rootmalta.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/drv/infrastructure/rootmalta/rootmalta.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -52,7 +52,5 @@
 #include <ipc/dev_iface.h>
 #include <ops/hw_res.h>
-#include <device/hw_res.h>
 #include <ops/pio_window.h>
-#include <device/pio_window.h>
 #include <byteorder.h>
 
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -50,7 +50,5 @@
 #include <ipc/dev_iface.h>
 #include <ops/hw_res.h>
-#include <device/hw_res.h>
 #include <ops/pio_window.h>
-#include <device/pio_window.h>
 
 #define NAME "rootpc"
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -101,4 +101,5 @@
 	generic/io/log.c \
 	generic/io/logctl.c \
+	generic/io/kio.c \
 	generic/io/klog.c \
 	generic/io/snprintf.c \
Index: uspace/lib/c/generic/assert.c
===================================================================
--- uspace/lib/c/generic/assert.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/generic/assert.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -33,5 +33,5 @@
 #include <assert.h>
 #include <stdio.h>
-#include <io/klog.h>
+#include <io/kio.h>
 #include <stdlib.h>
 #include <atomic.h>
@@ -44,7 +44,7 @@
 {
 	/*
-	 * Send the message safely to klog. Nested asserts should not occur.
+	 * Send the message safely to kio. Nested asserts should not occur.
 	 */
-	klog_printf("Assertion failed (%s) in file \"%s\", line %u.\n",
+	kio_printf("Assertion failed (%s) in file \"%s\", line %u.\n",
 	    cond, file, line);
 	
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/generic/io/io.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -42,5 +42,5 @@
 #include <malloc.h>
 #include <async.h>
-#include <io/klog.h>
+#include <io/kio.h>
 #include <vfs/vfs.h>
 #include <vfs/vfs_sess.h>
@@ -57,5 +57,5 @@
 	.error = true,
 	.eof = true,
-	.klog = false,
+	.kio = false,
 	.sess = NULL,
 	.btype = _IONBF,
@@ -67,9 +67,9 @@
 };
 
-static FILE stdout_klog = {
+static FILE stdout_kio = {
 	.fd = -1,
 	.error = false,
 	.eof = false,
-	.klog = true,
+	.kio = true,
 	.sess = NULL,
 	.btype = _IOLBF,
@@ -81,9 +81,9 @@
 };
 
-static FILE stderr_klog = {
+static FILE stderr_kio = {
 	.fd = -1,
 	.error = false,
 	.eof = false,
-	.klog = true,
+	.kio = true,
 	.sess = NULL,
 	.btype = _IONBF,
@@ -113,5 +113,5 @@
 		stdout = fdopen(1, "w");
 	} else {
-		stdout = &stdout_klog;
+		stdout = &stdout_kio;
 		list_append(&stdout->link, &files);
 	}
@@ -120,5 +120,5 @@
 		stderr = fdopen(2, "w");
 	} else {
-		stderr = &stderr_klog;
+		stderr = &stderr_kio;
 		list_append(&stderr->link, &files);
 	}
@@ -267,5 +267,5 @@
 	stream->error = false;
 	stream->eof = false;
-	stream->klog = false;
+	stream->kio = false;
 	stream->sess = NULL;
 	stream->need_sync = false;
@@ -289,5 +289,5 @@
 	stream->error = false;
 	stream->eof = false;
-	stream->klog = false;
+	stream->kio = false;
 	stream->sess = NULL;
 	stream->need_sync = false;
@@ -314,6 +314,6 @@
 	
 	if ((stream != &stdin_null)
-	    && (stream != &stdout_klog)
-	    && (stream != &stderr_klog))
+	    && (stream != &stdout_kio)
+	    && (stream != &stderr_kio))
 		free(stream);
 	
@@ -382,6 +382,6 @@
 		ssize_t wr;
 		
-		if (stream->klog)
-			wr = klog_write(buf + done, left);
+		if (stream->kio)
+			wr = kio_write(buf + done, left);
 		else
 			wr = write(stream->fd, buf + done, left);
@@ -705,6 +705,6 @@
 	_fflushbuf(stream);
 	
-	if (stream->klog) {
-		klog_update();
+	if (stream->kio) {
+		kio_update();
 		return EOK;
 	}
@@ -740,5 +740,5 @@
 int fileno(FILE *stream)
 {
-	if (stream->klog) {
+	if (stream->kio) {
 		errno = EBADF;
 		return -1;
Index: uspace/lib/c/generic/io/kio.c
===================================================================
--- uspace/lib/c/generic/io/kio.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/lib/c/generic/io/kio.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2006 Jakub Vana
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <libc.h>
+#include <str.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <abi/kio.h>
+#include <io/kio.h>
+#include <io/printf_core.h>
+
+size_t kio_write(const void *buf, size_t size)
+{
+	ssize_t ret = (ssize_t) __SYSCALL3(SYS_KIO, KIO_WRITE, (sysarg_t) buf, size);
+	
+	if (ret >= 0)
+		return (size_t) ret;
+	
+	return 0;
+}
+
+void kio_update(void)
+{
+	(void) __SYSCALL3(SYS_KIO, KIO_UPDATE, (uintptr_t) NULL, 0);
+}
+
+void kio_command(const void *buf, size_t size)
+{
+	(void) __SYSCALL3(SYS_KIO, KIO_COMMAND, (sysarg_t) buf, (sysarg_t) size);
+}
+
+/** Print formatted text to kio.
+ *
+ * @param fmt Format string
+ *
+ * \see For more details about format string see printf_core.
+ *
+ */
+int kio_printf(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	
+	int ret = kio_vprintf(fmt, args);
+	
+	va_end(args);
+	
+	return ret;
+}
+
+static int kio_vprintf_str_write(const char *str, size_t size, void *data)
+{
+	size_t wr = kio_write(str, size);
+	return str_nlength(str, wr);
+}
+
+static int kio_vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
+{
+	size_t offset = 0;
+	size_t chars = 0;
+	
+	while (offset < size) {
+		char buf[STR_BOUNDS(1)];
+		size_t sz = 0;
+		
+		if (chr_encode(str[chars], buf, &sz, STR_BOUNDS(1)) == EOK)
+			kio_write(buf, sz);
+		
+		chars++;
+		offset += sizeof(wchar_t);
+	}
+	
+	return chars;
+}
+
+/** Print formatted text to kio.
+ *
+ * @param fmt Format string
+ * @param ap  Format parameters
+ *
+ * \see For more details about format string see printf_core.
+ *
+ */
+int kio_vprintf(const char *fmt, va_list ap)
+{
+	printf_spec_t ps = {
+		kio_vprintf_str_write,
+		kio_vprintf_wstr_write,
+		NULL
+	};
+	
+	return printf_core(fmt, &ps, ap);
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/klog.c
===================================================================
--- uspace/lib/c/generic/io/klog.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/generic/io/klog.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2006 Jakub Vana
+ * Copyright (c) 2013 Martin Sucha
  * All rights reserved.
  *
@@ -41,9 +40,10 @@
 #include <abi/klog.h>
 #include <io/klog.h>
-#include <io/printf_core.h>
+#include <abi/log.h>
 
-size_t klog_write(const void *buf, size_t size)
+size_t klog_write(log_level_t lvl, const void *buf, size_t size)
 {
-	ssize_t ret = (ssize_t) __SYSCALL3(SYS_KLOG, KLOG_WRITE, (sysarg_t) buf, size);
+	ssize_t ret = (ssize_t) __SYSCALL4(SYS_KLOG, KLOG_WRITE, (sysarg_t) buf,
+	    size, lvl);
 	
 	if (ret >= 0)
@@ -53,75 +53,7 @@
 }
 
-void klog_update(void)
+int klog_read(void *data, size_t size)
 {
-	(void) __SYSCALL3(SYS_KLOG, KLOG_UPDATE, (uintptr_t) NULL, 0);
-}
-
-void klog_command(const void *buf, size_t size)
-{
-	(void) __SYSCALL3(SYS_KLOG, KLOG_COMMAND, (sysarg_t) buf, (sysarg_t) size);
-}
-
-/** Print formatted text to klog.
- *
- * @param fmt Format string
- *
- * \see For more details about format string see printf_core.
- *
- */
-int klog_printf(const char *fmt, ...)
-{
-	va_list args;
-	va_start(args, fmt);
-	
-	int ret = klog_vprintf(fmt, args);
-	
-	va_end(args);
-	
-	return ret;
-}
-
-static int klog_vprintf_str_write(const char *str, size_t size, void *data)
-{
-	size_t wr = klog_write(str, size);
-	return str_nlength(str, wr);
-}
-
-static int klog_vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
-{
-	size_t offset = 0;
-	size_t chars = 0;
-	
-	while (offset < size) {
-		char buf[STR_BOUNDS(1)];
-		size_t sz = 0;
-		
-		if (chr_encode(str[chars], buf, &sz, STR_BOUNDS(1)) == EOK)
-			klog_write(buf, sz);
-		
-		chars++;
-		offset += sizeof(wchar_t);
-	}
-	
-	return chars;
-}
-
-/** Print formatted text to klog.
- *
- * @param fmt Format string
- * @param ap  Format parameters
- *
- * \see For more details about format string see printf_core.
- *
- */
-int klog_vprintf(const char *fmt, va_list ap)
-{
-	printf_spec_t ps = {
-		klog_vprintf_str_write,
-		klog_vprintf_wstr_write,
-		NULL
-	};
-	
-	return printf_core(fmt, &ps, ap);
+	return (int) __SYSCALL4(SYS_KLOG, KLOG_READ, (uintptr_t) data, size, 0);
 }
 
Index: uspace/lib/c/generic/io/window.c
===================================================================
--- uspace/lib/c/generic/io/window.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/generic/io/window.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -40,11 +40,10 @@
 #include <stdio.h>
 
-int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out, 
-    sysarg_t x_offset, sysarg_t y_offset)
+int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_2_2(exch, WINDOW_REGISTER, x_offset, y_offset, in, out);
+	int ret = async_req_0_2(exch, WINDOW_REGISTER, in, out);
 	async_exchange_end(exch);
-
+	
 	return ret;
 }
@@ -92,25 +91,26 @@
 }
 
-int win_resize(async_sess_t *sess, sysarg_t width, sysarg_t height, void *cells)
+int win_resize(async_sess_t *sess, sysarg_t x, sysarg_t y, sysarg_t width,
+    sysarg_t height, window_placement_flags_t placement_flags, void *cells)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
-
+	
 	ipc_call_t answer;
-	aid_t req = async_send_2(exch, WINDOW_RESIZE, width, height, &answer);
-
+	aid_t req = async_send_5(exch, WINDOW_RESIZE, x, y, width, height,
+	    (sysarg_t) placement_flags, &answer);
+	
 	int rc = async_share_out_start(exch, cells, AS_AREA_READ | AS_AREA_CACHEABLE);
-
+	
 	async_exchange_end(exch);
-
+	
 	sysarg_t ret;
 	async_wait_for(req, &ret);
-
-	if (rc != EOK) {
+	
+	if (rc != EOK)
 		return rc;
-	} else if (ret != EOK) {
+	else if (ret != EOK)
 		return ret;
-	} else {
-		return EOK;
-	}
+	
+	return EOK;
 }
 
Index: uspace/lib/c/generic/private/stdio.h
===================================================================
--- uspace/lib/c/generic/private/stdio.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/generic/private/stdio.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -53,6 +53,6 @@
 	int eof;
 	
-	/** Klog indicator */
-	int klog;
+	/** KIO indicator */
+	int kio;
 	
 	/** Session to the file provider */
Index: uspace/lib/c/include/io/kio.h
===================================================================
--- uspace/lib/c/include/io/kio.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/lib/c/include/io/kio.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006 Jakub Vana
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IO_KIO_H_
+#define LIBC_IO_KIO_H_
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <io/verify.h>
+
+extern size_t kio_write(const void *, size_t);
+extern void kio_update(void);
+extern void kio_command(const void *, size_t);
+extern int kio_printf(const char *, ...)
+    PRINTF_ATTRIBUTE(1, 2);
+extern int kio_vprintf(const char *, va_list);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/klog.h
===================================================================
--- uspace/lib/c/include/io/klog.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/include/io/klog.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Jakub Vana
+ * Copyright (c) 2013 Martin Sucha
  * All rights reserved.
  *
@@ -39,11 +39,26 @@
 #include <stdarg.h>
 #include <io/verify.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <abi/log.h>
 
-extern size_t klog_write(const void *, size_t);
-extern void klog_update(void);
-extern void klog_command(const void *, size_t);
-extern int klog_printf(const char *, ...)
-    PRINTF_ATTRIBUTE(1, 2);
-extern int klog_vprintf(const char *, va_list);
+extern size_t klog_write(log_level_t, const void *, size_t);
+extern int klog_read(void *, size_t);
+
+#define KLOG_PRINTF(lvl, fmt, ...) ({ \
+	char *_fmt = str_dup(fmt); \
+	size_t _fmtsize = str_size(_fmt); \
+	if (_fmtsize > 0 && _fmt[_fmtsize - 1] == '\n') \
+		_fmt[_fmtsize - 1] = 0; \
+	char *_s; \
+	int _c = asprintf(&_s, _fmt, ##__VA_ARGS__); \
+	free(_fmt); \
+	if (_c >= 0) { \
+		_c = klog_write((lvl), _s, str_size(_s)); \
+		free(_s); \
+	}; \
+	(_c >= 0); \
+})
 
 #endif
Index: uspace/lib/c/include/io/log.h
===================================================================
--- uspace/lib/c/include/io/log.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/include/io/log.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -39,22 +39,5 @@
 #include <io/verify.h>
 
-/** Log message level. */
-typedef enum {
-	/** Fatal error, program is not able to recover at all. */
-	LVL_FATAL,
-	/** Serious error but the program can recover from it. */
-	LVL_ERROR,
-	/** Easily recoverable problem. */
-	LVL_WARN,
-	/** Information message that ought to be printed by default. */
-	LVL_NOTE,
-	/** Debugging purpose message. */
-	LVL_DEBUG,
-	/** More detailed debugging message. */
-	LVL_DEBUG2,
-	
-	/** For checking range of values */
-	LVL_LIMIT
-} log_level_t;
+#include <abi/log.h>
 
 /** Log itself (logging target). */
Index: uspace/lib/c/include/io/window.h
===================================================================
--- uspace/lib/c/include/io/window.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/include/io/window.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -43,14 +43,43 @@
 #include <io/pos_event.h>
 
+typedef enum {
+	GF_EMPTY = 0,
+	GF_MOVE_X = 1,
+	GF_MOVE_Y = 2,
+	GF_RESIZE_X = 4,
+	GF_RESIZE_Y = 8,
+	GF_SCALE_X = 16,
+	GF_SCALE_Y = 32
+} window_grab_flags_t;
+
+typedef enum {
+	WINDOW_PLACEMENT_ANY = 0,
+	WINDOW_PLACEMENT_CENTER_X = 1,
+	WINDOW_PLACEMENT_CENTER_Y = 2,
+	WINDOW_PLACEMENT_CENTER =
+	    WINDOW_PLACEMENT_CENTER_X | WINDOW_PLACEMENT_CENTER_Y,
+	WINDOW_PLACEMENT_LEFT = 4,
+	WINDOW_PLACEMENT_RIGHT = 8,
+	WINDOW_PLACEMENT_TOP = 16,
+	WINDOW_PLACEMENT_BOTTOM = 32,
+	WINDOW_PLACEMENT_ABSOLUTE_X = 64,
+	WINDOW_PLACEMENT_ABSOLUTE_Y = 128,
+	WINDOW_PLACEMENT_ABSOLUTE =
+	    WINDOW_PLACEMENT_ABSOLUTE_X | WINDOW_PLACEMENT_ABSOLUTE_Y
+} window_placement_flags_t;
+
 typedef struct {
 	sysarg_t object;
 	sysarg_t slot;
 	sysarg_t argument;
-} sig_event_t;
+} signal_event_t;
 
 typedef struct {
+	sysarg_t offset_x;
+	sysarg_t offset_y;
 	sysarg_t width;
 	sysarg_t height;
-} rsz_event_t;
+	window_placement_flags_t placement_flags;
+} resize_event_t;
 
 typedef enum {
@@ -69,6 +98,6 @@
 	kbd_event_t kbd;
 	pos_event_t pos;
-	sig_event_t sig;
-	rsz_event_t rsz;
+	signal_event_t signal;
+	resize_event_t resize;
 } window_event_data_t;
 
@@ -79,15 +108,5 @@
 } window_event_t;
 
-typedef enum {
-	GF_EMPTY = 0,
-	GF_MOVE_X = 1,
-	GF_MOVE_Y = 2,
-	GF_RESIZE_X = 4,
-	GF_RESIZE_Y = 8,
-	GF_SCALE_X = 16,
-	GF_SCALE_Y = 32
-} window_grab_flags_t;
-
-extern int win_register(async_sess_t *, service_id_t *, service_id_t *, sysarg_t, sysarg_t);
+extern int win_register(async_sess_t *, service_id_t *, service_id_t *);
 
 extern int win_get_event(async_sess_t *, window_event_t *);
@@ -95,5 +114,6 @@
 extern int win_damage(async_sess_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
 extern int win_grab(async_sess_t *, sysarg_t, sysarg_t);
-extern int win_resize(async_sess_t *, sysarg_t, sysarg_t, void *);
+extern int win_resize(async_sess_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    window_placement_flags_t, void *);
 extern int win_close(async_sess_t *);
 extern int win_close_request(async_sess_t *);
Index: uspace/lib/c/include/stdio.h
===================================================================
--- uspace/lib/c/include/stdio.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/c/include/stdio.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -40,5 +40,5 @@
 #include <str.h>
 #include <io/verify.h>
-#include <abi/klog.h>
+#include <abi/kio.h>
 
 #define EOF  (-1)
@@ -52,5 +52,5 @@
 		int _n = snprintf(_buf, sizeof(_buf), fmt, ##__VA_ARGS__); \
 		if (_n > 0) \
-			(void) __SYSCALL3(SYS_KLOG, KLOG_WRITE, (sysarg_t) _buf, str_size(_buf)); \
+			(void) __SYSCALL3(SYS_KIO, KIO_WRITE, (sysarg_t) _buf, str_size(_buf)); \
 	}
 
Index: uspace/lib/draw/cursor/embedded.c
===================================================================
--- uspace/lib/draw/cursor/embedded.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/draw/cursor/embedded.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -46,5 +46,5 @@
 	assert(state_count);
 	assert(data);
-
+	
 	(*state_count) = 1;
 	(*data) = NULL;
@@ -53,13 +53,10 @@
 static surface_t *cde_render(uint8_t state)
 {
-	if (state != 0) {
+	if (state != 0)
 		return NULL;
-	}
-
+	
 	surface_t *surface = surface_create(CURSOR_WIDTH, CURSOR_HEIGHT, NULL, 0);
-
-	if (!surface) {
+	if (!surface)
 		return NULL;
-	}
 	
 	for (unsigned int y = 0; y < CURSOR_HEIGHT; ++y) {
@@ -69,8 +66,10 @@
 			pixel_t pixel = (cursor_texture[offset] & (1 << (x % 8))) ?
 			    PIXEL(255, 0, 0, 0) : PIXEL(255, 255, 255, 255);
-			surface_put_pixel(surface, x, y, visible ? pixel : PIXEL(0, 0, 0, 0));
+			
+			if (visible)
+				surface_put_pixel(surface, x, y, pixel);
 		}
 	}
-
+	
 	return surface;
 }
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/drv/generic/driver.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -920,5 +920,5 @@
 
 /** Set function ops. */
-void ddf_fun_set_ops(ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)
+void ddf_fun_set_ops(ddf_fun_t *fun, const ddf_dev_ops_t *dev_ops)
 {
 	assert(fun->conn_handler == NULL);
Index: uspace/lib/drv/generic/private/driver.h
===================================================================
--- uspace/lib/drv/generic/private/driver.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/drv/generic/private/driver.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -93,5 +93,5 @@
 	
 	/** Implementation of operations provided by this function */
-	ddf_dev_ops_t *ops;
+	const ddf_dev_ops_t *ops;
 	
 	/** Connection handler or @c NULL to use the DDF default handler. */
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -137,5 +137,5 @@
 extern int ddf_fun_offline(ddf_fun_t *);
 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
-extern void ddf_fun_set_ops(ddf_fun_t *, ddf_dev_ops_t *);
+extern void ddf_fun_set_ops(ddf_fun_t *, const ddf_dev_ops_t *);
 extern void ddf_fun_set_conn_handler(ddf_fun_t *, async_client_conn_t);
 extern int ddf_fun_add_to_category(ddf_fun_t *, const char *);
Index: uspace/lib/gui/Makefile
===================================================================
--- uspace/lib/gui/Makefile	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -34,4 +34,5 @@
 
 SOURCES = \
+	common.c \
 	button.c \
 	canvas.c \
Index: uspace/lib/gui/button.c
===================================================================
--- uspace/lib/gui/button.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/button.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -36,45 +36,57 @@
 #include <str.h>
 #include <malloc.h>
-
 #include <drawctx.h>
 #include <surface.h>
-
+#include "common.h"
 #include "window.h"
 #include "button.h"
 
-static void paint_internal(widget_t *w)
-{
-	button_t *btn = (button_t *) w;
-
+static pixel_t color_highlight = PIXEL(255, 255, 255, 255);
+static pixel_t color_shadow = PIXEL(255, 85, 85, 85);
+
+static void paint_internal(widget_t *widget)
+{
+	button_t *btn = (button_t *) widget;
+	
 	surface_t *surface = window_claim(btn->widget.window);
-	if (!surface) {
+	if (!surface)
 		window_yield(btn->widget.window);
+	
+	source_t source;
+	source_init(&source);
+	
+	drawctx_t drawctx;
+	drawctx_init(&drawctx, surface);
+	
+	drawctx_set_source(&drawctx, &btn->background);
+	drawctx_transfer(&drawctx, widget->hpos, widget->vpos,
+	    widget->width, widget->height);
+	
+	if ((widget->width >= 8) && (widget->height >= 8)) {
+		drawctx_set_source(&drawctx, &source);
+		draw_bevel(&drawctx, &source, widget->hpos + 3, widget->vpos + 3,
+		    widget->width - 6, widget->height - 6, color_highlight,
+		    color_shadow);
+		
+		drawctx_set_source(&drawctx, &btn->foreground);
+		drawctx_transfer(&drawctx, widget->hpos + 4, widget->vpos + 4,
+		    widget->width - 8, widget->height - 8);
 	}
-
-	drawctx_t drawctx;
-
-	drawctx_init(&drawctx, surface);
-	drawctx_set_source(&drawctx, &btn->foreground);
-	drawctx_transfer(&drawctx, w->hpos, w->vpos, w->width, w->height);
-
-	if (w->width >= 6 && w->height >= 6) {
-		drawctx_set_source(&drawctx, &btn->background);
-		drawctx_transfer(&drawctx,
-		    w->hpos + 3, w->vpos + 3, w->width - 6, w->height - 6);
-	}
-
+	
 	sysarg_t cpt_width;
 	sysarg_t cpt_height;
 	font_get_box(&btn->font, btn->caption, &cpt_width, &cpt_height);
-	if (w->width >= cpt_width && w->height >= cpt_height) {
-		drawctx_set_source(&drawctx, &btn->foreground);
+	
+	if ((widget->width >= cpt_width) && (widget->height >= cpt_height)) {
+		sysarg_t x = ((widget->width - cpt_width) / 2) + widget->hpos;
+		sysarg_t y = ((widget->height - cpt_height) / 2) + widget->vpos;
+		
+		drawctx_set_source(&drawctx, &btn->text);
 		drawctx_set_font(&drawctx, &btn->font);
-		sysarg_t x = ((w->width - cpt_width) / 2) + w->hpos;
-		sysarg_t y = ((w->height - cpt_height) / 2) + w->vpos;
-		if (btn->caption) {
+		
+		if (btn->caption)
 			drawctx_print(&drawctx, btn->caption, x, y);
-		}
 	}
-
+	
 	window_yield(btn->widget.window);
 }
@@ -90,7 +102,6 @@
 {
 	button_t *btn = (button_t *) widget;
-
+	
 	deinit_button(btn);
-	
 	free(btn);
 }
@@ -117,7 +128,7 @@
 {
 	button_t *btn = (button_t *) widget;
-	if (event.key == KC_ENTER && event.type == KEY_PRESS) {
+	
+	if (event.key == KC_ENTER && event.type == KEY_PRESS)
 		sig_send(&btn->clicked, NULL);
-	}
 }
 
@@ -126,18 +137,17 @@
 	button_t *btn = (button_t *) widget;
 	widget->window->focus = widget;
-
+	
 	// TODO make the click logic more robust (mouse grabbing, mouse moves)
 	if (event.btn_num == 1) {
-		if (event.type == POS_RELEASE) {
+		if (event.type == POS_RELEASE)
 			sig_send(&btn->clicked, NULL);
-		}
 	}
 }
 
-bool init_button(button_t *btn, widget_t *parent,
-    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+bool init_button(button_t *btn, widget_t *parent, const char *caption,
+    uint16_t points, pixel_t background, pixel_t foreground, pixel_t text)
 {
 	widget_init(&btn->widget, parent);
-
+	
 	btn->widget.destroy = button_destroy;
 	btn->widget.reconfigure = button_reconfigure;
@@ -146,42 +156,45 @@
 	btn->widget.handle_keyboard_event = button_handle_keyboard_event;
 	btn->widget.handle_position_event = button_handle_position_event;
-
+	
 	source_init(&btn->background);
 	source_set_color(&btn->background, background);
+	
 	source_init(&btn->foreground);
 	source_set_color(&btn->foreground, foreground);
-
-	if (caption == NULL) {
+	
+	source_init(&btn->text);
+	source_set_color(&btn->text, text);
+	
+	if (caption == NULL)
 		btn->caption = NULL;
-	} else {
+	else
 		btn->caption = str_dup(caption);
-	}
+	
 	font_init(&btn->font, FONT_DECODER_EMBEDDED, NULL, points);
-
+	
 	sysarg_t cpt_width;
 	sysarg_t cpt_height;
 	font_get_box(&btn->font, btn->caption, &cpt_width, &cpt_height);
-	btn->widget.width_min = cpt_width + 8;
-	btn->widget.height_min = cpt_height + 8;
-	btn->widget.width_ideal = cpt_width + 28;
-	btn->widget.height_ideal = cpt_height + 8;
-
+	btn->widget.width_min = cpt_width + 10;
+	btn->widget.height_min = cpt_height + 10;
+	btn->widget.width_ideal = cpt_width + 30;
+	btn->widget.height_ideal = cpt_height + 10;
+	
 	return true;
 }
 
-button_t *create_button(widget_t *parent,
-    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+button_t *create_button(widget_t *parent, const char *caption, uint16_t points,
+    pixel_t background, pixel_t foreground, pixel_t text)
 {
 	button_t *btn = (button_t *) malloc(sizeof(button_t));
-	if (!btn) {
+	if (!btn)
 		return NULL;
-	}
-
-	if (init_button(btn, parent, caption, points, background, foreground)) {
+	
+	if (init_button(btn, parent, caption, points, background, foreground,
+	    text))
 		return btn;
-	} else {
-		free(btn);
-		return NULL;
-	}
+	
+	free(btn);
+	return NULL;
 }
 
Index: uspace/lib/gui/button.h
===================================================================
--- uspace/lib/gui/button.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/button.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -50,4 +50,5 @@
 	source_t background;
 	source_t foreground;
+	source_t text;
 	char *caption;
 	font_t font;
@@ -55,6 +56,8 @@
 } button_t;
 
-extern bool init_button(button_t *, widget_t *, const char *, uint16_t, pixel_t, pixel_t);
-extern button_t *create_button(widget_t *, const char *, uint16_t, pixel_t, pixel_t);
+extern bool init_button(button_t *, widget_t *, const char *, uint16_t, pixel_t,
+    pixel_t, pixel_t);
+extern button_t *create_button(widget_t *, const char *, uint16_t, pixel_t,
+    pixel_t, pixel_t);
 extern void deinit_button(button_t *);
 
Index: uspace/lib/gui/common.c
===================================================================
--- uspace/lib/gui/common.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/lib/gui/common.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup gui
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <sys/types.h>
+#include <drawctx.h>
+#include "common.h"
+
+#define CROSS_WIDTH   14
+#define CROSS_HEIGHT  14
+
+static uint8_t cross_texture[] = {
+	0x00, 0x00, 0x02, 0x08, 0x04, 0x04, 0x08, 0x02, 0x10, 0x01, 0xa0, 0x00,
+	0x40, 0x00, 0xa0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x04, 0x04, 0x02, 0x08,
+	0x01, 0x10, 0x00, 0x00
+};
+
+static uint8_t cross_mask[] = {
+	0x00, 0x00, 0x02, 0x18, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0x03, 0xb0, 0x01,
+	0xe0, 0x00, 0xe0, 0x00, 0xb0, 0x01, 0x18, 0x03, 0x0c, 0x06, 0x06, 0x0c,
+	0x03, 0x18, 0x00, 0x00
+};
+
+void draw_icon_cross(surface_t *surface, sysarg_t hpos, sysarg_t vpos,
+    pixel_t highlight, pixel_t shadow)
+{
+	for (unsigned int y = 0; y < CROSS_HEIGHT; y++) {
+		for (unsigned int x = 0; x < CROSS_WIDTH; x++) {
+			size_t offset = y * ((CROSS_WIDTH - 1) / 8 + 1) + x / 8;
+			bool visible = cross_mask[offset] & (1 << (x % 8));
+			pixel_t pixel = (cross_texture[offset] & (1 << (x % 8))) ?
+			    highlight : shadow;
+			
+			if (visible)
+				surface_put_pixel(surface, hpos + x, vpos + y, pixel);
+		}
+	}
+}
+
+void draw_bevel(drawctx_t *drawctx, source_t *source, sysarg_t hpos,
+    sysarg_t vpos, sysarg_t width, sysarg_t height, pixel_t highlight,
+    pixel_t shadow)
+{
+	source_set_color(source, highlight);
+	drawctx_transfer(drawctx, hpos, vpos, width - 1, 1);
+	drawctx_transfer(drawctx, hpos, vpos + 1, 1, height - 2);
+	
+	source_set_color(source, shadow);
+	drawctx_transfer(drawctx, hpos, vpos + height - 1, width, 1);
+	drawctx_transfer(drawctx, hpos + width - 1, vpos, 1, height);
+}
+
+/** @}
+ */
Index: uspace/lib/gui/common.h
===================================================================
--- uspace/lib/gui/common.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/lib/gui/common.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup gui
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef GUI_COMMON_H_
+#define GUI_COMMON_H_
+
+#include <sys/types.h>
+#include <drawctx.h>
+
+extern void draw_icon_cross(surface_t *, sysarg_t, sysarg_t, pixel_t, pixel_t);
+extern void draw_bevel(drawctx_t *, source_t *, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, pixel_t, pixel_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/connection.c
===================================================================
--- uspace/lib/gui/connection.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/connection.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -210,7 +210,7 @@
 			link_initialize(&event->link);
 			event->type = ET_SIGNAL_EVENT;
-			event->data.sig.object = (sysarg_t) cur->widget;
-			event->data.sig.slot = (sysarg_t) cur->slot;
-			event->data.sig.argument = (sysarg_t) data_copy;
+			event->data.signal.object = (sysarg_t) cur->widget;
+			event->data.signal.slot = (sysarg_t) cur->slot;
+			event->data.signal.argument = (sysarg_t) data_copy;
 			prodcons_produce(&cur->widget->window->events, &event->link);
 		} else {
Index: uspace/lib/gui/label.c
===================================================================
--- uspace/lib/gui/label.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/label.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -36,39 +36,39 @@
 #include <str.h>
 #include <malloc.h>
-
 #include <drawctx.h>
 #include <surface.h>
-
 #include "window.h"
 #include "label.h"
 
-static void paint_internal(widget_t *w)
+static void paint_internal(widget_t *widget)
 {
-	label_t *lbl = (label_t *) w;
+	label_t *lbl = (label_t *) widget;
 
 	surface_t *surface = window_claim(lbl->widget.window);
-	if (!surface) {
+	if (!surface)
 		window_yield(lbl->widget.window);
-	}
-
+	
 	drawctx_t drawctx;
-
 	drawctx_init(&drawctx, surface);
+	
 	drawctx_set_source(&drawctx, &lbl->background);
-	drawctx_transfer(&drawctx, w->hpos, w->vpos, w->width, w->height);
-
+	drawctx_transfer(&drawctx, widget->hpos, widget->vpos, widget->width,
+	    widget->height);
+	
 	sysarg_t cpt_width;
 	sysarg_t cpt_height;
 	font_get_box(&lbl->font, lbl->caption, &cpt_width, &cpt_height);
-	if (w->width >= cpt_width && w->height >= cpt_height) {
-		drawctx_set_source(&drawctx, &lbl->foreground);
+	
+	if ((widget->width >= cpt_width) && (widget->height >= cpt_height)) {
+		sysarg_t x = ((widget->width - cpt_width) / 2) + widget->hpos;
+		sysarg_t y = ((widget->height - cpt_height) / 2) + widget->vpos;
+		
+		drawctx_set_source(&drawctx, &lbl->text);
 		drawctx_set_font(&drawctx, &lbl->font);
-		sysarg_t x = ((w->width - cpt_width) / 2) + w->hpos;
-		sysarg_t y = ((w->height - cpt_height) / 2) + w->vpos;
-		if (lbl->caption) {
+		
+		if (lbl->caption)
 			drawctx_print(&drawctx, lbl->caption, x, y);
-		}
 	}
-
+	
 	window_yield(lbl->widget.window);
 }
@@ -78,15 +78,17 @@
 	if (data != NULL) {
 		label_t *lbl = (label_t *) widget;
+		
 		const char *new_caption = (const char *) data;
 		lbl->caption = str_dup(new_caption);
-
+		
 		sysarg_t cpt_width;
 		sysarg_t cpt_height;
 		font_get_box(&lbl->font, lbl->caption, &cpt_width, &cpt_height);
+		
 		lbl->widget.width_min = cpt_width + 4;
 		lbl->widget.height_min = cpt_height + 4;
 		lbl->widget.width_ideal = lbl->widget.width_min;
 		lbl->widget.height_ideal = lbl->widget.height_min;
-
+		
 		window_refresh(lbl->widget.window);
 	}
@@ -103,7 +105,6 @@
 {
 	label_t *lbl = (label_t *) widget;
-
+	
 	deinit_label(lbl);
-	
 	free(lbl);
 }
@@ -137,9 +138,9 @@
 }
 
-bool init_label(label_t *lbl, widget_t *parent,
-    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+bool init_label(label_t *lbl, widget_t *parent, const char *caption,
+    uint16_t points, pixel_t background, pixel_t text)
 {
 	widget_init(&lbl->widget, parent);
-
+	
 	lbl->widget.destroy = label_destroy;
 	lbl->widget.reconfigure = label_reconfigure;
@@ -148,47 +149,46 @@
 	lbl->widget.handle_keyboard_event = label_handle_keyboard_event;
 	lbl->widget.handle_position_event = label_handle_position_event;
-
+	
 	source_init(&lbl->background);
 	source_set_color(&lbl->background, background);
-	source_init(&lbl->foreground);
-	source_set_color(&lbl->foreground, foreground);
-
-	if (caption == NULL) {
+	
+	source_init(&lbl->text);
+	source_set_color(&lbl->text, text);
+	
+	if (caption == NULL)
 		lbl->caption = NULL;
-	} else {
+	else
 		lbl->caption = str_dup(caption);
-	}
+	
 	font_init(&lbl->font, FONT_DECODER_EMBEDDED, NULL, points);
-
+	
 	sysarg_t cpt_width;
 	sysarg_t cpt_height;
 	font_get_box(&lbl->font, lbl->caption, &cpt_width, &cpt_height);
+	
 	lbl->widget.width_min = cpt_width + 4;
 	lbl->widget.height_min = cpt_height + 4;
 	lbl->widget.width_ideal = lbl->widget.width_min;
 	lbl->widget.height_ideal = lbl->widget.height_min;
-
+	
 	lbl->rewrite = on_rewrite;
-
+	
 	return true;
 }
 
-label_t *create_label(widget_t *parent,
-    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+label_t *create_label(widget_t *parent, const char *caption, uint16_t points,
+    pixel_t background, pixel_t text)
 {
 	label_t *lbl = (label_t *) malloc(sizeof(label_t));
-	if (!lbl) {
+	if (!lbl)
 		return NULL;
-	}
-
-	if (init_label(lbl, parent, caption, points, background, foreground)) {
+	
+	if (init_label(lbl, parent, caption, points, background, text))
 		return lbl;
-	} else {
-		free(lbl);
-		return NULL;
-	}
+	
+	free(lbl);
+	return NULL;
 }
 
 /** @}
  */
-
Index: uspace/lib/gui/label.h
===================================================================
--- uspace/lib/gui/label.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/label.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -49,5 +49,5 @@
 	widget_t widget;
 	source_t background;
-	source_t foreground;
+	source_t text;
 	char *caption;
 	font_t font;
@@ -55,6 +55,8 @@
 } label_t;
 
-extern bool init_label(label_t *, widget_t *, const char *, uint16_t, pixel_t, pixel_t);
-extern label_t *create_label(widget_t *, const char *, uint16_t, pixel_t, pixel_t);
+extern bool init_label(label_t *, widget_t *, const char *, uint16_t, pixel_t,
+    pixel_t);
+extern label_t *create_label(widget_t *, const char *, uint16_t, pixel_t,
+    pixel_t);
 extern void deinit_label(label_t *);
 
Index: uspace/lib/gui/window.c
===================================================================
--- uspace/lib/gui/window.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/window.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -56,75 +56,133 @@
 #include <surface.h>
 
+#include "common.h"
 #include "connection.h"
 #include "widget.h"
 #include "window.h"
 
-static sysarg_t border_thickness = 5;
+static sysarg_t border_thickness = 4;
+static sysarg_t bevel_thickness = 1;
 static sysarg_t header_height = 20;
 static sysarg_t header_min_width = 40;
-static sysarg_t close_width = 20;
-
-static pixel_t border_color = PIXEL(255, 0, 0, 0);
-static pixel_t header_bg_focus_color = PIXEL(255, 88, 106, 196);
-static pixel_t header_fg_focus_color = PIXEL(255, 255, 255, 255);
-static pixel_t header_bg_unfocus_color = PIXEL(255, 12, 57, 92);
-static pixel_t header_fg_unfocus_color = PIXEL(255, 255, 255, 255);
-
-static void paint_internal(widget_t *w)
-{
-	surface_t *surface = window_claim(w->window);
-	if (!surface) {
-		window_yield(w->window);
-	}
-
+static sysarg_t close_thickness = 20;
+
+static pixel_t color_highlight = PIXEL(255, 255, 255, 255);
+static pixel_t color_shadow = PIXEL(255, 85, 85, 85);
+static pixel_t color_surface = PIXEL(255, 186, 186, 186);
+
+static pixel_t color_header_focus_highlight = PIXEL(255, 120, 145, 255);
+static pixel_t color_header_focus_shadow = PIXEL(255, 40, 48, 89);
+static pixel_t color_header_focus_surface = PIXEL(255, 88, 106, 196);
+
+static pixel_t color_header_unfocus_highlight = PIXEL(255, 16, 78, 126);
+static pixel_t color_header_unfocus_shadow = PIXEL(255, 5, 26, 42);
+static pixel_t color_header_unfocus_surface = PIXEL(255, 12, 57, 92);
+
+static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255);
+static pixel_t color_caption_unfocus = PIXEL(255, 207, 207, 207);
+
+static void paint_internal(widget_t *widget)
+{
+	surface_t *surface = window_claim(widget->window);
+	if (!surface)
+		window_yield(widget->window);
+	
 	source_t source;
-	font_t font;
+	source_init(&source);
+	
 	drawctx_t drawctx;
-
-	source_init(&source);
-	font_init(&font, FONT_DECODER_EMBEDDED, NULL, 16);
 	drawctx_init(&drawctx, surface);
 	drawctx_set_source(&drawctx, &source);
+	
+	/* Window border outer bevel */
+	
+	draw_bevel(&drawctx, &source, widget->vpos, widget->hpos,
+	    widget->width, widget->height, color_highlight, color_shadow);
+	
+	/* Window border surface */
+	
+	source_set_color(&source, color_surface);
+	drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
+	    widget->width - 2, 2);
+	drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
+	    2, widget->height - 2);
+	drawctx_transfer(&drawctx, widget->hpos + 1,
+	    widget->vpos + widget->height - 3, widget->width - 2, 2);
+	drawctx_transfer(&drawctx, widget->hpos + widget->width - 3,
+	    widget->vpos + 1, 2, widget->height - 4);
+	
+	/* Window border inner bevel */
+	
+	draw_bevel(&drawctx, &source, widget->hpos + 3, widget->vpos + 3,
+	    widget->width - 6, widget->height - 6, color_shadow,
+	    color_highlight);
+	
+	/* Header bevel */
+	
+	sysarg_t header_hpos = widget->hpos + border_thickness;
+	sysarg_t header_vpos = widget->vpos + border_thickness;
+	sysarg_t header_width = widget->width - 2 * border_thickness -
+	    close_thickness;
+	
+	draw_bevel(&drawctx, &source, header_hpos, header_vpos,
+	    header_width, header_height, widget->window->is_focused ?
+	    color_header_focus_highlight : color_header_unfocus_highlight,
+	    widget->window->is_focused ?
+	    color_header_focus_shadow : color_header_unfocus_shadow);
+	
+	/* Header surface */
+	
+	source_set_color(&source, widget->window->is_focused ?
+	    color_header_focus_surface : color_header_unfocus_surface);
+	drawctx_transfer(&drawctx, header_hpos + 1, header_vpos + 1,
+	    header_width - 2, header_height - 2);
+	
+	/* Close button bevel */
+	
+	sysarg_t close_hpos = widget->hpos + widget->width -
+	    border_thickness - close_thickness;
+	sysarg_t close_vpos = widget->vpos + border_thickness;
+	
+	draw_bevel(&drawctx, &source, close_hpos, close_vpos,
+	    close_thickness, close_thickness, color_highlight, color_shadow);
+	
+	/* Close button surface */
+	
+	source_set_color(&source, color_surface);
+	drawctx_transfer(&drawctx, close_hpos + 1, close_vpos + 1,
+	    close_thickness - 2, close_thickness - 2);
+	
+	/* Close button icon */
+	
+	draw_icon_cross(surface, close_hpos + 3, close_vpos + 3,
+	    color_highlight, color_shadow);
+	
+	/* Window caption */
+	
+	font_t font;
+	font_init(&font, FONT_DECODER_EMBEDDED, NULL, 16);
+	
 	drawctx_set_font(&drawctx, &font);
-
-	source_set_color(&source, border_color);
-	drawctx_transfer(&drawctx, w->hpos, w->vpos, border_thickness, w->height);
-	drawctx_transfer(&drawctx, w->hpos + w->width - border_thickness,
-	    w->vpos, border_thickness, w->height);
-	drawctx_transfer(&drawctx, w->hpos, w->vpos, w->width, border_thickness);
-	drawctx_transfer(&drawctx, w->hpos,
-	    w->vpos + w->height - border_thickness, w->width, border_thickness);
-
-	source_set_color(&source, 
-	    w->window->is_focused ? header_bg_focus_color : header_bg_unfocus_color);
-	drawctx_transfer(&drawctx,
-	    w->hpos + border_thickness, w->vpos + border_thickness,
-		w->width - 2 * border_thickness, header_height);
-
+	source_set_color(&source, widget->window->is_focused ?
+	    color_caption_focus : color_caption_unfocus);
+	
 	sysarg_t cpt_width;
 	sysarg_t cpt_height;
-	font_get_box(&font, w->window->caption, &cpt_width, &cpt_height);
-	sysarg_t cls_width;
-	sysarg_t cls_height;
-	char cls_pict[] = "x";
-	font_get_box(&font, cls_pict, &cls_width, &cls_height);
-	source_set_color(&source, 
-	    w->window->is_focused ? header_fg_focus_color : header_fg_unfocus_color);
-	sysarg_t cls_x = ((close_width - cls_width) / 2) + w->hpos + w->width -
-	    border_thickness - close_width;
-	sysarg_t cls_y = ((header_height - cls_height) / 2) + w->vpos + border_thickness;
-	drawctx_print(&drawctx, cls_pict, cls_x, cls_y);
-
-	bool draw_title = (w->width >= 2 * border_thickness + close_width + cpt_width);
+	font_get_box(&font, widget->window->caption, &cpt_width, &cpt_height);
+	
+	bool draw_title =
+	    (widget->width >= 2 * border_thickness + 2 * bevel_thickness +
+	    close_thickness + cpt_width);
 	if (draw_title) {
-		sysarg_t cpt_x = ((w->width - cpt_width) / 2) + w->hpos;
-		sysarg_t cpt_y = ((header_height - cpt_height) / 2) + w->vpos + border_thickness;
-		if (w->window->caption) {
-			drawctx_print(&drawctx, w->window->caption, cpt_x, cpt_y);
-		}
-	}
-
+		sysarg_t cpt_x = ((widget->width - cpt_width) / 2) + widget->hpos;
+		sysarg_t cpt_y = ((header_height - cpt_height) / 2) +
+		    widget->vpos + border_thickness;
+		
+		if (widget->window->caption)
+			drawctx_print(&drawctx, widget->window->caption, cpt_x, cpt_y);
+	}
+	
 	font_release(&font);
-	window_yield(w->window);
+	window_yield(widget->window);
 }
 
@@ -138,5 +196,5 @@
 	if (widget->window->is_decorated) {
 		list_foreach(widget->children, link, widget_t, child) {
-			child->rearrange(child, 
+			child->rearrange(child,
 			    widget->hpos + border_thickness,
 			    widget->vpos + border_thickness + header_height,
@@ -211,5 +269,6 @@
 		    (event.vpos >= border_thickness) &&
 		    (event.vpos < border_thickness + header_height);
-		bool close = header && (event.hpos >= width - border_thickness - close_width);
+		bool close = (header) &&
+		    (event.hpos >= width - border_thickness - close_thickness);
 
 		if (top && left && allowed_button) {
@@ -292,5 +351,5 @@
 }
 
-static void handle_signal_event(window_t *win, sig_event_t event)
+static void handle_signal_event(window_t *win, signal_event_t event)
 {
 	widget_t *widget = (widget_t *) event.object;
@@ -303,58 +362,56 @@
 }
 
-static void handle_resize(window_t *win, sysarg_t width, sysarg_t height)
-{
-	int rc;
-	surface_t *old_surface;
-	surface_t *new_surface;
-
+static void handle_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
+    sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
+{
 	if (width < 2 * border_thickness + header_min_width) {
 		win_damage(win->osess, 0, 0, 0, 0);
 		return;
 	}
-
+	
 	if (height < 2 * border_thickness + header_height) {
 		win_damage(win->osess, 0, 0, 0, 0);
 		return;
 	}
-
+	
 	/* Allocate resources for new surface. */
-	new_surface = surface_create(width, height, NULL, SURFACE_FLAG_SHARED);
-	if (!new_surface) {
+	surface_t *new_surface = surface_create(width, height, NULL,
+	    SURFACE_FLAG_SHARED);
+	if (!new_surface)
 		return;
-	}
-
+	
 	/* Switch new and old surface. */
 	fibril_mutex_lock(&win->guard);
-	old_surface = win->surface;
+	surface_t *old_surface = win->surface;
 	win->surface = new_surface;
 	fibril_mutex_unlock(&win->guard);
-
-	/* Let all widgets in the tree alter their position and size. Widgets might
-	 * also paint themselves onto the new surface. */
+	
+	/*
+	 * Let all widgets in the tree alter their position and size.
+	 * Widgets might also paint themselves onto the new surface.
+	 */
 	win->root.rearrange(&win->root, 0, 0, width, height);
-
+	
 	fibril_mutex_lock(&win->guard);
 	surface_reset_damaged_region(win->surface);
 	fibril_mutex_unlock(&win->guard);
-
+	
 	/* Inform compositor about new surface. */
-	rc = win_resize(win->osess,
-		width, height, surface_direct_access(new_surface));
-
+	int rc = win_resize(win->osess, offset_x, offset_y, width, height,
+	    placement_flags, surface_direct_access(new_surface));
+	
 	if (rc != EOK) {
 		/* Rollback to old surface. Reverse all changes. */
-
+		
 		sysarg_t old_width = 0;
 		sysarg_t old_height = 0;
-		if (old_surface) {
+		if (old_surface)
 			surface_get_resolution(old_surface, &old_width, &old_height);
-		}
-
+		
 		fibril_mutex_lock(&win->guard);
 		new_surface = win->surface;
 		win->surface = old_surface;
 		fibril_mutex_unlock(&win->guard);
-
+		
 		win->root.rearrange(&win->root, 0, 0, old_width, old_height);
 		
@@ -364,12 +421,10 @@
 			fibril_mutex_unlock(&win->guard);
 		}
-
+		
 		surface_destroy(new_surface);
-		return;
-	}
-
-	/* Finally deallocate old surface. */
-	if (old_surface) {
-		surface_destroy(old_surface);
+	} else {
+		/* Deallocate old surface. */
+		if (old_surface)
+			surface_destroy(old_surface);
 	}
 }
@@ -453,8 +508,10 @@
 			break;
 		case ET_SIGNAL_EVENT:
-			handle_signal_event(win, event->data.sig);
+			handle_signal_event(win, event->data.signal);
 			break;
 		case ET_WINDOW_RESIZE:
-			handle_resize(win, event->data.rsz.width, event->data.rsz.height);
+			handle_resize(win, event->data.resize.offset_x,
+			    event->data.resize.offset_y, event->data.resize.width,
+			    event->data.resize.height, event->data.resize.placement_flags);
 			break;
 		case ET_WINDOW_FOCUS:
@@ -530,13 +587,10 @@
 
 window_t *window_open(const char *winreg, bool is_main, bool is_decorated,
-    const char *caption, sysarg_t x_offset, sysarg_t y_offset)
-{
-	int rc;
-
+    const char *caption)
+{
 	window_t *win = (window_t *) malloc(sizeof(window_t));
-	if (!win) {
+	if (!win)
 		return NULL;
-	}
-
+	
 	win->is_main = is_main;
 	win->is_decorated = is_decorated;
@@ -544,4 +598,5 @@
 	prodcons_initialize(&win->events);
 	fibril_mutex_initialize(&win->guard);
+	
 	widget_init(&win->root, NULL);
 	win->root.window = win;
@@ -555,24 +610,22 @@
 	win->focus = NULL;
 	win->surface = NULL;
-
+	
 	service_id_t reg_dsid;
-	async_sess_t *reg_sess;
-
-	rc = loc_service_get_id(winreg, &reg_dsid, 0);
+	int rc = loc_service_get_id(winreg, &reg_dsid, 0);
 	if (rc != EOK) {
 		free(win);
 		return NULL;
 	}
-
-	reg_sess = loc_service_connect(EXCHANGE_SERIALIZE, reg_dsid, 0);
+	
+	async_sess_t *reg_sess = loc_service_connect(EXCHANGE_SERIALIZE,
+	    reg_dsid, 0);
 	if (reg_sess == NULL) {
 		free(win);
 		return NULL;
 	}
-
+	
 	service_id_t in_dsid;
 	service_id_t out_dsid;
-	
-	rc = win_register(reg_sess, &in_dsid, &out_dsid, x_offset, y_offset);
+	rc = win_register(reg_sess, &in_dsid, &out_dsid);
 	async_hangup(reg_sess);
 	if (rc != EOK) {
@@ -580,5 +633,5 @@
 		return NULL;
 	}
-
+	
 	win->osess = loc_service_connect(EXCHANGE_SERIALIZE, out_dsid, 0);
 	if (win->osess == NULL) {
@@ -586,5 +639,5 @@
 		return NULL;
 	}
-
+	
 	win->isess = loc_service_connect(EXCHANGE_SERIALIZE, in_dsid, 0);
 	if (win->isess == NULL) {
@@ -593,15 +646,15 @@
 		return NULL;
 	}
-
-	if (caption == NULL) {
+	
+	if (caption == NULL)
 		win->caption = NULL;
-	} else {
+	else
 		win->caption = str_dup(caption);
-	}
-
+	
 	return win;
 }
 
-void window_resize(window_t *win, sysarg_t width, sysarg_t height)
+void window_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
+    sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
 {
 	window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
@@ -609,6 +662,9 @@
 		link_initialize(&event->link);
 		event->type = ET_WINDOW_RESIZE;
-		event->data.rsz.width = width;
-		event->data.rsz.height = height;
+		event->data.resize.offset_x = offset_x;
+		event->data.resize.offset_y = offset_y;
+		event->data.resize.width = width;
+		event->data.resize.height = height;
+		event->data.resize.placement_flags = placement_flags;
 		prodcons_produce(&win->events, &event->link);
 	}
Index: uspace/lib/gui/window.h
===================================================================
--- uspace/lib/gui/window.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/lib/gui/window.h	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -66,6 +66,5 @@
  * If the window is declared as main, its closure causes termination of the
  * whole application. Note that opened window does not have any surface yet. */
-extern window_t *window_open(const char *, bool, bool, const char *, sysarg_t,
-    sysarg_t);
+extern window_t *window_open(const char *, bool, bool, const char *);
 
 /**
@@ -74,5 +73,6 @@
  * and to paint themselves on the new surface (top-bottom order). Should be
  * called also after opening new window to obtain surface. */
-extern void window_resize(window_t *, sysarg_t, sysarg_t);
+extern void window_resize(window_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    window_placement_flags_t);
 
 /**
Index: uspace/srv/hid/compositor/Makefile
===================================================================
--- uspace/srv/hid/compositor/Makefile	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/srv/hid/compositor/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -42,15 +42,5 @@
 
 SOURCES = \
-	compositor.c \
-	images.c
-
-IMAGES = \
-	gfx/nameic.tga
-
-PRE_DEPEND = images.c images.h
-EXTRA_CLEAN = images.c images.h
+	compositor.c
 
 include $(USPACE_PREFIX)/Makefile.common
-
-images.c images.h: $(IMAGES)
-	$(ROOT_PATH)/tools/mkarray.py images COMPOSITOR_IMAGES $^
Index: uspace/srv/hid/compositor/compositor.c
===================================================================
--- uspace/srv/hid/compositor/compositor.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/srv/hid/compositor/compositor.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -72,5 +72,4 @@
 #include <codec/tga.h>
 
-#include "images.h"
 #include "compositor.h"
 
@@ -162,5 +161,4 @@
 static void input_disconnect(void);
 
-
 static pointer_t *input_pointer(input_t *input)
 {
@@ -168,11 +166,10 @@
 }
 
-static pointer_t *pointer_create()
+static pointer_t *pointer_create(void)
 {
 	pointer_t *p = (pointer_t *) malloc(sizeof(pointer_t));
-	if (!p) {
+	if (!p)
 		return NULL;
-	}
-
+	
 	link_initialize(&p->link);
 	p->pos.x = coord_origin;
@@ -186,5 +183,5 @@
 	p->state = 0;
 	cursor_init(&p->cursor, CURSOR_DECODER_EMBEDDED, NULL);
-
+	
 	/* Ghost window for transformation animation. */
 	transform_identity(&p->ghost.transform);
@@ -199,5 +196,5 @@
 	p->accum_ghost.x = 0;
 	p->accum_ghost.y = 0;
-
+	
 	return p;
 }
@@ -211,19 +208,17 @@
 }
 
-static window_t *window_create(sysarg_t x_offset, sysarg_t y_offset)
+static window_t *window_create(void)
 {
 	window_t *win = (window_t *) malloc(sizeof(window_t));
-	if (!win) {
+	if (!win)
 		return NULL;
-	}
-
+	
 	link_initialize(&win->link);
 	atomic_set(&win->ref_cnt, 0);
 	prodcons_initialize(&win->queue);
 	transform_identity(&win->transform);
-	transform_translate(&win->transform, 
-	    coord_origin + x_offset, coord_origin + y_offset);
-	win->dx = coord_origin + x_offset;
-	win->dy = coord_origin + y_offset;
+	transform_translate(&win->transform, coord_origin, coord_origin);
+	win->dx = coord_origin;
+	win->dy = coord_origin;
 	win->fx = 1;
 	win->fy = 1;
@@ -231,5 +226,5 @@
 	win->opacity = 255;
 	win->surface = NULL;
-
+	
 	return win;
 }
@@ -294,16 +289,19 @@
     sysarg_t *x_out, sysarg_t *y_out, sysarg_t *w_out, sysarg_t *h_out)
 {
-	if (w_in > 0 && h_in > 0) {
+	if ((w_in > 0) && (h_in > 0)) {
 		sysarg_t x[4];
 		sysarg_t y[4];
+		
 		comp_coord_from_client(x_in, y_in, win_trans, &x[0], &y[0]);
 		comp_coord_from_client(x_in + w_in - 1, y_in, win_trans, &x[1], &y[1]);
 		comp_coord_from_client(x_in + w_in - 1, y_in + h_in - 1, win_trans, &x[2], &y[2]);
 		comp_coord_from_client(x_in, y_in + h_in - 1, win_trans, &x[3], &y[3]);
+		
 		(*x_out) = x[0];
 		(*y_out) = y[0];
 		(*w_out) = x[0];
 		(*h_out) = y[0];
-		for (int i = 1; i < 4; ++i) {
+		
+		for (unsigned int i = 1; i < 4; ++i) {
 			(*x_out) = (x[i] < (*x_out)) ? x[i] : (*x_out);
 			(*y_out) = (y[i] < (*y_out)) ? y[i] : (*y_out);
@@ -311,4 +309,5 @@
 			(*h_out) = (y[i] > (*h_out)) ? y[i] : (*h_out);
 		}
+		
 		(*w_out) = (*w_out) - (*x_out) + 1;
 		(*h_out) = (*h_out) - (*y_out) + 1;
@@ -321,13 +320,13 @@
 }
 
-static void comp_restrict_pointers(void)
+static void comp_update_viewport_bound_rect(void)
 {
 	fibril_mutex_lock(&viewport_list_mtx);
-
+	
 	sysarg_t x_res = coord_origin;
 	sysarg_t y_res = coord_origin;
 	sysarg_t w_res = 0;
 	sysarg_t h_res = 0;
-
+	
 	if (!list_empty(&viewport_list)) {
 		viewport_t *vp = (viewport_t *) list_first(&viewport_list);
@@ -336,23 +335,27 @@
 		surface_get_resolution(vp->surface, &w_res, &h_res);
 	}
-
+	
 	list_foreach(viewport_list, link, viewport_t, vp) {
 		sysarg_t w_vp, h_vp;
 		surface_get_resolution(vp->surface, &w_vp, &h_vp);
-		rectangle_union(
-		    x_res, y_res, w_res, h_res,
+		rectangle_union(x_res, y_res, w_res, h_res,
 		    vp->pos.x, vp->pos.y, w_vp, h_vp,
 		    &x_res, &y_res, &w_res, &h_res);
 	}
-
+	
 	viewport_bound_rect.x = x_res;
 	viewport_bound_rect.y = y_res;
 	viewport_bound_rect.w = w_res;
 	viewport_bound_rect.h = h_res;
-
+	
 	fibril_mutex_unlock(&viewport_list_mtx);
-
+}
+
+static void comp_restrict_pointers(void)
+{
+	comp_update_viewport_bound_rect();
+	
 	fibril_mutex_lock(&pointer_list_mtx);
-
+	
 	list_foreach(pointer_list, link, pointer_t, ptr) {
 		ptr->pos.x = ptr->pos.x > viewport_bound_rect.x ? ptr->pos.x : viewport_bound_rect.x;
@@ -363,5 +366,5 @@
 		    ptr->pos.y : viewport_bound_rect.y + viewport_bound_rect.h;
 	}
-
+	
 	fibril_mutex_unlock(&pointer_list_mtx);
 }
@@ -642,12 +645,39 @@
 }
 
+static void comp_recalc_transform(window_t *win)
+{
+	transform_t translate;
+	transform_identity(&translate);
+	transform_translate(&translate, win->dx, win->dy);
+	
+	transform_t scale;
+	transform_identity(&scale);
+	if ((win->fx != 1) || (win->fy != 1))
+		transform_scale(&scale, win->fx, win->fy);
+	
+	transform_t rotate;
+	transform_identity(&rotate);
+	if (win->angle != 0)
+		transform_rotate(&rotate, win->angle);
+	
+	transform_t transform;
+	transform_t temp;
+	transform_identity(&transform);
+	temp = transform;
+	transform_multiply(&transform, &temp, &translate);
+	temp = transform;
+	transform_multiply(&transform, &temp, &rotate);
+	temp = transform;
+	transform_multiply(&transform, &temp, &scale);
+	
+	win->transform = transform;
+}
+
 static void comp_window_resize(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
 {
-	int rc;
-
 	ipc_callid_t callid;
 	size_t size;
 	unsigned int flags;
-
+	
 	/* Start sharing resized window with client. */
 	if (!async_share_out_receive(&callid, &size, &flags)) {
@@ -655,15 +685,15 @@
 		return;
 	}
+	
 	void *new_cell_storage;
-	rc = async_share_out_finalize(callid, &new_cell_storage);
+	int rc = async_share_out_finalize(callid, &new_cell_storage);
 	if ((rc != EOK) || (new_cell_storage == AS_MAP_FAILED)) {
 		async_answer_0(iid, ENOMEM);
 		return;
 	}
-
+	
 	/* Create new surface for the resized window. */
-	surface_t *new_surface = surface_create(
-	    IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall),
-	    new_cell_storage, SURFACE_FLAG_SHARED);
+	surface_t *new_surface = surface_create(IPC_GET_ARG3(*icall),
+	    IPC_GET_ARG4(*icall), new_cell_storage, SURFACE_FLAG_SHARED);
 	if (!new_surface) {
 		as_area_destroy(new_cell_storage);
@@ -671,30 +701,88 @@
 		return;
 	}
-
+	
+	sysarg_t offset_x = IPC_GET_ARG1(*icall);
+	sysarg_t offset_y = IPC_GET_ARG2(*icall);
+	window_placement_flags_t placement_flags =
+	    (window_placement_flags_t) IPC_GET_ARG5(*icall);
+	
+	comp_update_viewport_bound_rect();
+	
 	/* Switch new surface with old surface and calculate damage. */
 	fibril_mutex_lock(&window_list_mtx);
-
+	
 	sysarg_t old_width = 0;
 	sysarg_t old_height = 0;
+	
 	if (win->surface) {
 		surface_get_resolution(win->surface, &old_width, &old_height);
 		surface_destroy(win->surface);
 	}
-
+	
 	win->surface = new_surface;
-
+	
 	sysarg_t new_width = 0;
 	sysarg_t new_height = 0;
 	surface_get_resolution(win->surface, &new_width, &new_height);
-
-	sysarg_t x, y;
-	sysarg_t width = old_width > new_width ? old_width : new_width;
-	sysarg_t height = old_height > new_height ? old_height : new_height;
-	comp_coord_bounding_rect(0, 0, width, height, win->transform, &x, &y, &width, &height);
-
+	
+	if (placement_flags & WINDOW_PLACEMENT_CENTER_X)
+		win->dx = viewport_bound_rect.x + viewport_bound_rect.w / 2 -
+		    new_width / 2;
+	
+	if (placement_flags & WINDOW_PLACEMENT_CENTER_Y)
+		win->dy = viewport_bound_rect.y + viewport_bound_rect.h / 2 -
+		    new_height / 2;
+	
+	if (placement_flags & WINDOW_PLACEMENT_LEFT)
+		win->dx = viewport_bound_rect.x;
+	
+	if (placement_flags & WINDOW_PLACEMENT_TOP)
+		win->dy = viewport_bound_rect.y;
+	
+	if (placement_flags & WINDOW_PLACEMENT_RIGHT)
+		win->dx = viewport_bound_rect.x + viewport_bound_rect.w -
+		    new_width;
+	
+	if (placement_flags & WINDOW_PLACEMENT_BOTTOM)
+		win->dy = viewport_bound_rect.y + viewport_bound_rect.h -
+		    new_height;
+	
+	if (placement_flags & WINDOW_PLACEMENT_ABSOLUTE_X)
+		win->dx = coord_origin + offset_x;
+	
+	if (placement_flags & WINDOW_PLACEMENT_ABSOLUTE_Y)
+		win->dy = coord_origin + offset_y;
+	
+	/* Transform the window and calculate damage. */
+	sysarg_t x1;
+	sysarg_t y1;
+	sysarg_t width1;
+	sysarg_t height1;
+	
+	comp_coord_bounding_rect(0, 0, old_width, old_height, win->transform,
+	    &x1, &y1, &width1, &height1);
+	
+	comp_recalc_transform(win);
+	
+	sysarg_t x2;
+	sysarg_t y2;
+	sysarg_t width2;
+	sysarg_t height2;
+	
+	comp_coord_bounding_rect(0, 0, new_width, new_height, win->transform,
+	    &x2, &y2, &width2, &height2);
+	
+	sysarg_t x;
+	sysarg_t y;
+	sysarg_t width;
+	sysarg_t height;
+	
+	rectangle_union(x1, y1, width1, height1, x2, y2, width2, height2,
+	    &x, &y, &width, &height);
+	
 	fibril_mutex_unlock(&window_list_mtx);
-
+	
 	comp_damage(x, y, width, height);
-
+	
 	async_answer_0(iid, EOK);
 }
@@ -703,5 +791,5 @@
 {
 	fibril_mutex_lock(&window_list_mtx);
-
+	
 	list_foreach(window_list, link, window_t, window) {
 		if (window == target) {
@@ -711,5 +799,5 @@
 		}
 	}
-
+	
 	fibril_mutex_unlock(&window_list_mtx);
 	free(event);
@@ -719,10 +807,11 @@
 {
 	fibril_mutex_lock(&window_list_mtx);
+	
 	window_t *win = (window_t *) list_first(&window_list);
-	if (win) {
+	if (win)
 		prodcons_produce(&win->queue, &event->link);
-	} else {
+	else
 		free(event);
-	}
+	
 	fibril_mutex_unlock(&window_list_mtx);
 }
@@ -801,5 +890,5 @@
 			fibril_mutex_lock(&window_list_mtx);
 
-			window_t *win = window_create(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			window_t *win = window_create();
 			if (!win) {
 				async_answer_2(callid, ENOMEM, 0, 0);
@@ -1173,36 +1262,4 @@
 }
 
-static void comp_recalc_transform(window_t *win)
-{
-	transform_t translate;
-	transform_identity(&translate);
-	transform_translate(&translate, win->dx, win->dy);
-
-	transform_t scale;
-	transform_identity(&scale);
-	if (win->fx != 1 || win->fy != 1) {
-		transform_scale(&scale, win->fx, win->fy);
-	}
-
-	transform_t rotate;
-	transform_identity(&rotate);
-	if (win->angle != 0) {
-		transform_rotate(&rotate, win->angle);
-	}
-
-	transform_t transform;
-	transform_t temp;
-	transform_identity(&transform);
-	temp = transform;
-	transform_multiply(&transform, &temp, &translate);
-	temp = transform;
-	transform_multiply(&transform, &temp, &rotate);
-	temp = transform;
-	transform_multiply(&transform, &temp, &scale);
-	
-
-	win->transform = transform;
-}
-
 static void comp_window_animate(pointer_t *pointer, window_t *win,
     sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
@@ -1226,26 +1283,27 @@
 		double cx = 0;
 		double cy = 0;
-		if (pointer->grab_flags & GF_MOVE_X) {
+		
+		if (pointer->grab_flags & GF_MOVE_X)
 			cx = 1;
-		}
-		if (pointer->grab_flags & GF_MOVE_Y) {
+		
+		if (pointer->grab_flags & GF_MOVE_Y)
 			cy = 1;
-		}
-
-		if ((scale || resize) && (win->angle != 0)) {
+		
+		if (((scale) || (resize)) && (win->angle != 0)) {
 			transform_t rotate;
 			transform_identity(&rotate);
+			
 			transform_rotate(&rotate, win->angle);
 			transform_apply_linear(&rotate, &cx, &cy);
 		}
 		
-		cx = (cx < 0) ? (-1 * cx) : cx; 
+		cx = (cx < 0) ? (-1 * cx) : cx;
 		cy = (cy < 0) ? (-1 * cy) : cy;
-
+		
 		win->dx += (cx * dx);
 		win->dy += (cy * dy);
 	}
 
-	if (scale || resize) {
+	if ((scale) || (resize)) {
 		double _dx = dx;
 		double _dy = dy;
@@ -1263,5 +1321,6 @@
 			if (fx > 0) {
 #if ANIMATE_WINDOW_TRANSFORMS == 0
-				if (scale) win->fx *= fx;
+				if (scale)
+					win->fx *= fx;
 #endif
 #if ANIMATE_WINDOW_TRANSFORMS == 1
@@ -1444,24 +1503,29 @@
 {
 	pointer_t *pointer = input_pointer(input);
-
+	
+	comp_update_viewport_bound_rect();
+	
 	/* Update pointer position. */
 	fibril_mutex_lock(&pointer_list_mtx);
+	
 	desktop_point_t old_pos = pointer->pos;
+	
 	sysarg_t cursor_width;
 	sysarg_t cursor_height;
-	surface_get_resolution(pointer->cursor.states[pointer->state], 
+	surface_get_resolution(pointer->cursor.states[pointer->state],
 	     &cursor_width, &cursor_height);
-	if (pointer->pos.x + dx < viewport_bound_rect.x) {
+	
+	if (pointer->pos.x + dx < viewport_bound_rect.x)
 		dx = -1 * (pointer->pos.x - viewport_bound_rect.x);
-	}
-	if (pointer->pos.y + dy < viewport_bound_rect.y) {
+	
+	if (pointer->pos.y + dy < viewport_bound_rect.y)
 		dy = -1 * (pointer->pos.y - viewport_bound_rect.y);
-	}
-	if (pointer->pos.x + dx > viewport_bound_rect.x + viewport_bound_rect.w) {
+	
+	if (pointer->pos.x + dx > viewport_bound_rect.x + viewport_bound_rect.w)
 		dx = (viewport_bound_rect.x + viewport_bound_rect.w - pointer->pos.x);
-	}
-	if (pointer->pos.y + dy > viewport_bound_rect.y + viewport_bound_rect.h) {
+	
+	if (pointer->pos.y + dy > viewport_bound_rect.y + viewport_bound_rect.h)
 		dy = (viewport_bound_rect.y + viewport_bound_rect.h - pointer->pos.y);
-	}
+	
 	pointer->pos.x += dx;
 	pointer->pos.y += dy;
@@ -1469,5 +1533,5 @@
 	comp_damage(old_pos.x, old_pos.y, cursor_width, cursor_height);
 	comp_damage(old_pos.x + dx, old_pos.y + dy, cursor_width, cursor_height);
-
+	
 	fibril_mutex_lock(&window_list_mtx);
 	fibril_mutex_lock(&pointer_list_mtx);
@@ -1630,5 +1694,5 @@
 
 #if ANIMATE_WINDOW_TRANSFORMS == 0
-		sysarg_t pre_x = 0; 
+		sysarg_t pre_x = 0;
 		sysarg_t pre_y = 0;
 		sysarg_t pre_width = 0;
@@ -1662,21 +1726,25 @@
 				link_initialize(&event_top->link);
 				event_top->type = ET_WINDOW_RESIZE;
-
+				
+				event_top->data.resize.offset_x = 0;
+				event_top->data.resize.offset_y = 0;
+				
 				int dx = (int) (((double) width) * (scale_back_x - 1.0));
 				int dy = (int) (((double) height) * (scale_back_y - 1.0));
-
-				if (pointer->grab_flags & GF_RESIZE_X) {
-					event_top->data.rsz.width =
-						((((int) width) + dx) >= 0) ? (width + dx) : 0;
-				} else {
-					event_top->data.rsz.width = width;
-				}
-
-				if (pointer->grab_flags & GF_RESIZE_Y) {
-					event_top->data.rsz.height =
-						((((int) height) + dy) >= 0) ? (height + dy) : 0;
-				} else {
-					event_top->data.rsz.height = height;
-				}
+				
+				if (pointer->grab_flags & GF_RESIZE_X)
+					event_top->data.resize.width =
+					    ((((int) width) + dx) >= 0) ? (width + dx) : 0;
+				else
+					event_top->data.resize.width = width;
+				
+				if (pointer->grab_flags & GF_RESIZE_Y)
+					event_top->data.resize.height =
+					    ((((int) height) + dy) >= 0) ? (height + dy) : 0;
+				else
+					event_top->data.resize.height = height;
+				
+				event_top->data.resize.placement_flags =
+				    WINDOW_PLACEMENT_ANY;
 			}
 
@@ -1746,9 +1814,8 @@
 	    key == KC_O || key == KC_P);
 	bool kconsole_switch = (mods & KM_ALT) && (key == KC_M);
-	bool compositor_test = (mods & KM_ALT) && (key == KC_H);
 
 	bool filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
 	    win_opacity || win_close || win_switch || viewport_move ||
-	    viewport_change || kconsole_switch || compositor_test);
+	    viewport_change || kconsole_switch);
 
 	if (filter) {
@@ -1816,34 +1883,39 @@
 				return ENOMEM;
 			}
-
+			
 			sysarg_t width, height;
 			surface_get_resolution(win->surface, &width, &height);
-
+			
 			link_initialize(&event->link);
 			event->type = ET_WINDOW_RESIZE;
-
+			
+			event->data.resize.offset_x = 0;
+			event->data.resize.offset_y = 0;
+			
 			switch (key) {
 			case KC_T:
-				event->data.rsz.width = width;
-				event->data.rsz.height = (height >= 20) ? height - 20 : 0;
+				event->data.resize.width = width;
+				event->data.resize.height = (height >= 20) ? height - 20 : 0;
 				break;
 			case KC_G:
-				event->data.rsz.width = width;
-				event->data.rsz.height = height + 20;
+				event->data.resize.width = width;
+				event->data.resize.height = height + 20;
 				break;
 			case KC_B:
-				event->data.rsz.width = (width >= 20) ? width - 20 : 0;;
-				event->data.rsz.height = height;
+				event->data.resize.width = (width >= 20) ? width - 20 : 0;;
+				event->data.resize.height = height;
 				break;
 			case KC_N:
-				event->data.rsz.width = width + 20;
-				event->data.rsz.height = height;
+				event->data.resize.width = width + 20;
+				event->data.resize.height = height;
 				break;
 			default:
-				event->data.rsz.width = 0;
-				event->data.rsz.height = 0;
-				break;
-			}
-
+				event->data.resize.width = 0;
+				event->data.resize.height = 0;
+				break;
+			}
+			
+			event->data.resize.placement_flags = WINDOW_PLACEMENT_ANY;
+			
 			fibril_mutex_unlock(&window_list_mtx);
 			comp_post_event_top(event);
@@ -2014,33 +2086,4 @@
 	} else if (kconsole_switch) {
 		__SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
-	} else if (compositor_test) {
-		fibril_mutex_lock(&window_list_mtx);
-
-		window_t *red_win = window_create(0, 0);
-		red_win->surface = surface_create(250, 150, NULL, 0);
-		pixel_t red_pix = PIXEL(255, 240, 0, 0);
-		for (sysarg_t y = 0; y <  150; ++y) {
-			for (sysarg_t x = 0; x < 250; ++x) {
-				surface_put_pixel(red_win->surface, x, y, red_pix);
-			}
-		}
-		list_prepend(&red_win->link, &window_list);
-
-		window_t *blue_win = window_create(0, 0);
-		blue_win->surface = surface_create(200, 100, NULL, 0);
-		pixel_t blue_pix = PIXEL(255, 0, 0, 240);
-		for (sysarg_t y = 0; y <  100; ++y) {
-			for (sysarg_t x = 0; x < 200; ++x) {
-				surface_put_pixel(blue_win->surface, x, y, blue_pix);
-			}
-		}
-		list_prepend(&blue_win->link, &window_list);
-		
-		window_t *nameic_win = window_create(0, 0);
-		nameic_win->surface = decode_tga((void *) nameic_tga, nameic_tga_size, 0);
-		list_prepend(&nameic_win->link, &window_list);
-
-		fibril_mutex_unlock(&window_list_mtx);
-		comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
 	} else {
 		window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
Index: uspace/srv/klog/Makefile
===================================================================
--- uspace/srv/klog/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/srv/klog/Makefile	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+BINARY = klog
+
+SOURCES = \
+	klog.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/klog/klog.c
===================================================================
--- uspace/srv/klog/klog.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
+++ uspace/srv/klog/klog.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2013 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup klog KLog
+ * @brief HelenOS KLog
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <async.h>
+#include <as.h>
+#include <ddi.h>
+#include <event.h>
+#include <errno.h>
+#include <str_error.h>
+#include <io/klog.h>
+#include <sysinfo.h>
+#include <malloc.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <adt/prodcons.h>
+#include <io/log.h>
+#include <io/logctl.h>
+
+#define NAME       "klog"
+
+typedef struct {
+	size_t entry_len;
+	uint32_t serial;
+	uint32_t facility;
+	uint32_t level;
+	char message[0];
+	
+} __attribute__((__packed__)) log_entry_t;
+
+/* Producer/consumer buffers */
+typedef struct {
+	link_t link;
+	size_t size;
+	log_entry_t *data;
+} item_t;
+
+static prodcons_t pc;
+
+/* Pointer to buffer where kernel stores new entries */
+#define BUFFER_SIZE PAGE_SIZE
+static void *buffer;
+
+/* Notification mutex */
+static FIBRIL_MUTEX_INITIALIZE(mtx);
+
+static log_t kernel_ctx;
+static const char *facility_name[] = {
+	"other",
+	"uspace",
+	"arch"
+};
+
+#define facility_len (sizeof(facility_name) / sizeof(const char *))
+static log_t facility_ctx[facility_len];
+
+/** Klog producer
+ *
+ * Copies the log entries to a producer/consumer queue.
+ *
+ * @param length Number of characters to copy.
+ * @param data   Pointer to the kernel klog buffer.
+ *
+ */
+static void producer()
+{
+	int read = klog_read(buffer, BUFFER_SIZE);
+	
+	if (read < 0) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "klog_read failed, rc = %d",
+		    read);
+		return;
+	}
+	
+	size_t len = read;
+	size_t offset = 0;
+	while (offset < len) {
+		size_t entry_len = *((size_t *) (buffer + offset));
+		
+		if (offset + entry_len > len || entry_len < sizeof(log_entry_t))
+			break;
+		
+		log_entry_t *buf = malloc(entry_len + 1);
+		if (buf == NULL)
+			break;
+		
+		item_t *item = malloc(sizeof(item_t));
+		if (item == NULL) {
+			free(buf);
+			break;
+		}
+		
+		memcpy(buf, buffer + offset, entry_len);
+		*((uint8_t *) buf + entry_len) = 0;
+		link_initialize(&item->link);
+		item->size = entry_len;
+		item->data = buf;
+		prodcons_produce(&pc, &item->link);
+		
+		offset += entry_len;
+	}
+}
+
+/** Klog consumer
+ *
+ * Waits in an infinite loop for the log data created by
+ * the producer and logs them to the logger.
+ *
+ * @param data Unused.
+ *
+ * @return Always EOK (unreachable).
+ *
+ */
+static int consumer(void *data)
+{
+	
+	while (true) {
+		link_t *link = prodcons_consume(&pc);
+		item_t *item = list_get_instance(link, item_t, link);
+		
+		if (item->size < sizeof(log_entry_t)) {
+			free(item->data);
+			free(item);
+			continue;
+		}
+		
+		if (item->data->facility == LF_USPACE) {
+			/* Avoid reposting messages */
+			free(item->data);
+			free(item);
+			continue;
+		}
+		
+		log_t ctx = kernel_ctx;
+		if (item->data->facility < facility_len) {
+			ctx = facility_ctx[item->data->facility];
+		}
+		
+		log_level_t lvl = item->data->level;
+		if (lvl > LVL_LIMIT)
+			lvl = LVL_NOTE;
+		
+		log_msg(ctx, lvl, "%s", item->data->message);
+		
+		free(item->data);
+		free(item);
+	}
+	
+	return EOK;
+}
+
+/** Kernel notification handler
+ *
+ * Receives kernel klog notifications.
+ *
+ * @param callid IPC call ID
+ * @param call   IPC call structure
+ * @param arg    Local argument
+ *
+ */
+static void notification_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	/*
+	 * Make sure we process only a single notification
+	 * at any time to limit the chance of the consumer
+	 * starving.
+	 */
+	
+	fibril_mutex_lock(&mtx);
+	
+	producer();
+	
+	event_unmask(EVENT_KLOG);
+	fibril_mutex_unlock(&mtx);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc = log_init(NAME);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to initialize log\n", NAME);
+		return rc;
+	}
+	
+	kernel_ctx = log_create("kernel", LOG_NO_PARENT);
+	for (unsigned int i = 0; i < facility_len; i++) {
+		facility_ctx[i] = log_create(facility_name[i], kernel_ctx);
+	}
+	
+	buffer = malloc(BUFFER_SIZE);
+	if (buffer == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to allocate buffer");
+		return 1;
+	}
+	
+	prodcons_initialize(&pc);
+	async_set_interrupt_received(notification_received);
+	rc = event_subscribe(EVENT_KLOG, 0);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "Unable to register klog notifications");
+		return rc;
+	}
+	
+	fid_t fid = fibril_create(consumer, NULL);
+	if (!fid) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "Unable to create consumer fibril");
+		return ENOMEM;
+	}
+	
+	fibril_add_ready(fid);
+	event_unmask(EVENT_KLOG);
+	
+	fibril_mutex_lock(&mtx);
+	producer();
+	fibril_mutex_unlock(&mtx);
+	
+	task_retval(0);
+	async_manager();
+	
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/logger/writer.c
===================================================================
--- uspace/srv/logger/writer.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
+++ uspace/srv/logger/writer.c	(revision 19b3cc6e811d9121b454895875bdd47387821c1e)
@@ -40,4 +40,5 @@
 #include <io/log.h>
 #include <io/logctl.h>
+#include <io/klog.h>
 #include <ns.h>
 #include <async.h>
@@ -79,5 +80,5 @@
 	}
 
-	printf("[%s] %s: %s\n",
+	KLOG_PRINTF(level, "[%s] %s: %s\n",
 	    log->full_name, log_level_str(level),
 	    (const char *) message);
